NS_IMETHODIMP nsMsgMaildirStore::ChangeKeywords(nsIArray *aHdrArray, const nsACString &aKeywords, bool aAdd) { NS_ENSURE_ARG_POINTER(aHdrArray); NS_ENSURE_ARG_POINTER(aHdrArray); nsCOMPtr<nsIOutputStream> outputStream; nsCOMPtr<nsISeekableStream> seekableStream; uint32_t messageCount; nsresult rv = aHdrArray->GetLength(&messageCount); NS_ENSURE_SUCCESS(rv, rv); if (!messageCount) return NS_ERROR_INVALID_ARG; nsAutoPtr<nsLineBuffer<char> > lineBuffer(new nsLineBuffer<char>); NS_ENSURE_TRUE(lineBuffer, NS_ERROR_OUT_OF_MEMORY); nsTArray<nsCString> keywordArray; ParseString(aKeywords, ' ', keywordArray); for (uint32_t i = 0; i < messageCount; ++i) // for each message { nsCOMPtr<nsIMsgDBHdr> message = do_QueryElementAt(aHdrArray, i, &rv); NS_ENSURE_SUCCESS(rv, rv); // get output stream for header nsCOMPtr<nsIOutputStream> outputStream; rv = GetOutputStream(message, outputStream); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsIInputStream> inputStream = do_QueryInterface(outputStream, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsISeekableStream> seekableStream(do_QueryInterface(inputStream, &rv)); NS_ENSURE_SUCCESS(rv, rv); uint32_t statusOffset = 0; (void)message->GetStatusOffset(&statusOffset); uint64_t desiredOffset = statusOffset; ChangeKeywordsHelper(message, desiredOffset, lineBuffer, keywordArray, aAdd, outputStream, seekableStream, inputStream); if (inputStream) inputStream->Close(); // ### TODO - if growKeywords property is set on the message header, // we need to rewrite the message file with extra room for the keywords, // or schedule some sort of background task to do this. } lineBuffer = nullptr; return NS_OK; }
nsresult nsMsgLocalStoreUtils::UpdateFolderFlag(nsIMsgDBHdr *mailHdr, bool bSet, nsMsgMessageFlagType flag, nsIOutputStream *fileStream) { uint32_t statusOffset; uint64_t msgOffset; nsresult rv = mailHdr->GetStatusOffset(&statusOffset); // This probably means there's no x-mozilla-status header, so // we just ignore this. if (NS_FAILED(rv) || (statusOffset == 0)) return NS_OK; rv = mailHdr->GetMessageOffset(&msgOffset); NS_ENSURE_SUCCESS(rv, rv); uint64_t statusPos = msgOffset + statusOffset; nsCOMPtr<nsISeekableStream> seekableStream( do_QueryInterface(fileStream, &rv)); NS_ENSURE_SUCCESS(rv, rv); rv = seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, statusPos); NS_ENSURE_SUCCESS(rv, rv); char buf[50]; buf[0] = '\0'; nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(fileStream, &rv); NS_ENSURE_SUCCESS(rv, rv); uint32_t bytesRead; if (NS_SUCCEEDED( inputStream->Read(buf, X_MOZILLA_STATUS_LEN + 6, &bytesRead))) { buf[bytesRead] = '\0'; if (strncmp(buf, X_MOZILLA_STATUS, X_MOZILLA_STATUS_LEN) == 0 && strncmp(buf + X_MOZILLA_STATUS_LEN, ": ", 2) == 0 && strlen(buf) >= X_MOZILLA_STATUS_LEN + 6) { uint32_t flags; uint32_t bytesWritten; (void)mailHdr->GetFlags(&flags); if (!(flags & nsMsgMessageFlags::Expunged)) { char *p = buf + X_MOZILLA_STATUS_LEN + 2; nsresult errorCode = NS_OK; flags = nsDependentCString(p).ToInteger(&errorCode, 16); uint32_t curFlags; (void)mailHdr->GetFlags(&curFlags); flags = (flags & nsMsgMessageFlags::Queued) | (curFlags & ~nsMsgMessageFlags::RuntimeOnly); if (bSet) flags |= flag; else flags &= ~flag; } else { flags &= ~nsMsgMessageFlags::RuntimeOnly; } seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, statusPos); // We are filing out x-mozilla-status flags here PR_snprintf(buf, sizeof(buf), X_MOZILLA_STATUS_FORMAT, flags & 0x0000FFFF); int32_t lineLen = PL_strlen(buf); uint64_t status2Pos = statusPos + lineLen; fileStream->Write(buf, lineLen, &bytesWritten); if (flag & 0xFFFF0000) { // Time to update x-mozilla-status2, // first find it by finding end of previous line, see bug 234935. seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos); do { rv = inputStream->Read(buf, 1, &bytesRead); status2Pos++; } while (NS_SUCCEEDED(rv) && (*buf == '\n' || *buf == '\r')); status2Pos--; seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos); if (NS_SUCCEEDED(inputStream->Read(buf, X_MOZILLA_STATUS2_LEN + 10, &bytesRead))) { if (strncmp(buf, X_MOZILLA_STATUS2, X_MOZILLA_STATUS2_LEN) == 0 && strncmp(buf + X_MOZILLA_STATUS2_LEN, ": ", 2) == 0 && strlen(buf) >= X_MOZILLA_STATUS2_LEN + 10) { uint32_t dbFlags; (void)mailHdr->GetFlags(&dbFlags); dbFlags &= 0xFFFF0000; seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos); PR_snprintf(buf, sizeof(buf), X_MOZILLA_STATUS2_FORMAT, dbFlags); fileStream->Write(buf, PL_strlen(buf), &bytesWritten); } } } } else { #ifdef DEBUG printf( "Didn't find %s where expected at position %ld\n" "instead, found %s.\n", X_MOZILLA_STATUS, (long)statusPos, buf); #endif rv = NS_ERROR_FAILURE; } } else rv = NS_ERROR_FAILURE; return rv; }
nsresult nsMailboxProtocol::Initialize(nsIURI * aURL) { NS_PRECONDITION(aURL, "invalid URL passed into MAILBOX Protocol"); nsresult rv = NS_OK; if (aURL) { rv = aURL->QueryInterface(NS_GET_IID(nsIMailboxUrl), (void **) getter_AddRefs(m_runningUrl)); if (NS_SUCCEEDED(rv) && m_runningUrl) { nsCOMPtr <nsIMsgWindow> window; rv = m_runningUrl->GetMailboxAction(&m_mailboxAction); // clear stopped flag on msg window, because we care. nsCOMPtr <nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningUrl); if (mailnewsUrl) { mailnewsUrl->GetMsgWindow(getter_AddRefs(window)); if (window) window->SetStopped(false); } if (m_mailboxAction == nsIMailboxUrl::ActionParseMailbox) { // Set the length of the file equal to the max progress nsCOMPtr<nsIFile> file; GetFileFromURL(aURL, getter_AddRefs(file)); if (file) { int64_t fileSize = 0; file->GetFileSize(&fileSize); mailnewsUrl->SetMaxProgress(fileSize); } rv = OpenFileSocket(aURL, 0, -1 /* read in all the bytes in the file */); } else { // we need to specify a byte range to read in so we read in JUST the message we want. rv = SetupMessageExtraction(); if (NS_FAILED(rv)) return rv; uint32_t aMsgSize = 0; rv = m_runningUrl->GetMessageSize(&aMsgSize); NS_ASSERTION(NS_SUCCEEDED(rv), "oops....i messed something up"); SetContentLength(aMsgSize); mailnewsUrl->SetMaxProgress(aMsgSize); if (RunningMultipleMsgUrl()) { rv = OpenFileSocketForReuse(aURL, m_msgOffset, aMsgSize); // if we're running multiple msg url, we clear the event sink because the multiple // msg urls will handle setting the progress. mProgressEventSink = nullptr; } else { nsCOMPtr<nsIMsgIncomingServer> server; nsCOMPtr<nsIMsgDBHdr> msgHdr; nsCOMPtr<nsIMsgFolder> folder; nsCOMPtr<nsIMsgMessageUrl> msgUrl = do_QueryInterface(m_runningUrl, &rv); NS_ENSURE_SUCCESS(rv,rv); rv = msgUrl->GetMessageHeader(getter_AddRefs(msgHdr)); if (msgHdr) { msgHdr->GetFolder(getter_AddRefs(folder)); if (folder) folder->GetServer(getter_AddRefs(server)); } if (server) { nsCOMPtr<nsIMsgPluggableStore> msgStore; rv = server->GetMsgStore(getter_AddRefs(msgStore)); NS_ENSURE_SUCCESS(rv, rv); if (NS_SUCCEEDED(rv) && msgHdr) { nsCOMPtr<nsIInputStream> stream; int64_t offset = 0; bool reusable = false; rv = folder->GetMsgInputStream(msgHdr, &reusable, getter_AddRefs(stream)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsISeekableStream> seekableStream(do_QueryInterface(stream, &rv)); NS_ENSURE_SUCCESS(rv, rv); seekableStream->Tell(&offset); // create input stream transport nsCOMPtr<nsIStreamTransportService> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; m_readCount = aMsgSize; rv = sts->CreateInputTransport(stream, offset, int64_t(aMsgSize), true, getter_AddRefs(m_transport)); m_socketIsOpen = false; } } else // must be a .eml file rv = OpenFileSocket(aURL, 0, aMsgSize); } NS_ASSERTION(NS_SUCCEEDED(rv), "oops....i messed something up"); } } } m_lineStreamBuffer = new nsMsgLineStreamBuffer(OUTPUT_BUFFER_SIZE, true); m_nextState = MAILBOX_READ_FOLDER; m_initialState = MAILBOX_READ_FOLDER; mCurrentProgress = 0; // do we really need both? m_tempMessageFile = m_tempMsgFile; return rv; }