Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / ftp / ftp_ctrl_response_buffer.cc
blobb3f2d2399a142c4be7f62951129fc043286fb28e
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/ftp/ftp_ctrl_response_buffer.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h"
11 #include "base/values.h"
12 #include "net/base/net_errors.h"
14 namespace net {
16 // static
17 const int FtpCtrlResponse::kInvalidStatusCode = -1;
19 FtpCtrlResponse::FtpCtrlResponse() : status_code(kInvalidStatusCode) {}
21 FtpCtrlResponse::~FtpCtrlResponse() {}
23 FtpCtrlResponseBuffer::FtpCtrlResponseBuffer(const BoundNetLog& net_log)
24 : multiline_(false),
25 net_log_(net_log) {
28 FtpCtrlResponseBuffer::~FtpCtrlResponseBuffer() {}
30 int FtpCtrlResponseBuffer::ConsumeData(const char* data, int data_length) {
31 buffer_.append(data, data_length);
32 ExtractFullLinesFromBuffer();
34 while (!lines_.empty()) {
35 ParsedLine line = lines_.front();
36 lines_.pop();
38 if (multiline_) {
39 if (!line.is_complete || line.status_code != response_buf_.status_code) {
40 line_buf_.append(line.raw_text);
41 continue;
44 response_buf_.lines.push_back(line_buf_);
46 line_buf_ = line.status_text;
47 DCHECK_EQ(line.status_code, response_buf_.status_code);
49 if (!line.is_multiline) {
50 response_buf_.lines.push_back(line_buf_);
51 responses_.push(response_buf_);
53 // Prepare to handle following lines.
54 response_buf_ = FtpCtrlResponse();
55 line_buf_.clear();
56 multiline_ = false;
58 } else {
59 if (!line.is_complete)
60 return ERR_INVALID_RESPONSE;
62 response_buf_.status_code = line.status_code;
63 if (line.is_multiline) {
64 line_buf_ = line.status_text;
65 multiline_ = true;
66 } else {
67 response_buf_.lines.push_back(line.status_text);
68 responses_.push(response_buf_);
70 // Prepare to handle following lines.
71 response_buf_ = FtpCtrlResponse();
72 line_buf_.clear();
77 return OK;
80 namespace {
82 scoped_ptr<base::Value> NetLogFtpCtrlResponseCallback(
83 const FtpCtrlResponse* response,
84 NetLogCaptureMode capture_mode) {
85 scoped_ptr<base::ListValue> lines(new base::ListValue());
86 lines->AppendStrings(response->lines);
88 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
89 dict->SetInteger("status_code", response->status_code);
90 dict->Set("lines", lines.Pass());
91 return dict.Pass();
94 } // namespace
96 FtpCtrlResponse FtpCtrlResponseBuffer::PopResponse() {
97 FtpCtrlResponse result = responses_.front();
98 responses_.pop();
100 net_log_.AddEvent(NetLog::TYPE_FTP_CONTROL_RESPONSE,
101 base::Bind(&NetLogFtpCtrlResponseCallback, &result));
103 return result;
106 FtpCtrlResponseBuffer::ParsedLine::ParsedLine()
107 : has_status_code(false),
108 is_multiline(false),
109 is_complete(false),
110 status_code(FtpCtrlResponse::kInvalidStatusCode) {
113 // static
114 FtpCtrlResponseBuffer::ParsedLine FtpCtrlResponseBuffer::ParseLine(
115 const std::string& line) {
116 ParsedLine result;
118 if (line.length() >= 3) {
119 if (base::StringToInt(base::StringPiece(line.begin(), line.begin() + 3),
120 &result.status_code))
121 result.has_status_code = (100 <= result.status_code &&
122 result.status_code <= 599);
123 if (result.has_status_code && line.length() >= 4 && line[3] == ' ') {
124 result.is_complete = true;
125 } else if (result.has_status_code && line.length() >= 4 && line[3] == '-') {
126 result.is_complete = true;
127 result.is_multiline = true;
131 if (result.is_complete) {
132 result.status_text = line.substr(4);
133 } else {
134 result.status_text = line;
137 result.raw_text = line;
139 return result;
142 void FtpCtrlResponseBuffer::ExtractFullLinesFromBuffer() {
143 int cut_pos = 0;
144 for (size_t i = 0; i < buffer_.length(); i++) {
145 if (i >= 1 && buffer_[i - 1] == '\r' && buffer_[i] == '\n') {
146 lines_.push(ParseLine(buffer_.substr(cut_pos, i - cut_pos - 1)));
147 cut_pos = i + 1;
150 buffer_.erase(0, cut_pos);
153 } // namespace net