commit 1474650
uint
·
2026-01-27 17:25:45 +0000 UTC
parent d97f7f0
move shared util functions to util.h/c, unify header reply with reply_hdr
5 files changed,
+175,
-237
+50,
-217
1@@ -1,4 +1,3 @@
2-#include <ctype.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6@@ -17,16 +16,15 @@
7 #include "json.h"
8 #include "log.h"
9 #include "scan.h"
10+#include "util.h"
11
12-static const char* cistrstr(const char* hay, const char* nee);
13 static int cors_build(char* out, size_t outsz, const char* hdr, int preflight);
14-static int get_host(char out[512], const char* hdr);
15 static const struct item* find_item(uint64_t id);
16-static int join_path(char* out, size_t outsz, const char* a, const char* b);
17 static const char* mime_from_path(const char* path);
18 static int parse_hex64(const char* s, uint64_t* out);
19 static int parse_range(const char* hdr, size_t total, size_t* start, size_t* end);
20 static int read_request(int c, char* method, size_t msz, char* path, size_t psz, char* hdr, size_t hsz);
21+static void reply_hdr(int c, const char* hdr, const char* status, const char* ctype, size_t len, int preflight);
22 static void reply_json(int c, const char* hdr, const char* status, const char* body, size_t len, int send_body);
23 static void reply_m3u(int c, const char* hdr, const char* status, size_t len);
24 static void reply_preflight(int c, const char* hdr);
25@@ -34,40 +32,9 @@ static void reply_text(int c, const char* hdr, const char* status, const char* b
26 static int queue_write(int c, const char* hdr, int head_only);
27 static int stat_item(const struct item* it, struct stat* st);
28 static int stream_file(int c, const struct item* it, const char* hdr, int head_only);
29-static int write_all(int fd, const void* buf, size_t n);
30-
31
32 extern struct library lib;
33
34-static const char* cistrstr(const char* hay, const char* nee)
35-{
36- size_t nl = strlen(nee);
37- if (nl == 0)
38- return hay;
39-
40- for (; *hay; hay++) {
41- size_t i = 0;
42-
43- for (;;) {
44- if (i == nl)
45- return hay;
46-
47- unsigned char a = (unsigned char)hay[i];
48- unsigned char b = (unsigned char)nee[i];
49-
50- if (a == '\0')
51- break;
52-
53- if (tolower(a) != tolower(b))
54- break;
55-
56- i++;
57- }
58- }
59-
60- return NULL;
61-}
62-
63 static int cors_origin_allowed(const char* origin)
64 {
65 if (cors_origin[0] == '\0')
66@@ -101,38 +68,6 @@ static int cors_origin_allowed(const char* origin)
67 return 0;
68 }
69
70-static int cors_get_origin(char out[512], const char* hdr)
71-{
72- const char* p = cistrstr(hdr, "\norigin:");
73- if (!p)
74- p = cistrstr(hdr, "\rorigin:");
75- if (!p)
76- p = cistrstr(hdr, "origin:");
77- if (!p)
78- return -1;
79-
80- p = strchr(p, ':');
81- if (!p)
82- return -1;
83- p++;
84-
85- while (*p == ' ' || *p == '\t')
86- p++;
87-
88- size_t n = 0;
89- while (*p && *p != '\r' && *p != '\n') {
90- if (n + 1 >= 512)
91- return -1;
92- out[n++] = *p++;
93- }
94- out[n] = '\0';
95-
96- if (n == 0)
97- return -1;
98-
99- return 0;
100-}
101-
102 static int cors_build(char* out, size_t outsz, const char* hdr, int preflight)
103 {
104 char origin[512];
105@@ -145,7 +80,7 @@ static int cors_build(char* out, size_t outsz, const char* hdr, int preflight)
106 if (cors_origin[0] == '\0')
107 return 0;
108
109- if (cors_get_origin(origin, hdr) < 0)
110+ if (hdr_get_value(origin, hdr, "origin") < 0)
111 return 0;
112
113 if (!cors_origin_allowed(origin))
114@@ -183,38 +118,6 @@ static int cors_build(char* out, size_t outsz, const char* hdr, int preflight)
115 return 1;
116 }
117
118-static int get_host(char out[512], const char* hdr)
119-{
120- const char* p = cistrstr(hdr, "\nhost:");
121- if (!p)
122- p = cistrstr(hdr, "\rhost:");
123- if (!p)
124- p = cistrstr(hdr, "host:");
125- if (!p)
126- return -1;
127-
128- p = strchr(p, ':');
129- if (!p)
130- return -1;
131- p++;
132-
133- while (*p == ' ' || *p == '\t')
134- p++;
135-
136- size_t n = 0;
137- while (*p && *p != '\r' && *p != '\n') {
138- if (n + 1 >= 512)
139- return -1;
140- out[n++] = *p++;
141- }
142- out[n] = '\0';
143-
144- if (n == 0)
145- return -1;
146-
147- return 0;
148-}
149-
150 static const struct item* find_item(uint64_t id)
151 {
152 for (size_t i = 0; i < lib.len; i++)
153@@ -224,18 +127,6 @@ static const struct item* find_item(uint64_t id)
154 return NULL;
155 }
156
157-static int join_path(char* out, size_t outsz, const char* a, const char* b)
158-{
159- int n = snprintf(out, outsz, "%s/%s", a, b);
160- if (n < 0)
161- return -1;
162-
163- if ((size_t)n >= outsz)
164- return -1;
165-
166- return 0;
167-}
168-
169 static const char* mime_from_path(const char* path)
170 {
171 const char* dot = strrchr(path, '.');
172@@ -432,24 +323,47 @@ static int read_request(int c, char* method, size_t msz, char* path, size_t psz,
173 return 0;
174 }
175
176-static void reply_json(int c, const char* hdr, const char* status, const char* body, size_t len, int send_body)
177+static void reply_hdr(int c, const char* hdr, const char* status, const char* ctype, size_t len, int preflight)
178 {
179 char resp[HTTP_RESP_MAX];
180 char cors[512];
181
182- (void)cors_build(cors, sizeof(cors), hdr, 0);
183- int n = snprintf(
184- resp, sizeof(resp),
185+ (void)cors_build(cors, sizeof(cors), hdr, preflight);
186+
187+ int n;
188+
189+ if (ctype && ctype[0]) {
190+ n = snprintf(
191+ resp, sizeof(resp),
192+
193+ "%s"
194+ "%s"
195+ "%s"
196+ HTTP_LENGTH
197+ HTTP_CLOSE
198+ "\r\n",
199+
200+ status,
201+ cors,
202+ ctype,
203+ len
204+ );
205+ }
206+ else {
207+ n = snprintf(
208+ resp, sizeof(resp),
209
210- "%s"
211- "%s"
212- HTTP_JSON
213- HTTP_LENGTH
214- HTTP_CLOSE
215- "\r\n",
216+ "%s"
217+ "%s"
218+ HTTP_LENGTH
219+ HTTP_CLOSE
220+ "\r\n",
221
222- status, cors, len
223- );
224+ status,
225+ cors,
226+ len
227+ );
228+ }
229
230 if (n < 0)
231 return;
232@@ -458,6 +372,12 @@ static void reply_json(int c, const char* hdr, const char* status, const char* b
233 n = (int)(sizeof(resp) - 1);
234
235 (void)write_all(c, resp, (size_t)n);
236+}
237+
238+
239+static void reply_json(int c, const char* hdr, const char* status, const char* body, size_t len, int send_body)
240+{
241+ reply_hdr(c, hdr, status, HTTP_JSON, len, 0);
242
243 if (send_body)
244 (void)write_all(c, body, len);
245@@ -466,88 +386,20 @@ static void reply_json(int c, const char* hdr, const char* status, const char* b
246
247 static void reply_m3u(int c, const char* hdr, const char* status, size_t len)
248 {
249- char resp[HTTP_RESP_MAX];
250- char cors[512];
251-
252- (void)cors_build(cors, sizeof(cors), hdr, 0);
253- int n = snprintf(
254- resp, sizeof(resp),
255-
256- "%s"
257- "%s"
258- HTTP_M3U
259- HTTP_LENGTH
260- HTTP_CLOSE
261- "\r\n",
262-
263- status, cors, len
264- );
265-
266- if (n < 0)
267- return;
268-
269- if ((size_t)n >= sizeof(resp))
270- n = (int)(sizeof(resp) - 1);
271-
272- (void)write_all(c, resp, (size_t)n);
273+ reply_hdr(c, hdr, status, HTTP_M3U, len, 0);
274 }
275
276 static void reply_preflight(int c, const char* hdr)
277 {
278- char resp[HTTP_RESP_MAX];
279- char cors[512];
280-
281- (void)cors_build(cors, sizeof(cors), hdr, 1);
282-
283- int n = snprintf(
284- resp, sizeof(resp),
285- "%s"
286- "%s"
287- HTTP_LENGTH
288- HTTP_CLOSE
289- "\r\n",
290- HTTP_204,
291- cors,
292- (size_t)0
293- );
294-
295- if (n < 0)
296- return;
297- if ((size_t)n >= sizeof(resp))
298- n = (int)(sizeof(resp) - 1);
299-
300- (void)write_all(c, resp, (size_t)n);
301+ reply_hdr(c, hdr, HTTP_204, NULL, (size_t)0, 1);
302 }
303
304 static void reply_text(int c, const char* hdr, const char* status, const char* body)
305 {
306- char resp[HTTP_RESP_MAX];
307- char cors[512];
308+ size_t len = strlen(body);
309
310- (void)cors_build(cors, sizeof(cors), hdr, 0);
311- int n = snprintf(
312- resp, sizeof(resp),
313-
314- "%s"
315- "%s"
316- HTTP_TEXT
317- HTTP_LENGTH
318- HTTP_CLOSE
319- "\r\n"
320- "%s",
321-
322- status,
323- cors,
324- strlen(body), body
325- );
326-
327- if (n < 0)
328- return;
329-
330- if ((size_t)n >= sizeof(resp))
331- n = (int)(sizeof(resp) - 1);
332-
333- (void)write_all(c, resp, (size_t)n);
334+ reply_hdr(c, hdr, status, HTTP_TEXT, len, 0);
335+ (void)write_all(c, body, len);
336 }
337
338 static int queue_write(int c, const char* hdr, int head_only)
339@@ -555,7 +407,7 @@ static int queue_write(int c, const char* hdr, int head_only)
340 char host[512];
341 char base[768];
342
343- if (get_host(host, hdr) == 0) {
344+ if (hdr_get_value(host, hdr, "host") == 0) {
345 if (snprintf(base, sizeof(base), "http://%s", host) >= (int)sizeof(base))
346 return -1;
347 }
348@@ -785,25 +637,6 @@ static int stream_file(int c, const struct item* it, const char* hdr, int head_o
349 return 0;
350 }
351
352-static int write_all(int fd, const void* buf, size_t n)
353-{
354- const char* p = buf;
355-
356- while (n > 0) {
357- ssize_t w = write(fd, p, n);
358- if (w < 0) {
359- if (errno == EINTR)
360- continue;
361- return -1;
362- }
363-
364- p += (size_t)w;
365- n -= (size_t)w;
366- }
367-
368- return 0;
369-}
370-
371 int http_handle(int c)
372 {
373 char method[16];
+12,
-0
1@@ -0,0 +1,12 @@
2+#ifndef UTIL_H
3+#define UTIL_H
4+
5+#include <stddef.h>
6+
7+const char* cistrstr(const char* hay, const char* nee);
8+int hdr_get_value(char out[512], const char* hdr, const char* key);
9+int join_path(char* out, size_t outsz, const char* a, const char* b);
10+int write_all(int fd, const void* buf, size_t n);
11+
12+#endif /* UTIL_H */
13+
+0,
-1
1@@ -28,7 +28,6 @@
2 void die(const char* s, int e);
3 void run(void);
4 void setup(void);
5-int write_all(int fd, const void* buf, size_t n);
6
7 int sock;
8 struct library lib;
+1,
-19
1@@ -11,9 +11,9 @@
2 #include "config.h"
3 #include "scan.h"
4 #include "log.h"
5+#include "util.h"
6
7 static uint64_t encode_fnv1a64(const char* s);
8-static int join_path(char* out, size_t outsz, const char* a, const char* b);
9 static int library_push(struct library* l, const char* rel);
10 static int scan_dir(struct library* l, const char* root, const char* rel);
11
12@@ -30,24 +30,6 @@ static uint64_t encode_fnv1a64(const char* s)
13 return h;
14 }
15
16-static int join_path(char* out, size_t outsz, const char* a, const char* b)
17-{
18- size_t al = strlen(a);
19- size_t bl = strlen(b);
20-
21- if (al + 1 + bl + 1 > outsz) {
22- LOG(verbose_log, "SCAN", "path too long");
23- return -1;
24- }
25-
26- memcpy(out, a, al);
27- out[al] = '/';
28- memcpy(out + al + 1, b, bl);
29- out[al + 1 + bl] = '\0';
30-
31- return 0;
32-}
33-
34 static int library_push(struct library* l, const char* rel)
35 {
36 if (l->len == l->cap) {
+112,
-0
1@@ -0,0 +1,112 @@
2+#include <ctype.h>
3+#include <errno.h>
4+#include <stdio.h>
5+#include <string.h>
6+#include <unistd.h>
7+
8+#include "util.h"
9+
10+const char* cistrstr(const char* hay, const char* nee)
11+{
12+ size_t nl = strlen(nee);
13+ if (nl == 0)
14+ return hay;
15+
16+ for (; *hay; hay++) {
17+ size_t i = 0;
18+
19+ for (;;) {
20+ if (i == nl)
21+ return hay;
22+
23+ unsigned char a = (unsigned char)hay[i];
24+ unsigned char b = (unsigned char)nee[i];
25+
26+ if (a == '\0')
27+ break;
28+
29+ if (tolower(a) != tolower(b))
30+ break;
31+
32+ i++;
33+ }
34+ }
35+
36+ return NULL;
37+}
38+
39+int hdr_get_value(char out[512], const char* hdr, const char* key)
40+{
41+ char pat1[64];
42+ char pat2[64];
43+ char pat3[64];
44+
45+ /* build patterns like "\nXXXX:" "\rXXXX:" "XXXX:" */
46+ if (snprintf(pat1, sizeof(pat1), "\n%s:", key) >= (int)sizeof(pat1))
47+ return -1;
48+ if (snprintf(pat2, sizeof(pat2), "\r%s:", key) >= (int)sizeof(pat2))
49+ return -1;
50+ if (snprintf(pat3, sizeof(pat3), "%s:", key) >= (int)sizeof(pat3))
51+ return -1;
52+
53+ const char* p = cistrstr(hdr, pat1);
54+ if (!p)
55+ p = cistrstr(hdr, pat2);
56+ if (!p)
57+ p = cistrstr(hdr, pat3);
58+ if (!p)
59+ return -1;
60+
61+ p = strchr(p, ':');
62+ if (!p)
63+ return -1;
64+ p++;
65+
66+ while (*p == ' ' || *p == '\t')
67+ p++;
68+
69+ size_t n = 0;
70+ while (*p && *p != '\r' && *p != '\n') {
71+ if (n + 1 >= 512)
72+ return -1;
73+ out[n++] = *p++;
74+ }
75+ out[n] = '\0';
76+
77+ if (n == 0)
78+ return -1;
79+
80+ return 0;
81+}
82+
83+int join_path(char* out, size_t outsz, const char* a, const char* b)
84+{
85+ int n = snprintf(out, outsz, "%s/%s", a, b);
86+ if (n < 0)
87+ return -1;
88+
89+ if ((size_t)n >= outsz)
90+ return -1;
91+
92+ return 0;
93+}
94+
95+int write_all(int fd, const void* buf, size_t n)
96+{
97+ const char* p = buf;
98+
99+ while (n > 0) {
100+ ssize_t w = write(fd, p, n);
101+ if (w < 0) {
102+ if (errno == EINTR)
103+ continue;
104+ return -1;
105+ }
106+
107+ p += (size_t)w;
108+ n -= (size_t)w;
109+ }
110+
111+ return 0;
112+}
113+