Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(703)

Unified Diff: net/ftp/ftp_directory_listing_parsers.cc

Issue 244008: Beginnings of our own FTP LIST parsing code. (Closed)
Patch Set: test even more (slightly) Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/ftp/ftp_directory_listing_parsers.h ('k') | net/ftp/ftp_directory_listing_parsers_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « net/ftp/ftp_directory_listing_parsers.h ('k') | net/ftp/ftp_directory_listing_parsers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698