1 // Copyright 2013 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/websockets/websocket_extension_parser.h"
7 #include "base/strings/string_util.h"
11 WebSocketExtensionParser::WebSocketExtensionParser() {}
13 WebSocketExtensionParser::~WebSocketExtensionParser() {}
15 void WebSocketExtensionParser::Parse(const char* data
, size_t size
) {
20 ConsumeExtension(&extension_
);
21 if (has_error_
) return;
23 has_error_
= has_error_
|| (current_
!= end_
);
26 void WebSocketExtensionParser::Consume(char c
) {
30 if (current_
== end_
|| c
!= current_
[0]) {
37 void WebSocketExtensionParser::ConsumeExtension(WebSocketExtension
* extension
) {
39 base::StringPiece name
;
41 if (has_error_
) return;
42 *extension
= WebSocketExtension(name
.as_string());
44 while (ConsumeIfMatch(';')) {
45 WebSocketExtension::Parameter
parameter((std::string()));
46 ConsumeExtensionParameter(¶meter
);
47 if (has_error_
) return;
48 extension
->Add(parameter
);
52 void WebSocketExtensionParser::ConsumeExtensionParameter(
53 WebSocketExtension::Parameter
* parameter
) {
55 base::StringPiece name
, value
;
56 std::string value_string
;
59 if (has_error_
) return;
60 if (!ConsumeIfMatch('=')) {
61 *parameter
= WebSocketExtension::Parameter(name
.as_string());
65 if (Lookahead('\"')) {
66 ConsumeQuotedToken(&value_string
);
69 value_string
= value
.as_string();
71 if (has_error_
) return;
72 *parameter
= WebSocketExtension::Parameter(name
.as_string(), value_string
);
75 void WebSocketExtensionParser::ConsumeToken(base::StringPiece
* token
) {
79 const char* head
= current_
;
80 while (current_
< end_
&&
81 !IsControl(current_
[0]) && !IsSeparator(current_
[0]))
83 if (current_
== head
) {
87 *token
= base::StringPiece(head
, current_
- head
);
90 void WebSocketExtensionParser::ConsumeQuotedToken(std::string
* token
) {
93 if (has_error_
) return;
95 while (current_
< end_
&& !IsControl(current_
[0])) {
96 if (UnconsumedBytes() >= 2 && current_
[0] == '\\') {
97 char next
= current_
[1];
98 if (IsControl(next
) || IsSeparator(next
)) break;
101 } else if (IsSeparator(current_
[0])) {
104 *token
+= current_
[0];
108 // We can't use Consume here because we don't want to consume spaces.
109 if (current_
< end_
&& current_
[0] == '"')
113 has_error_
= has_error_
|| token
->empty();
116 void WebSocketExtensionParser::ConsumeSpaces() {
118 while (current_
< end_
&& (current_
[0] == ' ' || current_
[0] == '\t'))
123 bool WebSocketExtensionParser::Lookahead(char c
) {
125 const char* head
= current_
;
128 bool result
= !has_error_
;
134 bool WebSocketExtensionParser::ConsumeIfMatch(char c
) {
136 const char* head
= current_
;
148 bool WebSocketExtensionParser::IsControl(char c
) {
149 return (0 <= c
&& c
<= 31) || c
== 127;
153 bool WebSocketExtensionParser::IsSeparator(char c
) {
154 const char separators
[] = "()<>@,;:\\\"/[]?={} \t";
155 return strchr(separators
, c
) != NULL
;