void nsEudoraWin32::GetMimeTypeFromExtension( nsCString& ext, nsCString& mimeType) { HKEY sKey; if (::RegOpenKeyEx( HKEY_CLASSES_ROOT, ext.get(), 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) { // get the value of "Current" BYTE *pBytes = GetValueBytes( sKey, "Content Type"); if (pBytes) { mimeType = (const char *)pBytes; delete [] pBytes; } ::RegCloseKey( sKey); } if (!mimeType.IsEmpty() || !m_mailImportLocation || (ext.Length() > 10)) return; // TLR: FIXME: We should/could cache the extension to mime type maps we find // and check the cache first before scanning all of eudora's mappings? // It's not in the registry, try and find the .ini file for Eudora's private // mime type list if (!m_pMimeSection) { nsCOMPtr <nsILocalFile> pFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); if (!pFile) return; pFile->InitWithFile(m_mailImportLocation); pFile->AppendNative(NS_LITERAL_CSTRING("eudora.ini")); bool exists = false; bool isFile = false; nsresult rv = pFile->Exists( &exists); if (NS_SUCCEEDED( rv)) rv = pFile->IsFile( &isFile); if (!isFile || !exists) { rv = pFile->InitWithFile( m_mailImportLocation); if (NS_FAILED( rv)) return; if (!FindMimeIniFile( pFile)) return; } nsCAutoString fileName; pFile->GetNativePath(fileName); if (fileName.IsEmpty()) return; // Read the mime map section DWORD size = 1024; DWORD dSize = size - 2; while (dSize == (size - 2)) { if (m_pMimeSection) delete [] m_pMimeSection; size += 1024; m_pMimeSection = new char[size]; dSize = ::GetPrivateProfileSection( "Mappings", m_pMimeSection, size, fileName.get()); } } if (!m_pMimeSection) return; IMPORT_LOG1( "Looking for mime type for extension: %s\n", ext.get()); // out/in/both=extension,mac creator,mac type,mime type1,mime type2 const char *pExt = ext.get(); pExt++; char * pChar = m_pMimeSection; char * pStart; int len; nsCString tStr; for(;;) { while (*pChar != '=') { if (!(*pChar) && !(*(pChar + 1))) return; pChar++; } if (*pChar) pChar++; pStart = pChar; len = 0; while (*pChar && (*pChar != ',')) { pChar++; len++; } if (!*pChar) return; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (!PL_strcasecmp( tStr.get(), pExt)) { // skip the mac creator and type pChar++; while (*pChar && (*pChar != ',')) pChar++; if (!*pChar) return; pChar++; while (*pChar && (*pChar != ',')) pChar++; if (!*pChar) return; pChar++; // Get the first mime type len = 0; pStart = pChar; while (*pChar && (*pChar != ',')) { pChar++; len++; } if (!*pChar) return; pChar++; if (!len) continue; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (tStr.IsEmpty()) continue; mimeType.Truncate(); mimeType.Append( tStr.get()); mimeType.Append( "/"); pStart = pChar; len = 0; // Skip to next end of line. while (*pChar && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) { pChar++; len++; } if (!len) continue; tStr.Truncate(); tStr.Append( pStart, len); tStr.Trim( kWhitespace); if (tStr.IsEmpty()) continue; mimeType.Append( tStr.get()); IMPORT_LOG1( "Found Mime Type: %s\n", mimeType.get()); return; } } }
void AppendUid(nsCString &msgIds, PRUint32 uid) { char buf[20]; PR_snprintf(buf, sizeof(buf), "%u", uid); msgIds.Append(buf); }
nsresult nsAbBoolExprToLDAPFilter::FilterCondition ( nsIAbLDAPAttributeMap* map, nsIAbBooleanConditionString* condition, nsCString& filter, int flags) { nsCString name; nsresult rv = condition->GetName(getter_Copies (name)); NS_ENSURE_SUCCESS(rv, rv); nsCAutoString ldapAttr(name); if (flags & TRANSLATE_CARD_PROPERTY) { rv = map->GetFirstAttribute (name, ldapAttr); if (!(flags & ALLOW_NON_CONVERTABLE_CARD_PROPERTY) && !ATTRMAP_FOUND_ATTR(rv, ldapAttr)) return NS_OK; } nsAbBooleanConditionType conditionType; rv = condition->GetCondition(&conditionType); NS_ENSURE_SUCCESS(rv, rv); nsString value; rv = condition->GetValue (getter_Copies (value)); NS_ENSURE_SUCCESS(rv, rv); NS_ConvertUTF16toUTF8 vUTF8 (value); switch (conditionType) { case nsIAbBooleanConditionTypes::DoesNotExist: filter.AppendLiteral("(!("); filter.Append(ldapAttr); filter.AppendLiteral("=*))"); break; case nsIAbBooleanConditionTypes::Exists: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("=*)"); break; case nsIAbBooleanConditionTypes::Contains: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.Append("=*"); filter.Append(vUTF8); filter.AppendLiteral("*)"); break; case nsIAbBooleanConditionTypes::DoesNotContain: filter.AppendLiteral("(!("); filter.Append(ldapAttr); filter.AppendLiteral("=*"); filter.Append(vUTF8); filter.AppendLiteral("*))"); break; case nsIAbBooleanConditionTypes::Is: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("="); filter.Append(vUTF8); filter.AppendLiteral(")"); break; case nsIAbBooleanConditionTypes::IsNot: filter.AppendLiteral("(!("); filter.Append(ldapAttr); filter.AppendLiteral("="); filter.Append(vUTF8); filter.AppendLiteral("))"); break; case nsIAbBooleanConditionTypes::BeginsWith: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("="); filter.Append(vUTF8); filter.AppendLiteral("*)"); break; case nsIAbBooleanConditionTypes::EndsWith: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("=*"); filter.Append(vUTF8); filter.AppendLiteral(")"); break; case nsIAbBooleanConditionTypes::LessThan: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("<="); filter.Append(vUTF8); filter.AppendLiteral(")"); break; case nsIAbBooleanConditionTypes::GreaterThan: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral(">="); filter.Append(vUTF8); filter.AppendLiteral(")"); break; case nsIAbBooleanConditionTypes::SoundsLike: filter.AppendLiteral("("); filter.Append(ldapAttr); filter.AppendLiteral("~="); filter.Append(vUTF8); filter.AppendLiteral(")"); break; case nsIAbBooleanConditionTypes::RegExp: break; default: break; } return rv; }
bool CAliasData::Process(const char *pLine, int32_t len) { // Extract any comments first! nsCString str; const char *pStart = pLine; int32_t tCnt = 0; int32_t cnt = 0; int32_t max = len; bool endCollect = false; // Keep track of the full entry without any processing for potential alias // nickname resolution. Previously alias resolution was done with m_email, // but unfortunately that doesn't work for nicknames with spaces. // For example for the nickname "Joe Smith", "Smith" was being interpreted // as the potential email address and placed in m_email, but routines like // ResolveAlias were failing because "Smith" is not the full nickname. // Now we just stash the full entry for nickname resolution before processing // the line as a potential entry in its own right. m_fullEntry.Append(pLine, len); while (max) { if (*pLine == '"') { if (tCnt && !endCollect) { str.Trim(kWhitespace); if (!str.IsEmpty()) str.Append(" ", 1); str.Append(pStart, tCnt); } cnt = nsEudoraAddress::CountQuote(pLine, max); if ((cnt > 2) && m_realName.IsEmpty()) { m_realName.Append(pLine + 1, cnt - 2); } pLine += cnt; max -= cnt; pStart = pLine; tCnt = 0; } else if (*pLine == '<') { if (tCnt && !endCollect) { str.Trim(kWhitespace); if (!str.IsEmpty()) str.Append(" ", 1); str.Append(pStart, tCnt); } cnt = nsEudoraAddress::CountAngle(pLine, max); if ((cnt > 2) && m_email.IsEmpty()) { m_email.Append(pLine + 1, cnt - 2); } pLine += cnt; max -= cnt; pStart = pLine; tCnt = 0; endCollect = true; } else if (*pLine == '(') { if (tCnt && !endCollect) { str.Trim(kWhitespace); if (!str.IsEmpty()) str.Append(" ", 1); str.Append(pStart, tCnt); } cnt = nsEudoraAddress::CountComment(pLine, max); if (cnt > 2) { if (!m_realName.IsEmpty() && m_nickName.IsEmpty()) m_nickName = m_realName; m_realName.Truncate(); m_realName.Append(pLine + 1, cnt - 2); } pLine += cnt; max -= cnt; pStart = pLine; tCnt = 0; } else { tCnt++; pLine++; max--; } } if (tCnt) { str.Trim(kWhitespace); if (!str.IsEmpty()) str.Append(" ", 1); str.Append(pStart, tCnt); } str.Trim(kWhitespace); if (!m_realName.IsEmpty() && !m_email.IsEmpty()) return true; // now we should have a string with any remaining non-delimitted text // we assume that the last token is the email // anything before that is realName if (!m_email.IsEmpty()) { m_realName = str; return true; } tCnt = str.RFindChar(' '); if (tCnt == -1) { if (!str.IsEmpty()) { m_email = str; return true; } return false; } m_email = Substring(str, tCnt + 1); m_realName = StringHead(str, tCnt); m_realName.Trim(kWhitespace); m_email.Trim(kWhitespace); return !m_email.IsEmpty(); }
void nsEudoraCompose::GetNthHeader(const char *pData, int32_t dataLen, int32_t n, nsCString& header, nsCString& val, bool unwrap) { header.Truncate(); val.Truncate(); if (!pData) return; int32_t index = 0; int32_t len; int32_t start = 0; const char *pChar = pData; const char *pStart; if (n == 0) { pStart = pChar; len = 0; while ((start < dataLen) && (*pChar != ':')) { start++; len++; pChar++; } header.Append(pStart, len); header.Trim(kWhitespace); start++; pChar++; } else { while (start < dataLen) { if ((*pChar != ' ') && (*pChar != '\t')) { if (n == index) { pStart = pChar; len = 0; while ((start < dataLen) && (*pChar != ':')) { start++; len++; pChar++; } header.Append(pStart, len); header.Trim(kWhitespace); start++; pChar++; break; } else index++; } // Skip to next end of line. while ((start < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) { start++; pChar++; } // Skip over end of line(s). while ((start < dataLen) && ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) { start++; pChar++; } } } if (start >= dataLen) return; int32_t lineEnd; int32_t end = start; while (end < dataLen) { // Skip to next end of line. while ((end < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) { end++; pChar++; } if (end > start) { val.Append(pData + start, end - start); } lineEnd = end; pStart = pChar; // Skip over end of line(s). while ((end < dataLen) && ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) { end++; pChar++; } start = end; // Skip over space(s) and tab(s). while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) { end++; pChar++; } if (start == end) break; if (unwrap) val.Append(' '); else { val.Append(pStart, end - lineEnd); } start = end; } val.Trim(kWhitespace); }
void nsEudoraCompose::GetHeaderValue(const char *pData, int32_t dataLen, const char *pHeader, nsCString& val, bool unwrap) { val.Truncate(); if (!pData) return; int32_t start = 0; int32_t len = strlen(pHeader); const char *pChar = pData; if (!PL_strncasecmp(pHeader, pData, len)) { start = len; } else { while (start < dataLen) { // Skip to next end of line. while ((start < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) { start++; pChar++; } // Skip over end of line(s). while ((start < dataLen) && ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) { start++; pChar++; } if ((start < dataLen) && !PL_strncasecmp(pChar, pHeader, len)) break; } if (start < dataLen) start += len; } if (start >= dataLen) return; int32_t end = start; int32_t lineEnd; const char * pStart; pChar = pData + start; while (end < dataLen) { // Skip to next end of line. while ((end < dataLen) && (*pChar != nsCRT::CR) && (*pChar != nsCRT::LF)) { end++; pChar++; } if (end > start) val.Append(pData + start, end - start); lineEnd = end; pStart = pChar; // Skip over the end of line(s). while ((end < dataLen) && ((*pChar == nsCRT::CR) || (*pChar == nsCRT::LF))) { end++; pChar++; } start = end; // Skip over space(s) and tab(s). while ((end < dataLen) && ((*pChar == ' ') || (*pChar == '\t'))) { end++; pChar++; } if (start == end) break; if (unwrap) val.Append(' '); else { val.Append(pStart, end - lineEnd); } start = end; } val.Trim(kWhitespace); }
bool nsTextAddress::GetField( const char *pLine, PRInt32 maxLen, PRInt32 index, nsCString& field, char delim) { bool result = false; const char *pChar = pLine; PRInt32 len = 0; char tab = '\t'; field.Truncate(); if (delim == tab) tab = 0; while (index && (len < maxLen)) { while (((*pChar == ' ') || (*pChar == tab)) && (len < maxLen)) { pChar++; len++; } if (len >= maxLen) break; if (*pChar == '"') { len = -1; do { len++; pChar++; if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) { len += 2; pChar += 2; } } while ((len < maxLen) && (*pChar != '"')); if (len < maxLen) { pChar++; len++; } } if (len >= maxLen) break; while ((len < maxLen) && (*pChar != delim)) { len++; pChar++; } if (len >= maxLen) break; index--; pChar++; len++; } if (len >= maxLen) { return( result); } result = true; while ((len < maxLen) && ((*pChar == ' ') || (*pChar == tab))) { len++; pChar++; } const char *pStart = pChar; PRInt32 fLen = 0; bool quoted = false; if (*pChar == '"') { pStart++; fLen = -1; do { pChar++; len++; fLen++; if (((len + 1) < maxLen) && (*pChar == '"') && (*(pChar + 1) == '"')) { quoted = true; len += 2; pChar += 2; fLen += 2; } } while ((len < maxLen) && (*pChar != '"')); } else { while ((len < maxLen) && (*pChar != delim)) { pChar++; len++; fLen++; } } if (!fLen) { return( result); } field.Append( pStart, fLen); field.Trim( kWhitespace); if (quoted) { PRInt32 offset = field.Find(NS_LITERAL_CSTRING("\"\"")); while (offset != -1) { field.Cut(offset, 1); offset = field.Find(NS_LITERAL_CSTRING("\"\""), offset + 1); } } return( result); }
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)); } }
// 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; }
/** * 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; }
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; }
/** * 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; }