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 "../Common/Result.h"
5#include "../Common/Span.h"
6#include "../Common/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 isFormData() const { return disposition.isFormData(); }
45 [[nodiscard]] bool hasFieldName() const { return disposition.hasName; }
46 [[nodiscard]] bool hasFileName() const { return disposition.hasFileName; }
47 [[nodiscard]] bool isField() const { return isFormData() and hasFieldName() and not hasFileName(); }
48 [[nodiscard]] bool isFile() const { return isFormData() and hasFieldName() and hasFileName(); }
49 [[nodiscard]] bool hasSafeFileName() const;
50 [[nodiscard]] bool isSafeFile() const { return isFile() and hasSafeFileName(); }
51};
52
54struct SC_HTTP_EXPORT HttpMultipartParser
55{
57 Result initWithBoundary(StringSpan boundary);
58
60 void reset();
61
63 enum class State
64 {
65 Parsing,
66 Result,
67 Finished,
68 };
69
71 enum class Token
72 {
73 HeaderName,
74 HeaderValue,
75 PartBody,
76 Boundary,
77 PartHeaderEnd,
78 Finished,
79 };
80
81 Token token = Token::Boundary;
82 State state = State::Parsing;
83
89 Result parse(Span<const char> data, size_t& readBytes, Span<const char>& parsedData);
90
91 private:
92 char boundaryStorage[71] = {0}; // MAX = 70 + NUL
93 char boundaryBuffer[128] = {0};
94
95 size_t tokenStart = 0;
96 size_t tokenLength = 0;
97 size_t globalStart = 0;
98 size_t globalLength = 0;
99 size_t matchIndex = 0; // For matching boundary and other fixed strings
100
101 int topLevelCoroutine = 0;
102 int nestedParserCoroutine = 0;
103
104 uint8_t boundaryMatchIndex = 0;
105 size_t boundaryCandidateLength = 0;
106 bool emitBoundaryCandidate = false;
107
108 StringSpan boundary;
109
110 // Helper functions for parsing
111 [[nodiscard]] bool parseBoundary(char currentChar);
112 [[nodiscard]] bool parseHeaders(char currentChar);
113 [[nodiscard]] bool parseBody(char currentChar);
114
115 // Specific parsers
116 [[nodiscard]] bool parsePreamble(char currentChar);
117 [[nodiscard]] bool parseBoundaryLine(char currentChar);
118 [[nodiscard]] bool parseHeaderName(char currentChar);
119 [[nodiscard]] bool parseHeaderValue(char currentChar);
120 [[nodiscard]] bool parseBodyUntilBoundary(char currentChar);
121
122 template <bool (HttpMultipartParser::*Func)(char), Token currentResult>
123 Result process(Span<const char>& data, size_t& readBytes, Span<const char>& parsedData);
124};
125
127} // 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:55
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:64
Token
One possible Token reported by the parser.
Definition HttpMultipartParser.h:72
Zero-copy view over common multipart part headers.
Definition HttpMultipartParser.h:33