TEST(CloneInputStream, NonCloneableInput_NoFallback) { nsTArray<char> inputData; testing::CreateData(4 * 1024, inputData); nsDependentCSubstring inputString(inputData.Elements(), inputData.Length()); nsCOMPtr<nsIInputStream> base; nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Take advantage of nsBufferedInputStream being non-cloneable right // now. If this changes in the future, then we need a different stream // type in this test. nsCOMPtr<nsIInputStream> stream; rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096); ASSERT_TRUE(NS_SUCCEEDED(rv)); nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream); ASSERT_TRUE(cloneable == nullptr); nsCOMPtr<nsIInputStream> clone; rv = NS_CloneInputStream(stream, getter_AddRefs(clone)); ASSERT_TRUE(NS_FAILED(rv)); ASSERT_TRUE(clone == nullptr); testing::ConsumeAndValidateStream(stream, inputString); }
NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr, const nsACString& aMimeType, imgIContainer **aContainer) { nsresult rv; NS_ENSURE_ARG_POINTER(aInStr); // If the caller didn't provide a container, create one if (!*aContainer) { NS_NEWXPCOM(*aContainer, imgContainer); if (!*aContainer) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*aContainer); } // Initialize the container. If we're using the one from the caller, we // require that it not be initialized nsCString mimeType(aMimeType); rv = (*aContainer)->Init(nsnull, mimeType.get(), imgIContainer::INIT_FLAG_NONE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInputStream> inStream = aInStr; if (!NS_InputStreamIsBuffered(aInStr)) { nsCOMPtr<nsIInputStream> bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024); if (NS_SUCCEEDED(rv)) inStream = bufStream; } // Figure out how much data we've been passed PRUint32 length; rv = inStream->Available(&length); NS_ENSURE_SUCCESS(rv, rv); // Send the source data to the container. WriteToContainer always // consumes everything it gets. PRUint32 bytesRead; rv = inStream->ReadSegments(imgContainer::WriteToContainer, static_cast<void*>(*aContainer), length, &bytesRead); NS_ENSURE_SUCCESS(rv, rv); // Let the container know we've sent all the data rv = (*aContainer)->SourceDataComplete(); NS_ENSURE_SUCCESS(rv, rv); // All done return NS_OK; }
TEST(CloneInputStream, NonCloneableInput_Fallback) { nsTArray<char> inputData; testing::CreateData(4 * 1024, inputData); nsDependentCSubstring inputString(inputData.Elements(), inputData.Length()); nsCOMPtr<nsIInputStream> base; nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Take advantage of nsBufferedInputStream being non-cloneable right // now. If this changes in the future, then we need a different stream // type in this test. nsCOMPtr<nsIInputStream> stream; rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096); ASSERT_TRUE(NS_SUCCEEDED(rv)); nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream); ASSERT_TRUE(cloneable == nullptr); nsCOMPtr<nsIInputStream> clone; nsCOMPtr<nsIInputStream> replacement; rv = NS_CloneInputStream(stream, getter_AddRefs(clone), getter_AddRefs(replacement)); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE(clone != nullptr); ASSERT_TRUE(replacement != nullptr); ASSERT_TRUE(stream.get() != replacement.get()); ASSERT_TRUE(clone.get() != replacement.get()); stream = replacement.forget(); // The stream is being copied asynchronously on the STS event target. Spin // a yield loop here until the data is available. Yes, this is a bit hacky, // but AFAICT, gtest does not support async test completion. uint64_t available; do { mozilla::unused << PR_Sleep(PR_INTERVAL_NO_WAIT); rv = stream->Available(&available); ASSERT_TRUE(NS_SUCCEEDED(rv)); } while(available < inputString.Length()); testing::ConsumeAndValidateStream(stream, inputString); testing::ConsumeAndValidateStream(clone, inputString); }
NS_IMETHODIMP nsXULFastLoadFileIO::GetInputStream(nsIInputStream** aResult) { if (! mInputStream) { nsresult rv; nsCOMPtr<nsIInputStream> fileInput; rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInput), mFile); if (NS_FAILED(rv)) return rv; rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream), fileInput, XUL_DESERIALIZATION_BUFFER_SIZE); if (NS_FAILED(rv)) return rv; } NS_ADDREF(*aResult = mInputStream); return NS_OK; }
NS_IMETHODIMP nsXPCFastLoadIO::GetInputStream(nsIInputStream **_retval) { if (! mInputStream) { nsCOMPtr<nsIInputStream> fileInput; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInput), mFile); NS_ENSURE_SUCCESS(rv, rv); rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream), fileInput, XPC_DESERIALIZATION_BUFFER_SIZE); NS_ENSURE_SUCCESS(rv, rv); } NS_ADDREF(*_retval = mInputStream); return NS_OK; }
nsresult VariableLengthPrefixSet::LoadFromFile(nsIFile* aFile) { MutexAutoLock lock(mLock); NS_ENSURE_ARG_POINTER(aFile); Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_VLPS_FILELOAD_TIME> timer; nsCOMPtr<nsIInputStream> localInFile; nsresult rv = NS_NewLocalFileInputStream(getter_AddRefs(localInFile), aFile, PR_RDONLY | nsIFile::OS_READAHEAD); NS_ENSURE_SUCCESS(rv, rv); // Calculate how big the file is, make sure our read buffer isn't bigger // than the file itself which is just wasting memory. int64_t fileSize; rv = aFile->GetFileSize(&fileSize); NS_ENSURE_SUCCESS(rv, rv); if (fileSize < 0 || fileSize > UINT32_MAX) { return NS_ERROR_FAILURE; } uint32_t bufferSize = std::min<uint32_t>(static_cast<uint32_t>(fileSize), MAX_BUFFER_SIZE); // Convert to buffered stream nsCOMPtr<nsIInputStream> in; rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(), bufferSize); NS_ENSURE_SUCCESS(rv, rv); rv = mFixedPrefixSet->LoadPrefixes(in); NS_ENSURE_SUCCESS(rv, rv); rv = LoadPrefixes(in); NS_ENSURE_SUCCESS(rv, rv); return NS_OK;; }
static nsresult CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen, nsCOMPtr<nsIInputStream> &aResult) { nsCOMPtr<nsIInputStream> stream; nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), reinterpret_cast<const char *>(aBuffer), aBufLen, NS_ASSIGNMENT_DEPEND); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInputStream> aBufferedStream; if (!NS_InputStreamIsBuffered(stream)) { rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096); NS_ENSURE_SUCCESS(rv, rv); stream = aBufferedStream; } aResult = stream; return NS_OK; }
nsresult FileReaderSyncPrivate::ReadAsDataURL(nsIDOMBlob* aBlob, nsAString& aResult) { nsAutoString scratchResult; scratchResult.AssignLiteral("data:"); nsString contentType; aBlob->GetType(contentType); if (contentType.IsEmpty()) { scratchResult.AppendLiteral("application/octet-stream"); } else { scratchResult.Append(contentType); } scratchResult.AppendLiteral(";base64,"); nsCOMPtr<nsIInputStream> stream; nsresult rv = aBlob->GetInternalStream(getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); uint64_t size; rv = aBlob->GetSize(&size); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInputStream> bufferedStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, size); NS_ENSURE_SUCCESS(rv, rv); nsAutoString encodedData; rv = Base64EncodeInputStream(bufferedStream, encodedData, size); NS_ENSURE_SUCCESS(rv, rv); scratchResult.Append(encodedData); aResult = scratchResult; return NS_OK; }
NS_IMETHOD Run() { nsresult rv; PRIntervalTime startTime = PR_IntervalNow(); PRIntervalTime endTime; nsCOMPtr<nsIInputStream> inStr; nsCOMPtr<nsIOutputStream> outStr; PRUint32 copyCount = 0; // Open the input stream: nsCOMPtr<nsIInputStream> fileIn; rv = NS_NewLocalFileInputStream(getter_AddRefs(fileIn), mInPath); if (NS_FAILED(rv)) return rv; rv = NS_NewBufferedInputStream(getter_AddRefs(inStr), fileIn, 65535); if (NS_FAILED(rv)) return rv; // Open the output stream: nsCOMPtr<nsIOutputStream> fileOut; rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut), mOutPath, PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE, 0664); if (NS_FAILED(rv)) return rv; rv = NS_NewBufferedOutputStream(getter_AddRefs(outStr), fileOut, 65535); if (NS_FAILED(rv)) return rv; // Copy from one to the other rv = Copy(inStr, outStr, mBuffer, mBufferSize, ©Count); if (NS_FAILED(rv)) return rv; endTime = PR_IntervalNow(); gTimeSampler.AddTime(endTime - startTime); return rv; }
nsresult nsHttpTransaction::Init(PRUint8 caps, nsHttpConnectionInfo *cinfo, nsHttpRequestHead *requestHead, nsIInputStream *requestBody, PRBool requestBodyHasHeaders, nsIEventTarget *target, nsIInterfaceRequestor *callbacks, nsITransportEventSink *eventsink, nsIAsyncInputStream **responseBody) { nsresult rv; LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps)); NS_ASSERTION(cinfo, "ouch"); NS_ASSERTION(requestHead, "ouch"); NS_ASSERTION(target, "ouch"); // create transport event sink proxy that coalesces all events rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink), eventsink, target, PR_TRUE); if (NS_FAILED(rv)) return rv; mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; PRBool active; rv = mActivityDistributor->GetIsActive(&active); if (NS_SUCCEEDED(rv) && active) { // there are some observers registered at activity distributor, gather // nsISupports for the channel that called Init() mChannel = do_QueryInterface(eventsink); LOG(("nsHttpTransaction::Init() " \ "mActivityDistributor is active " \ "this=%x", this)); } else // there is no observer, so don't use it mActivityDistributor = nsnull; NS_ADDREF(mConnInfo = cinfo); mCallbacks = callbacks; mConsumerTarget = target; mCaps = caps; if (requestHead->Method() == nsHttp::Head) mNoContent = PR_TRUE; // Make sure that there is "Content-Length: 0" header in the requestHead // in case of POST and PUT methods when there is no requestBody and // requestHead doesn't contain "Transfer-Encoding" header. // // RFC1945 section 7.2.2: // HTTP/1.0 requests containing an entity body must include a valid // Content-Length header field. // // RFC2616 section 4.4: // For compatibility with HTTP/1.0 applications, HTTP/1.1 requests // containing a message-body MUST include a valid Content-Length header // field unless the server is known to be HTTP/1.1 compliant. if ((requestHead->Method() == nsHttp::Post || requestHead->Method() == nsHttp::Put) && !requestBody && !requestHead->PeekHeader(nsHttp::Transfer_Encoding)) { requestHead->SetHeader(nsHttp::Content_Length, NS_LITERAL_CSTRING("0")); } // grab a weak reference to the request head mRequestHead = requestHead; // make sure we eliminate any proxy specific headers from // the request if we are talking HTTPS via a SSL tunnel. PRBool pruneProxyHeaders = cinfo->UsingSSL() && cinfo->UsingHttpProxy(); mReqHeaderBuf.Truncate(); requestHead->Flatten(mReqHeaderBuf, pruneProxyHeaders); #if defined(PR_LOGGING) if (LOG3_ENABLED()) { LOG3(("http request [\n")); LogHeaders(mReqHeaderBuf.get()); LOG3(("]\n")); } #endif // If the request body does not include headers or if there is no request // body, then we must add the header/body separator manually. if (!requestBodyHasHeaders || !requestBody) mReqHeaderBuf.AppendLiteral("\r\n"); // report the request header if (mActivityDistributor) mActivityDistributor->ObserveActivity( mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), LL_ZERO, mReqHeaderBuf); // Create a string stream for the request header buf (the stream holds // a non-owning reference to the request header data, so we MUST keep // mReqHeaderBuf around). nsCOMPtr<nsIInputStream> headers; rv = NS_NewByteInputStream(getter_AddRefs(headers), mReqHeaderBuf.get(), mReqHeaderBuf.Length()); if (NS_FAILED(rv)) return rv; if (requestBody) { mHasRequestBody = PR_TRUE; // wrap the headers and request body in a multiplexed input stream. nsCOMPtr<nsIMultiplexInputStream> multi = do_CreateInstance(kMultiplexInputStream, &rv); if (NS_FAILED(rv)) return rv; rv = multi->AppendStream(headers); if (NS_FAILED(rv)) return rv; rv = multi->AppendStream(requestBody); if (NS_FAILED(rv)) return rv; // wrap the multiplexed input stream with a buffered input stream, so // that we write data in the largest chunks possible. this is actually // necessary to workaround some common server bugs (see bug 137155). rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi, nsIOService::gDefaultSegmentSize); if (NS_FAILED(rv)) return rv; } else mRequestStream = headers; rv = mRequestStream->Available(&mRequestSize); if (NS_FAILED(rv)) return rv; // create pipe for response stream rv = NS_NewPipe2(getter_AddRefs(mPipeIn), getter_AddRefs(mPipeOut), PR_TRUE, PR_TRUE, nsIOService::gDefaultSegmentSize, nsIOService::gDefaultSegmentCount, nsIOService::gBufferCache); if (NS_FAILED(rv)) return rv; NS_ADDREF(*responseBody = mPipeIn); return NS_OK; }
/* static */ already_AddRefed<gfx::SourceSurface> ImageOps::DecodeToSurface(nsIInputStream* aInputStream, const nsACString& aMimeType, uint32_t aFlags) { MOZ_ASSERT(aInputStream); nsresult rv; // Prepare the input stream. nsCOMPtr<nsIInputStream> inputStream = aInputStream; if (!NS_InputStreamIsBuffered(aInputStream)) { nsCOMPtr<nsIInputStream> bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInputStream, 1024); if (NS_SUCCEEDED(rv)) { inputStream = bufStream; } } // Figure out how much data we've been passed. uint64_t length; rv = inputStream->Available(&length); if (NS_FAILED(rv) || length > UINT32_MAX) { return nullptr; } // Write the data into a SourceBuffer. RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); if (NS_FAILED(rv)) { return nullptr; } sourceBuffer->Complete(NS_OK); // Create a decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get()); RefPtr<Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, ToSurfaceFlags(aFlags)); if (!decoder) { return nullptr; } // Run the decoder synchronously. decoder->Decode(); if (!decoder->GetDecodeDone() || decoder->HasError()) { return nullptr; } // Pull out the surface. RawAccessFrameRef frame = decoder->GetCurrentFrameRef(); if (!frame) { return nullptr; } RefPtr<SourceSurface> surface = frame->GetSurface(); if (!surface) { return nullptr; } return surface.forget(); }
NS_IMETHODIMP nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, const char *aCharset, const char *aContentType) { // Don't call this in the middle of an async parse NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); NS_ENSURE_ARG(aStream); NS_ENSURE_ARG(aContentType); // Put the nsCOMPtr out here so we hold a ref to the stream as needed nsresult rv; nsCOMPtr<nsIInputStream> bufferedStream; if (!NS_InputStreamIsBuffered(aStream)) { rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aStream, 4096); NS_ENSURE_SUCCESS(rv, rv); aStream = bufferedStream; } rv = EnsureBaseURI(); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIChannel> parserChannel; rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI, aStream, nsDependentCString(aContentType)); if (!parserChannel || NS_FAILED(rv)) return NS_ERROR_FAILURE; if (aCharset) parserChannel->SetContentCharset(nsDependentCString(aCharset)); rv = InitParser(nullptr, parserChannel); NS_ENSURE_SUCCESS(rv, rv); rv = mListener->OnStartRequest(parserChannel, nullptr); if (NS_FAILED(rv)) parserChannel->Cancel(rv); /* When parsing a new document, we need to clear the XML identifiers. HandleStartDTD will set these values from the DTD declaration tag. We won't have them, of course, if there's a well-formedness error before the DTD tag (such as a space before an XML declaration). */ mSystemId.Truncate(); mPublicId.Truncate(); nsresult status; parserChannel->GetStatus(&status); uint64_t offset = 0; while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { uint64_t available; rv = aStream->Available(&available); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; available = 0; } if (NS_FAILED(rv)) { parserChannel->Cancel(rv); break; } if (! available) break; // blocking input stream has none available when done if (available > UINT32_MAX) available = UINT32_MAX; rv = mListener->OnDataAvailable(parserChannel, nullptr, aStream, offset, (uint32_t)available); if (NS_SUCCEEDED(rv)) offset += available; else parserChannel->Cancel(rv); parserChannel->GetStatus(&status); } rv = mListener->OnStopRequest(parserChannel, nullptr, status); mListener = nullptr; return rv; }
nsresult nsHttpTransaction::Init(PRUint8 caps, nsHttpConnectionInfo *cinfo, nsHttpRequestHead *requestHead, nsIInputStream *requestBody, PRBool requestBodyHasHeaders, nsIEventTarget *target, nsIInterfaceRequestor *callbacks, nsITransportEventSink *eventsink, nsIAsyncInputStream **responseBody) { nsresult rv; LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps)); NS_ASSERTION(cinfo, "ouch"); NS_ASSERTION(requestHead, "ouch"); NS_ASSERTION(target, "ouch"); // create transport event sink proxy that coalesces all events rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink), eventsink, target, PR_TRUE); if (NS_FAILED(rv)) return rv; // try to get the nsIHttpActivityObserver distributor mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv); // mActivityDistributor may not be valid if (NS_SUCCEEDED(rv) && mActivityDistributor) { // the service is valid, now check if it is active PRBool active; rv = mActivityDistributor->GetIsActive(&active); if (NS_SUCCEEDED(rv) && active) { // the service is valid and active, gather nsISupports // for the channel that called Init() mChannel = do_QueryInterface(eventsink); LOG(("nsHttpTransaction::Init() " \ "mActivityDistributor is active " \ "this=%x", this)); } else // the interface in valid but not active, so don't use it mActivityDistributor = nsnull; } NS_ADDREF(mConnInfo = cinfo); mCallbacks = callbacks; mConsumerTarget = target; mCaps = caps; if (requestHead->Method() == nsHttp::Head) mNoContent = PR_TRUE; // grab a weak reference to the request head mRequestHead = requestHead; // make sure we eliminate any proxy specific headers from // the request if we are talking HTTPS via a SSL tunnel. PRBool pruneProxyHeaders = cinfo->UsingSSL() && cinfo->UsingHttpProxy(); mReqHeaderBuf.Truncate(); requestHead->Flatten(mReqHeaderBuf, pruneProxyHeaders); #if defined(PR_LOGGING) if (LOG3_ENABLED()) { LOG3(("http request [\n")); LogHeaders(mReqHeaderBuf.get()); LOG3(("]\n")); } #endif // If the request body does not include headers or if there is no request // body, then we must add the header/body separator manually. if (!requestBodyHasHeaders || !requestBody) mReqHeaderBuf.AppendLiteral("\r\n"); // report the request header if (mActivityDistributor) mActivityDistributor->ObserveActivity( mChannel, NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, LL_ZERO, LL_ZERO, mReqHeaderBuf); // Create a string stream for the request header buf (the stream holds // a non-owning reference to the request header data, so we MUST keep // mReqHeaderBuf around). nsCOMPtr<nsIInputStream> headers; rv = NS_NewByteInputStream(getter_AddRefs(headers), mReqHeaderBuf.get(), mReqHeaderBuf.Length()); if (NS_FAILED(rv)) return rv; if (requestBody) { mHasRequestBody = PR_TRUE; // wrap the headers and request body in a multiplexed input stream. nsCOMPtr<nsIMultiplexInputStream> multi = do_CreateInstance(kMultiplexInputStream, &rv); if (NS_FAILED(rv)) return rv; rv = multi->AppendStream(headers); if (NS_FAILED(rv)) return rv; rv = multi->AppendStream(requestBody); if (NS_FAILED(rv)) return rv; // wrap the multiplexed input stream with a buffered input stream, so // that we write data in the largest chunks possible. this is actually // necessary to workaround some common server bugs (see bug 137155). rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi, NET_DEFAULT_SEGMENT_SIZE); if (NS_FAILED(rv)) return rv; } else mRequestStream = headers; rv = mRequestStream->Available(&mRequestSize); if (NS_FAILED(rv)) return rv; // create pipe for response stream rv = NS_NewPipe2(getter_AddRefs(mPipeIn), getter_AddRefs(mPipeOut), PR_TRUE, PR_TRUE, NS_HTTP_SEGMENT_SIZE, NS_HTTP_SEGMENT_COUNT, nsIOService::gBufferCache); if (NS_FAILED(rv)) return rv; NS_ADDREF(*responseBody = mPipeIn); return NS_OK; }
nsresult nsMsgFilterList::LoadTextFilters(nsIInputStream *aStream) { nsresult err = NS_OK; uint64_t bytesAvailable; nsCOMPtr<nsIInputStream> bufStream; err = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aStream, 10240); NS_ENSURE_SUCCESS(err, err); nsMsgFilterFileAttribValue attrib; nsCOMPtr<nsIMsgRuleAction> currentFilterAction; // We'd really like to move lot's of these into the objects that they refer to. do { nsAutoCString value; nsresult intToStringResult; char curChar; curChar = LoadAttrib(attrib, bufStream); if (curChar == (char) -1) //reached eof break; err = LoadValue(value, bufStream); if (NS_FAILED(err)) break; switch(attrib) { case nsIMsgFilterList::attribNone: if (m_curFilter) m_curFilter->SetUnparseable(true); break; case nsIMsgFilterList::attribVersion: m_fileVersion = value.ToInteger(&intToStringResult); if (NS_FAILED(intToStringResult)) { attrib = nsIMsgFilterList::attribNone; NS_ASSERTION(false, "error parsing filter file version"); } break; case nsIMsgFilterList::attribLogging: m_loggingEnabled = StrToBool(value); m_unparsedFilterBuffer.Truncate(); //we are going to buffer each filter as we read them, make sure no garbage is there m_startWritingToBuffer = true; //filters begin now break; case nsIMsgFilterList::attribName: //every filter starts w/ a name { if (m_curFilter) { int32_t nextFilterStartPos = m_unparsedFilterBuffer.RFind("name"); nsAutoCString nextFilterPart; nextFilterPart = Substring(m_unparsedFilterBuffer, nextFilterStartPos, m_unparsedFilterBuffer.Length()); m_unparsedFilterBuffer.SetLength(nextFilterStartPos); bool unparseableFilter; m_curFilter->GetUnparseable(&unparseableFilter); if (unparseableFilter) { m_curFilter->SetUnparsedBuffer(m_unparsedFilterBuffer); m_curFilter->SetEnabled(false); //disable the filter because we don't know how to apply it } m_unparsedFilterBuffer = nextFilterPart; } nsMsgFilter *filter = new nsMsgFilter; if (filter == nullptr) { err = NS_ERROR_OUT_OF_MEMORY; break; } filter->SetFilterList(static_cast<nsIMsgFilterList*>(this)); if (m_fileVersion == k45Version) { nsAutoString unicodeStr; err = nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(), value, unicodeStr); if (NS_FAILED(err)) break; filter->SetFilterName(unicodeStr); } else { // ### fix me - this is silly. PRUnichar *unicodeString = nsTextFormatter::smprintf(unicodeFormatter, value.get()); filter->SetFilterName(nsDependentString(unicodeString)); nsTextFormatter::smprintf_free(unicodeString); } m_curFilter = filter; m_filters.AppendElement(filter); } break; case nsIMsgFilterList::attribEnabled: if (m_curFilter) m_curFilter->SetEnabled(StrToBool(value)); break; case nsIMsgFilterList::attribDescription: if (m_curFilter) m_curFilter->SetFilterDesc(value); break; case nsIMsgFilterList::attribType: if (m_curFilter) { // Older versions of filters didn't have the ability to turn on/off the // manual filter context, so default manual to be on in that case int32_t filterType = value.ToInteger(&intToStringResult); if (m_fileVersion < kManualContextVersion) filterType |= nsMsgFilterType::Manual; m_curFilter->SetType((nsMsgFilterTypeType) filterType); } break; case nsIMsgFilterList::attribScriptFile: if (m_curFilter) m_curFilter->SetFilterScript(&value); break; case nsIMsgFilterList::attribAction: if (m_curFilter) { nsMsgRuleActionType actionType = nsMsgFilter::GetActionForFilingStr(value); if (actionType == nsMsgFilterAction::None) m_curFilter->SetUnparseable(true); else { err = m_curFilter->CreateAction(getter_AddRefs(currentFilterAction)); NS_ENSURE_SUCCESS(err, err); currentFilterAction->SetType(actionType); m_curFilter->AppendAction(currentFilterAction); } } break; case nsIMsgFilterList::attribActionValue: if (m_curFilter && currentFilterAction) { nsMsgRuleActionType type; currentFilterAction->GetType(&type); if (type == nsMsgFilterAction::MoveToFolder || type == nsMsgFilterAction::CopyToFolder) err = m_curFilter->ConvertMoveOrCopyToFolderValue(currentFilterAction, value); else if (type == nsMsgFilterAction::ChangePriority) { nsMsgPriorityValue outPriority; nsresult res = NS_MsgGetPriorityFromString(value.get(), outPriority); if (NS_SUCCEEDED(res)) currentFilterAction->SetPriority(outPriority); else NS_ASSERTION(false, "invalid priority in filter file"); } else if (type == nsMsgFilterAction::Label) { // upgrade label to corresponding tag/keyword nsresult res; int32_t labelInt = value.ToInteger(&res); if (NS_SUCCEEDED(res)) { nsAutoCString keyword("$label"); keyword.Append('0' + labelInt); currentFilterAction->SetType(nsMsgFilterAction::AddTag); currentFilterAction->SetStrValue(keyword); } } else if (type == nsMsgFilterAction::JunkScore) { nsresult res; int32_t junkScore = value.ToInteger(&res); if (NS_SUCCEEDED(res)) currentFilterAction->SetJunkScore(junkScore); } else if (type == nsMsgFilterAction::Forward || type == nsMsgFilterAction::Reply || type == nsMsgFilterAction::AddTag || type == nsMsgFilterAction::Custom) { currentFilterAction->SetStrValue(value); } } break; case nsIMsgFilterList::attribCondition: if (m_curFilter) { if (m_fileVersion == k45Version) { nsAutoString unicodeStr; err = nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(), value, unicodeStr); if (NS_FAILED(err)) break; char *utf8 = ToNewUTF8String(unicodeStr); value.Assign(utf8); nsMemory::Free(utf8); } err = ParseCondition(m_curFilter, value.get()); if (err == NS_ERROR_INVALID_ARG) err = m_curFilter->SetUnparseable(true); NS_ENSURE_SUCCESS(err, err); } break; case nsIMsgFilterList::attribCustomId: if (m_curFilter && currentFilterAction) { err = currentFilterAction->SetCustomId(value); NS_ENSURE_SUCCESS(err, err); } break; } } while (NS_SUCCEEDED(bufStream->Available(&bytesAvailable))); if (m_curFilter) { bool unparseableFilter; m_curFilter->GetUnparseable(&unparseableFilter); if (unparseableFilter) { m_curFilter->SetUnparsedBuffer(m_unparsedFilterBuffer); m_curFilter->SetEnabled(false); //disable the filter because we don't know how to apply it } } return err; }
NS_IMETHODIMP nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream, const char *aCharset, const char *aContentType) { // Don't call this in the middle of an async parse NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE); NS_ENSURE_ARG(aStream); NS_ENSURE_ARG(aContentType); // Put the nsCOMPtr out here so we hold a ref to the stream as needed nsresult rv; nsCOMPtr<nsIInputStream> bufferedStream; if (!NS_InputStreamIsBuffered(aStream)) { rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aStream, 4096); NS_ENSURE_SUCCESS(rv, rv); aStream = bufferedStream; } rv = EnsureBaseURI(); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIChannel> parserChannel; rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI, aStream, nsDependentCString(aContentType)); if (!parserChannel || NS_FAILED(rv)) return NS_ERROR_FAILURE; if (aCharset) parserChannel->SetContentCharset(nsDependentCString(aCharset)); rv = InitParser(nsnull, parserChannel); NS_ENSURE_SUCCESS(rv, rv); rv = mListener->OnStartRequest(parserChannel, nsnull); if (NS_FAILED(rv)) parserChannel->Cancel(rv); nsresult status; parserChannel->GetStatus(&status); PRUint32 offset = 0; while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) { PRUint32 available; rv = aStream->Available(&available); if (rv == NS_BASE_STREAM_CLOSED) { rv = NS_OK; available = 0; } if (NS_FAILED(rv)) { parserChannel->Cancel(rv); break; } if (! available) break; // blocking input stream has none available when done rv = mListener->OnDataAvailable(parserChannel, nsnull, aStream, offset, available); if (NS_SUCCEEDED(rv)) offset += available; else parserChannel->Cancel(rv); parserChannel->GetStatus(&status); } rv = mListener->OnStopRequest(parserChannel, nsnull, status); mListener = nsnull; return rv; }