summaryrefslogtreecommitdiffstats
path: root/net/url_request
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-22 21:05:47 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-22 21:05:47 +0000
commit64d50ed649d61c5b84b09369b091018f70547bf8 (patch)
tree32f25e3f4d6721d68f6ce553bc51172a218bb071 /net/url_request
parentdbf5e6c9053bf8e4c5fb08a1ca3005636380b5bb (diff)
downloadchromium_src-64d50ed649d61c5b84b09369b091018f70547bf8.zip
chromium_src-64d50ed649d61c5b84b09369b091018f70547bf8.tar.gz
chromium_src-64d50ed649d61c5b84b09369b091018f70547bf8.tar.bz2
Move FTP LIST parsing code to the renderer process.
TEST=none BUG=none Review URL: http://codereview.chromium.org/210027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26860 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/url_request')
-rw-r--r--net/url_request/url_request_new_ftp_job.cc241
-rw-r--r--net/url_request/url_request_new_ftp_job.h11
2 files changed, 12 insertions, 240 deletions
diff --git a/net/url_request/url_request_new_ftp_job.cc b/net/url_request/url_request_new_ftp_job.cc
index 83d1a9c..c4c3782 100644
--- a/net/url_request/url_request_new_ftp_job.cc
+++ b/net/url_request/url_request_new_ftp_job.cc
@@ -5,65 +5,18 @@
#include "net/url_request/url_request_new_ftp_job.h"
#include "base/compiler_specific.h"
-#include "base/file_version_info.h"
#include "base/message_loop.h"
-#include "base/sys_string_conversions.h"
#include "net/base/auth.h"
-#include "net/base/escape.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/ftp/ftp_response_info.h"
-#include "net/ftp/ftp_server_type_histograms.h"
#include "net/ftp/ftp_transaction_factory.h"
-#include "net/third_party/parseftp/ParseFTPList.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_error_job.h"
-#include "unicode/ucsdet.h"
-
-namespace {
-
-// A very simple-minded character encoding detection.
-// TODO(jungshik): We can apply more heuristics here (e.g. using various hints
-// like TLD, the UI language/default encoding of a client, etc). In that case,
-// this should be pulled out of here and moved somewhere in base because there
-// can be other use cases.
-std::string DetectEncoding(const char* input, size_t len) {
- if (IsStringASCII(std::string(input, len)))
- return std::string();
- UErrorCode status = U_ZERO_ERROR;
- UCharsetDetector* detector = ucsdet_open(&status);
- ucsdet_setText(detector, input, static_cast<int32_t>(len), &status);
- const UCharsetMatch* match = ucsdet_detect(detector, &status);
- const char* encoding = ucsdet_getName(match, &status);
- // Should we check the quality of the match? A rather arbitrary number is
- // assigned by ICU and it's hard to come up with a lower limit.
- if (U_FAILURE(status))
- return std::string();
- return encoding;
-}
-
-string16 RawByteSequenceToFilename(const char* raw_filename,
- const std::string& encoding) {
- if (encoding.empty())
- return ASCIIToUTF16(raw_filename);
-
- // Try the detected encoding before falling back to the native codepage.
- // Using the native codepage does not make much sense, but we don't have
- // much else to resort to.
- string16 filename;
- if (!CodepageToUTF16(raw_filename, encoding.c_str(),
- OnStringUtilConversionError::SUBSTITUTE, &filename))
- filename = WideToUTF16Hack(base::SysNativeMBToWide(raw_filename));
- return filename;
-}
-
-} // namespace
URLRequestNewFtpJob::URLRequestNewFtpJob(URLRequest* request)
: URLRequestJob(request),
- response_info_(NULL),
- dir_listing_buf_size_(0),
ALLOW_THIS_IN_INITIALIZER_LIST(
start_callback_(this, &URLRequestNewFtpJob::OnStartCompleted)),
ALLOW_THIS_IN_INITIALIZER_LIST(
@@ -90,6 +43,14 @@ URLRequestJob* URLRequestNewFtpJob::Factory(URLRequest* request,
return new URLRequestNewFtpJob(request);
}
+bool URLRequestNewFtpJob::GetMimeType(std::string* mime_type) const {
+ if (transaction_->GetResponseInfo()->is_directory_listing) {
+ *mime_type = "text/vnd.chromium.ftp-dir";
+ return true;
+ }
+ return false;
+}
+
void URLRequestNewFtpJob::Start() {
DCHECK(!transaction_.get());
request_info_.url = request_->url();
@@ -159,65 +120,13 @@ bool URLRequestNewFtpJob::ReadRawData(net::IOBuffer* buf,
DCHECK_NE(buf_size, 0);
DCHECK(bytes_read);
DCHECK(!read_in_progress_);
- if (response_info_ == NULL) {
- response_info_ = transaction_->GetResponseInfo();
- if (response_info_->is_directory_listing) {
- std::string escaped_path =
- UnescapeURLComponent(request_->url().path(),
- UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS);
- string16 path_utf16;
- // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII,
- // but many old FTP servers use legacy encodings. Try UTF-8 first and
- // detect the encoding.
- if (IsStringUTF8(escaped_path)) {
- path_utf16 = UTF8ToUTF16(escaped_path);
- } else {
- std::string encoding = DetectEncoding(escaped_path.c_str(),
- escaped_path.size());
- // Try the detected encoding. If it fails, resort to the
- // OS native encoding.
- if (encoding.empty() ||
- !CodepageToUTF16(escaped_path, encoding.c_str(),
- OnStringUtilConversionError::SUBSTITUTE,
- &path_utf16))
- path_utf16 = WideToUTF16Hack(base::SysNativeMBToWide(escaped_path));
- }
-
- directory_html_ = net::GetDirectoryListingHeader(path_utf16);
- // If this isn't top level directory (i.e. the path isn't "/",)
- // add a link to the parent directory.
- if (request_->url().path().length() > 1)
- directory_html_.append(
- net::GetDirectoryListingEntry(ASCIIToUTF16(".."),
- std::string(),
- false, 0,
- base::Time()));
- }
- }
- if (!directory_html_.empty()) {
- size_t bytes_to_copy = std::min(static_cast<size_t>(buf_size),
- directory_html_.size());
- memcpy(buf->data(), directory_html_.c_str(), bytes_to_copy);
- *bytes_read = bytes_to_copy;
- directory_html_.erase(0, bytes_to_copy);
- return true;
- }
int rv = transaction_->Read(buf, buf_size, &read_callback_);
if (rv >= 0) {
- if (response_info_->is_directory_listing) {
- *bytes_read = ProcessFtpDir(buf, buf_size, rv);
- } else {
- *bytes_read = rv;
- }
+ *bytes_read = rv;
return true;
}
- if (response_info_->is_directory_listing) {
- dir_listing_buf_ = buf;
- dir_listing_buf_size_ = buf_size;
- }
-
if (rv == net::ERR_IO_PENDING) {
read_in_progress_ = true;
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
@@ -227,130 +136,6 @@ bool URLRequestNewFtpJob::ReadRawData(net::IOBuffer* buf,
return false;
}
-int URLRequestNewFtpJob::ProcessFtpDir(net::IOBuffer *buf,
- int buf_size,
- int bytes_read) {
- std::string file_entry;
- std::string line;
-
- // If all we've seen so far is ASCII, encoding_ is empty. Try to detect the
- // encoding. We don't do the separate UTF-8 check here because the encoding
- // detection with a longer chunk (as opposed to the relatively short path
- // component of the url) is unlikely to mistake UTF-8 for a legacy encoding.
- // If it turns out to be wrong, a separate UTF-8 check has to be added.
- //
- // TODO(jungshik): UTF-8 has to be 'enforced' without any heuristics when
- // we're talking to an FTP server compliant to RFC 2640 (that is, its response
- // to FEAT command includes 'UTF8').
- // See http://wiki.filezilla-project.org/Character_Set
- if (encoding_.empty())
- encoding_ = DetectEncoding(buf->data(), bytes_read);
-
- int64 file_size;
- std::istringstream iss(std::string(buf->data(), bytes_read));
- struct net::list_state state;
- memset(&state, 0, sizeof(state));
- while (getline(iss, line)) {
- struct net::list_result result;
- std::replace(line.begin(), line.end(), '\r', '\0');
- int line_type = net::ParseFTPList(line.c_str(), &state, &result);
-
- // The original code assumed months are in range 0-11 (PRExplodedTime),
- // but our Time class expects a 1-12 range. Adjust it here, because
- // the third-party parsing code uses bit-shifting on the month,
- // and it'd be too easy to break that logic.
- result.fe_time.month++;
- DCHECK_LE(1, result.fe_time.month);
- DCHECK_GE(12, result.fe_time.month);
-
- switch (line_type) {
- case 'd': // Directory entry.
- file_entry.append(net::GetDirectoryListingEntry(
- RawByteSequenceToFilename(result.fe_fname, encoding_),
- result.fe_fname, true, 0,
- base::Time::FromLocalExploded(result.fe_time)));
- break;
- case 'f': // File entry.
- if (StringToInt64(result.fe_size, &file_size))
- file_entry.append(net::GetDirectoryListingEntry(
- RawByteSequenceToFilename(result.fe_fname, encoding_),
- result.fe_fname, false, file_size,
- base::Time::FromLocalExploded(result.fe_time)));
- break;
- case 'l': { // Symlink entry.
- std::string filename(result.fe_fname, result.fe_fnlen);
-
- // Parsers for styles 'U' and 'W' handle " -> " themselves.
- if (state.lstyle != 'U' && state.lstyle != 'W') {
- std::string::size_type offset = filename.find(" -> ");
- if (offset != std::string::npos)
- filename = filename.substr(0, offset);
- }
-
- if (StringToInt64(result.fe_size, &file_size)) {
- file_entry.append(net::GetDirectoryListingEntry(
- RawByteSequenceToFilename(filename.c_str(), encoding_),
- filename, false, file_size,
- base::Time::FromLocalExploded(result.fe_time)));
- }
- }
- break;
- case '?': // Junk entry.
- case '"': // Comment entry.
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-
- // We can't recognize server type based on empty directory listings. Only log
- // server type when we have enough data to recognize one.
- if (state.parsed_one)
- LogFtpServerType(state.lstyle);
-
- directory_html_.append(file_entry);
- size_t bytes_to_copy = std::min(static_cast<size_t>(buf_size),
- directory_html_.length());
- if (bytes_to_copy) {
- memcpy(buf->data(), directory_html_.c_str(), bytes_to_copy);
- directory_html_.erase(0, bytes_to_copy);
- }
- return bytes_to_copy;
-}
-
-void URLRequestNewFtpJob::LogFtpServerType(char server_type) {
- switch (server_type) {
- case 'E':
- net::UpdateFtpServerTypeHistograms(net::SERVER_EPLF);
- break;
- case 'V':
- net::UpdateFtpServerTypeHistograms(net::SERVER_VMS);
- break;
- case 'C':
- net::UpdateFtpServerTypeHistograms(net::SERVER_CMS);
- break;
- case 'W':
- net::UpdateFtpServerTypeHistograms(net::SERVER_DOS);
- break;
- case 'O':
- net::UpdateFtpServerTypeHistograms(net::SERVER_OS2);
- break;
- case 'U':
- net::UpdateFtpServerTypeHistograms(net::SERVER_LSL);
- break;
- case 'w':
- net::UpdateFtpServerTypeHistograms(net::SERVER_W16);
- break;
- case 'D':
- net::UpdateFtpServerTypeHistograms(net::SERVER_DLS);
- break;
- default:
- net::UpdateFtpServerTypeHistograms(net::SERVER_UNKNOWN);
- break;
- }
-}
-
void URLRequestNewFtpJob::OnStartCompleted(int result) {
// If the request was destroyed, then there is no more work to do.
if (!request_ || !request_->delegate())
@@ -396,11 +181,6 @@ void URLRequestNewFtpJob::OnReadCompleted(int result) {
} else if (result < 0) {
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
} else {
- // TODO(ibrar): find the best place to delete dir_listing_buf_
- // Filter for Directory listing.
- if (response_info_->is_directory_listing)
- result = ProcessFtpDir(dir_listing_buf_, dir_listing_buf_size_, result);
-
// Clear the IO_PENDING status
SetStatus(URLRequestStatus());
}
@@ -410,8 +190,6 @@ void URLRequestNewFtpJob::OnReadCompleted(int result) {
void URLRequestNewFtpJob::RestartTransactionWithAuth() {
DCHECK(server_auth_ && server_auth_->state == net::AUTH_STATE_HAVE_AUTH);
- response_info_ = NULL;
-
// No matter what, we want to report our status as IO pending since we will
// be notifying our consumer asynchronously via OnStartCompleted.
SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
@@ -457,5 +235,4 @@ void URLRequestNewFtpJob::DestroyTransaction() {
DCHECK(transaction_.get());
transaction_.reset();
- response_info_ = NULL;
}
diff --git a/net/url_request/url_request_new_ftp_job.h b/net/url_request/url_request_new_ftp_job.h
index e29687f..95b0a3b 100644
--- a/net/url_request/url_request_new_ftp_job.h
+++ b/net/url_request/url_request_new_ftp_job.h
@@ -30,6 +30,9 @@ class URLRequestNewFtpJob : public URLRequestJob {
static URLRequestJob* Factory(URLRequest* request, const std::string& scheme);
+ // URLRequestJob methods:
+ virtual bool GetMimeType(std::string* mime_type) const;
+
private:
// URLRequestJob methods:
virtual void Start();
@@ -54,23 +57,15 @@ class URLRequestNewFtpJob : public URLRequestJob {
void RestartTransactionWithAuth();
- int ProcessFtpDir(net::IOBuffer *buf, int buf_size, int bytes_read);
-
void LogFtpServerType(char server_type);
net::FtpRequestInfo request_info_;
scoped_ptr<net::FtpTransaction> transaction_;
- const net::FtpResponseInfo* response_info_;
-
- scoped_refptr<net::IOBuffer> dir_listing_buf_;
- int dir_listing_buf_size_;
net::CompletionCallbackImpl<URLRequestNewFtpJob> start_callback_;
net::CompletionCallbackImpl<URLRequestNewFtpJob> read_callback_;
- std::string directory_html_;
bool read_in_progress_;
- std::string encoding_;
scoped_refptr<net::AuthData> server_auth_;