| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 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 | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "net/ftp/ftp_directory_listing_parsers.h" | 5 #include "net/ftp/ftp_directory_listing_parsers.h" |
| 6 | 6 |
| 7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
| 8 | 8 |
| 9 namespace { | 9 namespace { |
| 10 | 10 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 base::Time::Exploded now_exploded; | 81 base::Time::Exploded now_exploded; |
| 82 base::Time::Now().LocalExplode(&now_exploded); | 82 base::Time::Now().LocalExplode(&now_exploded); |
| 83 time_exploded.year = now_exploded.year; | 83 time_exploded.year = now_exploded.year; |
| 84 } | 84 } |
| 85 | 85 |
| 86 // We don't know the time zone of the server, so just use local time. | 86 // We don't know the time zone of the server, so just use local time. |
| 87 *time = base::Time::FromLocalExploded(time_exploded); | 87 *time = base::Time::FromLocalExploded(time_exploded); |
| 88 return true; | 88 return true; |
| 89 } | 89 } |
| 90 | 90 |
| 91 bool WindowsDateListingToTime(const std::vector<string16>& columns, |
| 92 base::Time* time) { |
| 93 DCHECK_EQ(4U, columns.size()); |
| 94 |
| 95 base::Time::Exploded time_exploded = { 0 }; |
| 96 |
| 97 // Date should be in format MM-DD-YY[YY]. |
| 98 std::vector<string16> date_parts; |
| 99 SplitString(columns[0], '-', &date_parts); |
| 100 if (date_parts.size() != 3) |
| 101 return false; |
| 102 if (!StringToInt(date_parts[0], &time_exploded.month)) |
| 103 return false; |
| 104 if (!StringToInt(date_parts[1], &time_exploded.day_of_month)) |
| 105 return false; |
| 106 if (!StringToInt(date_parts[2], &time_exploded.year)) |
| 107 return false; |
| 108 if (time_exploded.year < 0) |
| 109 return false; |
| 110 // If year has only two digits then assume that 00-79 is 2000-2079, |
| 111 // and 80-99 is 1980-1999. |
| 112 if (time_exploded.year < 80) |
| 113 time_exploded.year += 2000; |
| 114 else if (time_exploded.year < 100) |
| 115 time_exploded.year += 1900; |
| 116 |
| 117 // Time should be in format HH:MM(AM|PM) |
| 118 if (columns[1].length() != 7) |
| 119 return false; |
| 120 std::vector<string16> time_parts; |
| 121 SplitString(columns[1].substr(0, 5), ':', &time_parts); |
| 122 if (time_parts.size() != 2) |
| 123 return false; |
| 124 if (!StringToInt(time_parts[0], &time_exploded.hour)) |
| 125 return false; |
| 126 if (!StringToInt(time_parts[1], &time_exploded.minute)) |
| 127 return false; |
| 128 string16 am_or_pm(columns[1].substr(5, 2)); |
| 129 if (EqualsASCII(am_or_pm, "PM")) |
| 130 time_exploded.hour += 12; |
| 131 else if (!EqualsASCII(am_or_pm, "AM")) |
| 132 return false; |
| 133 |
| 134 // We don't know the time zone of the server, so just use local time. |
| 135 *time = base::Time::FromLocalExploded(time_exploded); |
| 136 return true; |
| 137 } |
| 138 |
| 91 // Converts the filename component in listing to the filename we can display. | 139 // Converts the filename component in listing to the filename we can display. |
| 92 // Returns true on success. | 140 // Returns true on success. |
| 93 bool ParseVmsFilename(const string16& raw_filename, string16* parsed_filename, | 141 bool ParseVmsFilename(const string16& raw_filename, string16* parsed_filename, |
| 94 bool* is_directory) { | 142 bool* is_directory) { |
| 95 // On VMS, the files and directories are versioned. The version number is | 143 // On VMS, the files and directories are versioned. The version number is |
| 96 // separated from the file name by a semicolon. Example: ANNOUNCE.TXT;2. | 144 // separated from the file name by a semicolon. Example: ANNOUNCE.TXT;2. |
| 97 std::vector<string16> listing_parts; | 145 std::vector<string16> listing_parts; |
| 98 SplitString(raw_filename, ';', &listing_parts); | 146 SplitString(raw_filename, ';', &listing_parts); |
| 99 if (listing_parts.size() != 2) | 147 if (listing_parts.size() != 2) |
| 100 return false; | 148 return false; |
| 101 if (!IsStringNonNegativeInteger(listing_parts[1])) | 149 if (!IsStringNonNegativeInteger(listing_parts[1])) |
| 102 return false; | 150 return false; |
| 103 | 151 |
| 104 // Even directories have extensions in the listings. Don't display extensions | 152 // Even directories have extensions in the listings. Don't display extensions |
| 105 // for directories; it's awkward for non-VMS users. Also, VMS is | 153 // for directories; it's awkward for non-VMS users. Also, VMS is |
| 106 // case-insensitive, but generally uses uppercase characters. This may look | 154 // case-insensitive, but generally uses uppercase characters. This may look |
| 107 // awkward, so we convert them to lower case. | 155 // awkward, so we convert them to lower case. |
| 108 std::vector<string16> filename_parts; | 156 std::vector<string16> filename_parts; |
| 109 SplitString(listing_parts[0], '.', &filename_parts); | 157 SplitString(listing_parts[0], '.', &filename_parts); |
| 110 if (filename_parts.size() != 2) | 158 if (filename_parts.size() != 2) |
| 111 return false; | 159 return false; |
| 112 if (filename_parts[1] == ASCIIToUTF16("DIR")) { | 160 if (EqualsASCII(filename_parts[1], "DIR")) { |
| 113 *parsed_filename = StringToLowerASCII(filename_parts[0]); | 161 *parsed_filename = StringToLowerASCII(filename_parts[0]); |
| 114 *is_directory = true; | 162 *is_directory = true; |
| 115 } else { | 163 } else { |
| 116 *parsed_filename = StringToLowerASCII(listing_parts[0]); | 164 *parsed_filename = StringToLowerASCII(listing_parts[0]); |
| 117 *is_directory = false; | 165 *is_directory = false; |
| 118 } | 166 } |
| 119 return true; | 167 return true; |
| 120 } | 168 } |
| 121 | 169 |
| 122 bool ParseVmsFilesize(const string16& input, int64* size) { | 170 bool ParseVmsFilesize(const string16& input, int64* size) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 // systems in Unix emulation mode add an empty line before the first listing | 293 // systems in Unix emulation mode add an empty line before the first listing |
| 246 // entry. | 294 // entry. |
| 247 if (line.empty() && !received_nonempty_line_) | 295 if (line.empty() && !received_nonempty_line_) |
| 248 return true; | 296 return true; |
| 249 received_nonempty_line_ = true; | 297 received_nonempty_line_ = true; |
| 250 | 298 |
| 251 std::vector<string16> columns; | 299 std::vector<string16> columns; |
| 252 SplitString(CollapseWhitespace(line, false), ' ', &columns); | 300 SplitString(CollapseWhitespace(line, false), ' ', &columns); |
| 253 if (columns.size() == 11) { | 301 if (columns.size() == 11) { |
| 254 // Check if it is a symlink. | 302 // Check if it is a symlink. |
| 255 if (columns[9] != ASCIIToUTF16("->")) | 303 if (!EqualsASCII(columns[9], "->")) |
| 256 return false; | 304 return false; |
| 257 | 305 |
| 258 // Drop the symlink target from columns, we don't use it. | 306 // Drop the symlink target from columns, we don't use it. |
| 259 columns.resize(9); | 307 columns.resize(9); |
| 260 } | 308 } |
| 261 | 309 |
| 262 if (columns.size() != 9) | 310 if (columns.size() != 9) |
| 263 return false; | 311 return false; |
| 264 | 312 |
| 265 if (!LooksLikeUnixPermissionsListing(columns[0])) | 313 if (!LooksLikeUnixPermissionsListing(columns[0])) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 296 bool FtpLsDirectoryListingParser::EntryAvailable() const { | 344 bool FtpLsDirectoryListingParser::EntryAvailable() const { |
| 297 return !entries_.empty(); | 345 return !entries_.empty(); |
| 298 } | 346 } |
| 299 | 347 |
| 300 FtpDirectoryListingEntry FtpLsDirectoryListingParser::PopEntry() { | 348 FtpDirectoryListingEntry FtpLsDirectoryListingParser::PopEntry() { |
| 301 FtpDirectoryListingEntry entry = entries_.front(); | 349 FtpDirectoryListingEntry entry = entries_.front(); |
| 302 entries_.pop(); | 350 entries_.pop(); |
| 303 return entry; | 351 return entry; |
| 304 } | 352 } |
| 305 | 353 |
| 354 FtpWindowsDirectoryListingParser::FtpWindowsDirectoryListingParser() { |
| 355 } |
| 356 |
| 357 bool FtpWindowsDirectoryListingParser::ConsumeLine(const string16& line) { |
| 358 std::vector<string16> columns; |
| 359 SplitString(CollapseWhitespace(line, false), ' ', &columns); |
| 360 if (columns.size() != 4) |
| 361 return false; |
| 362 |
| 363 FtpDirectoryListingEntry entry; |
| 364 entry.name = columns[3]; |
| 365 |
| 366 if (EqualsASCII(columns[2], "<DIR>")) { |
| 367 entry.type = FtpDirectoryListingEntry::DIRECTORY; |
| 368 entry.size = -1; |
| 369 } else { |
| 370 entry.type = FtpDirectoryListingEntry::FILE; |
| 371 if (!StringToInt64(columns[2], &entry.size)) |
| 372 return false; |
| 373 if (entry.size < 0) |
| 374 return false; |
| 375 } |
| 376 |
| 377 if (!WindowsDateListingToTime(columns, &entry.last_modified)) |
| 378 return false; |
| 379 |
| 380 entries_.push(entry); |
| 381 return true; |
| 382 } |
| 383 |
| 384 bool FtpWindowsDirectoryListingParser::EntryAvailable() const { |
| 385 return !entries_.empty(); |
| 386 } |
| 387 |
| 388 FtpDirectoryListingEntry FtpWindowsDirectoryListingParser::PopEntry() { |
| 389 FtpDirectoryListingEntry entry = entries_.front(); |
| 390 entries_.pop(); |
| 391 return entry; |
| 392 } |
| 393 |
| 306 FtpVmsDirectoryListingParser::FtpVmsDirectoryListingParser() | 394 FtpVmsDirectoryListingParser::FtpVmsDirectoryListingParser() |
| 307 : state_(STATE_INITIAL), | 395 : state_(STATE_INITIAL), |
| 308 last_is_directory_(false) { | 396 last_is_directory_(false) { |
| 309 } | 397 } |
| 310 | 398 |
| 311 bool FtpVmsDirectoryListingParser::ConsumeLine(const string16& line) { | 399 bool FtpVmsDirectoryListingParser::ConsumeLine(const string16& line) { |
| 312 switch (state_) { | 400 switch (state_) { |
| 313 case STATE_INITIAL: | 401 case STATE_INITIAL: |
| 314 DCHECK(last_filename_.empty()); | 402 DCHECK(last_filename_.empty()); |
| 315 if (line.empty()) | 403 if (line.empty()) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 if (entry.type != FtpDirectoryListingEntry::FILE) | 513 if (entry.type != FtpDirectoryListingEntry::FILE) |
| 426 entry.size = -1; | 514 entry.size = -1; |
| 427 if (!VmsDateListingToTime(columns, &entry.last_modified)) | 515 if (!VmsDateListingToTime(columns, &entry.last_modified)) |
| 428 return false; | 516 return false; |
| 429 | 517 |
| 430 entries_.push(entry); | 518 entries_.push(entry); |
| 431 return true; | 519 return true; |
| 432 } | 520 } |
| 433 | 521 |
| 434 } // namespace net | 522 } // namespace net |
| OLD | NEW |