| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/url_request/url_request_new_ftp_job.h" | 5 #include "net/url_request/url_request_new_ftp_job.h" |
| 6 | 6 |
| 7 #include "base/file_version_info.h" | 7 #include "base/file_version_info.h" |
| 8 #include "base/message_loop.h" |
| 9 #include "net/base/escape.h" |
| 8 #include "net/base/net_util.h" | 10 #include "net/base/net_util.h" |
| 11 #include "net/ftp/ftp_directory_parser.h" |
| 12 #include "net/ftp/ftp_response_info.h" |
| 13 #include "net/ftp/ftp_transaction_factory.h" |
| 9 #include "net/url_request/url_request.h" | 14 #include "net/url_request/url_request.h" |
| 10 #include "net/url_request/url_request_context.h" | 15 #include "net/url_request/url_request_context.h" |
| 11 #include "net/url_request/url_request_error_job.h" | 16 #include "net/url_request/url_request_error_job.h" |
| 12 | 17 |
| 13 | 18 |
| 14 URLRequestNewFtpJob::URLRequestNewFtpJob(URLRequest* request) | 19 URLRequestNewFtpJob::URLRequestNewFtpJob(URLRequest* request) |
| 15 : URLRequestJob(request), | 20 : URLRequestJob(request), |
| 16 server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), | 21 server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), |
| 17 ALLOW_THIS_IN_INITIALIZER_LIST( | 22 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 18 start_callback_(this, &URLRequestNewFtpJob::OnStartCompleted)), | 23 start_callback_(this, &URLRequestNewFtpJob::OnStartCompleted)), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 33 if (request->url().has_port() && | 38 if (request->url().has_port() && |
| 34 !net::IsPortAllowedByFtp(request->url().IntPort())) | 39 !net::IsPortAllowedByFtp(request->url().IntPort())) |
| 35 return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT); | 40 return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT); |
| 36 | 41 |
| 37 DCHECK(request->context()); | 42 DCHECK(request->context()); |
| 38 DCHECK(request->context()->ftp_transaction_factory()); | 43 DCHECK(request->context()->ftp_transaction_factory()); |
| 39 return new URLRequestNewFtpJob(request); | 44 return new URLRequestNewFtpJob(request); |
| 40 } | 45 } |
| 41 | 46 |
| 42 void URLRequestNewFtpJob::Start() { | 47 void URLRequestNewFtpJob::Start() { |
| 43 NOTIMPLEMENTED(); | 48 DCHECK(!transaction_.get()); |
| 49 request_info_.url = request_->url(); |
| 50 StartTransaction(); |
| 44 } | 51 } |
| 45 | 52 |
| 46 void URLRequestNewFtpJob::Kill() { | 53 void URLRequestNewFtpJob::Kill() { |
| 47 NOTIMPLEMENTED(); | 54 if (!transaction_.get()) |
| 48 } | 55 return; |
| 49 | 56 DestroyTransaction(); |
| 50 uint64 URLRequestNewFtpJob::GetUploadProgress() const { | 57 URLRequestJob::Kill(); |
| 51 NOTIMPLEMENTED(); | |
| 52 return 0; | |
| 53 } | |
| 54 | |
| 55 void URLRequestNewFtpJob::GetResponseInfo() { | |
| 56 NOTIMPLEMENTED(); | |
| 57 } | |
| 58 | |
| 59 int URLRequestNewFtpJob::GetResponseCode() const { | |
| 60 NOTIMPLEMENTED(); | |
| 61 return -1; | |
| 62 } | |
| 63 | |
| 64 bool URLRequestNewFtpJob::GetMoreData() { | |
| 65 NOTIMPLEMENTED(); | |
| 66 return false; | |
| 67 } | 58 } |
| 68 | 59 |
| 69 bool URLRequestNewFtpJob::ReadRawData(net::IOBuffer* buf, | 60 bool URLRequestNewFtpJob::ReadRawData(net::IOBuffer* buf, |
| 70 int buf_size, | 61 int buf_size, |
| 71 int *bytes_read) { | 62 int *bytes_read) { |
| 72 NOTIMPLEMENTED(); | 63 DCHECK_NE(buf_size, 0); |
| 64 DCHECK(bytes_read); |
| 65 DCHECK(!read_in_progress_); |
| 66 if (response_info_ == NULL) { |
| 67 response_info_ = transaction_->GetResponseInfo(); |
| 68 if (response_info_->is_directory_listing) { |
| 69 // Unescape the URL path and pass the raw 8bit directly to the browser. |
| 70 directory_html_ = net::GetDirectoryListingHeader( |
| 71 UnescapeURLComponent(request_->url().path(), |
| 72 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS)); |
| 73 // If this isn't top level directory (i.e. the path isn't "/",) |
| 74 // add a link to the parent directory. |
| 75 if (request_->url().path().length() > 1) |
| 76 directory_html_.append(net::GetDirectoryListingEntry("..", |
| 77 false, |
| 78 0, |
| 79 base::Time())); |
| 80 } |
| 81 } |
| 82 if (!directory_html_.empty()) { |
| 83 size_t bytes_to_copy = std::min(static_cast<size_t>(buf_size), |
| 84 directory_html_.size()); |
| 85 memcpy(buf->data(), directory_html_.c_str(), bytes_to_copy); |
| 86 *bytes_read = bytes_to_copy; |
| 87 directory_html_.erase(0, bytes_to_copy); |
| 88 return true; |
| 89 } |
| 90 int rv = transaction_->Read(buf, buf_size, &read_callback_); |
| 91 if (response_info_->is_directory_listing) { |
| 92 std::string file_entry; |
| 93 if (rv > 0) { |
| 94 std::string line; |
| 95 buf->data()[rv] = 0; |
| 96 std::istringstream iss(buf->data()); |
| 97 while (getline(iss, line)) { |
| 98 struct net::ListState state; |
| 99 struct net::ListResult result; |
| 100 net::LineType lt = ParseFTPLine(line.c_str(), &state, &result); |
| 101 switch (lt) { |
| 102 case net::FTP_TYPE_DIRECTORY: |
| 103 file_entry.append(net::GetDirectoryListingEntry(result.fe_fname, |
| 104 true, |
| 105 rv, |
| 106 base::Time())); |
| 107 break; |
| 108 case net::FTP_TYPE_FILE: |
| 109 file_entry.append(net::GetDirectoryListingEntry(result.fe_fname, |
| 110 false, |
| 111 rv, |
| 112 base::Time())); |
| 113 break; |
| 114 case net::FTP_TYPE_SYMLINK: |
| 115 case net::FTP_TYPE_JUNK: |
| 116 case net::FTP_TYPE_COMMENT: |
| 117 break; |
| 118 default: |
| 119 break; |
| 120 } |
| 121 } |
| 122 memcpy(buf->data(), file_entry.c_str(), file_entry.length()); |
| 123 *bytes_read = file_entry.length(); |
| 124 return true; |
| 125 } |
| 126 } else { |
| 127 rv = transaction_->Read(buf, buf_size, &read_callback_); |
| 128 } |
| 129 if (rv >= 0) { |
| 130 *bytes_read = rv; |
| 131 return true; |
| 132 } |
| 133 if (rv == net::ERR_IO_PENDING) { |
| 134 read_in_progress_ = true; |
| 135 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); |
| 136 } else { |
| 137 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); |
| 138 } |
| 73 return false; | 139 return false; |
| 74 } | 140 } |
| 75 | 141 |
| 76 void URLRequestNewFtpJob::OnStartCompleted(int result) { | 142 void URLRequestNewFtpJob::OnStartCompleted(int result) { |
| 77 NOTIMPLEMENTED(); | 143 // If the request was destroyed, then there is no more work to do. |
| 144 if (!request_ || !request_->delegate()) |
| 145 return; |
| 146 // If the transaction was destroyed, then the job was cancelled, and |
| 147 // we can just ignore this notification. |
| 148 if (!transaction_.get()) |
| 149 return; |
| 150 // Clear the IO_PENDING status |
| 151 SetStatus(URLRequestStatus()); |
| 152 if (result == net::OK) { |
| 153 URLRequestJob::NotifyHeadersComplete(); |
| 154 } else { |
| 155 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); |
| 156 } |
| 78 } | 157 } |
| 79 | 158 |
| 80 void URLRequestNewFtpJob::OnReadCompleted(int result) { | 159 void URLRequestNewFtpJob::OnReadCompleted(int result) { |
| 81 NOTIMPLEMENTED(); | 160 read_in_progress_ = false; |
| 161 if (result == 0) { |
| 162 NotifyDone(URLRequestStatus()); |
| 163 } else if (result < 0) { |
| 164 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); |
| 165 } else { |
| 166 // Clear the IO_PENDING status |
| 167 SetStatus(URLRequestStatus()); |
| 168 } |
| 169 NotifyReadComplete(result); |
| 170 } |
| 171 |
| 172 void URLRequestNewFtpJob::StartTransaction() { |
| 173 // Create a transaction. |
| 174 DCHECK(!transaction_.get()); |
| 175 DCHECK(request_->context()); |
| 176 DCHECK(request_->context()->ftp_transaction_factory()); |
| 177 |
| 178 transaction_.reset( |
| 179 request_->context()->ftp_transaction_factory()->CreateTransaction()); |
| 180 |
| 181 // No matter what, we want to report our status as IO pending since we will |
| 182 // be notifying our consumer asynchronously via OnStartCompleted. |
| 183 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); |
| 184 int rv; |
| 185 if (transaction_.get()) { |
| 186 rv = transaction_->Start(&request_info_, &start_callback_); |
| 187 if (rv == net::ERR_IO_PENDING) |
| 188 return; |
| 189 } else { |
| 190 rv = net::ERR_FAILED; |
| 191 } |
| 192 // The transaction started synchronously, but we need to notify the |
| 193 // URLRequest delegate via the message loop. |
| 194 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 195 this, &URLRequestNewFtpJob::OnStartCompleted, rv)); |
| 82 } | 196 } |
| 83 | 197 |
| 84 void URLRequestNewFtpJob::DestroyTransaction() { | 198 void URLRequestNewFtpJob::DestroyTransaction() { |
| 85 NOTIMPLEMENTED(); | 199 DCHECK(transaction_.get()); |
| 200 |
| 201 transaction_.reset(); |
| 202 response_info_ = NULL; |
| 86 } | 203 } |
| 87 | |
| 88 void URLRequestNewFtpJob::StartTransaction() { | |
| 89 NOTIMPLEMENTED(); | |
| 90 } | |
| OLD | NEW |