mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
161 lines
4.3 KiB
C++
161 lines
4.3 KiB
C++
|
// 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_ctrl_response_buffer.h"
|
||
|
|
||
|
#include <utility>
|
||
|
|
||
|
#include "base/bind.h"
|
||
|
#include "base/logging.h"
|
||
|
#include "net/base/parse_number.h"
|
||
|
#include "base/strings/string_piece.h"
|
||
|
#include "base/values.h"
|
||
|
#include "net/base/net_errors.h"
|
||
|
#include "net/log/net_log_event_type.h"
|
||
|
|
||
|
namespace net {
|
||
|
|
||
|
// static
|
||
|
const int FtpCtrlResponse::kInvalidStatusCode = -1;
|
||
|
|
||
|
FtpCtrlResponse::FtpCtrlResponse() : status_code(kInvalidStatusCode) {}
|
||
|
|
||
|
FtpCtrlResponse::FtpCtrlResponse(const FtpCtrlResponse& other) = default;
|
||
|
|
||
|
FtpCtrlResponse::~FtpCtrlResponse() = default;
|
||
|
|
||
|
FtpCtrlResponseBuffer::FtpCtrlResponseBuffer(const NetLogWithSource& net_log)
|
||
|
: multiline_(false), net_log_(net_log) {}
|
||
|
|
||
|
FtpCtrlResponseBuffer::~FtpCtrlResponseBuffer() = default;
|
||
|
|
||
|
int FtpCtrlResponseBuffer::ConsumeData(const char* data, int data_length) {
|
||
|
buffer_.append(data, data_length);
|
||
|
ExtractFullLinesFromBuffer();
|
||
|
|
||
|
while (!lines_.empty()) {
|
||
|
ParsedLine line = lines_.front();
|
||
|
lines_.pop();
|
||
|
|
||
|
if (multiline_) {
|
||
|
if (!line.is_complete || line.status_code != response_buf_.status_code) {
|
||
|
line_buf_.append(line.raw_text);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
response_buf_.lines.push_back(line_buf_);
|
||
|
|
||
|
line_buf_ = line.status_text;
|
||
|
DCHECK_EQ(line.status_code, response_buf_.status_code);
|
||
|
|
||
|
if (!line.is_multiline) {
|
||
|
response_buf_.lines.push_back(line_buf_);
|
||
|
responses_.push(response_buf_);
|
||
|
|
||
|
// Prepare to handle following lines.
|
||
|
response_buf_ = FtpCtrlResponse();
|
||
|
line_buf_.clear();
|
||
|
multiline_ = false;
|
||
|
}
|
||
|
} else {
|
||
|
if (!line.is_complete)
|
||
|
return ERR_INVALID_RESPONSE;
|
||
|
|
||
|
response_buf_.status_code = line.status_code;
|
||
|
if (line.is_multiline) {
|
||
|
line_buf_ = line.status_text;
|
||
|
multiline_ = true;
|
||
|
} else {
|
||
|
response_buf_.lines.push_back(line.status_text);
|
||
|
responses_.push(response_buf_);
|
||
|
|
||
|
// Prepare to handle following lines.
|
||
|
response_buf_ = FtpCtrlResponse();
|
||
|
line_buf_.clear();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return OK;
|
||
|
}
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
std::unique_ptr<base::Value> NetLogFtpCtrlResponseCallback(
|
||
|
const FtpCtrlResponse* response,
|
||
|
NetLogCaptureMode capture_mode) {
|
||
|
std::unique_ptr<base::ListValue> lines(new base::ListValue());
|
||
|
lines->AppendStrings(response->lines);
|
||
|
|
||
|
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
|
||
|
dict->SetInteger("status_code", response->status_code);
|
||
|
dict->Set("lines", std::move(lines));
|
||
|
return std::move(dict);
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
FtpCtrlResponse FtpCtrlResponseBuffer::PopResponse() {
|
||
|
FtpCtrlResponse result = responses_.front();
|
||
|
responses_.pop();
|
||
|
|
||
|
net_log_.AddEvent(NetLogEventType::FTP_CONTROL_RESPONSE,
|
||
|
base::Bind(&NetLogFtpCtrlResponseCallback, &result));
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
FtpCtrlResponseBuffer::ParsedLine::ParsedLine()
|
||
|
: has_status_code(false),
|
||
|
is_multiline(false),
|
||
|
is_complete(false),
|
||
|
status_code(FtpCtrlResponse::kInvalidStatusCode) {
|
||
|
}
|
||
|
|
||
|
FtpCtrlResponseBuffer::ParsedLine::ParsedLine(const ParsedLine& other) =
|
||
|
default;
|
||
|
|
||
|
// static
|
||
|
FtpCtrlResponseBuffer::ParsedLine FtpCtrlResponseBuffer::ParseLine(
|
||
|
const std::string& line) {
|
||
|
ParsedLine result;
|
||
|
|
||
|
if (line.length() >= 3) {
|
||
|
if (ParseInt32(base::StringPiece(line.begin(), line.begin() + 3),
|
||
|
ParseIntFormat::NON_NEGATIVE, &result.status_code)) {
|
||
|
result.has_status_code =
|
||
|
(100 <= result.status_code && result.status_code <= 599);
|
||
|
}
|
||
|
if (result.has_status_code && line.length() >= 4 && line[3] == ' ') {
|
||
|
result.is_complete = true;
|
||
|
} else if (result.has_status_code && line.length() >= 4 && line[3] == '-') {
|
||
|
result.is_complete = true;
|
||
|
result.is_multiline = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (result.is_complete) {
|
||
|
result.status_text = line.substr(4);
|
||
|
} else {
|
||
|
result.status_text = line;
|
||
|
}
|
||
|
|
||
|
result.raw_text = line;
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void FtpCtrlResponseBuffer::ExtractFullLinesFromBuffer() {
|
||
|
int cut_pos = 0;
|
||
|
for (size_t i = 0; i < buffer_.length(); i++) {
|
||
|
if (i >= 1 && buffer_[i - 1] == '\r' && buffer_[i] == '\n') {
|
||
|
lines_.push(ParseLine(buffer_.substr(cut_pos, i - cut_pos - 1)));
|
||
|
cut_pos = i + 1;
|
||
|
}
|
||
|
}
|
||
|
buffer_.erase(0, cut_pos);
|
||
|
}
|
||
|
|
||
|
} // namespace net
|