Back to index

lightning-sunbird  0.9+nobinonly
nsParserUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsParserUtils.h"
00039 #include "nsIParser.h" // for kQuote et. al.
00040 #include "jsapi.h"
00041 #include "nsReadableUtils.h"
00042 #include "nsCRT.h"
00043 #include "nsContentUtils.h"
00044 #include "nsIParserService.h"
00045 
00046 #define SKIP_WHITESPACE(iter, end_iter)                          \
00047   while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
00048     ++(iter);                                                    \
00049   }                                                              \
00050   if ((iter) == (end_iter))                                      \
00051     break
00052 
00053 #define SKIP_ATTR_NAME(iter, end_iter)                            \
00054   while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
00055          *(iter) != '=') {                                        \
00056     ++(iter);                                                     \
00057   }                                                               \
00058   if ((iter) == (end_iter))                                       \
00059     break
00060 
00061 PRBool
00062 nsParserUtils::GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
00063                                        nsAString& aValue,
00064                                        PRBool aComplyWithSpec)
00065 {
00066   aValue.Truncate();
00067 
00068   const PRUnichar *start = aSource.get();
00069   const PRUnichar *end = start + aSource.Length();
00070   const PRUnichar *iter;
00071   
00072   while (start != end) {
00073     SKIP_WHITESPACE(start, end);
00074     iter = start;
00075     SKIP_ATTR_NAME(iter, end);
00076 
00077     // Remember the attr name.
00078     const nsDependentSubstring & attrName = Substring(start, iter);
00079 
00080     // Now check whether this is a valid name="value" pair.
00081     start = iter;
00082     SKIP_WHITESPACE(start, end);
00083     if (*start != '=') {
00084       // No '=', so this is not a name="value" pair.  We don't know
00085       // what it is, and we have no way to handle it.
00086       break;
00087     }
00088     
00089     // Have to skip the value.
00090     ++start;
00091     SKIP_WHITESPACE(start, end);
00092     PRUnichar q = *start;
00093     if (q != kQuote && q != kApostrophe) {
00094       // Not a valid quoted value, so bail.
00095       break;
00096     }
00097     
00098     ++start;  // Point to the first char of the value.
00099     iter = start;
00100 
00101     while (iter != end && *iter != q) {
00102       ++iter;
00103     }
00104 
00105     if (iter == end) {
00106       // Oops, unterminated quoted string.
00107       break;
00108     }
00109 
00110     // At this point attrName holds the name of the "attribute" and
00111     // the value is between start and iter.
00112     
00113     if (aName->Equals(attrName)) {
00114       if (!aComplyWithSpec) {
00115         aValue.Append(start, iter - start);
00116 
00117         return PR_TRUE;
00118       }
00119 
00120       nsCOMPtr<nsIParserService_MOZILLA_1_8_BRANCH> parserService =
00121         do_QueryInterface(nsContentUtils::GetParserServiceWeakRef());
00122       NS_ENSURE_TRUE(parserService, PR_FALSE);
00123 
00124       // We'll accumulate as many characters as possible (until we hit either
00125       // the end of the string or the beginning of an entity). Chunks will be
00126       // delimited by start and chunkEnd.
00127       const PRUnichar *chunkEnd = start;
00128       while (chunkEnd != iter) {
00129         if (*chunkEnd == kLessThan) {
00130           aValue.Truncate();
00131 
00132           return PR_FALSE;
00133         }
00134 
00135         if (*chunkEnd == kAmpersand) {
00136           aValue.Append(start, chunkEnd - start);
00137 
00138           // Point to first character after the ampersand.
00139           ++chunkEnd;
00140 
00141           const PRUnichar *afterEntity;
00142           PRUnichar result[2];
00143           PRUint32 count =
00144             parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
00145           if (count == 0) {
00146             aValue.Truncate();
00147 
00148             return PR_FALSE;
00149           }
00150 
00151           aValue.Append(result, count);
00152 
00153           // Advance to after the entity and begin a new chunk.
00154           start = chunkEnd = afterEntity;
00155         }
00156         else {
00157           ++chunkEnd;
00158         }
00159       }
00160 
00161       // Append remainder.
00162       aValue.Append(start, iter - start);
00163 
00164       return PR_TRUE;
00165     }
00166 
00167     // Resume scanning after the end of the attribute value (past the quote
00168     // char).
00169     start = iter + 1;
00170   }
00171 
00172   return PR_FALSE;
00173 }
00174 
00175 
00176 // XXX Stolen from nsHTMLContentSink. Needs to be shared.
00177 // XXXbe share also with nsRDFParserUtils.cpp and nsHTMLContentSink.cpp
00178 // Returns PR_TRUE if the language name is a version of JavaScript and
00179 // PR_FALSE otherwise
00180 PRBool
00181 nsParserUtils::IsJavaScriptLanguage(const nsString& aName, const char* *aVersion)
00182 {
00183   JSVersion version = JSVERSION_UNKNOWN;
00184 
00185   if (aName.LowerCaseEqualsLiteral("javascript") ||
00186       aName.LowerCaseEqualsLiteral("livescript") ||
00187       aName.LowerCaseEqualsLiteral("mocha")) {
00188     version = JSVERSION_DEFAULT;
00189   }
00190   else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
00191     version = JSVERSION_1_0;
00192   }
00193   else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
00194     version = JSVERSION_1_1;
00195   }
00196   else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
00197     version = JSVERSION_1_2;
00198   }
00199   else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
00200     version = JSVERSION_1_3;
00201   }
00202   else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
00203     version = JSVERSION_1_4;
00204   }
00205   else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
00206     version = JSVERSION_1_5;
00207   }
00208   else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
00209     version = JSVERSION_1_6;
00210   }
00211   else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
00212     version = JSVERSION_1_7;
00213   }
00214   if (version == JSVERSION_UNKNOWN)
00215     return PR_FALSE;
00216   *aVersion = JS_VersionToString(version);
00217   return PR_TRUE;
00218 }
00219 
00220 void
00221 nsParserUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
00222                              nsString& aParams)
00223 {
00224   aType.Truncate();
00225   aParams.Truncate();
00226   PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
00227   if (-1 != semiIndex) {
00228     aType = Substring(aValue, 0, semiIndex);
00229     aParams = Substring(aValue, semiIndex + 1,
00230                        aValue.Length() - (semiIndex + 1));
00231     aParams.StripWhitespace();
00232   }
00233   else {
00234     aType = aValue;
00235   }
00236   aType.StripWhitespace();
00237 }