annotate hg-web/main.c @ 242:543df0fe7168

[tools] Add full HLS player support
author MrJuneJune <me@mrjunejune.com>
date Mon, 03 Aug 2026 13:14:41 -0700
parents 3007ef5fc0ed
children c5129452493e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
1 #include "seobeo/seobeo.h"
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
2 #include "dowa/dowa.h"
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
3
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
4 #include <ctype.h>
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
5 #include <errno.h>
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
6 #include <stdio.h>
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
7 #include <stdlib.h>
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
8 #include <string.h>
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
9 #include <strings.h>
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
10 #include <time.h>
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
11 #include <unistd.h>
135
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
12
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
13 #define HG_SERVE_HOST "127.0.0.1"
147
6de849867459 [HgWeb] Updated logic to use Seobeo Client.
June Park <parkjune1995@gmail.com>
parents: 135
diff changeset
14 #define HG_SERVE_PORT "4444"
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
15 #define HG_API_TIMEOUT_MS 15000
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
16 #define HG_STREAM_IDLE_TIMEOUT_MS 60000
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
17 #define MAX_PATH_LENGTH 4096
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
18 #define MAX_WIRE_QUERY_LENGTH 8192
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
19 #define MAX_WIRE_HEADER_LENGTH 8192
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
20
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
21 static const char *map_value_case_insensitive(Seobeo_Request_Entry *map, const char *key)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
22 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
23 if (!map || !key)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
24 return NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
25
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
26 for (size_t i = 0; i < Dowa_Array_Length(map); i++)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
27 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
28 if (map[i].key && strcasecmp(map[i].key, key) == 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
29 return map[i].value;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
30 }
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
31 return NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
32 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
33
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
34 static char *arena_string(Dowa_Arena *arena, const char *value)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
35 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
36 size_t length = strlen(value);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
37 char *copy = Dowa_Arena_Allocate(arena, length + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
38 memcpy(copy, value, length + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
39 return copy;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
40 }
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
41
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
42 static Seobeo_Request_Entry *text_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
43 Dowa_Arena *arena,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
44 const char *status,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
45 const char *content_type,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
46 const char *body)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
47 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
48 Seobeo_Request_Entry *response = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
49 Dowa_HashMap_Push_Arena(response, "status", arena_string(arena, status), arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
50 Dowa_HashMap_Push_Arena(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
51 response, "content-type", arena_string(arena, content_type), arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
52 Dowa_HashMap_Push_Arena(response, "body", arena_string(arena, body), arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
53 return response;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
54 }
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
55
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
56 static boolean decode_url_component(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
57 const char *encoded,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
58 Dowa_Arena *arena,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
59 char **decoded_out,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
60 size_t *decoded_length_out)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
61 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
62 if (!encoded || !decoded_out)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
63 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
64
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
65 size_t encoded_length = strlen(encoded);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
66 if (encoded_length >= MAX_PATH_LENGTH)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
67 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
68
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
69 char *decoded = Dowa_Arena_Allocate(arena, encoded_length + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
70 size_t output_length = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
71 for (size_t i = 0; i < encoded_length; i++)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
72 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
73 unsigned char value = (unsigned char)encoded[i];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
74 if (encoded[i] == '%')
188
32ce881452fa Fixing few stuff.
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
75 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
76 if (i + 2 >= encoded_length ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
77 !isxdigit((unsigned char)encoded[i + 1]) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
78 !isxdigit((unsigned char)encoded[i + 2]))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
79 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
80
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
81 char hex[3] = {encoded[i + 1], encoded[i + 2], '\0'};
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
82 value = (unsigned char)strtoul(hex, NULL, 16);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
83 i += 2;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
84 if (value == '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
85 return FALSE;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
86 }
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
87 decoded[output_length++] = (char)value;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
88 }
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
89 decoded[output_length] = '\0';
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
90
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
91 *decoded_out = decoded;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
92 if (decoded_length_out)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
93 *decoded_length_out = output_length;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
94 return TRUE;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
95 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
96
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
97 static boolean normalize_repository_path(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
98 const char *encoded_path,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
99 Dowa_Arena *arena,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
100 char **normalized_out)
135
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
101 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
102 char *decoded = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
103 size_t decoded_length = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
104 if (!decode_url_component(encoded_path ? encoded_path : "", arena, &decoded, &decoded_length))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
105 return FALSE;
135
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
106
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
107 size_t start = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
108 size_t end = decoded_length;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
109 if (start < end && decoded[start] == '/')
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
110 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
111 start++;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
112 if (start < end && decoded[start] == '/')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
113 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
114 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
115 if (end > start && decoded[end - 1] == '/')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
116 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
117 if (end - 1 > start && decoded[end - 2] == '/')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
118 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
119 end--;
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
120 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
121
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
122 size_t segment_start = start;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
123 for (size_t i = start; i <= end; i++)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
124 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
125 boolean at_end = i == end;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
126 unsigned char c = at_end ? '/' : (unsigned char)decoded[i];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
127 if (!at_end && (iscntrl(c) || c == '\\' || c == '?' || c == '#'))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
128 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
129
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
130 if (c == '/')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
131 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
132 size_t segment_length = i - segment_start;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
133 if (segment_length == 0 && !at_end)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
134 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
135 if ((segment_length == 1 && decoded[segment_start] == '.') ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
136 (segment_length == 2 && decoded[segment_start] == '.' &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
137 decoded[segment_start + 1] == '.'))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
138 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
139 segment_start = i + 1;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
140 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
141 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
142
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
143 size_t normalized_length = end - start;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
144 char *normalized = Dowa_Arena_Allocate(arena, normalized_length + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
145 memcpy(normalized, decoded + start, normalized_length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
146 normalized[normalized_length] = '\0';
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
147 *normalized_out = normalized;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
148 return TRUE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
149 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
150
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
151 static boolean validate_revision(const char *revision)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
152 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
153 if (!revision || revision[0] == '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
154 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
155 if (strcmp(revision, "tip") == 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
156 return TRUE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
157
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
158 size_t length = strlen(revision);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
159 if (length > 40)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
160 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
161 for (size_t i = 0; i < length; i++)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
162 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
163 if (!isxdigit((unsigned char)revision[i]))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
164 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
165 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
166 return TRUE;
135
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
167 }
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
168
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
169 static char *encode_repository_path(const char *path, Dowa_Arena *arena)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
170 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
171 static const char hex[] = "0123456789ABCDEF";
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
172 size_t length = strlen(path);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
173 char *encoded = Dowa_Arena_Allocate(arena, length * 3 + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
174 size_t output = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
175 for (size_t i = 0; i < length; i++)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
176 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
177 unsigned char c = (unsigned char)path[i];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
178 if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~' || c == '/')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
179 encoded[output++] = (char)c;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
180 else
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
181 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
182 encoded[output++] = '%';
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
183 encoded[output++] = hex[c >> 4];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
184 encoded[output++] = hex[c & 0x0F];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
185 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
186 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
187 encoded[output] = '\0';
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
188 return encoded;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
189 }
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
190
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
191 static boolean safe_header_value(const char *value, size_t maximum_length)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
192 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
193 if (!value)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
194 return TRUE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
195 size_t length = strlen(value);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
196 return length <= maximum_length &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
197 strchr(value, '\r') == NULL &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
198 strchr(value, '\n') == NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
199 }
135
ffb764d2fcc5 [HgWeb] Updated hg web so it works
June Park <parkjune1995@gmail.com>
parents: 109
diff changeset
200
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
201 static boolean extension_is(const char *extension, const char *expected)
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
202 {
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
203 return extension && strcasecmp(extension, expected) == 0;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
204 }
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
205
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
206 static const char *repository_file_content_type(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
207 const char *path,
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
208 boolean *inline_preview,
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
209 boolean *sandbox_content)
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
210 {
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
211 const char *extension = strrchr(path, '.');
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
212 *inline_preview = TRUE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
213 *sandbox_content = FALSE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
214
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
215 if (extension_is(extension, ".png")) return "image/png";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
216 if (extension_is(extension, ".jpg") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
217 extension_is(extension, ".jpeg")) return "image/jpeg";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
218 if (extension_is(extension, ".gif")) return "image/gif";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
219 if (extension_is(extension, ".webp")) return "image/webp";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
220 if (extension_is(extension, ".avif")) return "image/avif";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
221 if (extension_is(extension, ".bmp")) return "image/bmp";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
222 if (extension_is(extension, ".ico")) return "image/x-icon";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
223 if (extension_is(extension, ".svg"))
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
224 {
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
225 *sandbox_content = TRUE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
226 return "image/svg+xml";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
227 }
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
228 if (extension_is(extension, ".mp4") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
229 extension_is(extension, ".m4v")) return "video/mp4";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
230 if (extension_is(extension, ".webm")) return "video/webm";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
231 if (extension_is(extension, ".mov")) return "video/quicktime";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
232 if (extension_is(extension, ".ogv")) return "video/ogg";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
233 if (extension_is(extension, ".mp3")) return "audio/mpeg";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
234 if (extension_is(extension, ".wav")) return "audio/wav";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
235 if (extension_is(extension, ".ogg") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
236 extension_is(extension, ".oga")) return "audio/ogg";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
237 if (extension_is(extension, ".flac")) return "audio/flac";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
238 if (extension_is(extension, ".m4a")) return "audio/mp4";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
239 if (extension_is(extension, ".aac")) return "audio/aac";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
240 if (extension_is(extension, ".pdf")) return "application/pdf";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
241 if (extension_is(extension, ".wasm")) return "application/wasm";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
242
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
243 *inline_preview = FALSE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
244 if (extension_is(extension, ".md") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
245 extension_is(extension, ".markdown")) return "text/markdown; charset=utf-8";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
246 if (extension_is(extension, ".txt") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
247 extension_is(extension, ".log") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
248 extension_is(extension, ".c") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
249 extension_is(extension, ".h") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
250 extension_is(extension, ".cc") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
251 extension_is(extension, ".cpp") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
252 extension_is(extension, ".js") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
253 extension_is(extension, ".jsx") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
254 extension_is(extension, ".ts") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
255 extension_is(extension, ".tsx") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
256 extension_is(extension, ".css") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
257 extension_is(extension, ".html") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
258 extension_is(extension, ".htm") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
259 extension_is(extension, ".xml") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
260 extension_is(extension, ".json") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
261 extension_is(extension, ".yaml") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
262 extension_is(extension, ".yml") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
263 extension_is(extension, ".toml") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
264 extension_is(extension, ".sh") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
265 extension_is(extension, ".py") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
266 extension_is(extension, ".rs") ||
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
267 extension_is(extension, ".go"))
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
268 return "text/plain; charset=utf-8";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
269 return "application/octet-stream";
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
270 }
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
271
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
272 static Seobeo_Client_Response *hg_proxy_request(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
273 const char *method,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
274 const char *path,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
275 const char *request_body,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
276 size_t request_body_length,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
277 const char *hg_argument,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
278 const char *accept)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
279 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
280 char url[MAX_PATH_LENGTH];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
281 int url_length = snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
282 url, sizeof(url), "http://%s:%s%s", HG_SERVE_HOST, HG_SERVE_PORT, path);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
283 if (url_length < 0 || (size_t)url_length >= sizeof(url))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
284 return NULL;
106
daf2d393741a Debugging in server.
June Park <parkjune1995@gmail.com>
parents: 104
diff changeset
285
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
286 Seobeo_Client_Request *request = Seobeo_Client_Request_Create(url);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
287 if (!request)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
288 return NULL;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
289
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
290 Seobeo_Client_Request_Set_Method(request, method);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
291 Seobeo_Client_Request_Add_Header_Map(request, "User-Agent", "Seobeo/1.0");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
292 Seobeo_Client_Request_Add_Header_Map(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
293 request, "Accept", accept ? accept : "application/json");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
294 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, HG_API_TIMEOUT_MS);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
295
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
296 if (hg_argument && hg_argument[0] != '\0')
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
297 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
298 if (!safe_header_value(hg_argument, MAX_WIRE_HEADER_LENGTH))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
299 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
300 Seobeo_Client_Request_Destroy(request);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
301 return NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
302 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
303 Seobeo_Client_Request_Add_Header_Map(request, "x-hgarg-1", hg_argument);
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
304 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
305
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
306 if (request_body && request_body_length > 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
307 Seobeo_Client_Request_Set_Body(request, request_body, request_body_length);
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
308
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
309 Seobeo_Client_Response *response = Seobeo_Client_Request_Execute(request);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
310 Seobeo_Client_Request_Destroy(request);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
311 return response;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
312 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
313
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
314 static Seobeo_Request_Entry *forward_hg_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
315 Seobeo_Client_Response *hg_response,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
316 const char *default_content_type,
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
317 const char *override_content_type,
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
318 Dowa_Arena *arena)
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
319 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
320 if (!hg_response)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
321 return text_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
322 arena, "502", "application/json", "{\"error\":\"Mercurial backend unavailable\"}");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
323
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
324 const char *upstream_content_type =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
325 map_value_case_insensitive(hg_response->headers, "Content-Type");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
326 const char *upstream_or_default_content_type =
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
327 override_content_type
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
328 ? override_content_type
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
329 : upstream_content_type ? upstream_content_type : default_content_type;
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
330 if (!upstream_or_default_content_type)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
331 upstream_or_default_content_type = "application/octet-stream";
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
332 char *content_type = arena_string(arena, upstream_or_default_content_type);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
333
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
334 char *status = Dowa_Arena_Allocate(arena, 8);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
335 snprintf(status, 8, "%d", hg_response->status_code);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
336
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
337 size_t body_length = hg_response->body ? hg_response->body_length : 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
338 char *body = Dowa_Arena_Allocate(arena, body_length + 1);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
339 if (body_length > 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
340 memcpy(body, hg_response->body, body_length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
341 body[body_length] = '\0';
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
342 char *content_length = Dowa_Arena_Allocate(arena, 32);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
343 snprintf(content_length, 32, "%zu", body_length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
344
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
345 Seobeo_Request_Entry *response = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
346 Dowa_HashMap_Push_Arena(response, "status", status, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
347 Dowa_HashMap_Push_Arena(response, "content-type", content_type, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
348 Dowa_HashMap_Push_Arena(response, "body", body, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
349 Dowa_HashMap_Push_Arena(response, "content-length", content_length, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
350 Seobeo_Client_Response_Destroy(hg_response);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
351 return response;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
352 }
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
353
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
354 Seobeo_Request_Entry *ApiListDirectory(Seobeo_Request_Entry *request, Dowa_Arena *arena)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
355 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
356 const char *encoded_path = map_value_case_insensitive(request, "query_path");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
357 char *path = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
358 if (!normalize_repository_path(encoded_path ? encoded_path : "", arena, &path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
359 return text_response(arena, "400", "application/json", "{\"error\":\"Invalid repository path\"}");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
360
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
361 char *encoded = encode_repository_path(path, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
362 char hg_path[MAX_PATH_LENGTH];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
363 int length = snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
364 hg_path,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
365 sizeof(hg_path),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
366 encoded[0] ? "/file/tip/%s?style=json" : "/file/tip/?style=json",
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
367 encoded);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
368 if (length < 0 || (size_t)length >= sizeof(hg_path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
369 return text_response(arena, "400", "application/json", "{\"error\":\"Repository path is too long\"}");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
370
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
371 return forward_hg_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
372 hg_proxy_request("GET", hg_path, NULL, 0, NULL, "application/json"),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
373 "application/json",
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
374 NULL,
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
375 arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
376 }
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
377
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
378 Seobeo_Request_Entry *ApiGetFile(Seobeo_Request_Entry *request, Dowa_Arena *arena)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
379 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
380 const char *encoded_path = map_value_case_insensitive(request, "query_path");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
381 char *path = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
382 if (!normalize_repository_path(encoded_path ? encoded_path : "", arena, &path) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
383 path[0] == '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
384 return text_response(arena, "400", "text/plain", "A valid file path is required");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
385
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
386 char *encoded = encode_repository_path(path, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
387 char hg_path[MAX_PATH_LENGTH];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
388 int length = snprintf(hg_path, sizeof(hg_path), "/raw-file/tip/%s", encoded);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
389 if (length < 0 || (size_t)length >= sizeof(hg_path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
390 return text_response(arena, "400", "text/plain", "File path is too long");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
391
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
392 Seobeo_Client_Response *hg_response =
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
393 hg_proxy_request("GET", hg_path, NULL, 0, NULL, "application/octet-stream");
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
394 if (!hg_response)
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
395 return forward_hg_response(NULL, "application/json", NULL, arena);
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
396
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
397 boolean inline_preview = FALSE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
398 boolean sandbox_content = FALSE;
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
399 const char *content_type =
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
400 repository_file_content_type(path, &inline_preview, &sandbox_content);
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
401 Seobeo_Request_Entry *response = forward_hg_response(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
402 hg_response, "application/octet-stream", content_type, arena);
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
403 Dowa_HashMap_Push_Arena(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
404 response,
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
405 "Content-Disposition",
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
406 inline_preview ? "inline" : "attachment",
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
407 arena);
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
408 Dowa_HashMap_Push_Arena(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
409 response, "X-Content-Type-Options", "nosniff", arena);
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
410 if (sandbox_content)
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
411 Dowa_HashMap_Push_Arena(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
412 response, "Content-Security-Policy", "sandbox", arena);
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
413 return response;
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
414 }
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
415
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
416 Seobeo_Request_Entry *ApiGetReadme(Seobeo_Request_Entry *request, Dowa_Arena *arena)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
417 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
418 const char *encoded_path = map_value_case_insensitive(request, "query_path");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
419 char *directory = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
420 if (!normalize_repository_path(encoded_path ? encoded_path : "", arena, &directory))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
421 return text_response(arena, "400", "text/plain", "Invalid repository path");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
422
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
423 size_t readme_length = strlen(directory) + strlen("/README.md") + 1;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
424 if (readme_length >= MAX_PATH_LENGTH)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
425 return text_response(arena, "400", "text/plain", "README path is too long");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
426
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
427 char *readme_path = Dowa_Arena_Allocate(arena, readme_length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
428 snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
429 readme_path,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
430 readme_length,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
431 directory[0] ? "%s/README.md" : "README.md",
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
432 directory);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
433 char *encoded = encode_repository_path(readme_path, arena);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
434
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
435 char hg_path[MAX_PATH_LENGTH];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
436 int length = snprintf(hg_path, sizeof(hg_path), "/raw-file/tip/%s", encoded);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
437 if (length < 0 || (size_t)length >= sizeof(hg_path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
438 return text_response(arena, "400", "text/plain", "README path is too long");
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
439
223
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
440 Seobeo_Client_Response *hg_response =
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
441 hg_proxy_request("GET", hg_path, NULL, 0, NULL, "text/markdown");
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
442 if (hg_response && hg_response->status_code == HTTP_NOT_FOUND)
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
443 {
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
444 Seobeo_Client_Response_Destroy(hg_response);
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
445 return text_response(arena, "204", "text/markdown", "");
0e7b9464248d [hg-web] Add browser route regression coverage
MrJuneJune <me@mrjunejune.com>
parents: 221
diff changeset
446 }
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
447 return forward_hg_response(
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
448 hg_response, "text/markdown", "text/markdown; charset=utf-8", arena);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
449 }
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
450
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
451 Seobeo_Request_Entry *ApiGetGraph(Seobeo_Request_Entry *request, Dowa_Arena *arena)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
452 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
453 const char *graph_id = map_value_case_insensitive(request, ":graph_id");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
454 if (!validate_revision(graph_id))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
455 return text_response(arena, "400", "application/json", "{\"error\":\"Invalid graph revision\"}");
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
456
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
457 const char *encoded_graph_top =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
458 map_value_case_insensitive(request, "query_graphtop");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
459 char *graph_top = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
460 if (encoded_graph_top)
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
461 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
462 if (!decode_url_component(encoded_graph_top, arena, &graph_top, NULL) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
463 !validate_revision(graph_top))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
464 return text_response(arena, "400", "application/json", "{\"error\":\"Invalid graph top revision\"}");
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
465 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
466
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
467 char hg_path[MAX_PATH_LENGTH];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
468 int length = graph_top
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
469 ? snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
470 hg_path,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
471 sizeof(hg_path),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
472 "/graph/%s?graphtop=%s&style=json",
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
473 graph_id,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
474 graph_top)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
475 : snprintf(hg_path, sizeof(hg_path), "/graph/%s?style=json", graph_id);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
476 if (length < 0 || (size_t)length >= sizeof(hg_path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
477 return text_response(arena, "400", "application/json", "{\"error\":\"Graph request is too long\"}");
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
478
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
479 return forward_hg_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
480 hg_proxy_request("GET", hg_path, NULL, 0, NULL, "application/json"),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
481 "application/json",
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
482 NULL,
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
483 arena);
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
484 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
485
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
486 Seobeo_Request_Entry *ApiGetChangeset(Seobeo_Request_Entry *request, Dowa_Arena *arena)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
487 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
488 const char *changeset_id = map_value_case_insensitive(request, ":changeset_id");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
489 if (!validate_revision(changeset_id))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
490 return text_response(arena, "400", "application/json", "{\"error\":\"Invalid changeset revision\"}");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
491
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
492 char hg_path[128];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
493 int length = snprintf(hg_path, sizeof(hg_path), "/json-rev/%s", changeset_id);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
494 if (length < 0 || (size_t)length >= sizeof(hg_path))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
495 return text_response(arena, "400", "application/json", "{\"error\":\"Changeset request is too long\"}");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
496
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
497 return forward_hg_response(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
498 hg_proxy_request("GET", hg_path, NULL, 0, NULL, "application/json"),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
499 "application/json",
224
3007ef5fc0ed [hg-web] Simplify visuals and preview static files
MrJuneJune <me@mrjunejune.com>
parents: 223
diff changeset
500 NULL,
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
501 arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
502 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
503
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
504 static int64_t monotonic_milliseconds(void)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
505 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
506 struct timespec now;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
507 clock_gettime(CLOCK_MONOTONIC, &now);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
508 return (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
509 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
510
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
511 static size_t find_http_header_length(const uint8 *buffer, size_t length)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
512 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
513 if (!buffer || length < 4)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
514 return 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
515 for (size_t i = 0; i + 3 < length; i++)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
516 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
517 if (buffer[i] == '\r' && buffer[i + 1] == '\n' &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
518 buffer[i + 2] == '\r' && buffer[i + 3] == '\n')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
519 return i + 4;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
520 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
521 return 0;
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
522 }
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
523
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
524 static void send_proxy_error(Seobeo_Handle *client, int status, const char *message)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
525 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
526 const char *reason = status == 504 ? "Gateway Timeout" : "Bad Gateway";
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
527 char response[512];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
528 int length = snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
529 response,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
530 sizeof(response),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
531 "HTTP/1.1 %d %s\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
532 "Content-Type: text/plain\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
533 "Content-Length: %zu\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
534 "Connection: close\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
535 "\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
536 "%s",
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
537 status,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
538 reason,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
539 strlen(message),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
540 message);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
541 if (length > 0 && (size_t)length < sizeof(response))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
542 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
543 Seobeo_Handle_Queue(client, (const uint8 *)response, (uint32)length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
544 Seobeo_Handle_Flush(client);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
545 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
546 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
547
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
548 static boolean parse_content_length(const char *value, size_t *length_out)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
549 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
550 if (!value || !length_out || value[0] == '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
551 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
552 errno = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
553 char *end = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
554 unsigned long long parsed = strtoull(value, &end, 10);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
555 if (errno != 0 || !end || *end != '\0' || parsed > SIZE_MAX)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
556 return FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
557 *length_out = (size_t)parsed;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
558 return TRUE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
559 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
560
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
561 void StreamHgWireProtocol(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
562 Seobeo_Handle *client,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
563 Seobeo_Request_Entry *request,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
564 Dowa_Arena *arena)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
565 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
566 (void)arena;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
567 const char *method = map_value_case_insensitive(request, "HTTP_Method");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
568 const char *query = map_value_case_insensitive(request, "QueryString");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
569 const char *body = map_value_case_insensitive(request, "Body");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
570 const char *content_length_value =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
571 map_value_case_insensitive(request, "Content-Length");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
572 const char *content_type = map_value_case_insensitive(request, "Content-Type");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
573 const char *hg_argument = map_value_case_insensitive(request, "x-hgarg-1");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
574
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
575 if (!method || !query ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
576 (strcmp(method, "GET") != 0 && strcmp(method, "POST") != 0) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
577 !safe_header_value(query, MAX_WIRE_QUERY_LENGTH) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
578 !safe_header_value(hg_argument, MAX_WIRE_HEADER_LENGTH) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
579 !safe_header_value(content_type, 256))
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
580 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
581 send_proxy_error(client, 502, "Invalid Mercurial proxy request");
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
582 return;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
583 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
584
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
585 size_t body_length = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
586 if (content_length_value &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
587 !parse_content_length(content_length_value, &body_length))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
588 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
589 send_proxy_error(client, 502, "Invalid Mercurial request length");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
590 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
591 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
592 if (body_length > 0 && !body)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
593 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
594 send_proxy_error(client, 502, "Missing Mercurial request body");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
595 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
596 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
597 if (body_length > UINT32_MAX)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
598 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
599 send_proxy_error(client, 502, "Mercurial request body is too large");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
600 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
601 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
602
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
603 Seobeo_Handle *upstream =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
604 Seobeo_Stream_Handle_Client_Create(HG_SERVE_HOST, HG_SERVE_PORT, FALSE);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
605 if (!upstream || upstream->socket < 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
606 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
607 if (upstream)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
608 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
609 send_proxy_error(client, 502, "Mercurial backend unavailable");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
610 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
611 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
612
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
613 char request_header[16384];
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
614 int header_length = snprintf(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
615 request_header,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
616 sizeof(request_header),
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
617 "%s /?%s HTTP/1.1\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
618 "Host: %s:%s\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
619 "User-Agent: Seobeo/1.0\r\n"
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
620 "Connection: close\r\n",
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
621 method,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
622 query,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
623 HG_SERVE_HOST,
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
624 HG_SERVE_PORT);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
625 if (header_length < 0 || (size_t)header_length >= sizeof(request_header))
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
626 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
627 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
628 send_proxy_error(client, 502, "Mercurial request headers are too large");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
629 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
630 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
631
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
632 #define APPEND_WIRE_HEADER(...) \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
633 do { \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
634 int appended = snprintf( \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
635 request_header + header_length, \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
636 sizeof(request_header) - (size_t)header_length, \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
637 __VA_ARGS__); \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
638 if (appended < 0 || (size_t)appended >= sizeof(request_header) - (size_t)header_length) { \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
639 Seobeo_Handle_Destroy(upstream); \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
640 send_proxy_error(client, 502, "Mercurial request headers are too large"); \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
641 return; \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
642 } \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
643 header_length += appended; \
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
644 } while (0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
645
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
646 if (hg_argument && hg_argument[0] != '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
647 APPEND_WIRE_HEADER("x-hgarg-1: %s\r\n", hg_argument);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
648 if (content_type && content_type[0] != '\0')
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
649 APPEND_WIRE_HEADER("Content-Type: %s\r\n", content_type);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
650 if (body_length > 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
651 APPEND_WIRE_HEADER("Content-Length: %zu\r\n", body_length);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
652 APPEND_WIRE_HEADER("\r\n");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
653 #undef APPEND_WIRE_HEADER
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
654
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
655 if (Seobeo_Handle_Queue(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
656 upstream, (const uint8 *)request_header, (uint32)header_length) != 0 ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
657 (body_length > 0 &&
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
658 Seobeo_Handle_Queue(upstream, (const uint8 *)body, (uint32)body_length) != 0) ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
659 Seobeo_Handle_Flush(upstream) != 0)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
660 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
661 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
662 send_proxy_error(client, 502, "Mercurial backend write failed");
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
663 return;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
664 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
665
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
666 boolean response_started = FALSE;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
667 int64_t last_progress = monotonic_milliseconds();
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
668 while (!response_started)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
669 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
670 int read_result = Seobeo_Handle_Read(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
671 if (read_result == -2 || read_result < 0)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
672 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
673 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
674 send_proxy_error(client, 502, "Mercurial backend closed before responding");
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
675 return;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
676 }
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
677 if (read_result > 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
678 last_progress = monotonic_milliseconds();
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
679
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
680 size_t header_size =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
681 find_http_header_length(upstream->read_buffer, upstream->read_buffer_len);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
682 if (header_size > 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
683 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
684 (void)header_size;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
685 if (Seobeo_Handle_Queue(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
686 client, upstream->read_buffer, upstream->read_buffer_len) != 0 ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
687 Seobeo_Handle_Flush(client) != 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
688 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
689 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
690 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
691 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
692 Seobeo_Handle_Consume(upstream, upstream->read_buffer_len);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
693 response_started = TRUE;
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
694 break;
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
695 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
696
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
697 if (read_result == 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
698 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
699 if (monotonic_milliseconds() - last_progress >= HG_STREAM_IDLE_TIMEOUT_MS)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
700 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
701 Seobeo_Handle_Destroy(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
702 send_proxy_error(client, 504, "Mercurial backend response timed out");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
703 return;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
704 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
705 usleep(1000);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
706 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
707 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
708
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
709 while (TRUE)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
710 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
711 int read_result = Seobeo_Handle_Read(upstream);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
712 if (read_result == -2)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
713 break;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
714 if (read_result < 0)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
715 break;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
716 if (read_result == 0)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
717 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
718 if (monotonic_milliseconds() - last_progress >= HG_STREAM_IDLE_TIMEOUT_MS)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
719 {
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
720 Seobeo_Log(SEOBEO_ERROR, "Mercurial response stream timed out\n");
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
721 break;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
722 }
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
723 usleep(1000);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
724 continue;
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
725 }
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
726
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
727 last_progress = monotonic_milliseconds();
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
728 if (Seobeo_Handle_Queue(
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
729 client, upstream->read_buffer, upstream->read_buffer_len) != 0 ||
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
730 Seobeo_Handle_Flush(client) != 0)
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
731 break;
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
732 Seobeo_Handle_Consume(upstream, upstream->read_buffer_len);
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
733 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
734
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
735 Seobeo_Handle_Destroy(upstream);
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
736 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
737
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
738 Seobeo_Request_Entry *GetReactHome(Seobeo_Request_Entry *request, Dowa_Arena *arena)
108
f07abbcd2ec5 [HgWeb] Will probably hold off on using it since it is not urgent.
June Park <parkjune1995@gmail.com>
parents: 107
diff changeset
739 {
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
740 (void)request;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
741 size_t file_size = 0;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
742 char *html = Seobeo_Web_LoadFile("/index.html", &file_size);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
743 if (!html)
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
744 return text_response(arena, "500", "text/plain", "Application shell unavailable");
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
745
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
746 Seobeo_Request_Entry *response = NULL;
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
747 char *content_length = Dowa_Arena_Allocate(arena, 32);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
748 snprintf(content_length, 32, "%zu", file_size);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
749 Dowa_HashMap_Push_Arena(response, "status", "200", arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
750 Dowa_HashMap_Push_Arena(response, "content-type", "text/html", arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
751 Dowa_HashMap_Push_Arena(response, "body", html, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
752 Dowa_HashMap_Push_Arena(response, "content-length", content_length, arena);
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
753 return response;
108
f07abbcd2ec5 [HgWeb] Will probably hold off on using it since it is not urgent.
June Park <parkjune1995@gmail.com>
parents: 107
diff changeset
754 }
f07abbcd2ec5 [HgWeb] Will probably hold off on using it since it is not urgent.
June Park <parkjune1995@gmail.com>
parents: 107
diff changeset
755
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
756 int main(void)
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
757 {
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
758 Seobeo_Router_Init();
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
759
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
760 Seobeo_Router_Register("GET", "/", GetReactHome);
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
761 Seobeo_Router_Register("GET", "/directories", GetReactHome);
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
762 Seobeo_Router_Register("GET", "/directory", GetReactHome);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
763 Seobeo_Router_Register("GET", "/graph", GetReactHome);
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
764 Seobeo_Router_Register("GET", "/changeset/:changeset_id", GetReactHome);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
765
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
766 Seobeo_Router_Register("GET", "/api/repo/list", ApiListDirectory);
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
767 Seobeo_Router_Register("GET", "/api/repo/file", ApiGetFile);
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
768 Seobeo_Router_Register("GET", "/api/repo/readme", ApiGetReadme);
193
9f4429c49733 [HgWeb] Making progress....
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
769 Seobeo_Router_Register("GET", "/api/graph/:graph_id", ApiGetGraph);
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
770 Seobeo_Router_Register("GET", "/api/changeset/:changeset_id", ApiGetChangeset);
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
771
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
772 Seobeo_Router_Register_Stream("GET", "/repo", StreamHgWireProtocol);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents: 147
diff changeset
773 Seobeo_Router_Register_Stream("POST", "/repo", StreamHgWireProtocol);
108
f07abbcd2ec5 [HgWeb] Will probably hold off on using it since it is not urgent.
June Park <parkjune1995@gmail.com>
parents: 107
diff changeset
774
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
775 printf("Starting on Port 6970...\n");
221
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
776 int result =
ce7f4400c2de [hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents: 193
diff changeset
777 Seobeo_Web_Server_Start("hg-web/src", "6970", SEOBEO_MODE_EDGE, 1);
104
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
778 Seobeo_Router_Destroy();
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
779 return result;
2301aeb7503b [Hg Web] Super simple mercurial server.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
780 }