Serenity Operating System
1/*
2 * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/GenericLexer.h>
8#include <AK/String.h>
9#include <AK/StringBuilder.h>
10#include <LibWeb/Fetch/Infrastructure/HTTP.h>
11
12namespace Web::Fetch::Infrastructure {
13
14// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
15ErrorOr<String> collect_an_http_quoted_string(GenericLexer& lexer, HttpQuotedStringExtractValue extract_value)
16{
17 // To collect an HTTP quoted string from a string input, given a position variable position and optionally an extract-value flag, run these steps:
18 // 1. Let positionStart be position.
19 auto position_start = lexer.tell();
20
21 // 2. Let value be the empty string.
22 StringBuilder value;
23
24 // 3. Assert: the code point at position within input is U+0022 (").
25 VERIFY(lexer.peek() == '"');
26
27 // 4. Advance position by 1.
28 lexer.ignore(1);
29
30 // 5. While true:
31 while (true) {
32 // 1. Append the result of collecting a sequence of code points that are not U+0022 (") or U+005C (\) from input, given position, to value.
33 auto value_part = lexer.consume_until([](char ch) {
34 return ch == '"' || ch == '\\';
35 });
36
37 value.append(value_part);
38
39 // 2. If position is past the end of input, then break.
40 if (lexer.is_eof())
41 break;
42
43 // 3. Let quoteOrBackslash be the code point at position within input.
44 // 4. Advance position by 1.
45 char quote_or_backslash = lexer.consume();
46
47 // 5. If quoteOrBackslash is U+005C (\), then:
48 if (quote_or_backslash == '\\') {
49 // 1. If position is past the end of input, then append U+005C (\) to value and break.
50 if (lexer.is_eof()) {
51 value.append('\\');
52 break;
53 }
54
55 // 2. Append the code point at position within input to value.
56 // 3. Advance position by 1.
57 value.append(lexer.consume());
58 }
59
60 // 6. Otherwise:
61 else {
62 // 1. Assert: quoteOrBackslash is U+0022 (").
63 VERIFY(quote_or_backslash == '"');
64
65 // 2. Break.
66 break;
67 }
68 }
69
70 // 6. If the extract-value flag is set, then return value.
71 if (extract_value == HttpQuotedStringExtractValue::Yes)
72 return value.to_string();
73
74 // 7. Return the code points from positionStart to position, inclusive, within input.
75 auto position = lexer.tell();
76 auto number_of_characters_to_consume = position - position_start + 1;
77 lexer.retreat(number_of_characters_to_consume);
78 return String::from_utf8(lexer.consume(number_of_characters_to_consume));
79}
80
81}