| Index: net/ftp/ftp_directory_listing_parsers.cc
|
| diff --git a/net/ftp/ftp_directory_listing_parsers.cc b/net/ftp/ftp_directory_listing_parsers.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c1a7f76028d7a383e10b34e4f536d793608ae12a
|
| --- /dev/null
|
| +++ b/net/ftp/ftp_directory_listing_parsers.cc
|
| @@ -0,0 +1,153 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
|
| +// source code is governed by a BSD-style license that can be found in the
|
| +// LICENSE file.
|
| +
|
| +#include "net/ftp/ftp_directory_listing_parsers.h"
|
| +
|
| +#include "base/string_util.h"
|
| +
|
| +namespace {
|
| +
|
| +bool LooksLikeUnixPermission(const string16& text) {
|
| + if (text.length() != 3)
|
| + return false;
|
| +
|
| + return ((text[0] == 'r' || text[0] == '-') &&
|
| + (text[1] == 'w' || text[1] == '-') &&
|
| + (text[2] == 'x' || text[2] == 's' || text[2] == 'S' ||
|
| + text[2] == '-'));
|
| +}
|
| +
|
| +bool LooksLikeUnixPermissionsListing(const string16& text) {
|
| + if (text.length() != 10)
|
| + return false;
|
| +
|
| + if (text[0] != 'b' && text[0] != 'c' && text[0] != 'd' &&
|
| + text[0] != 'l' && text[0] != 'p' && text[0] != 's' &&
|
| + text[0] != '-')
|
| + return false;
|
| +
|
| + return (LooksLikeUnixPermission(text.substr(1, 3)) &&
|
| + LooksLikeUnixPermission(text.substr(4, 3)) &&
|
| + LooksLikeUnixPermission(text.substr(7, 3)));
|
| +}
|
| +
|
| +bool IsStringNonNegativeNumber(const string16& text) {
|
| + int number;
|
| + if (!StringToInt(text, &number))
|
| + return false;
|
| +
|
| + return number >= 0;
|
| +}
|
| +
|
| +bool ThreeLetterMonthToNumber(const string16& text, int* number) {
|
| + const static char* months[] = { "jan", "feb", "mar", "apr", "may", "jun",
|
| + "jul", "aug", "sep", "oct", "nov", "dec" };
|
| +
|
| + for (size_t i = 0; i < arraysize(months); i++) {
|
| + if (LowerCaseEqualsASCII(text, months[i])) {
|
| + *number = i + 1;
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +bool UnixDateListingToTime(const std::vector<string16>& columns,
|
| + base::Time* time) {
|
| + DCHECK_EQ(9U, columns.size());
|
| +
|
| + base::Time::Exploded time_exploded = { 0 };
|
| +
|
| + if (!ThreeLetterMonthToNumber(columns[5], &time_exploded.month))
|
| + return false;
|
| +
|
| + if (!StringToInt(columns[6], &time_exploded.day_of_month))
|
| + return false;
|
| +
|
| + if (!StringToInt(columns[7], &time_exploded.year)) {
|
| + // Maybe it's time. Does it look like time (MM:HH)?
|
| + if (columns[7].length() != 5 || columns[7][2] != ':')
|
| + return false;
|
| +
|
| + if (!StringToInt(columns[7].substr(0, 2), &time_exploded.hour))
|
| + return false;
|
| +
|
| + if (!StringToInt(columns[7].substr(3, 2), &time_exploded.minute))
|
| + return false;
|
| +
|
| + // Use current year.
|
| + base::Time::Exploded now_exploded;
|
| + base::Time::Now().LocalExplode(&now_exploded);
|
| + time_exploded.year = now_exploded.year;
|
| + }
|
| +
|
| + // We don't know the time zone of the server, so just use local time.
|
| + *time = base::Time::FromLocalExploded(time_exploded);
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace net {
|
| +
|
| +FtpDirectoryListingParser::~FtpDirectoryListingParser() {
|
| +}
|
| +
|
| +FtpLsDirectoryListingParser::FtpLsDirectoryListingParser() {
|
| +}
|
| +
|
| +bool FtpLsDirectoryListingParser::ConsumeLine(const string16& line) {
|
| + std::vector<string16> columns;
|
| + SplitString(CollapseWhitespace(line, false), ' ', &columns);
|
| + if (columns.size() == 11) {
|
| + // Check if it is a symlink.
|
| + if (columns[9] != ASCIIToUTF16("->"))
|
| + return false;
|
| +
|
| + // Drop the symlink target from columns, we don't use it.
|
| + columns.resize(9);
|
| + }
|
| +
|
| + if (columns.size() != 9)
|
| + return false;
|
| +
|
| + if (!LooksLikeUnixPermissionsListing(columns[0]))
|
| + return false;
|
| +
|
| + FtpDirectoryListingEntry entry;
|
| + if (columns[0][0] == 'l') {
|
| + entry.type = FtpDirectoryListingEntry::SYMLINK;
|
| + } else if (columns[0][0] == 'd') {
|
| + entry.type = FtpDirectoryListingEntry::DIRECTORY;
|
| + } else {
|
| + entry.type = FtpDirectoryListingEntry::FILE;
|
| + }
|
| +
|
| + if (!IsStringNonNegativeNumber(columns[1]))
|
| + return false;
|
| +
|
| + if (!IsStringNonNegativeNumber(columns[4]))
|
| + return false;
|
| +
|
| + if (!UnixDateListingToTime(columns, &entry.last_modified))
|
| + return false;
|
| +
|
| + entry.name = columns[8];
|
| +
|
| + entries_.push(entry);
|
| + return true;
|
| +}
|
| +
|
| +bool FtpLsDirectoryListingParser::EntryAvailable() const {
|
| + return !entries_.empty();
|
| +}
|
| +
|
| +FtpDirectoryListingEntry FtpLsDirectoryListingParser::PopEntry() {
|
| + FtpDirectoryListingEntry entry = entries_.front();
|
| + entries_.pop();
|
| + return entry;
|
| +}
|
| +
|
| +} // namespace net
|
|
|