| OLD | NEW |
| 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 Loading... |
| 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 |
| OLD | NEW |