Example #1
0
nsresult
nsDataHandler::ParseURI(nsCString& spec,
                        nsCString& contentType,
                        nsCString& contentCharset,
                        bool&    isBase64,
                        nsCString& dataBuffer,
                        nsCString& hashRef) {
    isBase64 = false;

    // move past "data:"
    char *buffer = (char *) PL_strcasestr(spec.BeginWriting(), "data:");
    if (!buffer) {
        // malformed uri
        return NS_ERROR_MALFORMED_URI;
    }
    buffer += 5;

    // First, find the start of the data
    char *comma = strchr(buffer, ',');
    char *hash = strchr(buffer, '#');
    if (!comma || (hash && hash < comma))
        return NS_ERROR_MALFORMED_URI;

    *comma = '\0';

    // determine if the data is base64 encoded.
    char *base64 = PL_strcasestr(buffer, BASE64_EXTENSION);
    if (base64) {
        char *beyond = base64 + strlen(BASE64_EXTENSION);
        // per the RFC 2397 grammar, "base64" MUST be followed by a comma
        // previously substituted by '\0', but we also allow it in between
        // parameters so a subsequent ";" is ok as well (this deals with
        // *broken* data URIs, see bug 781693 for an example)
        if (*beyond == '\0' || *beyond == ';') {
            isBase64 = true;
            *base64 = '\0';
        }
    }

    if (comma == buffer) {
        // nothing but data
        contentType.AssignLiteral("text/plain");
        contentCharset.AssignLiteral("US-ASCII");
    } else {
        // everything else is content type
        char *semiColon = (char *) strchr(buffer, ';');
        if (semiColon)
            *semiColon = '\0';
        
        if (semiColon == buffer || base64 == buffer) {
            // there is no content type, but there are other parameters
            contentType.AssignLiteral("text/plain");
        } else {
            contentType = buffer;
            ToLowerCase(contentType);
        }

        if (semiColon) {
            char *charset = PL_strcasestr(semiColon + 1, "charset=");
            if (charset)
                contentCharset = charset + sizeof("charset=") - 1;

            *semiColon = ';';
        }
    }

    *comma = ',';
    if (isBase64)
        *base64 = ';';

    contentType.StripWhitespace();
    contentCharset.StripWhitespace();

    // Split encoded data from terminal "#ref" (if present)
    char *data = comma + 1;
    if (!hash) {
        dataBuffer.Assign(data);
        hashRef.Truncate();
    } else {
        dataBuffer.Assign(data, hash - data);
        hashRef.Assign(hash);
    }

    return NS_OK;
}
nsHtml5Parser::GetCommand(nsCString& aCommand)
{
  aCommand.Assign("view");
}
  // Determine if this line meets Eudora standards for a separator line
  // This logic is based on Eudora 1.3.1's strict requirements for what
  // makes a valid separator line.  This may need to be relaxed for newer
  // versions of Eudora.
  // A sample from line:
  // From [email protected] Wed Jan 14 12:36:18 1989
PRInt32  nsEudoraMailbox::IsEudoraFromSeparator( const char *pChar, PRInt32 maxLen, nsCString& defaultDate)
{
  if (maxLen < 12)
    return( -1);

  PRInt32    len = 0;
  if ((*pChar != 'F') || (*(pChar + 1) != 'r') || (*(pChar + 2) != 'o') || (*(pChar + 3) != 'm'))
    return( -1);
  pChar += 4;
  len += 4;

  // According to Eudora the next char MUST be a space, and there can only be 1 space
  // before the return mail address.
  // I'll be nicer and allow any amount of whitespace
  while (((*pChar == ' ') || (*pChar == '\t')) && (len < maxLen)) {
    pChar++;
    len++;
  }
  if (len == maxLen)
    return( -1);

  // Determine the length of the line
  PRInt32      lineLen = len;
  const char *  pTok = pChar;
  while ((lineLen < maxLen) && (*pTok != 0x0D) && (*pTok != 0x0A)) {
    lineLen++;
    pTok++;
  }

  if (len >= lineLen)
    return( -1);

  // Eudora allows the return address to be double quoted or not at all..
  // I'll allow single or double quote, but other than that, just skip
  // the return address until you hit a space char (I allow tab as well)
  char  quote = *pChar;
  if ((quote == '"') || (quote == '\'')) {
    pChar++;
    len++;
    while ((len < lineLen) && (*pChar != quote)) {
      pChar++;
      len++;
    }
    if (len == lineLen)
      return( -1);
    len++;
    pChar++;
  }
  else {
    while ((len < lineLen) && (*pChar != ' ') && (*pChar != '\t')) {
      pChar++;
      len++;
    }
  }
  while (((*pChar == ' ') || (*pChar == '\t')) && (len < lineLen)) {
    pChar++;
    len++;
  }
  if (len == lineLen)
    return( -1);

  // we've passed the address, now check for the remaining data
  // Now it gets really funky!
  // In no particular order, with token separators space, tab, comma, newline
  // a - the phrase "remote from", remote must be first, from is optional.  2 froms or 2 remotes fails
  // b - one and only one time value xx:xx or xx:xx:xx
  // c - one and only one day, 1 to 31
  // d - one and only one year, 2 digit anything or 4 digit > 1900
  // e - one and only one weekday, 3 letter abreviation
  // f - one and only one month, 3 letter abreviation
  // 2 allowable "other" tokens
  // to be valid, day, year, month, & tym must exist and other must be less than 3

  int    day = 0;
  int    month = 0;
  int    year = 0;
  int    weekDay = 0;
  int    other = 0;
  int    result;
  char  tymStr[9];  // Make it a null terminated string (used in PR_snprintf() call()).
  PRBool  tym = PR_FALSE;
  PRBool  remote = PR_FALSE;
  PRBool  from = PR_FALSE;
  PRInt32  tokLen;
  PRInt32  tokStart;
  PRInt32  num;

  while ((len < lineLen) && (other < 3)) {
    pTok = pChar;
    tokStart = len;
    while ((len < lineLen) && (*pChar != ' ') && (*pChar != '\t') && (*pChar != ',')) {
      pChar++;
      len++;
    }
    tokLen = len - tokStart;
    if (tokLen) {
      num = AsciiToLong( pTok, tokLen);
      if ((tokLen == 3) && ((result = IsWeekDayStr( pTok)) != 0)) {
        if (weekDay)
          return( -1);
        weekDay = result;
      }
      else if ((tokLen == 3) && ((result = IsMonthStr( pTok)) != 0)) {
        if (month)
          return( -1);
        month = result;
      }
      else if ((tokLen == 6) && !PL_strncasecmp( pTok, "remote", 6)) {
        if (remote || from)
          return( -1);
        remote = PR_TRUE;
      }
      else if ((tokLen == 4) && !PL_strncasecmp( pTok, "from", 4)) {
        if (!remote || from)
          return( -1);
        from = PR_TRUE;
      }
      else if ((tokLen == 4) && ((num > 1900) || !strncmp( pTok, "0000", 4))) {
        if (year)
          return( -1);
        year = (int)num;
        if (!year)
          year = 1900;
      }
      else if (!year && day && (tokLen == 2) && (*(pTok + 1) >= '0') && (*(pTok + 1) <= '9')) {
        if (num < 65)
          num += 1900;
        else
           num += 2000;
         year = (int) num;
      }
      else if ((tokLen <= 2) && (*pTok >= '0') && (*pTok <= '9')) {
        day = (int) num;
        if ((day < 1) || (day > 31))
          day = 1;
      }
      else if ((tokLen >= 5) && (pTok[2] == ':') && ((tokLen == 5) || ((tokLen == 8) && (pTok[5] == ':')))) {
        // looks like the tym...
        for (result = 0; result < (int)tokLen; result++) {
          if ((result != 2) && (result != 5)) {
            if ((pTok[result] < '0') || (pTok[result] > '9')) {
              break;
            }
          }
        }
        if (result == tokLen) {
          if (tym)
            return( -1);
          tym = PR_TRUE;
          // for future use, get the time value
          memcpy( tymStr, pTok, tokLen);
          if (tokLen == 5) {
            tymStr[5] = ':';
            tymStr[6] = '0';
            tymStr[7] = '0';
          }
          tymStr[8] = 0;
        }
        else {
          other++;
        }
      }
      else
        other++;
    }
    // Skip the space chars...
    while ((len < lineLen) && ((*pChar == ' ') || (*pChar == '\t') || (*pChar == ','))) {
      pChar++;
      len++;
    }
  } // end while (len < lineLen) token loop

  // Now let's see what we found on the line
  if (day && year && month && tym && (other < 3)) {
    // Now we need to make sure the next line
    // isn't blank!
    while (len < lineLen) {
      len++;
      pChar++;
    }
    if (len == maxLen)
      return( -1);

    if (*pChar == 0x0D) {
      len++;
      pChar++;
      if (*pChar == 0x0A) {
        len++;
        pChar++;
      }
    }
    else if (*pChar == 0x0A) {
      len++;
      pChar++;
    }
    else
      return( -1);
    if (len >= maxLen)
      return( -1);

    while (len < maxLen) {
      if ((*pChar == 0x0D) || (*pChar == 0x0A))
        return( -1);
      if ((*pChar != ' ') && (*pChar != '\t'))
        break;
      pChar++;
      len++;
    }

    // Whew!, the next line isn't blank.
    // Generate the default date header in case the date header is missing when we
    // write out headers later. The header looks like "Date: Tue, 5 Feb 2002 23:05:04"
    char date_header_str[DATE_STR_LEN];
    PR_snprintf(date_header_str, DATE_STR_LEN, "Date: %s, %2d %s %4d %s", eudoraWeekDays[weekDay-1], day, eudoraMonths[month-1], year, tymStr);
    defaultDate.Assign(date_header_str);

    return( lineLen);
  }

  return( -1);

}
nsresult
nsAboutCacheEntry::Channel::ParseURI(nsIURI *uri,
                                     nsACString &storageName,
                                     nsILoadContextInfo **loadInfo,
                                     nsCString &enahnceID,
                                     nsIURI **cacheUri)
{
    //
    // about:cache-entry?storage=[string]&contenxt=[string]&eid=[string]&uri=[string]
    //
    nsresult rv;

    nsAutoCString path;
    rv = uri->GetPath(path);
    if (NS_FAILED(rv))
        return rv;

    nsACString::const_iterator keyBegin, keyEnd, valBegin, begin, end;
    path.BeginReading(begin);
    path.EndReading(end);

    keyBegin = begin; keyEnd = end;
    if (!FindInReadable(NS_LITERAL_CSTRING("?storage="), keyBegin, keyEnd))
        return NS_ERROR_FAILURE;

    valBegin = keyEnd; // the value of the storage key starts after the key

    keyBegin = keyEnd; keyEnd = end;
    if (!FindInReadable(NS_LITERAL_CSTRING("&context="), keyBegin, keyEnd))
        return NS_ERROR_FAILURE;

    storageName.Assign(Substring(valBegin, keyBegin));
    valBegin = keyEnd; // the value of the context key starts after the key

    keyBegin = keyEnd; keyEnd = end;
    if (!FindInReadable(NS_LITERAL_CSTRING("&eid="), keyBegin, keyEnd))
        return NS_ERROR_FAILURE;

    nsAutoCString contextKey(Substring(valBegin, keyBegin));
    valBegin = keyEnd; // the value of the eid key starts after the key

    keyBegin = keyEnd; keyEnd = end;
    if (!FindInReadable(NS_LITERAL_CSTRING("&uri="), keyBegin, keyEnd))
        return NS_ERROR_FAILURE;

    enahnceID.Assign(Substring(valBegin, keyBegin));

    valBegin = keyEnd; // the value of the uri key starts after the key
    nsAutoCString uriSpec(Substring(valBegin, end)); // uri is the last one

    // Uf... parsing done, now get some objects from it...

    nsCOMPtr<nsILoadContextInfo> info =
      CacheFileUtils::ParseKey(contextKey);
    if (!info)
        return NS_ERROR_FAILURE;
    info.forget(loadInfo);

    rv = NS_NewURI(cacheUri, uriSpec);
    if (NS_FAILED(rv))
        return rv;

    return NS_OK;
}
/**
 * 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;
}
Example #7
0
void ConfigWebRtcLog(mozilla::LogLevel level, uint32_t trace_mask,
                     nsCString &aLogFile, bool multi_log)
{
  if (gWebRtcTraceLoggingOn) {
    return;
  }

#if defined(ANDROID)
  // Special case: use callback to pipe to NSPR logging.
  aLogFile.Assign(default_log_name);
#else

  rtc::LoggingSeverity log_level;
  switch (level) {
    case mozilla::LogLevel::Verbose:
      log_level = rtc::LoggingSeverity::LS_VERBOSE;
      break;
    case mozilla::LogLevel::Debug:
    case mozilla::LogLevel::Info:
      log_level = rtc::LoggingSeverity::LS_INFO;
      break;
    case mozilla::LogLevel::Warning:
      log_level = rtc::LoggingSeverity::LS_WARNING;
      break;
    case mozilla::LogLevel::Error:
      log_level = rtc::LoggingSeverity::LS_ERROR;
      break;
    case mozilla::LogLevel::Disabled:
      log_level = rtc::LoggingSeverity::LS_NONE;
      break;
    default:
      MOZ_ASSERT(false);
      break;
  }
  rtc::LogMessage::LogToDebug(log_level);
  if (level != mozilla::LogLevel::Disabled) {
    // always capture LOG(...) << ... logging in webrtc.org code to nspr logs
    if (!sSink) {
      sSink = new LogSinkImpl();
      rtc::LogMessage::AddLogToStream(sSink, log_level);
      // it's ok if this leaks to program end
    }
  } else if (sSink) {
    rtc::LogMessage::RemoveLogToStream(sSink);
    sSink = nullptr;
  }

  webrtc::Trace::set_level_filter(trace_mask);
  if (trace_mask != 0) {
    // default WEBRTC_TRACE logs to a rotating file, but allow redirecting to nspr
    // XXX always redirect in e10s if the sandbox blocks file access, or somehow proxy
    if (aLogFile.EqualsLiteral("nspr") || aLogFile.EqualsLiteral("moz_log")) {
      rtc::LogMessage::SetLogToStderr(false);
      webrtc::Trace::SetTraceCallback(&gWebRtcCallback);
    } else {
      rtc::LogMessage::SetLogToStderr(true);
      webrtc::Trace::SetTraceFile(aLogFile.get(), multi_log);
    }
  } else {
    rtc::LogMessage::SetLogToStderr(false);
  }

  if (aLogFile.IsEmpty()) {
    nsCOMPtr<nsIFile> tempDir;
    nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir));
    if (NS_SUCCEEDED(rv)) {
      tempDir->AppendNative(default_log_name);
#ifdef XP_WIN
      // WebRTC wants a path encoded in the native charset, not UTF-8.
      nsAutoString logFile;
      tempDir->GetPath(logFile);
      NS_CopyUnicodeToNative(logFile, aLogFile);
#else
      tempDir->GetNativePath(aLogFile);
#endif
    }
  }
#endif

  if (XRE_IsParentProcess()) {
    // Capture the final choice for the trace setting.
    mozilla::Preferences::SetCString("media.webrtc.debug.log_file", aLogFile);
  }
}
/**
 * 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, &gtime);

        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;
}