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

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

Issue 460139: Compatibility improvements for "ls -l" FTP LIST response format. (Closed)
Patch Set: y2038 Created 11 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
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_parser_ls.h" 5 #include "net/ftp/ftp_directory_listing_parser_ls.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "net/ftp/ftp_util.h" 10 #include "net/ftp/ftp_util.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 return result; 57 return result;
58 } 58 }
59 59
60 bool DetectColumnOffset(const std::vector<string16>& columns, int* offset) { 60 bool DetectColumnOffset(const std::vector<string16>& columns, int* offset) {
61 base::Time time; 61 base::Time time;
62 62
63 if (columns.size() >= 8 && 63 if (columns.size() >= 8 &&
64 net::FtpUtil::LsDateListingToTime(columns[5], columns[6], columns[7], 64 net::FtpUtil::LsDateListingToTime(columns[5], columns[6], columns[7],
65 &time)) { 65 &time)) {
66 // Standard listing, exactly like ls -l. 66 // Standard listing, exactly like ls -l.
67 *offset = 1; 67 *offset = 2;
68 return true; 68 return true;
69 } 69 }
70 70
71 if (columns.size() >= 7 && 71 if (columns.size() >= 7 &&
72 net::FtpUtil::LsDateListingToTime(columns[4], columns[5], columns[6], 72 net::FtpUtil::LsDateListingToTime(columns[4], columns[5], columns[6],
73 &time)) { 73 &time)) {
74 // wu-ftpd listing, no "number of links" column. 74 // wu-ftpd listing, no "number of links" column.
75 *offset = 1;
76 return true;
77 }
78
79 if (columns.size() >= 6 &&
80 net::FtpUtil::LsDateListingToTime(columns[3], columns[4], columns[5],
81 &time)) {
82 // Xplain FTP Server listing for folders, like this:
83 // drwxr-xr-x folder 0 Jul 17 2006 online
75 *offset = 0; 84 *offset = 0;
76 return true; 85 return true;
77 } 86 }
78 87
79 // Unrecognized listing style. 88 // Unrecognized listing style.
80 return false; 89 return false;
81 } 90 }
82 91
83 } // namespace 92 } // namespace
84 93
85 namespace net { 94 namespace net {
86 95
87 FtpDirectoryListingParserLs::FtpDirectoryListingParserLs() 96 FtpDirectoryListingParserLs::FtpDirectoryListingParserLs()
88 : received_nonempty_line_(false), 97 : received_nonempty_line_(false),
89 received_total_line_(false), 98 received_total_line_(false) {
90 column_offset_(-1) {
91 } 99 }
92 100
93 bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) { 101 bool FtpDirectoryListingParserLs::ConsumeLine(const string16& line) {
94 std::vector<string16> columns;
95 SplitString(CollapseWhitespace(line, false), ' ', &columns);
96
97 if (line.empty() && !received_nonempty_line_) { 102 if (line.empty() && !received_nonempty_line_) {
98 // Allow empty lines only at the beginning of the listing. For example VMS 103 // Allow empty lines only at the beginning of the listing. For example VMS
99 // systems in Unix emulation mode add an empty line before the first listing 104 // systems in Unix emulation mode add an empty line before the first listing
100 // entry. 105 // entry.
101 return true; 106 return true;
102 } 107 }
108 received_nonempty_line_ = true;
109
110 std::vector<string16> columns;
111 SplitString(CollapseWhitespace(line, false), ' ', &columns);
112
103 // Some FTP servers put a "total n" line at the beginning of the listing 113 // Some FTP servers put a "total n" line at the beginning of the listing
104 // (n is an integer). Allow such a line, but only once, and only if it's 114 // (n is an integer). Allow such a line, but only once, and only if it's
105 // the first non-empty line. Do not match the word exactly, because it may be 115 // the first non-empty line. Do not match the word exactly, because it may be
106 // in different languages (at least English and German have been seen in the 116 // in different languages (at least English and German have been seen in the
107 // field). 117 // field).
108 if (columns.size() == 2 && !received_total_line_) { 118 if (columns.size() == 2 && !received_total_line_) {
109 received_total_line_ = true; 119 received_total_line_ = true;
110 120
111 int total_number; 121 int total_number;
112 if (!StringToInt(columns[1], &total_number)) 122 if (!StringToInt(columns[1], &total_number))
113 return false; 123 return false;
114 if (total_number < 0) 124 if (total_number < 0)
115 return false; 125 return false;
116 126
117 return true; 127 return true;
118 } 128 }
119 if (!received_nonempty_line_ && !DetectColumnOffset(columns, &column_offset_)) 129
130 int column_offset;
131 if (!DetectColumnOffset(columns, &column_offset))
120 return false; 132 return false;
121 received_nonempty_line_ = true;
122 133
123 // We may receive file names containing spaces, which can make the number of 134 // We may receive file names containing spaces, which can make the number of
124 // columns arbitrarily large. We will handle that later. For now just make 135 // columns arbitrarily large. We will handle that later. For now just make
125 // sure we have all the columns that should normally be there. 136 // sure we have all the columns that should normally be there.
126 if (columns.size() < 8U + column_offset_) 137 if (columns.size() < 7U + column_offset)
127 return false; 138 return false;
128 139
129 if (!LooksLikeUnixPermissionsListing(columns[0])) 140 if (!LooksLikeUnixPermissionsListing(columns[0]))
130 return false; 141 return false;
131 142
132 FtpDirectoryListingEntry entry; 143 FtpDirectoryListingEntry entry;
133 if (columns[0][0] == 'l') { 144 if (columns[0][0] == 'l') {
134 entry.type = FtpDirectoryListingEntry::SYMLINK; 145 entry.type = FtpDirectoryListingEntry::SYMLINK;
135 } else if (columns[0][0] == 'd') { 146 } else if (columns[0][0] == 'd') {
136 entry.type = FtpDirectoryListingEntry::DIRECTORY; 147 entry.type = FtpDirectoryListingEntry::DIRECTORY;
137 } else { 148 } else {
138 entry.type = FtpDirectoryListingEntry::FILE; 149 entry.type = FtpDirectoryListingEntry::FILE;
139 } 150 }
140 151
141 if (!StringToInt64(columns[3 + column_offset_], &entry.size)) 152 if (!StringToInt64(columns[2 + column_offset], &entry.size))
142 return false; 153 return false;
143 if (entry.size < 0) 154 if (entry.size < 0)
144 return false; 155 return false;
145 if (entry.type != FtpDirectoryListingEntry::FILE) 156 if (entry.type != FtpDirectoryListingEntry::FILE)
146 entry.size = -1; 157 entry.size = -1;
147 158
148 if (!FtpUtil::LsDateListingToTime(columns[4 + column_offset_], 159 if (!FtpUtil::LsDateListingToTime(columns[3 + column_offset],
149 columns[5 + column_offset_], 160 columns[4 + column_offset],
150 columns[6 + column_offset_], 161 columns[5 + column_offset],
151 &entry.last_modified)) { 162 &entry.last_modified)) {
152 return false; 163 return false;
153 } 164 }
154 165
155 entry.name = GetStringPartAfterColumns(line, 7 + column_offset_); 166 entry.name = GetStringPartAfterColumns(line, 6 + column_offset);
156 if (entry.type == FtpDirectoryListingEntry::SYMLINK) { 167 if (entry.type == FtpDirectoryListingEntry::SYMLINK) {
157 string16::size_type pos = entry.name.rfind(ASCIIToUTF16(" -> ")); 168 string16::size_type pos = entry.name.rfind(ASCIIToUTF16(" -> "));
158 if (pos == string16::npos) 169 if (pos == string16::npos)
159 return false; 170 return false;
160 entry.name = entry.name.substr(0, pos); 171 entry.name = entry.name.substr(0, pos);
161 } 172 }
162 173
163 entries_.push(entry); 174 entries_.push(entry);
164 return true; 175 return true;
165 } 176 }
166 177
167 bool FtpDirectoryListingParserLs::OnEndOfInput() { 178 bool FtpDirectoryListingParserLs::OnEndOfInput() {
168 return true; 179 return true;
169 } 180 }
170 181
171 bool FtpDirectoryListingParserLs::EntryAvailable() const { 182 bool FtpDirectoryListingParserLs::EntryAvailable() const {
172 return !entries_.empty(); 183 return !entries_.empty();
173 } 184 }
174 185
175 FtpDirectoryListingEntry FtpDirectoryListingParserLs::PopEntry() { 186 FtpDirectoryListingEntry FtpDirectoryListingParserLs::PopEntry() {
176 FtpDirectoryListingEntry entry = entries_.front(); 187 FtpDirectoryListingEntry entry = entries_.front();
177 entries_.pop(); 188 entries_.pop();
178 return entry; 189 return entry;
179 } 190 }
180 191
181 } // namespace net 192 } // namespace net
OLDNEW
« no previous file with comments | « net/ftp/ftp_directory_listing_parser_ls.h ('k') | net/ftp/ftp_directory_listing_parser_ls_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698