Home | History | Annotate | Download | only in ftp
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this
      2 // source code is governed by a BSD-style license that can be found in the
      3 // LICENSE file.
      4 
      5 #include "net/ftp/ftp_directory_listing_parser_windows.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/string_util.h"
     10 #include "net/ftp/ftp_util.h"
     11 
     12 namespace {
     13 
     14 bool WindowsDateListingToTime(const std::vector<string16>& columns,
     15                               base::Time* time) {
     16   DCHECK_LE(4U, columns.size());
     17 
     18   base::Time::Exploded time_exploded = { 0 };
     19 
     20   // Date should be in format MM-DD-YY[YY].
     21   std::vector<string16> date_parts;
     22   SplitString(columns[0], '-', &date_parts);
     23   if (date_parts.size() != 3)
     24     return false;
     25   if (!StringToInt(date_parts[0], &time_exploded.month))
     26     return false;
     27   if (!StringToInt(date_parts[1], &time_exploded.day_of_month))
     28     return false;
     29   if (!StringToInt(date_parts[2], &time_exploded.year))
     30     return false;
     31   if (time_exploded.year < 0)
     32     return false;
     33   // If year has only two digits then assume that 00-79 is 2000-2079,
     34   // and 80-99 is 1980-1999.
     35   if (time_exploded.year < 80)
     36     time_exploded.year += 2000;
     37   else if (time_exploded.year < 100)
     38     time_exploded.year += 1900;
     39 
     40   // Time should be in format HH:MM(AM|PM)
     41   if (columns[1].length() != 7)
     42     return false;
     43   std::vector<string16> time_parts;
     44   SplitString(columns[1].substr(0, 5), ':', &time_parts);
     45   if (time_parts.size() != 2)
     46     return false;
     47   if (!StringToInt(time_parts[0], &time_exploded.hour))
     48     return false;
     49   if (!StringToInt(time_parts[1], &time_exploded.minute))
     50     return false;
     51   string16 am_or_pm(columns[1].substr(5, 2));
     52   if (EqualsASCII(am_or_pm, "PM"))
     53     time_exploded.hour += 12;
     54   else if (!EqualsASCII(am_or_pm, "AM"))
     55     return false;
     56 
     57   // We don't know the time zone of the server, so just use local time.
     58   *time = base::Time::FromLocalExploded(time_exploded);
     59   return true;
     60 }
     61 
     62 }  // namespace
     63 
     64 namespace net {
     65 
     66 FtpDirectoryListingParserWindows::FtpDirectoryListingParserWindows() {
     67 }
     68 
     69 bool FtpDirectoryListingParserWindows::ConsumeLine(const string16& line) {
     70   std::vector<string16> columns;
     71   SplitString(CollapseWhitespace(line, false), ' ', &columns);
     72 
     73   // We may receive file names containing spaces, which can make the number of
     74   // columns arbitrarily large. We will handle that later. For now just make
     75   // sure we have all the columns that should normally be there.
     76   if (columns.size() < 4)
     77     return false;
     78 
     79   FtpDirectoryListingEntry entry;
     80   entry.name = FtpUtil::GetStringPartAfterColumns(line, 3);
     81 
     82   if (EqualsASCII(columns[2], "<DIR>")) {
     83     entry.type = FtpDirectoryListingEntry::DIRECTORY;
     84     entry.size = -1;
     85   } else {
     86     entry.type = FtpDirectoryListingEntry::FILE;
     87     if (!StringToInt64(columns[2], &entry.size))
     88       return false;
     89     if (entry.size < 0)
     90       return false;
     91   }
     92 
     93   if (!WindowsDateListingToTime(columns, &entry.last_modified))
     94     return false;
     95 
     96   entries_.push(entry);
     97   return true;
     98 }
     99 
    100 bool FtpDirectoryListingParserWindows::OnEndOfInput() {
    101   return true;
    102 }
    103 
    104 bool FtpDirectoryListingParserWindows::EntryAvailable() const {
    105   return !entries_.empty();
    106 }
    107 
    108 FtpDirectoryListingEntry FtpDirectoryListingParserWindows::PopEntry() {
    109   FtpDirectoryListingEntry entry = entries_.front();
    110   entries_.pop();
    111   return entry;
    112 }
    113 
    114 }  // namespace net
    115