示例#1
0
NS_IMETHODIMP
nsSmtpServer::GetServerURI(nsACString &aResult)
{
    nsCAutoString uri(NS_LITERAL_CSTRING("smtp://"));

    nsCString username;
    nsresult rv = GetUsername(username);

    if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
        nsCString escapedUsername;
        MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
        // not all servers have a username
        uri.Append(escapedUsername);
        uri.AppendLiteral("@");
    }

    nsCString hostname;
    rv = GetHostname(hostname);

    if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
        nsCString escapedHostname;
        *((char **)getter_Copies(escapedHostname)) =
            nsEscape(hostname.get(), url_Path);
        // not all servers have a hostname
        uri.Append(escapedHostname);
    }

    aResult = uri;
    return NS_OK;
}
示例#2
0
NS_IMETHODIMP
nsSmtpServer::ForgetPassword()
{
  nsresult rv;
  nsCOMPtr<nsILoginManager> loginMgr =
    do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the current server URI without the username
  nsCAutoString serverUri(NS_LITERAL_CSTRING("smtp://"));

  nsCString hostname;
  rv = GetHostname(hostname);

  if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
    nsCString escapedHostname;
    *((char **)getter_Copies(escapedHostname)) =
      nsEscape(hostname.get(), url_Path);
    // not all servers have a hostname
    serverUri.Append(escapedHostname);
  }

  PRUint32 count;
  nsILoginInfo** logins;

  NS_ConvertUTF8toUTF16 currServer(serverUri);

  nsCString serverCUsername;
  rv = GetUsername(serverCUsername);
  NS_ENSURE_SUCCESS(rv, rv);

  NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);

  rv = loginMgr->FindLogins(&count, currServer, EmptyString(),
                            currServer, &logins);
  NS_ENSURE_SUCCESS(rv, rv);

  // There should only be one-login stored for this url, however just in case
  // there isn't.
  nsString username;
  for (PRUint32 i = 0; i < count; ++i)
  {
    if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
        username.Equals(serverUsername))
    {
      // If this fails, just continue, we'll still want to remove the password
      // from our local cache.
      loginMgr->RemoveLogin(logins[i]);
    }
  }
  NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);

  rv = SetPassword(EmptyCString());
  m_logonFailed = PR_TRUE;
  return rv;
}
示例#3
0
//----------------------------------------------------------------------------------------
void nsFileURL::operator +=(const char* inRelativeUnixPath)
//----------------------------------------------------------------------------------------
{
    char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
    mURL += escapedPath;
    nsCRT::free(escapedPath);
#if defined(XP_MAC)
    mFileSpec += inRelativeUnixPath;
#endif
} // nsFileURL::operator +=
NS_IMETHODIMP  nsTextToSubURI::ConvertAndEscape(
  const char *charset, const PRUnichar *text, char **_retval) 
{
  if(nullptr == _retval)
    return NS_ERROR_NULL_POINTER;
  *_retval = nullptr;
  nsresult rv = NS_OK;
  
  // Get Charset, get the encoder.
  nsICharsetConverterManager *ccm;
  rv = CallGetService(kCharsetConverterManagerCID, &ccm);
  if(NS_SUCCEEDED(rv)) {
     nsIUnicodeEncoder *encoder;
     rv = ccm->GetUnicodeEncoder(charset, &encoder);
     NS_RELEASE(ccm);
     if (NS_SUCCEEDED(rv)) {
       rv = encoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nullptr, (PRUnichar)'?');
       if(NS_SUCCEEDED(rv))
       {
          char buf[256];
          char *pBuf = buf;
          int32_t ulen = text ? NS_strlen(text) : 0;
          int32_t outlen = 0;
          if(NS_SUCCEEDED(rv = encoder->GetMaxLength(text, ulen, &outlen))) 
          {
             if(outlen >= 256) {
                pBuf = (char*)NS_Alloc(outlen+1);
             }
             if(nullptr == pBuf) {
                outlen = 255;
                pBuf = buf;
             }
             int32_t bufLen = outlen;
             if(NS_SUCCEEDED(rv = encoder->Convert(text,&ulen, pBuf, &outlen))) {
                // put termination characters (e.g. ESC(B of ISO-2022-JP) if necessary
                int32_t finLen = bufLen - outlen;
                if (finLen > 0) {
                  if (NS_SUCCEEDED(encoder->Finish((char *)(pBuf+outlen), &finLen)))
                    outlen += finLen;
                }
                pBuf[outlen] = '\0';
                *_retval = nsEscape(pBuf, url_XPAlphas);
                if(nullptr == *_retval)
                  rv = NS_ERROR_OUT_OF_MEMORY;
             }
          }
          if(pBuf != buf)
             NS_Free(pBuf);
       }
       NS_RELEASE(encoder);
     }
  }
  
  return rv;
}
示例#5
0
//----------------------------------------------------------------------------------------
void nsFileURL::operator = (const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
{
    mURL = kFileURLPrefix;
    char* original = (char*)(const char*)inOther; // we shall modify, but restore.
    if (!original || !*original) return;
#if defined(XP_WIN) || defined(XP_OS2)
    // because we don't want to escape the '|' character, change it to a letter.
    // Note that a UNC path will not have a '|' character.
    char oldchar = original[2];
    original[2] = 'x';
    char* escapedPath = nsEscape(original, url_Path);
    original[2] = escapedPath[2] = oldchar; // restore it
#else
    char* escapedPath = nsEscape(original, url_Path);
#endif
    if (escapedPath)
        mURL += escapedPath;
    nsCRT::free(escapedPath);
} // nsFileURL::operator =
示例#6
0
//----------------------------------------------------------------------------------------
void nsFilePath::operator +=(const char* inRelativeUnixPath)
//----------------------------------------------------------------------------------------
{
	NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");

    char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
    mPath += escapedPath;
    nsCRT::free(escapedPath);
#if defined(XP_MAC)
    mFileSpec += inRelativeUnixPath;
#endif
} // nsFilePath::operator +=
示例#7
0
static nsresult MangleKeywordIntoURI(const char *aKeyword, const char *aURL,
                                     nsCString& query)
{
    query = (*aKeyword == '?') ? (aKeyword + 1) : aKeyword;
    query.Trim(" "); // pull leading/trailing spaces.

    // encode
    char * encQuery = nsEscape(query.get(), url_XPAlphas);
    if (!encQuery) return NS_ERROR_OUT_OF_MEMORY;
    query.Adopt(encQuery);

    // prepend the query with the keyword url
    // XXX this url should come from somewhere else
    query.Insert(aURL, 0);
    return NS_OK;
}
示例#8
0
// XXX i18n helper routines
void
nsIsIndexFrame::URLEncode(const nsString& aString, nsIUnicodeEncoder* encoder, nsString& oString) 
{
  char* inBuf = nsnull;
  if(encoder)
    inBuf  = UnicodeToNewBytes(aString.get(), aString.Length(), encoder);

  if(nsnull == inBuf)
    inBuf  = ToNewCString(aString);

  // convert to CRLF breaks
  char* convertedBuf = nsLinebreakConverter::ConvertLineBreaks(inBuf,
                           nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakNet);
  delete [] inBuf;
  
  char* outBuf = nsEscape(convertedBuf, url_XPAlphas);
  oString.AssignASCII(outBuf);
  nsMemory::Free(outBuf);
  nsMemory::Free(convertedBuf);
}
示例#9
0
NS_IMETHODIMP nsPop3Service::NewURI(const nsACString &aSpec,
                                    const char *aOriginCharset, // ignored
                                    nsIURI *aBaseURI,
                                    nsIURI **_retval)
{
    nsresult rv = NS_ERROR_FAILURE;
    if (!_retval) return rv;
    nsCAutoString folderUri(aSpec);
    nsCOMPtr<nsIRDFResource> resource;
    PRInt32 offset = folderUri.Find("?");
    if (offset != -1)
        folderUri.Truncate(offset);

    const nsCString &flatSpec = PromiseFlatCString(aSpec);
    const char *uidl = PL_strstr(flatSpec.get(), "uidl=");
    if (!uidl) return NS_ERROR_FAILURE;

    nsCOMPtr<nsIRDFService> rdfService(do_GetService(kRDFServiceCID, &rv)); 
    if (NS_FAILED(rv)) return rv;
    rv = rdfService->GetResource(folderUri, getter_AddRefs(resource));
    if (NS_FAILED(rv)) return rv;
    nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(resource, &rv);
    if (NS_FAILED(rv)) return rv;
    nsCOMPtr<nsIMsgIncomingServer> server;

    nsLocalFolderScanState folderScanState;
    nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(folder);
    nsCOMPtr <nsIMailboxUrl> mailboxUrl = do_QueryInterface(aBaseURI);

    nsCOMPtr<nsIFileSpec> path;
    rv = folder->GetPath(getter_AddRefs(path));
    if (NS_FAILED(rv)) return rv;

    nsFileSpec fileSpec;
    path->GetFileSpec(&fileSpec);
    folderScanState.m_fileSpec = &fileSpec;
    if (mailboxUrl && localFolder)
    {
      rv = localFolder->GetFolderScanState(&folderScanState);
      NS_ENSURE_SUCCESS(rv, rv);
      nsCOMPtr <nsIMsgDBHdr> msgHdr;
      nsCOMPtr<nsIMsgMessageUrl> msgUrl = do_QueryInterface(mailboxUrl, &rv);
      NS_ENSURE_SUCCESS(rv,rv);
      msgUrl->GetMessageHeader(getter_AddRefs(msgHdr));
      // we do this to get the account key
      if (msgHdr)
        localFolder->GetUidlFromFolder(&folderScanState, msgHdr);
      if (!folderScanState.m_accountKey.IsEmpty())
      {
        nsCOMPtr<nsIMsgAccountManager> accountManager = 
                 do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
        if (accountManager)
        {
          nsCOMPtr <nsIMsgAccount> account;
          accountManager->GetAccount(folderScanState.m_accountKey.get(), getter_AddRefs(account));
          if (account)
            account->GetIncomingServer(getter_AddRefs(server));
        }
      }
    }

    if (!server)
    rv = folder->GetServer(getter_AddRefs(server));
    if (NS_FAILED(rv)) return rv;
    nsCOMPtr<nsIPop3IncomingServer> popServer = do_QueryInterface(server,&rv);
    if (NS_FAILED(rv)) return rv;
    nsXPIDLCString hostname;
    nsXPIDLCString username;
    server->GetHostName(getter_Copies(hostname));
    server->GetUsername(getter_Copies(username));

    PRInt32 port;
    server->GetPort(&port);
    if (port == -1) port = POP3_PORT;
    
	// we need to escape the username because it may contain
	// characters like / % or @
    nsXPIDLCString escapedUsername;
    *((char **)getter_Copies(escapedUsername)) =
      nsEscape(username, url_XAlphas);
    
    nsCAutoString popSpec("pop://");
    popSpec += escapedUsername;
    popSpec += "@";
    popSpec += hostname;
    popSpec += ":";
    popSpec.AppendInt(port);
    popSpec += "?";
    popSpec += uidl;
    nsCOMPtr<nsIUrlListener> urlListener = do_QueryInterface(folder, &rv);
    if (NS_FAILED(rv)) return rv;
    rv = BuildPop3Url(popSpec.get(), folder, popServer,
                      urlListener, _retval, nsnull); 
    if (NS_SUCCEEDED(rv))
    {
        nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = 
            do_QueryInterface(*_retval, &rv);
        if (NS_SUCCEEDED(rv))
        {
			// escape the username before we call SetUsername().  we do this because GetUsername()
			// will unescape the username
            mailnewsurl->SetUsername(escapedUsername);
        }
        nsCOMPtr<nsIPop3URL> popurl = do_QueryInterface(mailnewsurl, &rv);
        if (NS_SUCCEEDED(rv))
        {
            nsCAutoString messageUri (aSpec);
            messageUri.ReplaceSubstring("mailbox:", "mailbox-message:");
            messageUri.ReplaceSubstring("?number=", "#");
            offset = messageUri.Find("&");
            if (offset != -1)
                messageUri.Truncate(offset);
            popurl->SetMessageUri(messageUri.get());
            nsCOMPtr<nsIPop3Sink> pop3Sink;
            rv = popurl->GetPop3Sink(getter_AddRefs(pop3Sink));
            if (NS_SUCCEEDED(rv))
                pop3Sink->SetBuildMessageUri(PR_TRUE);
        }
    }
    return rv;
}
示例#10
0
nsresult nsPop3Service::GetMail(PRBool downloadNewMail,
                                nsIMsgWindow* aMsgWindow, 
                                nsIUrlListener * aUrlListener,
                                nsIMsgFolder *aInbox, 
                                nsIPop3IncomingServer *aPopServer,
                                nsIURI ** aURL)
{

  NS_ENSURE_ARG_POINTER(aInbox);
  nsXPIDLCString popHost;
  nsXPIDLCString popUser;
  PRInt32 popPort = -1;
  
  nsCOMPtr<nsIMsgIncomingServer> server;
  nsCOMPtr<nsIURI> url;
  
  server = do_QueryInterface(aPopServer);
  
  nsCOMPtr <nsIMsgLocalMailFolder> destLocalFolder = do_QueryInterface(aInbox);
  if (destLocalFolder)
  {
    PRBool destFolderTooBig;
    destLocalFolder->WarnIfLocalFileTooBig(aMsgWindow, &destFolderTooBig);
    if (destFolderTooBig)
      return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
  }

  if (!server) 
    return NS_MSG_INVALID_OR_MISSING_SERVER;
  
  nsresult rv = server->GetHostName(getter_Copies(popHost));
  NS_ENSURE_SUCCESS(rv, rv);
  if (!((const char *)popHost)) 
    return NS_MSG_INVALID_OR_MISSING_SERVER;
  
  rv = server->GetPort(&popPort);
  NS_ENSURE_SUCCESS(rv, rv);
  
  rv = server->GetUsername(getter_Copies(popUser));
  NS_ENSURE_SUCCESS(rv, rv);
  if (!((const char *)popUser)) 
    return NS_MSG_SERVER_USERNAME_MISSING;
  
  nsXPIDLCString escapedUsername;
  *((char**)getter_Copies(escapedUsername)) = nsEscape(popUser, url_XAlphas);
  
  if (NS_SUCCEEDED(rv) && aPopServer)
  {
    // now construct a pop3 url...
    // we need to escape the username because it may contain
    // characters like / % or @
    char * urlSpec = (downloadNewMail)
      ? PR_smprintf("pop3://%s@%s:%d", (const char *)escapedUsername, (const char *)popHost, popPort)
      : PR_smprintf("pop3://%s@%s:%d/?check", (const char *)escapedUsername, (const char *)popHost, popPort);
    rv = BuildPop3Url(urlSpec, aInbox, aPopServer, aUrlListener, getter_AddRefs(url), aMsgWindow);
    PR_Free(urlSpec);
  }
  
  
  if (NS_SUCCEEDED(rv) && url) 
    rv = RunPopUrl(server, url);
  
  if (aURL && url) // we already have a ref count on pop3url...
    NS_IF_ADDREF(*aURL = url);
  
  return rv;
}
NS_IMETHODIMP
nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
{
    if (mStatus == NS_BASE_STREAM_CLOSED) {
        *aReadCount = 0;
        return NS_OK;
    }
    if (NS_FAILED(mStatus))
        return mStatus;

    PRUint32 nread = 0;

    // If anything is enqueued (or left-over) in mBuf, then feed it to
    // the reader first.
    while (mOffset < (PRInt32)mBuf.Length() && aCount != 0) {
        *(aBuf++) = char(mBuf.CharAt(mOffset++));
        --aCount;
        ++nread;
    }

    // Room left?
    if (aCount > 0) {
        mOffset = 0;
        mBuf.Truncate();

        // Okay, now we'll suck stuff off of our iterator into the mBuf...
        while (PRUint32(mBuf.Length()) < aCount) {
            bool more = mPos < mArray.Count();
            if (!more) break;

            // don't addref, for speed - an addref happened when it
            // was placed in the array, so it's not going to go stale
            nsIFile* current = mArray.ObjectAt(mPos);
            ++mPos;

#ifdef PR_LOGGING
            if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {
                nsCAutoString path;
                current->GetNativePath(path);
                PR_LOG(gLog, PR_LOG_DEBUG,
                       ("nsDirectoryIndexStream[%p]: iterated %s",
                        this, path.get()));
            }
#endif

            // rjc: don't return hidden files/directories!
            // bbaetz: why not?
            nsresult rv;
#ifndef XP_UNIX
            bool hidden = false;
            current->IsHidden(&hidden);
            if (hidden) {
                PR_LOG(gLog, PR_LOG_DEBUG,
                       ("nsDirectoryIndexStream[%p]: skipping hidden file/directory",
                        this));
                continue;
            }
#endif

            PRInt64 fileSize = 0;
            current->GetFileSize( &fileSize );

            PRInt64 fileInfoModifyTime = 0;
            current->GetLastModifiedTime( &fileInfoModifyTime );
            fileInfoModifyTime *= PR_USEC_PER_MSEC;

            mBuf.AppendLiteral("201: ");

            // The "filename" field
            char* escaped = nsnull;
            if (!NS_IsNativeUTF8()) {
                nsAutoString leafname;
                rv = current->GetLeafName(leafname);
                if (NS_FAILED(rv)) return rv;
                if (!leafname.IsEmpty())
                    escaped = nsEscape(NS_ConvertUTF16toUTF8(leafname).get(), url_Path);
            } else {
                nsCAutoString leafname;
                rv = current->GetNativeLeafName(leafname);
                if (NS_FAILED(rv)) return rv;
                if (!leafname.IsEmpty())
                    escaped = nsEscape(leafname.get(), url_Path);
            }
            if (escaped) {
                mBuf += escaped;
                mBuf.Append(' ');
                nsMemory::Free(escaped);
            }

            // The "content-length" field
            mBuf.AppendInt(fileSize, 10);
            mBuf.Append(' ');

            // The "last-modified" field
            PRExplodedTime tm;
            PR_ExplodeTime(fileInfoModifyTime, PR_GMTParameters, &tm);
            {
                char buf[64];
                PR_FormatTimeUSEnglish(buf, sizeof(buf), "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm);
                mBuf.Append(buf);
            }

            // The "file-type" field
            bool isFile = true;
            current->IsFile(&isFile);
            if (isFile) {
                mBuf.AppendLiteral("FILE ");
            }
            else {
                bool isDir;
                rv = current->IsDirectory(&isDir);
                if (NS_FAILED(rv)) return rv; 
                if (isDir) {
                    mBuf.AppendLiteral("DIRECTORY ");
                }
                else {
                    bool isLink;
                    rv = current->IsSymlink(&isLink);
                    if (NS_FAILED(rv)) return rv; 
                    if (isLink) {
                        mBuf.AppendLiteral("SYMBOLIC-LINK ");
                    }
                }
            }

            mBuf.Append('\n');
        }

        // ...and once we've either run out of directory entries, or
        // filled up the buffer, then we'll push it to the reader.
        while (mOffset < (PRInt32)mBuf.Length() && aCount != 0) {
            *(aBuf++) = char(mBuf.CharAt(mOffset++));
            --aCount;
            ++nread;
        }
    }

    *aReadCount = nread;
    return NS_OK;
}
示例#12
0
char *
nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
    char *line = aBuffer;
    char *eol;
    bool cr = false;

    list_state state;
    state.magic = 0;

    // while we have new lines, parse 'em into application/http-index-format.
    while ( line && (eol = PL_strchr(line, nsCRT::LF)) ) {
        // yank any carriage returns too.
        if (eol > line && *(eol-1) == nsCRT::CR) {
            eol--;
            *eol = '\0';
            cr = true;
        } else {
            *eol = '\0';
            cr = false;
        }

        list_result result;

        int type = ParseFTPList(line, &state, &result );

        // if it is other than a directory, file, or link -OR- if it is a 
        // directory named . or .., skip over this line.
        if ((type != 'd' && type != 'f' && type != 'l') || 
            (result.fe_type == 'd' && result.fe_fname[0] == '.' &&
            (result.fe_fnlen == 1 || (result.fe_fnlen == 2 &&  result.fe_fname[1] == '.'))) )
        {
            if (cr)
                line = eol+2;
            else
                line = eol+1;
            
            continue;
        }

        // blast the index entry into the indexFormat buffer as a 201: line.
        aString.AppendLiteral("201: ");
        // FILENAME

        // parsers for styles 'U' and 'W' handle sequence " -> " themself
	if (state.lstyle != 'U' && state.lstyle != 'W') {
            const char* offset = strstr(result.fe_fname, " -> ");
            if (offset) {
                result.fe_fnlen = offset - result.fe_fname;
            }
        }

        nsCAutoString buf;
        aString.Append('\"');
        aString.Append(NS_EscapeURL(Substring(result.fe_fname, 
                                              result.fe_fname+result.fe_fnlen),
                                    esc_Minimal|esc_OnlyASCII|esc_Forced,buf));
        aString.AppendLiteral("\" ");
 
        // CONTENT LENGTH
        
        if (type != 'd') 
        {
            for (int i = 0; i < int(sizeof(result.fe_size)); ++i)
            {
                if (result.fe_size[i] != '\0')
                    aString.Append((const char*)&result.fe_size[i], 1);
            }
            
            aString.Append(' ');
        }
        else
            aString.AppendLiteral("0 ");


        // MODIFIED DATE
        char buffer[256] = "";
        // Note: The below is the RFC822/1123 format, as required by
        // the application/http-index-format specs
        // viewers of such a format can then reformat this into the
        // current locale (or anything else they choose)
        PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
                               "%a, %d %b %Y %H:%M:%S", &result.fe_time );

        char *escapedDate = nsEscape(buffer, url_Path);
        aString.Append(escapedDate);
        nsMemory::Free(escapedDate);
        aString.Append(' ');

        // ENTRY TYPE
        if (type == 'd')
            aString.AppendLiteral("DIRECTORY");
        else if (type == 'l')
            aString.AppendLiteral("SYMBOLIC-LINK");
        else
            aString.AppendLiteral("FILE");
        
        aString.Append(' ');

        aString.Append(char(nsCRT::LF)); // complete this line
        // END 201:

        if (cr)
            line = eol+2;
        else
            line = eol+1;
    } // end while(eol)

    return line;
}
nsresult
nsXHTMLContentSerializer::EscapeURI(nsIContent* aContent, const nsAString& aURI, nsAString& aEscapedURI)
{
  // URL escape %xx cannot be used in JS.
  // No escaping if the scheme is 'javascript'.
  if (IsJavaScript(aContent, nsGkAtoms::href, kNameSpaceID_None, aURI)) {
    aEscapedURI = aURI;
    return NS_OK;
  }

  // nsITextToSubURI does charset convert plus uri escape
  // This is needed to convert to a document charset which is needed to support existing browsers.
  // But we eventually want to use UTF-8 instead of a document charset, then the code would be much simpler.
  // See HTML 4.01 spec, "Appendix B.2.1 Non-ASCII characters in URI attribute values"
  nsCOMPtr<nsITextToSubURI> textToSubURI;
  nsAutoString uri(aURI); // in order to use FindCharInSet()
  nsresult rv = NS_OK;

  if (!mCharset.IsEmpty() && !IsASCII(uri)) {
    textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  PRInt32 start = 0;
  PRInt32 end;
  nsAutoString part;
  nsXPIDLCString escapedURI;
  aEscapedURI.Truncate(0);

  // Loop and escape parts by avoiding escaping reserved characters
  // (and '%', '#', as well as '[' and ']' for IPv6 address literals).
  while ((end = uri.FindCharInSet("%#;/?:@&=+$,[]", start)) != -1) {
    part = Substring(aURI, start, (end-start));
    if (textToSubURI && !IsASCII(part)) {
      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else {
      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
    }
    AppendASCIItoUTF16(escapedURI, aEscapedURI);

    // Append a reserved character without escaping.
    part = Substring(aURI, end, 1);
    aEscapedURI.Append(part);
    start = end + 1;
  }

  if (start < (PRInt32) aURI.Length()) {
    // Escape the remaining part.
    part = Substring(aURI, start, aURI.Length()-start);
    if (textToSubURI) {
      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else {
      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
    }
    AppendASCIItoUTF16(escapedURI, aEscapedURI);
  }

  return rv;
}
nsresult
FileSystemDataSource::GetFolderList(nsIRDFResource *source, bool allowHidden,
                                    bool onlyFirst, nsISimpleEnumerator** aResult)
{
    if (!isDirURI(source))
        return(NS_RDF_NO_VALUE);

    nsresult                    rv;

    const char      *parentURI = nullptr;
    rv = source->GetValueConst(&parentURI);
    if (NS_FAILED(rv))
        return(rv);
    if (!parentURI)
        return(NS_ERROR_UNEXPECTED);

    nsCOMPtr<nsIURI>    aIURI;
    if (NS_FAILED(rv = NS_NewURI(getter_AddRefs(aIURI), nsDependentCString(parentURI))))
        return(rv);

    nsCOMPtr<nsIFileURL>    fileURL = do_QueryInterface(aIURI);
    if (!fileURL)
        return NS_OK;

    nsCOMPtr<nsIFile>   aDir;
    if (NS_FAILED(rv = fileURL->GetFile(getter_AddRefs(aDir))))
        return(rv);

    // ensure that we DO NOT resolve aliases
    aDir->SetFollowLinks(false);

    nsCOMPtr<nsISimpleEnumerator>   dirContents;
    if (NS_FAILED(rv = aDir->GetDirectoryEntries(getter_AddRefs(dirContents))))
        return(rv);
    if (!dirContents)
        return(NS_ERROR_UNEXPECTED);

    nsCOMArray<nsIRDFResource> resources;
    bool            hasMore;
    while(NS_SUCCEEDED(rv = dirContents->HasMoreElements(&hasMore)) &&
            hasMore)
    {
        nsCOMPtr<nsISupports>   isupports;
        if (NS_FAILED(rv = dirContents->GetNext(getter_AddRefs(isupports))))
            break;

        nsCOMPtr<nsIFile>   aFile = do_QueryInterface(isupports);
        if (!aFile)
            break;

        if (!allowHidden)
        {
            bool            hiddenFlag = false;
            if (NS_FAILED(rv = aFile->IsHidden(&hiddenFlag)))
                break;
            if (hiddenFlag)
                continue;
        }

        nsAutoString leafStr;
        if (NS_FAILED(rv = aFile->GetLeafName(leafStr)))
            break;
        if (leafStr.IsEmpty())
            continue;

        nsAutoCString           fullURI;
        fullURI.Assign(parentURI);
        if (fullURI.Last() != '/')
        {
            fullURI.Append('/');
        }

        char    *escLeafStr = nsEscape(NS_ConvertUTF16toUTF8(leafStr).get(), url_Path);
        leafStr.Truncate();

        if (!escLeafStr)
            continue;

        nsAutoCString           leaf(escLeafStr);
        free(escLeafStr);
        escLeafStr = nullptr;

        // using nsEscape() [above] doesn't escape slashes, so do that by hand
        int32_t         aOffset;
        while ((aOffset = leaf.FindChar('/')) >= 0)
        {
            leaf.Cut((uint32_t)aOffset, 1);
            leaf.Insert("%2F", (uint32_t)aOffset);
        }

        // append the encoded name
        fullURI.Append(leaf);

        bool            dirFlag = false;
        rv = aFile->IsDirectory(&dirFlag);
        if (NS_SUCCEEDED(rv) && dirFlag)
        {
            fullURI.Append('/');
        }

        nsCOMPtr<nsIRDFResource>    fileRes;
        mRDFService->GetResource(fullURI, getter_AddRefs(fileRes));

        resources.AppendObject(fileRes);

        if (onlyFirst)
            break;
    }

    return NS_NewArrayEnumerator(aResult, resources);
}