Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
HttpMultipartParser.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/Result.h"
5#include "../Foundation/Span.h"
6#include "../Foundation/StringSpan.h"
7#include "HttpExport.h"
8
9namespace SC
10{
13
15SC_HTTP_EXPORT bool HttpMultipartIsSafeFileName(StringSpan fileName);
16
19{
20 StringSpan disposition;
21 StringSpan name;
22 StringSpan fileName;
23
24 bool hasName = false;
25 bool hasFileName = false;
26
27 Result parse(StringSpan headerValue);
28 [[nodiscard]] bool isFormData() const;
29};
30
32struct SC_HTTP_EXPORT HttpMultipartPartHeadersView
33{
34 StringSpan contentDisposition;
35 StringSpan contentType;
36
38
39 void reset();
40 Result addHeader(StringSpan name, StringSpan value);
41
42 [[nodiscard]] StringSpan fieldName() const { return disposition.name; }
43 [[nodiscard]] StringSpan fileName() const { return disposition.fileName; }
44 [[nodiscard]] bool hasFileName() const { return disposition.hasFileName; }
45 [[nodiscard]] bool hasSafeFileName() const;
46};
47
49struct SC_HTTP_EXPORT HttpMultipartParser
50{
53
55 void reset();
56
58 enum class State
59 {
60 Parsing,
61 Result,
62 Finished,
63 };
64
66 enum class Token
67 {
68 HeaderName,
69 HeaderValue,
70 PartBody,
71 Boundary,
72 PartHeaderEnd,
73 Finished,
74 };
75
76 Token token = Token::Boundary;
77 State state = State::Parsing;
78
84 Result parse(Span<const char> data, size_t& readBytes, Span<const char>& parsedData);
85
86 private:
87 char boundaryStorage[71] = {0}; // MAX = 70 + NUL
88 char boundaryBuffer[128] = {0};
89
90 size_t tokenStart = 0;
91 size_t tokenLength = 0;
92 size_t globalStart = 0;
93 size_t globalLength = 0;
94 size_t matchIndex = 0; // For matching boundary and other fixed strings
95
96 int topLevelCoroutine = 0;
97 int nestedParserCoroutine = 0;
98
99 uint8_t boundaryMatchIndex = 0;
100 size_t boundaryCandidateLength = 0;
101 bool emitBoundaryCandidate = false;
102
103 StringSpan boundary;
104
105 // Helper functions for parsing
106 [[nodiscard]] bool parseBoundary(char currentChar);
107 [[nodiscard]] bool parseHeaders(char currentChar);
108 [[nodiscard]] bool parseBody(char currentChar);
109
110 // Specific parsers
111 [[nodiscard]] bool parsePreamble(char currentChar);
112 [[nodiscard]] bool parseBoundaryLine(char currentChar);
113 [[nodiscard]] bool parseHeaderName(char currentChar);
114 [[nodiscard]] bool parseHeaderValue(char currentChar);
115 [[nodiscard]] bool parseBodyUntilBoundary(char currentChar);
116
117 template <bool (HttpMultipartParser::*Func)(char), Token currentResult>
118 Result process(Span<const char>& data, size_t& readBytes, Span<const char>& parsedData);
119};
120
122} // namespace SC
SC_HTTP_EXPORT bool HttpMultipartIsSafeFileName(StringSpan fileName)
Conservative multipart filename safety check for upload sinks.
Zero-copy view of a Content-Disposition multipart header value.
Definition HttpMultipartParser.h:19
Incremental HTTP multipart/form-data parser.
Definition HttpMultipartParser.h:50
void reset()
Resets the parser state.
Result parse(Span< const char > data, size_t &readBytes, Span< const char > &parsedData)
Parse an incoming chunk of bytes, returning actually parsed span.
Result initWithBoundary(StringSpan boundary)
Initializes the parser with the given boundary (that excludes the leading '–')
State
State of the parser.
Definition HttpMultipartParser.h:59
Token
One possible Token reported by the parser.
Definition HttpMultipartParser.h:67
Zero-copy view over common multipart part headers.
Definition HttpMultipartParser.h:33
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37