💾 Archived View for gemini.rmf-dev.com › repo › Vaati › UploadService › files › 8c7d81c9d78000fcd8c3… captured on 2023-12-28 at 15:49:05. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-09-08)
-=-=-=-=-=-=-
0 /* See LICENSE for license details. */
1 #include "parser.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <strings.h>
6 size_t strlcpy(char*, const char*, size_t);
7
8 const char* methods[] = {
9 "GET",
10 "HEAD",
11 "POST",
12 "PUT",
13 "DELETE",
14 "CONNECT",
15 "OPTIONS",
16 "TRACE"
17 };
18
19 int
20 parse_method(const char* method, size_t len)
21 {
22 size_t i;
23 for (i = 0; i < sizeof(methods)/sizeof(const char*); i++)
24 if (!strncmp(method, methods[i], len)) return i;
25 return -1;
26 }
27
28 int
29 get_parameter(struct http_request* req, char* name, int len,
30 char** ptr, int* psizeof)
31 {
32 if (!strncmp(name, "Host", len)) {
33 *ptr = req->host;
34 *psizeof = sizeof(req->host);
35 return 0;
36 }
37 if (!strncmp(name, "X-Real-IP", len)) {
38 *ptr = req->xrealip;
39 *psizeof = sizeof(req->xrealip);
40 return 0;
41 }
42 if (!strncmp(name, "X-Forwarded-Proto", len)) {
43 *ptr = req->xforwardedproto;
44 *psizeof = sizeof(req->xforwardedproto);
45 return 0;
46 }
47 if (!strncmp(name, "User-Agent", len)) {
48 *ptr = req->useragent;
49 *psizeof = sizeof(req->useragent);
50 return 0;
51 }
52 if (!strncmp(name, "Content-Type", len)) {
53 *ptr = req->contenttype;
54 *psizeof = sizeof(req->contenttype);
55 return 0;
56 }
57 if (!strncmp(name, "Content-Length", len)) {
58 *ptr = req->contentlength;
59 *psizeof = sizeof(req->contentlength);
60 return 0;
61 }
62 return -1;
63 }
64
65 int
66 http_parse(struct http_request* req)
67 {
68 const char *pos[3], *start;
69 char buf[64];
70 size_t len;
71 const char* end = req->packet + req->size;
72 const char* ptr = req->packet;
73 int in_value = 0;
74 char parameter[4096];
75 char* value = NULL;
76 int sizeof_value = 0;
77 int i = 0;
78 /* header */
79 while (++ptr && ptr < end - 1) {
80 if (*ptr == '\r' && *(ptr+1) == '\n') {
81 pos[i] = ptr;
82 if (i != 2) return -1;
83 break;
84 }
85 if (*ptr != ' ') continue;
86 if (i > 1) {
87 return -1;
88 }
89 pos[i] = ptr+1;
90 i++;
91 }
92 len = pos[0] - req->packet;
93 if (len >= sizeof(buf)) return -2;
94 strlcpy(buf, req->packet, len);
95 req->method = parse_method(buf, len);
96 len = pos[1] - pos[0];
97 if (len >= sizeof(req->uri)) return -2;
98 strlcpy(req->uri, pos[0], len);
99 len = ptr - pos[1] + 1;
100 if (len >= sizeof(req->version)) return -2;
101 strlcpy(req->version, pos[1], len);
102
103 /* parameters */
104 ptr+=2;
105 start = ptr;
106 ptr--;
107 req->boundary_found = 0;
108 while (ptr++ && ptr < end - 1) {
109 if ((ptr-1)[0] == '\n' && req->boundary_found &&
110 !memcmp(ptr, req->boundary,
111 strnlen(req->boundary, sizeof(req->boundary)))) {
112 start = ptr;
113 break;
114 }
115 if (in_value && ptr + sizeof("boundary=") < end - 1 &&
116 !memcmp(ptr, "boundary=", sizeof("boundary=")-1)) {
117 const char* bstart = ptr + sizeof("boundary=") - 1;
118 ptr += sizeof("boundary=") - 2;
119 while (ptr++ && ptr < end - 1 &&
120 *ptr != '\n' && *ptr != '\r')
121 req->boundary[ptr - bstart] = *ptr;
122 req->boundary_found = 1;
123 }
124 if (*ptr == '\r' && *(ptr+1) == '\n') {
125 ptr+=2;
126 start = ptr;
127 in_value = 0;
128 }
129 if (!in_value && *ptr == ':') {
130 if ((size_t)(ptr - start) > sizeof(parameter))
131 return -1;
132 strlcpy(parameter, start, ptr - start + 1);
133 if (!get_parameter(req, parameter, sizeof(parameter),
134 &value, &sizeof_value)) {
135 while (++ptr && ptr < end - 1 && *ptr != ' ') ;
136 start = ptr+1;
137 in_value = 1;
138 continue;
139 }
140 while (++ptr && ptr < end - 1 && *ptr != '\n') ;
141 ++ptr;
142 start = ptr;
143 }
144 if (in_value) {
145 if (ptr - start > sizeof_value)
146 return -1;
147 value[ptr - start] = *ptr;
148 }
149 }
150 return 0;
151 }
152