OLD | NEW |
(Empty) | |
| 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_parsers.h" |
| 6 |
| 7 #include "base/string_util.h" |
| 8 |
| 9 namespace { |
| 10 |
| 11 bool LooksLikeUnixPermission(const string16& text) { |
| 12 if (text.length() != 3) |
| 13 return false; |
| 14 |
| 15 return ((text[0] == 'r' || text[0] == '-') && |
| 16 (text[1] == 'w' || text[1] == '-') && |
| 17 (text[2] == 'x' || text[2] == 's' || text[2] == 'S' || |
| 18 text[2] == '-')); |
| 19 } |
| 20 |
| 21 bool LooksLikeUnixPermissionsListing(const string16& text) { |
| 22 if (text.length() != 10) |
| 23 return false; |
| 24 |
| 25 if (text[0] != 'b' && text[0] != 'c' && text[0] != 'd' && |
| 26 text[0] != 'l' && text[0] != 'p' && text[0] != 's' && |
| 27 text[0] != '-') |
| 28 return false; |
| 29 |
| 30 return (LooksLikeUnixPermission(text.substr(1, 3)) && |
| 31 LooksLikeUnixPermission(text.substr(4, 3)) && |
| 32 LooksLikeUnixPermission(text.substr(7, 3))); |
| 33 } |
| 34 |
| 35 bool IsStringNonNegativeNumber(const string16& text) { |
| 36 int number; |
| 37 if (!StringToInt(text, &number)) |
| 38 return false; |
| 39 |
| 40 return number >= 0; |
| 41 } |
| 42 |
| 43 bool ThreeLetterMonthToNumber(const string16& text, int* number) { |
| 44 const static char* months[] = { "jan", "feb", "mar", "apr", "may", "jun", |
| 45 "jul", "aug", "sep", "oct", "nov", "dec" }; |
| 46 |
| 47 for (size_t i = 0; i < arraysize(months); i++) { |
| 48 if (LowerCaseEqualsASCII(text, months[i])) { |
| 49 *number = i + 1; |
| 50 return true; |
| 51 } |
| 52 } |
| 53 |
| 54 return false; |
| 55 } |
| 56 |
| 57 bool UnixDateListingToTime(const std::vector<string16>& columns, |
| 58 base::Time* time) { |
| 59 DCHECK_EQ(9U, columns.size()); |
| 60 |
| 61 base::Time::Exploded time_exploded = { 0 }; |
| 62 |
| 63 if (!ThreeLetterMonthToNumber(columns[5], &time_exploded.month)) |
| 64 return false; |
| 65 |
| 66 if (!StringToInt(columns[6], &time_exploded.day_of_month)) |
| 67 return false; |
| 68 |
| 69 if (!StringToInt(columns[7], &time_exploded.year)) { |
| 70 // Maybe it's time. Does it look like time (MM:HH)? |
| 71 if (columns[7].length() != 5 || columns[7][2] != ':') |
| 72 return false; |
| 73 |
| 74 if (!StringToInt(columns[7].substr(0, 2), &time_exploded.hour)) |
| 75 return false; |
| 76 |
| 77 if (!StringToInt(columns[7].substr(3, 2), &time_exploded.minute)) |
| 78 return false; |
| 79 |
| 80 // Use current year. |
| 81 base::Time::Exploded now_exploded; |
| 82 base::Time::Now().LocalExplode(&now_exploded); |
| 83 time_exploded.year = now_exploded.year; |
| 84 } |
| 85 |
| 86 // We don't know the time zone of the server, so just use local time. |
| 87 *time = base::Time::FromLocalExploded(time_exploded); |
| 88 return true; |
| 89 } |
| 90 |
| 91 } // namespace |
| 92 |
| 93 namespace net { |
| 94 |
| 95 FtpDirectoryListingParser::~FtpDirectoryListingParser() { |
| 96 } |
| 97 |
| 98 FtpLsDirectoryListingParser::FtpLsDirectoryListingParser() { |
| 99 } |
| 100 |
| 101 bool FtpLsDirectoryListingParser::ConsumeLine(const string16& line) { |
| 102 std::vector<string16> columns; |
| 103 SplitString(CollapseWhitespace(line, false), ' ', &columns); |
| 104 if (columns.size() == 11) { |
| 105 // Check if it is a symlink. |
| 106 if (columns[9] != ASCIIToUTF16("->")) |
| 107 return false; |
| 108 |
| 109 // Drop the symlink target from columns, we don't use it. |
| 110 columns.resize(9); |
| 111 } |
| 112 |
| 113 if (columns.size() != 9) |
| 114 return false; |
| 115 |
| 116 if (!LooksLikeUnixPermissionsListing(columns[0])) |
| 117 return false; |
| 118 |
| 119 FtpDirectoryListingEntry entry; |
| 120 if (columns[0][0] == 'l') { |
| 121 entry.type = FtpDirectoryListingEntry::SYMLINK; |
| 122 } else if (columns[0][0] == 'd') { |
| 123 entry.type = FtpDirectoryListingEntry::DIRECTORY; |
| 124 } else { |
| 125 entry.type = FtpDirectoryListingEntry::FILE; |
| 126 } |
| 127 |
| 128 if (!IsStringNonNegativeNumber(columns[1])) |
| 129 return false; |
| 130 |
| 131 if (!IsStringNonNegativeNumber(columns[4])) |
| 132 return false; |
| 133 |
| 134 if (!UnixDateListingToTime(columns, &entry.last_modified)) |
| 135 return false; |
| 136 |
| 137 entry.name = columns[8]; |
| 138 |
| 139 entries_.push(entry); |
| 140 return true; |
| 141 } |
| 142 |
| 143 bool FtpLsDirectoryListingParser::EntryAvailable() const { |
| 144 return !entries_.empty(); |
| 145 } |
| 146 |
| 147 FtpDirectoryListingEntry FtpLsDirectoryListingParser::PopEntry() { |
| 148 FtpDirectoryListingEntry entry = entries_.front(); |
| 149 entries_.pop(); |
| 150 return entry; |
| 151 } |
| 152 |
| 153 } // namespace net |
OLD | NEW |