Index: net/ftp/ftp_util.cc |
diff --git a/net/ftp/ftp_util.cc b/net/ftp/ftp_util.cc |
deleted file mode 100644 |
index b5580664736bc1aa613dc680c569e67f6a789270..0000000000000000000000000000000000000000 |
--- a/net/ftp/ftp_util.cc |
+++ /dev/null |
@@ -1,373 +0,0 @@ |
-// Copyright (c) 2011 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_util.h" |
- |
-#include <map> |
-#include <vector> |
- |
-#include "base/i18n/case_conversion.h" |
-#include "base/i18n/char_iterator.h" |
-#include "base/logging.h" |
-#include "base/memory/singleton.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/string_piece.h" |
-#include "base/strings/string_split.h" |
-#include "base/strings/string_tokenizer.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/time/time.h" |
-#include "third_party/icu/source/common/unicode/uchar.h" |
-#include "third_party/icu/source/i18n/unicode/datefmt.h" |
-#include "third_party/icu/source/i18n/unicode/dtfmtsym.h" |
- |
-using base::ASCIIToUTF16; |
-using base::StringPiece16; |
- |
-// For examples of Unix<->VMS path conversions, see the unit test file. On VMS |
-// a path looks differently depending on whether it's a file or directory. |
- |
-namespace net { |
- |
-// static |
-std::string FtpUtil::UnixFilePathToVMS(const std::string& unix_path) { |
- if (unix_path.empty()) |
- return std::string(); |
- |
- base::StringTokenizer tokenizer(unix_path, "/"); |
- std::vector<std::string> tokens; |
- while (tokenizer.GetNext()) |
- tokens.push_back(tokenizer.token()); |
- |
- if (unix_path[0] == '/') { |
- // It's an absolute path. |
- |
- if (tokens.empty()) { |
- DCHECK_EQ(1U, unix_path.length()); |
- return "[]"; |
- } |
- |
- if (tokens.size() == 1) |
- return unix_path.substr(1); // Drop the leading slash. |
- |
- std::string result(tokens[0] + ":["); |
- if (tokens.size() == 2) { |
- // Don't ask why, it just works that way on VMS. |
- result.append("000000"); |
- } else { |
- result.append(tokens[1]); |
- for (size_t i = 2; i < tokens.size() - 1; i++) |
- result.append("." + tokens[i]); |
- } |
- result.append("]" + tokens[tokens.size() - 1]); |
- return result; |
- } |
- |
- if (tokens.size() == 1) |
- return unix_path; |
- |
- std::string result("["); |
- for (size_t i = 0; i < tokens.size() - 1; i++) |
- result.append("." + tokens[i]); |
- result.append("]" + tokens[tokens.size() - 1]); |
- return result; |
-} |
- |
-// static |
-std::string FtpUtil::UnixDirectoryPathToVMS(const std::string& unix_path) { |
- if (unix_path.empty()) |
- return std::string(); |
- |
- std::string path(unix_path); |
- |
- if (path[path.length() - 1] != '/') |
- path.append("/"); |
- |
- // Reuse logic from UnixFilePathToVMS by appending a fake file name to the |
- // real path and removing it after conversion. |
- path.append("x"); |
- path = UnixFilePathToVMS(path); |
- return path.substr(0, path.length() - 1); |
-} |
- |
-// static |
-std::string FtpUtil::VMSPathToUnix(const std::string& vms_path) { |
- if (vms_path.empty()) |
- return "."; |
- |
- if (vms_path[0] == '/') { |
- // This is not really a VMS path. Most likely the server is emulating UNIX. |
- // Return path as-is. |
- return vms_path; |
- } |
- |
- if (vms_path == "[]") |
- return "/"; |
- |
- std::string result(vms_path); |
- if (vms_path[0] == '[') { |
- // It's a relative path. |
- ReplaceFirstSubstringAfterOffset(&result, 0, "[.", std::string()); |
- } else { |
- // It's an absolute path. |
- result.insert(0, "/"); |
- ReplaceSubstringsAfterOffset(&result, 0, ":[000000]", "/"); |
- ReplaceSubstringsAfterOffset(&result, 0, ":[", "/"); |
- } |
- std::replace(result.begin(), result.end(), '.', '/'); |
- std::replace(result.begin(), result.end(), ']', '/'); |
- |
- // Make sure the result doesn't end with a slash. |
- if (result.length() && result[result.length() - 1] == '/') |
- result = result.substr(0, result.length() - 1); |
- |
- return result; |
-} |
- |
-namespace { |
- |
-// Lazy-initialized map of abbreviated month names. |
-class AbbreviatedMonthsMap { |
- public: |
- static AbbreviatedMonthsMap* GetInstance() { |
- return Singleton<AbbreviatedMonthsMap>::get(); |
- } |
- |
- // Converts abbreviated month name |text| to its number (in range 1-12). |
- // On success returns true and puts the number in |number|. |
- bool GetMonthNumber(const base::string16& text, int* number) { |
- // Ignore the case of the month names. The simplest way to handle that |
- // is to make everything lowercase. |
- base::string16 text_lower(base::i18n::ToLower(text)); |
- |
- if (map_.find(text_lower) == map_.end()) |
- return false; |
- |
- *number = map_[text_lower]; |
- return true; |
- } |
- |
- private: |
- friend struct DefaultSingletonTraits<AbbreviatedMonthsMap>; |
- |
- // Constructor, initializes the map based on ICU data. It is much faster |
- // to do that just once. |
- AbbreviatedMonthsMap() { |
- int32_t locales_count; |
- const icu::Locale* locales = |
- icu::DateFormat::getAvailableLocales(locales_count); |
- |
- for (int32_t locale = 0; locale < locales_count; locale++) { |
- UErrorCode status(U_ZERO_ERROR); |
- |
- icu::DateFormatSymbols format_symbols(locales[locale], status); |
- |
- // If we cannot get format symbols for some locale, it's not a fatal |
- // error. Just try another one. |
- if (U_FAILURE(status)) |
- continue; |
- |
- int32_t months_count; |
- const icu::UnicodeString* months = |
- format_symbols.getShortMonths(months_count); |
- |
- for (int32_t month = 0; month < months_count; month++) { |
- base::string16 month_name(months[month].getBuffer(), |
- static_cast<size_t>(months[month].length())); |
- |
- // Ignore the case of the month names. The simplest way to handle that |
- // is to make everything lowercase. |
- month_name = base::i18n::ToLower(month_name); |
- |
- map_[month_name] = month + 1; |
- |
- // Sometimes ICU returns longer strings, but in FTP listings a shorter |
- // abbreviation is used (for example for the Russian locale). Make sure |
- // we always have a map entry for a three-letter abbreviation. |
- map_[month_name.substr(0, 3)] = month + 1; |
- } |
- } |
- |
- // Fail loudly if the data returned by ICU is obviously incomplete. |
- // This is intended to catch cases like http://crbug.com/177428 |
- // much earlier. Note that the issue above turned out to be non-trivial |
- // to reproduce - crash data is much better indicator of a problem |
- // than incomplete bug reports. |
- CHECK_EQ(1, map_[ASCIIToUTF16("jan")]); |
- CHECK_EQ(2, map_[ASCIIToUTF16("feb")]); |
- CHECK_EQ(3, map_[ASCIIToUTF16("mar")]); |
- CHECK_EQ(4, map_[ASCIIToUTF16("apr")]); |
- CHECK_EQ(5, map_[ASCIIToUTF16("may")]); |
- CHECK_EQ(6, map_[ASCIIToUTF16("jun")]); |
- CHECK_EQ(7, map_[ASCIIToUTF16("jul")]); |
- CHECK_EQ(8, map_[ASCIIToUTF16("aug")]); |
- CHECK_EQ(9, map_[ASCIIToUTF16("sep")]); |
- CHECK_EQ(10, map_[ASCIIToUTF16("oct")]); |
- CHECK_EQ(11, map_[ASCIIToUTF16("nov")]); |
- CHECK_EQ(12, map_[ASCIIToUTF16("dec")]); |
- } |
- |
- // Maps lowercase month names to numbers in range 1-12. |
- std::map<base::string16, int> map_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AbbreviatedMonthsMap); |
-}; |
- |
-} // namespace |
- |
-// static |
-bool FtpUtil::AbbreviatedMonthToNumber(const base::string16& text, |
- int* number) { |
- return AbbreviatedMonthsMap::GetInstance()->GetMonthNumber(text, number); |
-} |
- |
-// static |
-bool FtpUtil::LsDateListingToTime(const base::string16& month, |
- const base::string16& day, |
- const base::string16& rest, |
- const base::Time& current_time, |
- base::Time* result) { |
- base::Time::Exploded time_exploded = { 0 }; |
- |
- if (!AbbreviatedMonthToNumber(month, &time_exploded.month)) { |
- // Work around garbage sent by some servers in the same column |
- // as the month. Take just last 3 characters of the string. |
- if (month.length() < 3 || |
- !AbbreviatedMonthToNumber(month.substr(month.length() - 3), |
- &time_exploded.month)) { |
- return false; |
- } |
- } |
- |
- if (!base::StringToInt(day, &time_exploded.day_of_month)) |
- return false; |
- if (time_exploded.day_of_month > 31) |
- return false; |
- |
- if (!base::StringToInt(rest, &time_exploded.year)) { |
- // Maybe it's time. Does it look like time? Note that it can be any of |
- // "HH:MM", "H:MM", "HH:M" or maybe even "H:M". |
- if (rest.length() > 5) |
- return false; |
- |
- size_t colon_pos = rest.find(':'); |
- if (colon_pos == base::string16::npos) |
- return false; |
- if (colon_pos > 2) |
- return false; |
- |
- if (!base::StringToInt( |
- StringPiece16(rest.begin(), rest.begin() + colon_pos), |
- &time_exploded.hour)) { |
- return false; |
- } |
- if (!base::StringToInt( |
- StringPiece16(rest.begin() + colon_pos + 1, rest.end()), |
- &time_exploded.minute)) { |
- return false; |
- } |
- |
- // Guess the year. |
- base::Time::Exploded current_exploded; |
- current_time.LocalExplode(¤t_exploded); |
- |
- // If it's not possible for the parsed date to be in the current year, |
- // use the previous year. |
- if (time_exploded.month > current_exploded.month || |
- (time_exploded.month == current_exploded.month && |
- time_exploded.day_of_month > current_exploded.day_of_month)) { |
- time_exploded.year = current_exploded.year - 1; |
- } else { |
- time_exploded.year = current_exploded.year; |
- } |
- } |
- |
- // We don't know the time zone of the listing, so just use local time. |
- *result = base::Time::FromLocalExploded(time_exploded); |
- return true; |
-} |
- |
-// static |
-bool FtpUtil::WindowsDateListingToTime(const base::string16& date, |
- const base::string16& time, |
- base::Time* result) { |
- base::Time::Exploded time_exploded = { 0 }; |
- |
- // Date should be in format MM-DD-YY[YY]. |
- std::vector<base::string16> date_parts; |
- base::SplitString(date, '-', &date_parts); |
- if (date_parts.size() != 3) |
- return false; |
- if (!base::StringToInt(date_parts[0], &time_exploded.month)) |
- return false; |
- if (!base::StringToInt(date_parts[1], &time_exploded.day_of_month)) |
- return false; |
- if (!base::StringToInt(date_parts[2], &time_exploded.year)) |
- return false; |
- if (time_exploded.year < 0) |
- return false; |
- // If year has only two digits then assume that 00-79 is 2000-2079, |
- // and 80-99 is 1980-1999. |
- if (time_exploded.year < 80) |
- time_exploded.year += 2000; |
- else if (time_exploded.year < 100) |
- time_exploded.year += 1900; |
- |
- // Time should be in format HH:MM[(AM|PM)] |
- if (time.length() < 5) |
- return false; |
- |
- std::vector<base::string16> time_parts; |
- base::SplitString(time.substr(0, 5), ':', &time_parts); |
- if (time_parts.size() != 2) |
- return false; |
- if (!base::StringToInt(time_parts[0], &time_exploded.hour)) |
- return false; |
- if (!base::StringToInt(time_parts[1], &time_exploded.minute)) |
- return false; |
- if (!time_exploded.HasValidValues()) |
- return false; |
- |
- if (time.length() > 5) { |
- if (time.length() != 7) |
- return false; |
- base::string16 am_or_pm(time.substr(5, 2)); |
- if (EqualsASCII(am_or_pm, "PM")) { |
- if (time_exploded.hour < 12) |
- time_exploded.hour += 12; |
- } else if (EqualsASCII(am_or_pm, "AM")) { |
- if (time_exploded.hour == 12) |
- time_exploded.hour = 0; |
- } else { |
- return false; |
- } |
- } |
- |
- // We don't know the time zone of the server, so just use local time. |
- *result = base::Time::FromLocalExploded(time_exploded); |
- return true; |
-} |
- |
-// static |
-base::string16 FtpUtil::GetStringPartAfterColumns(const base::string16& text, |
- int columns) { |
- base::i18n::UTF16CharIterator iter(&text); |
- |
- // TODO(jshin): Is u_isspace the right function to use here? |
- for (int i = 0; i < columns; i++) { |
- // Skip the leading whitespace. |
- while (!iter.end() && u_isspace(iter.get())) |
- iter.Advance(); |
- |
- // Skip the actual text of i-th column. |
- while (!iter.end() && !u_isspace(iter.get())) |
- iter.Advance(); |
- } |
- |
- base::string16 result(text.substr(iter.array_pos())); |
- base::TrimWhitespace(result, base::TRIM_ALL, &result); |
- return result; |
-} |
- |
-} // namespace |