static void SetSMValue(SmPropValue& val, const nsCString& data) { val.value = static_cast<SmPointer>(const_cast<char*>(data.get())); val.length = data.Length(); }
// Return number of bytes consumed (>= 0) or -1 on error PRInt32 nsPipeFilterListener::MatchDelimiter(const char* buf, PRUint32 bufLen, LineMatchStatus& delim, nsCString& delimStr, nsCString& delimLine) { //DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: bufLen=%d\n", bufLen)); PRUint32 count = bufLen; while ((count > 0) && (delim.matchCount <= delim.skipCount)) { if (delim.matchOffset < delimStr.Length()) { PRUint32 consumed = MatchString(buf, count, delimStr.get(), delimStr.Length(), delim.matchOffset); //DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: consumed=%d\n", consumed)); if (!consumed) { ERROR_LOG(("nsPipeFilterListener::MatchDelimiter: consumed=%d\n", consumed)); return -1; } buf += consumed; count -= consumed; if (delim.matchOffset >= delimStr.Length()) { DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: delimStr='%s'\n", delimStr.get())); if (mLastMatch) { delimLine = mPartMatch; mPartMatch = ""; } else { delimLine = delimStr; } mLinebreak = 0; } if (!count) return bufLen; if (delim.matchOffset < delimStr.Length()) { ERROR_LOG(("nsPipeFilterListener::MatchDelimiter: count=%d, delim.matchOffset=%d, delimStr='%s'\n", count, delim.matchOffset, delimStr.get() )); return -1; } } // Match to end of line while (count > 0) { char ch = buf[0]; if (delim.matchedCR) { // Already matched a CR if (ch == '\n') { // Consume LF following CR delimLine.Append(ch); buf++; count--; } delim.matchedLine = PR_TRUE; break; } delimLine.Append(ch); buf++; count--; if (ch == '\n') { delim.matchedLine = PR_TRUE; break; } if (ch == '\r') { delim.matchedCR = PR_TRUE; } } if (delim.matchedLine) { delim.matchCount++; delim.matchOffset = 0; delim.matchedCR = PR_FALSE; delim.matchedLine = PR_FALSE; DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: delimLine(%d)='%s'\n", delimLine.Length(), delimLine.get())); DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: matchCount=%d\n", delim.matchCount)); if (mAutoMimeBoundary) { // Eliminate all trailing whitespace (including linebreaks) for delimiter mAutoMimeBoundary = PR_FALSE; mStartDelimiter = mStartLine; mStartDelimiter.Trim(" \t\r\n", PR_FALSE, PR_TRUE); mEndDelimiter = mStartDelimiter; DEBUG_LOG(("nsPipeFilterListener::MatchDelimiter: Mime Boundary='%s'\n", mStartDelimiter.get())); } } } return bufLen - count; }
nsresult nsMsgProtocol::DoGSSAPIStep2(nsCString &commandResponse, nsCString &response) { #ifdef DEBUG_BenB printf("GSSAPI step 2\n"); #endif nsresult rv; void *inBuf, *outBuf; uint32_t inBufLen, outBufLen; uint32_t len = commandResponse.Length(); // Cyrus SASL may send us zero length tokens (grrrr) if (len > 0) { // decode into the input secbuffer inBufLen = (len * 3)/4; // sufficient size (see plbase64.h) inBuf = nsMemory::Alloc(inBufLen); if (!inBuf) return NS_ERROR_OUT_OF_MEMORY; // strip off any padding (see bug 230351) const char *challenge = commandResponse.get(); while (challenge[len - 1] == '=') len--; // We need to know the exact length of the decoded string to give to // the GSSAPI libraries. But NSPR's base64 routine doesn't seem capable // of telling us that. So, we figure it out for ourselves. // For every 4 characters, add 3 to the destination // If there are 3 remaining, add 2 // If there are 2 remaining, add 1 // 1 remaining is an error inBufLen = (len / 4)*3 + ((len % 4 == 3)?2:0) + ((len % 4 == 2)?1:0); rv = (PL_Base64Decode(challenge, len, (char *)inBuf)) ? m_authModule->GetNextToken(inBuf, inBufLen, &outBuf, &outBufLen) : NS_ERROR_FAILURE; nsMemory::Free(inBuf); } else { rv = m_authModule->GetNextToken(NULL, 0, &outBuf, &outBufLen); } if (NS_SUCCEEDED(rv)) { // And in return, we may need to send Cyrus zero length tokens back if (outBuf) { char *base64Str = PL_Base64Encode((char *)outBuf, outBufLen, nullptr); if (base64Str) response.Adopt(base64Str); else rv = NS_ERROR_OUT_OF_MEMORY; } else response.Adopt((char *)nsMemory::Clone("",1)); } #ifdef DEBUG_BenB printf(NS_SUCCEEDED(rv) ? "GSSAPI step 2 succeeded\n" : "GSSAPI step 2 failed\n"); #endif return rv; }
// use the flagState to determine if the gaps in the msgUids correspond to gaps in the mailbox, // in which case we can still use ranges. If flagState is null, we won't do this. void AllocateImapUidString(uint32_t *msgUids, uint32_t &msgCount, nsImapFlagAndUidState *flagState, nsCString &returnString) { uint32_t startSequence = (msgCount > 0) ? msgUids[0] : 0xFFFFFFFF; uint32_t curSequenceEnd = startSequence; uint32_t total = msgCount; int32_t curFlagStateIndex = -1; // a partial fetch flag state doesn't help us, so don't use it. if (flagState && flagState->GetPartialUIDFetch()) flagState = nullptr; for (uint32_t keyIndex = 0; keyIndex < total; keyIndex++) { uint32_t curKey = msgUids[keyIndex]; uint32_t nextKey = (keyIndex + 1 < total) ? msgUids[keyIndex + 1] : 0xFFFFFFFF; bool lastKey = (nextKey == 0xFFFFFFFF); if (lastKey) curSequenceEnd = curKey; if (!lastKey) { if (nextKey == curSequenceEnd + 1) { curSequenceEnd = nextKey; curFlagStateIndex++; continue; } if (flagState) { if (curFlagStateIndex == -1) { bool foundIt; flagState->GetMessageFlagsFromUID(curSequenceEnd, &foundIt, &curFlagStateIndex); if (!foundIt) { NS_WARNING("flag state missing key"); // The start of this sequence is missing from flag state, so move // on to the next key. curFlagStateIndex = -1; curSequenceEnd = startSequence = nextKey; continue; } } curFlagStateIndex++; uint32_t nextUidInFlagState; nsresult rv = flagState->GetUidOfMessage(curFlagStateIndex, &nextUidInFlagState); if (NS_SUCCEEDED(rv) && nextUidInFlagState == nextKey) { curSequenceEnd = nextKey; continue; } } } if (curSequenceEnd > startSequence) { returnString.AppendInt((int64_t) startSequence); returnString += ':'; returnString.AppendInt((int64_t) curSequenceEnd); startSequence = nextKey; curSequenceEnd = startSequence; curFlagStateIndex = -1; } else { startSequence = nextKey; curSequenceEnd = startSequence; returnString.AppendInt((int64_t) msgUids[keyIndex]); curFlagStateIndex = -1; } // check if we've generated too long a string - if there's no flag state, // it means we just need to go ahead and generate a too long string // because the calling code won't handle breaking up the strings. if (flagState && returnString.Length() > 950) { msgCount = keyIndex; break; } // If we are not the last item then we need to add the comma // but it's important we do it here, after the length check if (!lastKey) returnString += ','; } }
static void HandleMailtoSubject(nsCString& aPath) { // Walk through the string and see if we have a subject already. bool hasSubject = false; bool hasParams = false; int32_t paramSep = aPath.FindChar('?'); while (paramSep != kNotFound && paramSep < (int32_t)aPath.Length()) { hasParams = true; // Get the end of the name at the = op. If it is *after* the next &, // assume that someone made a parameter without an = in it int32_t nameEnd = aPath.FindChar('=', paramSep+1); int32_t nextParamSep = aPath.FindChar('&', paramSep+1); if (nextParamSep == kNotFound) { nextParamSep = aPath.Length(); } // If the = op is after the &, this parameter is a name without value. // If there is no = op, same thing. if (nameEnd == kNotFound || nextParamSep < nameEnd) { nameEnd = nextParamSep; } if (nameEnd != kNotFound) { if (Substring(aPath, paramSep+1, nameEnd-(paramSep+1)). LowerCaseEqualsLiteral("subject")) { hasSubject = true; break; } } paramSep = nextParamSep; } // If there is no subject, append a preformed subject to the mailto line if (!hasSubject) { if (hasParams) { aPath.Append('&'); } else { aPath.Append('?'); } // Get the default subject nsXPIDLString brandName; nsresult rv = nsContentUtils::GetLocalizedString(nsContentUtils::eBRAND_PROPERTIES, "brandShortName", brandName); if (NS_FAILED(rv)) return; const char16_t *formatStrings[] = { brandName.get() }; nsXPIDLString subjectStr; rv = nsContentUtils::FormatLocalizedString( nsContentUtils::eFORMS_PROPERTIES, "DefaultFormSubject", formatStrings, subjectStr); if (NS_FAILED(rv)) return; aPath.AppendLiteral("subject="); nsCString subjectStrEscaped; aPath.Append(NS_EscapeURL(NS_ConvertUTF16toUTF8(subjectStr), esc_Query, subjectStrEscaped)); } }
GMPErr Write(const nsCString& aRecordName, const nsTArray<uint8_t>& aBytes) override { if (!IsOpen(aRecordName)) { return GMPClosedErr; } Record* record = nullptr; mRecords.Get(aRecordName, &record); MOZ_ASSERT(record && !!record->mFileDesc); // IsOpen() guarantees this. // Write operations overwrite the entire record. So close it now. PR_Close(record->mFileDesc); record->mFileDesc = nullptr; // Writing 0 bytes means removing (deleting) the file. if (aBytes.Length() == 0) { nsresult rv = RemoveStorageFile(record->mFilename); if (NS_WARN_IF(NS_FAILED(rv))) { // Could not delete file -> Continue with trying to erase the contents. } else { return GMPNoErr; } } // Write operations overwrite the entire record. So re-open the file // in truncate mode, to clear its contents. if (NS_FAILED(OpenStorageFile(record->mFilename, Truncate, &record->mFileDesc))) { return GMPGenericErr; } // Store the length of the record name followed by the record name // at the start of the file. int32_t bytesWritten = 0; char buf[sizeof(uint32_t)] = {0}; LittleEndian::writeUint32(buf, aRecordName.Length()); bytesWritten = PR_Write(record->mFileDesc, buf, MOZ_ARRAY_LENGTH(buf)); if (bytesWritten != MOZ_ARRAY_LENGTH(buf)) { NS_WARNING("Failed to write GMPStorage record name length."); return GMPRecordCorrupted; } bytesWritten = PR_Write(record->mFileDesc, aRecordName.get(), aRecordName.Length()); if (bytesWritten != (int32_t)aRecordName.Length()) { NS_WARNING("Failed to write GMPStorage record name."); return GMPRecordCorrupted; } bytesWritten = PR_Write(record->mFileDesc, aBytes.Elements(), aBytes.Length()); if (bytesWritten != (int32_t)aBytes.Length()) { NS_WARNING("Failed to write GMPStorage record data."); return GMPRecordCorrupted; } // Try to sync the file to disk, so that in the event of a crash, // the record is less likely to be corrupted. PR_Sync(record->mFileDesc); return GMPNoErr; }
nsresult nsMsgI18NConvertToUnicode(const char* aCharset, const nsCString& inString, nsAString& outString, bool aIsCharsetCanonical) { if (inString.IsEmpty()) { outString.Truncate(); return NS_OK; } else if (!*aCharset || !PL_strcasecmp(aCharset, "us-ascii") || !PL_strcasecmp(aCharset, "ISO-8859-1")) { // Despite its name, it also works for Latin-1. CopyASCIItoUTF16(inString, outString); return NS_OK; } else if (!PL_strcasecmp(aCharset, "UTF-8")) { if (MsgIsUTF8(inString)) { nsAutoString tmp; CopyUTF8toUTF16(inString, tmp); if (!tmp.IsEmpty() && tmp.get()[0] == char16_t(0xFEFF)) tmp.Cut(0, 1); outString.Assign(tmp); return NS_OK; } NS_WARNING("Invalid UTF-8 string"); return NS_ERROR_UNEXPECTED; } nsresult rv; nsCOMPtr <nsICharsetConverterManager> ccm = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr <nsIUnicodeDecoder> decoder; // get an unicode converter if (aIsCharsetCanonical) // optimize for modified UTF-7 used by IMAP rv = ccm->GetUnicodeDecoderRaw(aCharset, getter_AddRefs(decoder)); else rv = ccm->GetUnicodeDecoderInternal(aCharset, getter_AddRefs(decoder)); NS_ENSURE_SUCCESS(rv, rv); const char *originalSrcPtr = inString.get(); const char *currentSrcPtr = originalSrcPtr; int32_t originalLength = inString.Length(); int32_t srcLength; int32_t dstLength; char16_t localbuf[512]; int32_t consumedLen = 0; outString.Truncate(); // convert while (consumedLen < originalLength) { srcLength = originalLength - consumedLen; dstLength = 512; rv = decoder->Convert(currentSrcPtr, &srcLength, localbuf, &dstLength); if (NS_FAILED(rv) || dstLength == 0) break; outString.Append(localbuf, dstLength); currentSrcPtr += srcLength; consumedLen = currentSrcPtr - originalSrcPtr; // src length used so far } return rv; }
static bool SetOperator(OperatorData* aOperatorData, nsOperatorFlags aForm, const nsCString& aOperator, nsString& aAttributes) { static const char16_t kNullCh = char16_t('\0'); // aOperator is in the expanded format \uNNNN\uNNNN ... // First compress these Unicode points to the internal nsString format int32_t i = 0; nsAutoString name, value; int32_t len = aOperator.Length(); char16_t c = aOperator[i++]; uint32_t state = 0; char16_t uchar = 0; while (i <= len) { if (0 == state) { if (c != '\\') return false; if (i < len) c = aOperator[i]; i++; if (('u' != c) && ('U' != c)) return false; if (i < len) c = aOperator[i]; i++; state++; } else { if (('0' <= c) && (c <= '9')) uchar = (uchar << 4) | (c - '0'); else if (('a' <= c) && (c <= 'f')) uchar = (uchar << 4) | (c - 'a' + 0x0a); else if (('A' <= c) && (c <= 'F')) uchar = (uchar << 4) | (c - 'A' + 0x0a); else return false; if (i < len) c = aOperator[i]; i++; state++; if (5 == state) { value.Append(uchar); uchar = 0; state = 0; } } } if (0 != state) return false; // Quick return when the caller doesn't care about the attributes and just wants // to know if this is a valid operator (this is the case at the first pass of the // parsing of the dictionary in InitOperators()) if (!aForm) return true; // Add operator to hash table aOperatorData->mFlags |= aForm; aOperatorData->mStr.Assign(value); value.AppendInt(aForm, 10); nsStringKey key(value); gOperatorTable->Put(&key, aOperatorData); #ifdef DEBUG NS_LossyConvertUTF16toASCII str(aAttributes); #endif // Loop over the space-delimited list of attributes to get the name:value pairs aAttributes.Append(kNullCh); // put an extra null at the end char16_t* start = aAttributes.BeginWriting(); char16_t* end = start; while ((kNullCh != *start) && (kDashCh != *start)) { name.SetLength(0); value.SetLength(0); // skip leading space, the dash amounts to the end of the line while ((kNullCh!=*start) && (kDashCh!=*start) && nsCRT::IsAsciiSpace(*start)) { ++start; } end = start; // look for ':' while ((kNullCh!=*end) && (kDashCh!=*end) && !nsCRT::IsAsciiSpace(*end) && (kColonCh!=*end)) { ++end; } // If ':' is not found, then it's a boolean property bool IsBooleanProperty = (kColonCh != *end); *end = kNullCh; // end segment here // this segment is the name if (start < end) { name.Assign(start); } if (IsBooleanProperty) { SetBooleanProperty(aOperatorData, name); } else { start = ++end; // look for space or end of line while ((kNullCh!=*end) && (kDashCh!=*end) && !nsCRT::IsAsciiSpace(*end)) { ++end; } *end = kNullCh; // end segment here if (start < end) { // this segment is the value value.Assign(start); } SetProperty(aOperatorData, name, value); } start = ++end; } return true; }
/** * This method applies a sequence of transformations to the line. * * It applies the following sequences in order * * Removes headers if the searcher doesn't want them * (sets m_pastHeaders) * * Determines the current MIME type. * (via SniffPossibleMIMEHeader) * * Strips any HTML if the searcher doesn't want it * * Strips non-text parts * * Decodes any base64 part * (resetting part variables: m_base64part, m_pastHeaders, m_partIsHtml, * m_partIsText) * * @param line (in) the current line * @param length (in) the length of said line * @param eatThisLine (out) whether or not to ignore this line * @param buf (inout) if m_base64part, the current part as needed for * decoding; else, it is treated as an out param (a * redundant version of line). * @return the length of the line after applying transformations */ PRInt32 nsMsgBodyHandler::ApplyTransformations (const nsCString &line, PRInt32 length, bool &eatThisLine, nsCString &buf) { PRInt32 newLength = length; eatThisLine = PR_FALSE; if (!m_pastHeaders) // line is a line from the message headers { if (m_stripHeaders) eatThisLine = PR_TRUE; // We have already grabbed all worthwhile information from the headers, // so there is no need to keep track of the current lines buf.Assign(line); SniffPossibleMIMEHeader(buf); m_pastHeaders = buf.IsEmpty() || buf.First() == '\r' || buf.First() == '\n'; return length; } // Check to see if this is the boundary string if (m_isMultipart && StringBeginsWith(line, boundary)) { if (m_base64part && m_partIsText) { Base64Decode(buf); // Work on the parsed string if (!buf.Length()) { NS_WARNING("Trying to transform an empty buffer"); eatThisLine = PR_TRUE; } else { ApplyTransformations(buf, buf.Length(), eatThisLine, buf); // Avoid spurious failures eatThisLine = PR_FALSE; } } else { buf.Truncate(); eatThisLine = PR_TRUE; // We have no content... } // Reset all assumed headers m_base64part = PR_FALSE; m_pastHeaders = PR_FALSE; m_partIsHtml = PR_FALSE; m_partIsText = PR_TRUE; return buf.Length(); } if (!m_partIsText) { // Ignore non-text parts buf.Truncate(); eatThisLine = PR_TRUE; return 0; } if (m_base64part) { // We need to keep track of all lines to parse base64encoded... buf.Append(line.get()); eatThisLine = PR_TRUE; return buf.Length(); } // ... but there's no point if we're not parsing base64. buf.Assign(line); if (m_stripHtml && m_partIsHtml) { StripHtml (buf); newLength = buf.Length(); } return newLength; }
// Finds the base domain for a host, with requested number of additional parts. // This will fail, generating an error, if the host is an IPv4/IPv6 address, // if more subdomain parts are requested than are available, or if the hostname // includes characters that are not valid in a URL. Normalization is performed // on the host string and the result will be in UTF8. nsresult nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname, int32_t aAdditionalParts, nsACString &aBaseDomain) { if (aHostname.IsEmpty()) return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS; // chomp any trailing dot, and keep track of it for later bool trailingDot = aHostname.Last() == '.'; if (trailingDot) aHostname.Truncate(aHostname.Length() - 1); // check the edge cases of the host being '.' or having a second trailing '.', // since subsequent checks won't catch it. if (aHostname.IsEmpty() || aHostname.Last() == '.') return NS_ERROR_INVALID_ARG; // Check if we're dealing with an IPv4/IPv6 hostname, and return PRNetAddr addr; PRStatus result = PR_StringToNetAddr(aHostname.get(), &addr); if (result == PR_SUCCESS) return NS_ERROR_HOST_IS_IP_ADDRESS; // Walk up the domain tree, most specific to least specific, // looking for matches at each level. Note that a given level may // have multiple attributes (e.g. IsWild() and IsNormal()). const char *prevDomain = nullptr; const char *currDomain = aHostname.get(); const char *nextDot = strchr(currDomain, '.'); const char *end = currDomain + aHostname.Length(); const char *eTLD = currDomain; while (1) { // sanity check the string we're about to look up: it should not begin with // a '.'; this would mean the hostname began with a '.' or had an // embedded '..' sequence. if (*currDomain == '.') return NS_ERROR_INVALID_ARG; // perform the hash lookup. nsDomainEntry *entry = mHash.GetEntry(currDomain); if (entry) { if (entry->IsWild() && prevDomain) { // wildcard rules imply an eTLD one level inferior to the match. eTLD = prevDomain; break; } else if (entry->IsNormal() || !nextDot) { // specific match, or we've hit the top domain level eTLD = currDomain; break; } else if (entry->IsException()) { // exception rules imply an eTLD one level superior to the match. eTLD = nextDot + 1; break; } } if (!nextDot) { // we've hit the top domain level; use it by default. eTLD = currDomain; break; } prevDomain = currDomain; currDomain = nextDot + 1; nextDot = strchr(currDomain, '.'); } const char *begin, *iter; if (aAdditionalParts < 0) { NS_ASSERTION(aAdditionalParts == -1, "aAdditionalParts can't be negative and different from -1"); for (iter = aHostname.get(); iter != eTLD && *iter != '.'; iter++); if (iter != eTLD) { iter++; } if (iter != eTLD) { aAdditionalParts = 0; } } else { // count off the number of requested domains. begin = aHostname.get(); iter = eTLD; while (1) { if (iter == begin) break; if (*(--iter) == '.' && aAdditionalParts-- == 0) { ++iter; ++aAdditionalParts; break; } } } if (aAdditionalParts != 0) return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS; aBaseDomain = Substring(iter, end); // add on the trailing dot, if applicable if (trailingDot) aBaseDomain.Append('.'); return NS_OK; }
GnomeVFSResult nsGnomeVFSInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead) { GnomeVFSResult rv; if (mHandle) { GnomeVFSFileSize bytesRead; rv = gnome_vfs_read(mHandle, aBuf, aCount, &bytesRead); if (rv == GNOME_VFS_OK) { // XXX 64-bit here *aCountRead = (PRUint32) bytesRead; mBytesRemaining -= *aCountRead; } } else if (mDirOpen) { rv = GNOME_VFS_OK; while (aCount && rv != GNOME_VFS_ERROR_EOF) { // Copy data out of our buffer PRUint32 bufLen = mDirBuf.Length() - mDirBufCursor; if (bufLen) { PRUint32 n = PR_MIN(bufLen, aCount); memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n); *aCountRead += n; aBuf += n; aCount -= n; mDirBufCursor += n; } if (!mDirListPtr) // Are we at the end of the directory list? { rv = GNOME_VFS_ERROR_EOF; } else if (aCount) // Do we need more data? { GnomeVFSFileInfo *info = (GnomeVFSFileInfo *) mDirListPtr->data; // Prune '.' and '..' from directory listing. if (info->name[0] == '.' && (info->name[1] == '\0' || (info->name[1] == '.' && info->name[2] == '\0'))) { mDirListPtr = mDirListPtr->next; continue; } mDirBuf.Assign("201: "); // The "filename" field nsCString escName; nsCOMPtr<nsINetUtil> nu = do_GetService(NS_NETUTIL_CONTRACTID); if (nu) { nu->EscapeString(nsDependentCString(info->name), nsINetUtil::ESCAPE_URL_PATH, escName); mDirBuf.Append(escName); mDirBuf.Append(' '); } // The "content-length" field // XXX truncates size from 64-bit to 32-bit mDirBuf.AppendInt(PRInt32(info->size)); mDirBuf.Append(' '); // The "last-modified" field // // NSPR promises: PRTime is compatible with time_t // we just need to convert from seconds to microseconds PRExplodedTime tm; PRTime pt = ((PRTime) info->mtime) * 1000000; PR_ExplodeTime(pt, PR_GMTParameters, &tm); { char buf[64]; PR_FormatTimeUSEnglish(buf, sizeof(buf), "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm); mDirBuf.Append(buf); } // The "file-type" field switch (info->type) { case GNOME_VFS_FILE_TYPE_REGULAR: mDirBuf.Append("FILE "); break; case GNOME_VFS_FILE_TYPE_DIRECTORY: mDirBuf.Append("DIRECTORY "); break; case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK: mDirBuf.Append("SYMBOLIC-LINK "); break; default: break; } mDirBuf.Append('\n'); mDirBufCursor = 0; mDirListPtr = mDirListPtr->next; } } } else { NS_NOTREACHED("reading from what?"); rv = GNOME_VFS_ERROR_GENERIC; } return rv; }
GnomeVFSResult nsGnomeVFSInputStream::DoOpen() { GnomeVFSResult rv; NS_ASSERTION(mHandle == nsnull, "already open"); // Push a callback handler on the stack for this thread, so we can intercept // authentication requests from GnomeVFS. We'll use the channel to get a // nsIAuthPrompt instance. gnome_vfs_module_callback_push(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION, AuthCallback, mChannel, NULL); // Query the mime type first (this could return NULL). // // XXX We need to do this up-front in order to determine how to open the URI. // Unfortunately, the error code GNOME_VFS_ERROR_IS_DIRECTORY is not // always returned by gnome_vfs_open when we pass it a URI to a directory! // Otherwise, we could have used that as a way to failover to opening the // URI as a directory. Also, it would have been ideal if // gnome_vfs_get_file_info_from_handle were actually implemented by the // smb:// module, since that would have allowed us to potentially save a // round trip to the server to discover the mime type of the document in // the case where gnome_vfs_open would have been used. (Oh well! /me // throws hands up in the air and moves on...) GnomeVFSFileInfo info = {0}; rv = gnome_vfs_get_file_info(mSpec.get(), &info, GnomeVFSFileInfoOptions( GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS)); if (rv == GNOME_VFS_OK) { if (info.type == GNOME_VFS_FILE_TYPE_DIRECTORY) { rv = gnome_vfs_directory_list_load(&mDirList, mSpec.get(), GNOME_VFS_FILE_INFO_DEFAULT); LOG(("gnomevfs: gnome_vfs_directory_list_load returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } else { rv = gnome_vfs_open(&mHandle, mSpec.get(), GNOME_VFS_OPEN_READ); LOG(("gnomevfs: gnome_vfs_open returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } } gnome_vfs_module_callback_pop(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION); if (rv == GNOME_VFS_OK) { if (mHandle) { // Here we set the content type of the channel to the value of the mime // type determined by GnomeVFS. However, if GnomeVFS is telling us that // the document is binary, we'll ignore that and keep the channel's // content type unspecified. That will enable our content type sniffing // algorithms. This should provide more consistent mime type handling. if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0)) SetContentTypeOfChannel(info.mime_type); mBytesRemaining = info.size; // Update the content length attribute on the channel. We do this // synchronously without proxying. This hack is not as bad as it looks! if (mBytesRemaining != PRUint64(-1)) mChannel->SetContentLength(mBytesRemaining); } else { mDirOpen = PR_TRUE; // Sort mDirList mDirList = g_list_sort(mDirList, FileInfoComparator); mDirListPtr = mDirList; // Write base URL (make sure it ends with a '/') mDirBuf.Append("300: "); mDirBuf.Append(mSpec); if (mSpec.get()[mSpec.Length() - 1] != '/') mDirBuf.Append('/'); mDirBuf.Append('\n'); // Write column names mDirBuf.Append("200: filename content-length last-modified file-type\n"); // Write charset (assume UTF-8) // XXX is this correct? mDirBuf.Append("301: UTF-8\n"); SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT); } } gnome_vfs_file_info_clear(&info); return rv; }
nsresult PendingLookup::OnStopRequestInternal(nsIRequest *aRequest, nsISupports *aContext, nsresult aResult, bool* aShouldBlock) { if (NS_FAILED(aResult)) { Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_FAILED); return aResult; } *aShouldBlock = false; nsresult rv; nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest, &rv); if (NS_FAILED(rv)) { Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_FAILED); return rv; } uint32_t status = 0; rv = channel->GetResponseStatus(&status); if (NS_FAILED(rv)) { Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_FAILED); return rv; } if (status != 200) { Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_FAILED); return NS_ERROR_NOT_AVAILABLE; } std::string buf(mResponse.Data(), mResponse.Length()); safe_browsing::ClientDownloadResponse response; if (!response.ParseFromString(buf)) { LOG(("Invalid protocol buffer response [this = %p]: %s", this, buf.c_str())); Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_INVALID); return NS_ERROR_CANNOT_CONVERT_DATA; } // There are several more verdicts, but we only respect DANGEROUS and // DANGEROUS_HOST for now and treat everything else as SAFE. Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER, SERVER_RESPONSE_VALID); // Clamp responses 0-7, we only know about 0-4 for now. Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_SERVER_VERDICT, std::min<uint32_t>(response.verdict(), 7)); switch(response.verdict()) { case safe_browsing::ClientDownloadResponse::DANGEROUS: case safe_browsing::ClientDownloadResponse::DANGEROUS_HOST: *aShouldBlock = true; break; default: break; } return NS_OK; }
/** * Read content of file or create file list from directory * @param aBuf read destination buffer * @param aCount length of destination buffer * @param aCountRead number of read characters * @return NS_OK when read successfully, NS_BASE_STREAM_CLOSED when end of file, * error code otherwise */ nsresult nsGIOInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead) { nsresult rv = NS_ERROR_NOT_AVAILABLE; if (mStream) { // file read GError *error = NULL; PRUint32 bytes_read = g_input_stream_read(G_INPUT_STREAM(mStream), aBuf, aCount, NULL, &error); if (error) { rv = MapGIOResult(error); *aCountRead = 0; g_warning("Cannot read from file: %s", error->message); g_error_free(error); return rv; } *aCountRead = bytes_read; mBytesRemaining -= *aCountRead; return NS_OK; } else if (mDirOpen) { // directory read while (aCount && rv != NS_BASE_STREAM_CLOSED) { // Copy data out of our buffer PRUint32 bufLen = mDirBuf.Length() - mDirBufCursor; if (bufLen) { PRUint32 n = NS_MIN(bufLen, aCount); memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n); *aCountRead += n; aBuf += n; aCount -= n; mDirBufCursor += n; } if (!mDirListPtr) // Are we at the end of the directory list? { rv = NS_BASE_STREAM_CLOSED; } else if (aCount) // Do we need more data? { GFileInfo *info = (GFileInfo *) mDirListPtr->data; // Prune '.' and '..' from directory listing. const char * fname = g_file_info_get_name(info); if (fname && fname[0] == '.' && (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0'))) { mDirListPtr = mDirListPtr->next; continue; } mDirBuf.Assign("201: "); // The "filename" field nsCString escName; nsCOMPtr<nsINetUtil> nu = do_GetService(NS_NETUTIL_CONTRACTID); if (nu && fname) { nu->EscapeString(nsDependentCString(fname), nsINetUtil::ESCAPE_URL_PATH, escName); mDirBuf.Append(escName); mDirBuf.Append(' '); } // The "content-length" field // XXX truncates size from 64-bit to 32-bit mDirBuf.AppendInt(PRInt32(g_file_info_get_size(info))); mDirBuf.Append(' '); // The "last-modified" field // // NSPR promises: PRTime is compatible with time_t // we just need to convert from seconds to microseconds GTimeVal gtime; g_file_info_get_modification_time(info, >ime); PRExplodedTime tm; PRTime pt = ((PRTime) gtime.tv_sec) * 1000000; PR_ExplodeTime(pt, PR_GMTParameters, &tm); { char buf[64]; PR_FormatTimeUSEnglish(buf, sizeof(buf), "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm); mDirBuf.Append(buf); } // The "file-type" field switch (g_file_info_get_file_type(info)) { case G_FILE_TYPE_REGULAR: mDirBuf.Append("FILE "); break; case G_FILE_TYPE_DIRECTORY: mDirBuf.Append("DIRECTORY "); break; case G_FILE_TYPE_SYMBOLIC_LINK: mDirBuf.Append("SYMBOLIC-LINK "); break; default: break; } mDirBuf.Append('\n'); mDirBufCursor = 0; mDirListPtr = mDirListPtr->next; } } } return rv; }