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

Side by Side Diff: net/ftp/ftp_directory_listing_parser_mlsd.cc

Issue 5669001: FTP: fix compatibility problems with MLSD by removing MLSD support. (Closed)
Patch Set: Created 10 years 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/ftp/ftp_directory_listing_parser_mlsd.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "base/stl_util-inl.h"
11 #include "base/string_number_conversions.h"
12 #include "base/string_split.h"
13 #include "base/string_util.h"
14 #include "base/utf_string_conversions.h"
15
16 // You can read the specification of the MLSD format at
17 // http://tools.ietf.org/html/rfc3659#page-23.
18
19 namespace {
20
21 // The MLSD date listing is specified at
22 // http://tools.ietf.org/html/rfc3659#page-6.
23 bool MlsdDateListingToTime(const string16& text, base::Time* time) {
24 base::Time::Exploded time_exploded = { 0 };
25
26 // We will only test 12 characters, but RFC-3659 requires 14 (we ignore the
27 // last two digits, which contain the number of seconds).
28 if (text.length() < 14)
29 return false;
30
31 if (!base::StringToInt(text.begin(), text.begin() + 4, &time_exploded.year))
32 return false;
33 if (!base::StringToInt(text.begin() + 4,
34 text.begin() + 6,
35 &time_exploded.month))
36 return false;
37 if (!base::StringToInt(text.begin() + 6,
38 text.begin() + 8,
39 &time_exploded.day_of_month))
40 return false;
41 if (!base::StringToInt(text.begin() + 8,
42 text.begin() + 10,
43 &time_exploded.hour))
44 return false;
45 if (!base::StringToInt(text.begin() + 10,
46 text.begin() + 12,
47 &time_exploded.minute))
48 return false;
49
50 // We don't know the time zone of the server, so just use local time.
51 *time = base::Time::FromLocalExploded(time_exploded);
52 return true;
53 }
54
55 } // namespace
56
57 namespace net {
58
59 FtpDirectoryListingParserMlsd::FtpDirectoryListingParserMlsd() {}
60
61 FtpDirectoryListingParserMlsd::~FtpDirectoryListingParserMlsd() {}
62
63 bool FtpDirectoryListingParserMlsd::ConsumeLine(const string16& line) {
64 // The first space indicates where the filename begins.
65 string16::size_type first_space_pos = line.find(' ');
66 if (first_space_pos == string16::npos || first_space_pos < 1)
67 return false;
68
69 string16 facts_string = line.substr(0, first_space_pos - 1);
70 string16 filename = line.substr(first_space_pos + 1);
71 std::vector<string16> facts_split;
72 base::SplitString(facts_string, ';', &facts_split);
73
74 const char* keys[] = {
75 "modify",
76 "size",
77 "type",
78 };
79
80 std::map<std::string, string16> facts;
81 for (std::vector<string16>::const_iterator i = facts_split.begin();
82 i != facts_split.end(); ++i) {
83 string16::size_type equal_sign_pos = i->find('=');
84 if (equal_sign_pos == string16::npos)
85 return false;
86 string16 key = i->substr(0, equal_sign_pos);
87 string16 value = i->substr(equal_sign_pos + 1);
88
89 // If we're interested in a key, record its value. Note that we don't detect
90 // a case when the server is sending duplicate keys. We're not validating
91 // the input, just parsing it.
92 for (size_t j = 0; j < arraysize(keys); j++)
93 if (LowerCaseEqualsASCII(key, keys[j]))
94 facts[keys[j]] = value;
95 }
96 if (!ContainsKey(facts, "type"))
97 return false;
98
99 FtpDirectoryListingEntry entry;
100 entry.name = filename;
101
102 if (LowerCaseEqualsASCII(facts["type"], "dir")) {
103 entry.type = FtpDirectoryListingEntry::DIRECTORY;
104 entry.size = -1;
105 } else if (LowerCaseEqualsASCII(facts["type"], "file")) {
106 entry.type = FtpDirectoryListingEntry::FILE;
107 if (!ContainsKey(facts, "size"))
108 return false;
109 if (!base::StringToInt64(facts["size"], &entry.size))
110 return false;
111 } else {
112 // Ignore other types of entries. They are either not interesting for us
113 // (cdir, pdir), or not regular files (OS-specific types). There is no
114 // specific type for symlink. Symlinks get a type of their target.
115 return true;
116 }
117
118 if (!ContainsKey(facts, "modify"))
119 return false;
120 if (!MlsdDateListingToTime(facts["modify"], &entry.last_modified))
121 return false;
122
123 entries_.push(entry);
124 return true;
125 }
126
127 bool FtpDirectoryListingParserMlsd::OnEndOfInput() {
128 return true;
129 }
130
131 bool FtpDirectoryListingParserMlsd::EntryAvailable() const {
132 return !entries_.empty();
133 }
134
135 FtpDirectoryListingEntry FtpDirectoryListingParserMlsd::PopEntry() {
136 DCHECK(EntryAvailable());
137 FtpDirectoryListingEntry entry = entries_.front();
138 entries_.pop();
139 return entry;
140 }
141
142 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698