summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP.cpp
blob: 8f8df4c3a83be6b1609b2c4b75b47471e78153cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/GenericLexer.h>
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <LibWeb/Fetch/Infrastructure/HTTP.h>

namespace Web::Fetch::Infrastructure {

// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string
ErrorOr<String> collect_an_http_quoted_string(GenericLexer& lexer, HttpQuotedStringExtractValue extract_value)
{
    // To collect an HTTP quoted string from a string input, given a position variable position and optionally an extract-value flag, run these steps:
    // 1. Let positionStart be position.
    auto position_start = lexer.tell();

    // 2. Let value be the empty string.
    StringBuilder value;

    // 3. Assert: the code point at position within input is U+0022 (").
    VERIFY(lexer.peek() == '"');

    // 4. Advance position by 1.
    lexer.ignore(1);

    // 5. While true:
    while (true) {
        // 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.
        auto value_part = lexer.consume_until([](char ch) {
            return ch == '"' || ch == '\\';
        });

        value.append(value_part);

        // 2. If position is past the end of input, then break.
        if (lexer.is_eof())
            break;

        // 3. Let quoteOrBackslash be the code point at position within input.
        // 4. Advance position by 1.
        char quote_or_backslash = lexer.consume();

        // 5. If quoteOrBackslash is U+005C (\), then:
        if (quote_or_backslash == '\\') {
            // 1. If position is past the end of input, then append U+005C (\) to value and break.
            if (lexer.is_eof()) {
                value.append('\\');
                break;
            }

            // 2. Append the code point at position within input to value.
            // 3. Advance position by 1.
            value.append(lexer.consume());
        }

        // 6. Otherwise:
        else {
            // 1. Assert: quoteOrBackslash is U+0022 (").
            VERIFY(quote_or_backslash == '"');

            // 2. Break.
            break;
        }
    }

    // 6. If the extract-value flag is set, then return value.
    if (extract_value == HttpQuotedStringExtractValue::Yes)
        return value.to_string();

    // 7. Return the code points from positionStart to position, inclusive, within input.
    auto position = lexer.tell();
    auto number_of_characters_to_consume = position - position_start + 1;
    lexer.retreat(number_of_characters_to_consume);
    return String::from_utf8(lexer.consume(number_of_characters_to_consume));
}

}