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

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

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