예제 #1
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;
}
예제 #2
0
static gboolean
g_vfs_ftp_dir_cache_funcs_process (GInputStream *        stream,
                                   int                   debug_id,
                                   const GVfsFtpFile *   dir,
                                   GVfsFtpDirCacheEntry *entry,
                                   gboolean              is_unix,
                                   GCancellable *        cancellable,
                                   GError **             error)
{
  struct list_state state = { NULL, };
  GDataInputStream *data;
  GFileInfo *info;
  int type;
  GVfsFtpFile *file;
  char *line, *s;
  gsize length;

  /* protect against code reorg - in current code, error never is NULL */
  g_assert (error != NULL);
  g_assert (*error == NULL);

  data = g_data_input_stream_new (stream);
  /* we use LF only, because the mozilla code can handle lines ending in CR */
  g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_LF);
  while ((line = g_data_input_stream_read_line (data, &length, cancellable, error)))
    {
      struct list_result result = { 0, };
      GFileType file_type = G_FILE_TYPE_UNKNOWN;
      GTimeVal tv = { 0, 0 };

      /* strip trailing \r - ParseFTPList only removes it if the line ends in \r\n,
       * but we stripped the \n already.
       */
      if (length > 0 && line[length - 1] == '\r')
        line[--length] = '\0';

      g_debug ("<<%2d <<  %s\n", debug_id, line);
      type = ParseFTPList (line, &state, &result);
      if (type != 'd' && type != 'f' && type != 'l')
        {
          g_free (line);
          continue;
        }

      /* don't list . and .. directories
       * Let's hope they're not important files on some ftp servers
       */
      if (result.fe_fnlen == 1 &&
          result.fe_fname[0] == '.')
        {
          g_free (line);
          continue;
        }
      if (result.fe_fnlen == 2 &&
          result.fe_fname[0] == '.' &&
          result.fe_fname[1] == '.')
        {
          g_free (line);
          continue;
        }

      s = g_strndup (result.fe_fname, result.fe_fnlen);
      file = g_vfs_ftp_file_new_child  (dir, s, NULL);
      g_free (s);
      if (file == NULL)
        {
          g_debug ("# invalid filename, skipping");
          g_free (line);
          continue;
        }

      info = g_file_info_new ();

      s = g_path_get_basename (g_vfs_ftp_file_get_gvfs_path (file));
      g_file_info_set_name (info, s);
      g_free (s);

      if (type == 'l')
        {
          char *link;

          link = g_strndup (result.fe_lname, result.fe_lnlen);
          g_file_info_set_symlink_target (info, link);
          g_file_info_set_is_symlink (info, TRUE);
          g_free (link);
        }

      g_file_info_set_size (info, g_ascii_strtoull (result.fe_size, NULL, 10));

      /* If unix format then parse the attributes */
      if (state.lstyle == 'U')
        {
          char file_mode[10], uid[64], gid[64];
          guint32 mode;

          /* POSIX ls -l form: mode, links, owner, group */
          if (sscanf(line, "%10c %*u %63s %63s", file_mode, uid, gid) == 3)
            {
              if (g_vfs_ftp_parse_mode (file_mode, &mode, &file_type))
                {
                  g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, mode);
                  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER, uid);
                  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP, gid);
                }
            }
          else
            g_debug ("# unknown listing format\n");
        }

      if (file_type == G_FILE_TYPE_UNKNOWN)
        {
          file_type = type == 'f' ? G_FILE_TYPE_REGULAR :
                      type == 'l' ? G_FILE_TYPE_SYMBOLIC_LINK :
                      G_FILE_TYPE_DIRECTORY;
        }

      gvfs_file_info_populate_default (info,
                                       g_vfs_ftp_file_get_gvfs_path (file),
                                       file_type);

      if (is_unix)
        g_file_info_set_is_hidden (info, result.fe_fnlen > 0 &&
                                         result.fe_fname[0] == '.');

      /* Workaround:
       * result.fetime.tm_year contains actual year instead of offset-from-1900,
       * which mktime expects.
       */
      if (result.fe_time.tm_year >= 1900)
              result.fe_time.tm_year -= 1900;

      tv.tv_sec = mktime (&result.fe_time);
      if (tv.tv_sec != -1)
        g_file_info_set_modification_time (info, &tv);

      g_vfs_ftp_dir_cache_entry_add (entry, file, info);
      g_free (line);
    }

  g_object_unref (data);
  return *error != NULL;
}