1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is Robert Sayre.
18 : *
19 : * Portions created by the Initial Developer are Copyright (C) 2005
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Brett Wilson <brettw@gmail.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsIInputStream.h"
40 : #include "nsNetCID.h"
41 : #include "nsNetUtil.h"
42 : #include "nsCharsetAlias.h"
43 : #include "nsParserCIID.h"
44 : #include "nsStreamUtils.h"
45 : #include "nsStringStream.h"
46 : #include "nsIScriptError.h"
47 : #include "nsSAXAttributes.h"
48 : #include "nsSAXLocator.h"
49 : #include "nsSAXXMLReader.h"
50 :
51 : #define XMLNS_URI "http://www.w3.org/2000/xmlns/"
52 :
53 : static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
54 :
55 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsSAXXMLReader)
56 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsSAXXMLReader)
57 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContentHandler)
58 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDTDHandler)
59 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mErrorHandler)
60 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLexicalHandler)
61 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mBaseURI)
62 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListener)
63 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParserObserver)
64 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
65 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsSAXXMLReader)
66 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContentHandler)
67 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDTDHandler)
68 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mErrorHandler)
69 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLexicalHandler)
70 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBaseURI)
71 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListener)
72 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParserObserver)
73 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
74 2052 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader)
75 2257 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader)
76 3897 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader)
77 2872 : NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader)
78 2462 : NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
79 2255 : NS_INTERFACE_MAP_ENTRY(nsIExtendedExpatSink)
80 2050 : NS_INTERFACE_MAP_ENTRY(nsIContentSink)
81 1640 : NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
82 1640 : NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
83 1640 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader)
84 1435 : NS_INTERFACE_MAP_END
85 :
86 205 : nsSAXXMLReader::nsSAXXMLReader() : mIsAsyncParse(false)
87 : {
88 205 : }
89 :
90 : // nsIContentSink
91 : NS_IMETHODIMP
92 205 : nsSAXXMLReader::WillBuildModel(nsDTDMode)
93 : {
94 205 : if (mContentHandler)
95 205 : return mContentHandler->StartDocument();
96 :
97 0 : return NS_OK;
98 : }
99 :
100 : NS_IMETHODIMP
101 205 : nsSAXXMLReader::DidBuildModel(bool aTerminated)
102 : {
103 205 : if (mContentHandler)
104 205 : return mContentHandler->EndDocument();
105 :
106 0 : return NS_OK;
107 : }
108 :
109 : NS_IMETHODIMP
110 205 : nsSAXXMLReader::SetParser(nsParserBase *aParser)
111 : {
112 205 : return NS_OK;
113 : }
114 :
115 : // nsIExtendedExpatSink
116 : NS_IMETHODIMP
117 2563 : nsSAXXMLReader::HandleStartElement(const PRUnichar *aName,
118 : const PRUnichar **aAtts,
119 : PRUint32 aAttsCount,
120 : PRInt32 aIndex,
121 : PRUint32 aLineNumber)
122 : {
123 2563 : if (!mContentHandler)
124 0 : return NS_OK;
125 :
126 5126 : nsCOMPtr<nsSAXAttributes> atts = new nsSAXAttributes();
127 2563 : if (!atts)
128 0 : return NS_ERROR_OUT_OF_MEMORY;
129 5126 : nsAutoString uri, localName, qName;
130 3901 : for (; *aAtts; aAtts += 2) {
131 1338 : SplitExpatName(aAtts[0], uri, localName, qName);
132 : // XXX don't have attr type information
133 2676 : NS_NAMED_LITERAL_STRING(cdataType, "CDATA");
134 : // could support xmlns reporting, it's a standard SAX feature
135 1338 : if (!uri.EqualsLiteral(XMLNS_URI)) {
136 1018 : NS_ASSERTION(aAtts[1], "null passed to handler");
137 1018 : atts->AddAttribute(uri, localName, qName, cdataType,
138 1018 : nsDependentString(aAtts[1]));
139 : }
140 : }
141 :
142 : // Deal with the element name
143 2563 : SplitExpatName(aName, uri, localName, qName);
144 2563 : return mContentHandler->StartElement(uri, localName, qName, atts);
145 : }
146 :
147 : NS_IMETHODIMP
148 2559 : nsSAXXMLReader::HandleEndElement(const PRUnichar *aName)
149 : {
150 2559 : if (mContentHandler) {
151 5118 : nsAutoString uri, localName, qName;
152 2559 : SplitExpatName(aName, uri, localName, qName);
153 2559 : return mContentHandler->EndElement(uri, localName, qName);
154 : }
155 0 : return NS_OK;
156 : }
157 :
158 : NS_IMETHODIMP
159 224 : nsSAXXMLReader::HandleComment(const PRUnichar *aName)
160 : {
161 224 : NS_ASSERTION(aName, "null passed to handler");
162 224 : if (mLexicalHandler)
163 2 : return mLexicalHandler->Comment(nsDependentString(aName));
164 :
165 222 : return NS_OK;
166 : }
167 :
168 : NS_IMETHODIMP
169 25 : nsSAXXMLReader::HandleCDataSection(const PRUnichar *aData,
170 : PRUint32 aLength)
171 : {
172 : nsresult rv;
173 25 : if (mLexicalHandler) {
174 2 : rv = mLexicalHandler->StartCDATA();
175 2 : NS_ENSURE_SUCCESS(rv, rv);
176 : }
177 :
178 25 : if (mContentHandler) {
179 25 : rv = mContentHandler->Characters(Substring(aData, aData+aLength));
180 25 : NS_ENSURE_SUCCESS(rv, rv);
181 : }
182 :
183 25 : if (mLexicalHandler) {
184 2 : rv = mLexicalHandler->EndCDATA();
185 2 : NS_ENSURE_SUCCESS(rv, rv);
186 : }
187 :
188 25 : return NS_OK;
189 : }
190 :
191 : NS_IMETHODIMP
192 4 : nsSAXXMLReader::HandleStartDTD(const PRUnichar *aName,
193 : const PRUnichar *aSystemId,
194 : const PRUnichar *aPublicId)
195 : {
196 4 : PRUnichar nullChar = PRUnichar(0);
197 4 : if (!aName)
198 0 : aName = &nullChar;
199 4 : if (!aSystemId)
200 2 : aSystemId = &nullChar;
201 4 : if (!aPublicId)
202 4 : aPublicId = &nullChar;
203 :
204 4 : mSystemId = aSystemId;
205 4 : mPublicId = aPublicId;
206 4 : if (mLexicalHandler) {
207 4 : return mLexicalHandler->StartDTD(nsDependentString(aName),
208 2 : nsDependentString(aSystemId),
209 4 : nsDependentString(aPublicId));
210 : }
211 :
212 2 : return NS_OK;
213 : }
214 :
215 : NS_IMETHODIMP
216 4 : nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset,
217 : const nsAString & aName,
218 : const nsAString & aSystemId,
219 : const nsAString & aPublicId,
220 : nsISupports* aCatalogData)
221 : {
222 4 : if (mLexicalHandler)
223 2 : return mLexicalHandler->EndDTD();
224 :
225 2 : return NS_OK;
226 : }
227 :
228 : NS_IMETHODIMP
229 8362 : nsSAXXMLReader::HandleCharacterData(const PRUnichar *aData,
230 : PRUint32 aLength)
231 : {
232 8362 : if (mContentHandler)
233 8362 : return mContentHandler->Characters(Substring(aData, aData+aLength));
234 :
235 0 : return NS_OK;
236 : }
237 :
238 : NS_IMETHODIMP
239 320 : nsSAXXMLReader::HandleStartNamespaceDecl(const PRUnichar *aPrefix,
240 : const PRUnichar *aUri)
241 : {
242 320 : if (!mContentHandler)
243 0 : return NS_OK;
244 :
245 320 : PRUnichar nullChar = PRUnichar(0);
246 320 : if (!aPrefix)
247 180 : aPrefix = &nullChar;
248 320 : if (!aUri)
249 0 : aUri = &nullChar;
250 :
251 640 : return mContentHandler->StartPrefixMapping(nsDependentString(aPrefix),
252 640 : nsDependentString(aUri));
253 : }
254 :
255 : NS_IMETHODIMP
256 314 : nsSAXXMLReader::HandleEndNamespaceDecl(const PRUnichar *aPrefix)
257 : {
258 314 : if (!mContentHandler)
259 0 : return NS_OK;
260 :
261 314 : if (aPrefix)
262 135 : return mContentHandler->EndPrefixMapping(nsDependentString(aPrefix));
263 :
264 179 : return mContentHandler->EndPrefixMapping(EmptyString());
265 : }
266 :
267 : NS_IMETHODIMP
268 3 : nsSAXXMLReader::HandleProcessingInstruction(const PRUnichar *aTarget,
269 : const PRUnichar *aData)
270 : {
271 3 : NS_ASSERTION(aTarget && aData, "null passed to handler");
272 3 : if (mContentHandler) {
273 6 : return mContentHandler->ProcessingInstruction(nsDependentString(aTarget),
274 6 : nsDependentString(aData));
275 : }
276 :
277 0 : return NS_OK;
278 : }
279 :
280 : NS_IMETHODIMP
281 0 : nsSAXXMLReader::HandleNotationDecl(const PRUnichar *aNotationName,
282 : const PRUnichar *aSystemId,
283 : const PRUnichar *aPublicId)
284 : {
285 0 : NS_ASSERTION(aNotationName, "null passed to handler");
286 0 : if (mDTDHandler) {
287 0 : PRUnichar nullChar = PRUnichar(0);
288 0 : if (!aSystemId)
289 0 : aSystemId = &nullChar;
290 0 : if (!aPublicId)
291 0 : aPublicId = &nullChar;
292 :
293 0 : return mDTDHandler->NotationDecl(nsDependentString(aNotationName),
294 0 : nsDependentString(aSystemId),
295 0 : nsDependentString(aPublicId));
296 : }
297 :
298 0 : return NS_OK;
299 : }
300 :
301 : NS_IMETHODIMP
302 0 : nsSAXXMLReader::HandleUnparsedEntityDecl(const PRUnichar *aEntityName,
303 : const PRUnichar *aSystemId,
304 : const PRUnichar *aPublicId,
305 : const PRUnichar *aNotationName)
306 : {
307 0 : NS_ASSERTION(aEntityName && aNotationName, "null passed to handler");
308 0 : if (mDTDHandler) {
309 0 : PRUnichar nullChar = PRUnichar(0);
310 0 : if (!aSystemId)
311 0 : aSystemId = &nullChar;
312 0 : if (!aPublicId)
313 0 : aPublicId = &nullChar;
314 :
315 0 : return mDTDHandler->UnparsedEntityDecl(nsDependentString(aEntityName),
316 0 : nsDependentString(aSystemId),
317 0 : nsDependentString(aPublicId),
318 0 : nsDependentString(aNotationName));
319 : }
320 :
321 0 : return NS_OK;
322 : }
323 :
324 : NS_IMETHODIMP
325 201 : nsSAXXMLReader::HandleXMLDeclaration(const PRUnichar *aVersion,
326 : const PRUnichar *aEncoding,
327 : PRInt32 aStandalone)
328 : {
329 : // XXX need to decide what to do with this. It's a separate
330 : // optional interface in SAX.
331 201 : return NS_OK;
332 : }
333 :
334 : NS_IMETHODIMP
335 2 : nsSAXXMLReader::ReportError(const PRUnichar* aErrorText,
336 : const PRUnichar* aSourceText,
337 : nsIScriptError *aError,
338 : bool *_retval)
339 : {
340 2 : NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
341 : // Normally, the expat driver should report the error.
342 2 : *_retval = true;
343 :
344 2 : if (mErrorHandler) {
345 : PRUint32 lineNumber;
346 2 : nsresult rv = aError->GetLineNumber(&lineNumber);
347 2 : NS_ENSURE_SUCCESS(rv, rv);
348 :
349 : PRUint32 columnNumber;
350 2 : rv = aError->GetColumnNumber(&columnNumber);
351 2 : NS_ENSURE_SUCCESS(rv, rv);
352 :
353 : nsCOMPtr<nsISAXLocator> locator = new nsSAXLocator(mPublicId,
354 : mSystemId,
355 : lineNumber,
356 4 : columnNumber);
357 2 : if (!locator)
358 0 : return NS_ERROR_OUT_OF_MEMORY;
359 :
360 2 : rv = mErrorHandler->FatalError(locator, nsDependentString(aErrorText));
361 2 : if (NS_SUCCEEDED(rv)) {
362 : // The error handler has handled the script error. Don't log to console.
363 2 : *_retval = false;
364 : }
365 : }
366 :
367 2 : return NS_OK;
368 : }
369 :
370 : // nsISAXXMLReader
371 :
372 : NS_IMETHODIMP
373 0 : nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI)
374 : {
375 0 : NS_IF_ADDREF(*aBaseURI = mBaseURI);
376 0 : return NS_OK;
377 : }
378 :
379 : NS_IMETHODIMP
380 203 : nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI)
381 : {
382 203 : mBaseURI = aBaseURI;
383 203 : return NS_OK;
384 : }
385 :
386 : NS_IMETHODIMP
387 0 : nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler)
388 : {
389 0 : NS_IF_ADDREF(*aContentHandler = mContentHandler);
390 0 : return NS_OK;
391 : }
392 :
393 : NS_IMETHODIMP
394 2548 : nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler)
395 : {
396 2548 : mContentHandler = aContentHandler;
397 2548 : return NS_OK;
398 : }
399 :
400 : NS_IMETHODIMP
401 0 : nsSAXXMLReader::GetDtdHandler(nsISAXDTDHandler **aDtdHandler)
402 : {
403 0 : NS_IF_ADDREF(*aDtdHandler = mDTDHandler);
404 0 : return NS_OK;
405 : }
406 :
407 : NS_IMETHODIMP
408 4 : nsSAXXMLReader::SetDtdHandler(nsISAXDTDHandler *aDtdHandler)
409 : {
410 4 : mDTDHandler = aDtdHandler;
411 4 : return NS_OK;
412 : }
413 :
414 : NS_IMETHODIMP
415 0 : nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler)
416 : {
417 0 : NS_IF_ADDREF(*aErrorHandler = mErrorHandler);
418 0 : return NS_OK;
419 : }
420 :
421 : NS_IMETHODIMP
422 207 : nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
423 : {
424 207 : mErrorHandler = aErrorHandler;
425 207 : return NS_OK;
426 : }
427 :
428 : NS_IMETHODIMP
429 2 : nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue)
430 : {
431 2 : return NS_ERROR_NOT_IMPLEMENTED;
432 : }
433 :
434 : NS_IMETHODIMP
435 0 : nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult)
436 : {
437 0 : return NS_ERROR_NOT_IMPLEMENTED;
438 : }
439 :
440 : NS_IMETHODIMP
441 0 : nsSAXXMLReader::GetLexicalHandler(nsISAXLexicalHandler **aLexicalHandler)
442 : {
443 0 : NS_IF_ADDREF(*aLexicalHandler = mLexicalHandler);
444 0 : return NS_OK;
445 : }
446 :
447 : NS_IMETHODIMP
448 4 : nsSAXXMLReader::SetLexicalHandler(nsISAXLexicalHandler *aLexicalHandler)
449 : {
450 4 : mLexicalHandler = aLexicalHandler;
451 4 : return NS_OK;
452 : }
453 :
454 : NS_IMETHODIMP
455 0 : nsSAXXMLReader::SetProperty(const nsAString &aName, nsISupports* aValue)
456 : {
457 0 : return NS_ERROR_NOT_IMPLEMENTED;
458 : }
459 :
460 : NS_IMETHODIMP
461 0 : nsSAXXMLReader::GetProperty(const nsAString &aName, bool *aResult)
462 : {
463 0 : return NS_ERROR_NOT_IMPLEMENTED;
464 : }
465 :
466 : NS_IMETHODIMP
467 2 : nsSAXXMLReader::ParseFromString(const nsAString &aStr,
468 : const char *aContentType)
469 : {
470 : // Don't call this in the middle of an async parse
471 2 : NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
472 :
473 4 : NS_ConvertUTF16toUTF8 data(aStr);
474 :
475 : // The new stream holds a reference to the buffer
476 4 : nsCOMPtr<nsIInputStream> stream;
477 2 : nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
478 2 : data.get(), data.Length(),
479 2 : NS_ASSIGNMENT_DEPEND);
480 2 : NS_ENSURE_SUCCESS(rv, rv);
481 2 : return ParseFromStream(stream, "UTF-8", aContentType);
482 : }
483 :
484 : NS_IMETHODIMP
485 205 : nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
486 : const char *aCharset,
487 : const char *aContentType)
488 : {
489 : // Don't call this in the middle of an async parse
490 205 : NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
491 :
492 205 : NS_ENSURE_ARG(aStream);
493 205 : NS_ENSURE_ARG(aContentType);
494 :
495 : // Put the nsCOMPtr out here so we hold a ref to the stream as needed
496 : nsresult rv;
497 410 : nsCOMPtr<nsIInputStream> bufferedStream;
498 205 : if (!NS_InputStreamIsBuffered(aStream)) {
499 203 : rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
500 203 : aStream, 4096);
501 203 : NS_ENSURE_SUCCESS(rv, rv);
502 203 : aStream = bufferedStream;
503 : }
504 :
505 205 : rv = EnsureBaseURI();
506 205 : NS_ENSURE_SUCCESS(rv, rv);
507 :
508 410 : nsCOMPtr<nsIChannel> parserChannel;
509 205 : rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI,
510 410 : aStream, nsDependentCString(aContentType));
511 205 : if (!parserChannel || NS_FAILED(rv))
512 0 : return NS_ERROR_FAILURE;
513 :
514 205 : if (aCharset)
515 2 : parserChannel->SetContentCharset(nsDependentCString(aCharset));
516 :
517 205 : rv = InitParser(nsnull, parserChannel);
518 205 : NS_ENSURE_SUCCESS(rv, rv);
519 :
520 205 : rv = mListener->OnStartRequest(parserChannel, nsnull);
521 205 : if (NS_FAILED(rv))
522 0 : parserChannel->Cancel(rv);
523 :
524 : /* When parsing a new document, we need to clear the XML identifiers.
525 : HandleStartDTD will set these values from the DTD declaration tag.
526 : We won't have them, of course, if there's a well-formedness error
527 : before the DTD tag (such as a space before an XML declaration).
528 : */
529 205 : mSystemId.Truncate();
530 205 : mPublicId.Truncate();
531 :
532 : nsresult status;
533 205 : parserChannel->GetStatus(&status);
534 :
535 205 : PRUint32 offset = 0;
536 615 : while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
537 : PRUint32 available;
538 410 : rv = aStream->Available(&available);
539 410 : if (rv == NS_BASE_STREAM_CLOSED) {
540 0 : rv = NS_OK;
541 0 : available = 0;
542 : }
543 410 : if (NS_FAILED(rv)) {
544 0 : parserChannel->Cancel(rv);
545 0 : break;
546 : }
547 410 : if (! available)
548 205 : break; // blocking input stream has none available when done
549 :
550 205 : rv = mListener->OnDataAvailable(parserChannel, nsnull,
551 205 : aStream, offset, available);
552 205 : if (NS_SUCCEEDED(rv))
553 205 : offset += available;
554 : else
555 0 : parserChannel->Cancel(rv);
556 205 : parserChannel->GetStatus(&status);
557 : }
558 205 : rv = mListener->OnStopRequest(parserChannel, nsnull, status);
559 205 : mListener = nsnull;
560 :
561 205 : return rv;
562 : }
563 :
564 : NS_IMETHODIMP
565 0 : nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver)
566 : {
567 0 : mParserObserver = aObserver;
568 0 : mIsAsyncParse = true;
569 0 : return NS_OK;
570 : }
571 :
572 : // nsIRequestObserver
573 :
574 : NS_IMETHODIMP
575 0 : nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
576 : {
577 0 : NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
578 : nsresult rv;
579 0 : rv = EnsureBaseURI();
580 0 : NS_ENSURE_SUCCESS(rv, rv);
581 0 : nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
582 0 : rv = InitParser(mParserObserver, channel);
583 0 : NS_ENSURE_SUCCESS(rv, rv);
584 : // we don't need or want this anymore
585 0 : mParserObserver = nsnull;
586 0 : return mListener->OnStartRequest(aRequest, aContext);
587 : }
588 :
589 : NS_IMETHODIMP
590 0 : nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
591 : nsresult status)
592 : {
593 0 : NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
594 0 : NS_ENSURE_STATE(mListener);
595 0 : nsresult rv = mListener->OnStopRequest(aRequest, aContext, status);
596 0 : mListener = nsnull;
597 0 : mIsAsyncParse = false;
598 0 : return rv;
599 : }
600 :
601 : // nsIStreamListener
602 :
603 : NS_IMETHODIMP
604 0 : nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
605 : nsIInputStream *aInputStream, PRUint32 offset,
606 : PRUint32 count)
607 : {
608 0 : NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
609 0 : NS_ENSURE_STATE(mListener);
610 0 : return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset,
611 0 : count);
612 : }
613 :
614 : nsresult
615 205 : nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel)
616 : {
617 : nsresult rv;
618 :
619 : // setup the parser
620 410 : nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID, &rv);
621 205 : NS_ENSURE_SUCCESS(rv, rv);
622 :
623 205 : parser->SetContentSink(this);
624 :
625 205 : PRInt32 charsetSource = kCharsetFromDocTypeDefault;
626 410 : nsCAutoString charset(NS_LITERAL_CSTRING("UTF-8"));
627 205 : TryChannelCharset(aChannel, charsetSource, charset);
628 205 : parser->SetDocumentCharset(charset, charsetSource);
629 :
630 205 : rv = parser->Parse(mBaseURI, aObserver);
631 205 : NS_ENSURE_SUCCESS(rv, rv);
632 :
633 205 : mListener = do_QueryInterface(parser, &rv);
634 :
635 205 : return rv;
636 : }
637 :
638 : // from nsDocument.cpp
639 : bool
640 205 : nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel,
641 : PRInt32& aCharsetSource,
642 : nsACString& aCharset)
643 : {
644 205 : if (aCharsetSource >= kCharsetFromChannel)
645 0 : return true;
646 :
647 205 : if (aChannel) {
648 410 : nsCAutoString charsetVal;
649 205 : nsresult rv = aChannel->GetContentCharset(charsetVal);
650 205 : if (NS_SUCCEEDED(rv)) {
651 410 : nsCAutoString preferred;
652 205 : if (NS_FAILED(nsCharsetAlias::GetPreferred(charsetVal, preferred)))
653 203 : return false;
654 :
655 2 : aCharset = preferred;
656 2 : aCharsetSource = kCharsetFromChannel;
657 2 : return true;
658 : }
659 : }
660 :
661 0 : return false;
662 : }
663 :
664 : nsresult
665 205 : nsSAXXMLReader::EnsureBaseURI()
666 : {
667 205 : if (mBaseURI)
668 203 : return NS_OK;
669 :
670 2 : return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank");
671 : }
672 :
673 : nsresult
674 6460 : nsSAXXMLReader::SplitExpatName(const PRUnichar *aExpatName,
675 : nsString &aURI,
676 : nsString &aLocalName,
677 : nsString &aQName)
678 : {
679 : /**
680 : * Adapted from RDFContentSinkImpl
681 : *
682 : * Expat can send the following:
683 : * localName
684 : * namespaceURI<separator>localName
685 : * namespaceURI<separator>localName<separator>prefix
686 : *
687 : * and we use 0xFFFF for the <separator>.
688 : *
689 : */
690 :
691 6460 : NS_ASSERTION(aExpatName, "null passed to handler");
692 12920 : nsDependentString expatStr(aExpatName);
693 6460 : PRInt32 break1, break2 = kNotFound;
694 6460 : break1 = expatStr.FindChar(PRUnichar(0xFFFF));
695 :
696 6460 : if (break1 == kNotFound) {
697 2081 : aLocalName = expatStr; // no namespace
698 2081 : aURI.Truncate();
699 2081 : aQName = expatStr;
700 : } else {
701 4379 : aURI = StringHead(expatStr, break1);
702 4379 : break2 = expatStr.FindChar(PRUnichar(0xFFFF), break1 + 1);
703 4379 : if (break2 == kNotFound) { // namespace, but no prefix
704 3598 : aLocalName = Substring(expatStr, break1 + 1);
705 3598 : aQName = aLocalName;
706 : } else { // namespace with prefix
707 781 : aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1);
708 781 : aQName = Substring(expatStr, break2 + 1) +
709 1562 : NS_LITERAL_STRING(":") + aLocalName;
710 : }
711 : }
712 :
713 6460 : return NS_OK;
714 4392 : }
|