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