adamc@436
|
1 #define _XOPEN_SOURCE
|
adamc@436
|
2
|
adamc@117
|
3 #include <stdlib.h>
|
adamc@102
|
4 #include <stdio.h>
|
adamc@117
|
5 #include <string.h>
|
adamc@457
|
6 #include <strings.h>
|
adamc@106
|
7 #include <ctype.h>
|
adamc@167
|
8 #include <setjmp.h>
|
adamc@167
|
9 #include <stdarg.h>
|
adamc@102
|
10
|
adamc@102
|
11 #include "types.h"
|
adamc@102
|
12
|
adamc@311
|
13 uw_unit uw_unit_v = {};
|
adamc@102
|
14
|
adamc@167
|
15 #define ERROR_BUF_LEN 1024
|
adamc@167
|
16
|
adamc@323
|
17 typedef struct regions {
|
adamc@323
|
18 struct regions *next;
|
adamc@323
|
19 } regions;
|
adamc@323
|
20
|
adamc@425
|
21 typedef struct {
|
adamc@425
|
22 void (*func)(void*);
|
adamc@425
|
23 void *arg;
|
adamc@425
|
24 } cleanup;
|
adamc@425
|
25
|
adamc@311
|
26 struct uw_context {
|
adamc@458
|
27 char *headers, *headers_end;
|
adamc@457
|
28
|
adamc@462
|
29 char *outHeaders, *outHeaders_front, *outHeaders_back;
|
adamc@117
|
30 char *page, *page_front, *page_back;
|
adamc@136
|
31 char *heap, *heap_front, *heap_back;
|
adamc@144
|
32 char **inputs;
|
adamc@167
|
33
|
adamc@562
|
34 char *script, *script_front, *script_back;
|
adamc@565
|
35 int source_count;
|
adamc@562
|
36
|
adamc@272
|
37 void *db;
|
adamc@272
|
38
|
adamc@167
|
39 jmp_buf jmp_buf;
|
adamc@167
|
40
|
adamc@323
|
41 regions *regions;
|
adamc@323
|
42
|
adamc@425
|
43 cleanup *cleanup, *cleanup_front, *cleanup_back;
|
adamc@425
|
44
|
adamc@643
|
45 const char *script_header;
|
adamc@643
|
46
|
adamc@167
|
47 char error_message[ERROR_BUF_LEN];
|
adamc@117
|
48 };
|
adamc@117
|
49
|
adamc@311
|
50 extern int uw_inputs_len;
|
adamc@144
|
51
|
adamc@562
|
52 uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, size_t heap_len) {
|
adamc@311
|
53 uw_context ctx = malloc(sizeof(struct uw_context));
|
adamc@136
|
54
|
adamc@458
|
55 ctx->headers = ctx->headers_end = NULL;
|
adamc@457
|
56
|
adamc@462
|
57 ctx->outHeaders_front = ctx->outHeaders = malloc(outHeaders_len);
|
adamc@462
|
58 ctx->outHeaders_back = ctx->outHeaders_front + outHeaders_len;
|
adamc@462
|
59
|
adamc@462
|
60 ctx->heap_front = ctx->heap = malloc(heap_len);
|
adamc@462
|
61
|
adamc@117
|
62 ctx->page_front = ctx->page = malloc(page_len);
|
adamc@117
|
63 ctx->page_back = ctx->page_front + page_len;
|
adamc@136
|
64
|
adamc@136
|
65 ctx->heap_front = ctx->heap = malloc(heap_len);
|
adamc@136
|
66 ctx->heap_back = ctx->heap_front + heap_len;
|
adamc@136
|
67
|
adamc@311
|
68 ctx->inputs = calloc(uw_inputs_len, sizeof(char *));
|
adamc@144
|
69
|
adamc@272
|
70 ctx->db = NULL;
|
adamc@272
|
71
|
adamc@323
|
72 ctx->regions = NULL;
|
adamc@323
|
73
|
adamc@425
|
74 ctx->cleanup_front = ctx->cleanup_back = ctx->cleanup = malloc(0);
|
adamc@425
|
75
|
adamc@643
|
76 ctx->script_header = "";
|
adamc@643
|
77
|
adamc@167
|
78 ctx->error_message[0] = 0;
|
adamc@167
|
79
|
adamc@562
|
80 ctx->script_front = ctx->script = malloc(script_len);
|
adamc@562
|
81 ctx->script_back = ctx->script_front + script_len;
|
adamc@565
|
82 ctx->source_count = 0;
|
adamc@562
|
83
|
adamc@117
|
84 return ctx;
|
adamc@106
|
85 }
|
adamc@106
|
86
|
adamc@311
|
87 void uw_set_db(uw_context ctx, void *db) {
|
adamc@272
|
88 ctx->db = db;
|
adamc@272
|
89 }
|
adamc@272
|
90
|
adamc@311
|
91 void *uw_get_db(uw_context ctx) {
|
adamc@272
|
92 return ctx->db;
|
adamc@272
|
93 }
|
adamc@272
|
94
|
adamc@311
|
95 void uw_free(uw_context ctx) {
|
adamc@462
|
96 free(ctx->outHeaders);
|
adamc@562
|
97 free(ctx->script);
|
adamc@117
|
98 free(ctx->page);
|
adamc@136
|
99 free(ctx->heap);
|
adamc@144
|
100 free(ctx->inputs);
|
adamc@425
|
101 free(ctx->cleanup);
|
adamc@136
|
102 free(ctx);
|
adamc@136
|
103 }
|
adamc@136
|
104
|
adamc@562
|
105 void uw_reset_keep_error_message(uw_context ctx) {
|
adamc@462
|
106 ctx->outHeaders_front = ctx->outHeaders;
|
adamc@562
|
107 ctx->script_front = ctx->script;
|
adamc@138
|
108 ctx->page_front = ctx->page;
|
adamc@138
|
109 ctx->heap_front = ctx->heap;
|
adamc@323
|
110 ctx->regions = NULL;
|
adamc@425
|
111 ctx->cleanup_front = ctx->cleanup;
|
adamc@565
|
112 ctx->source_count = 0;
|
adamc@167
|
113 }
|
adamc@167
|
114
|
adamc@562
|
115 void uw_reset_keep_request(uw_context ctx) {
|
adamc@562
|
116 uw_reset_keep_error_message(ctx);
|
adamc@562
|
117 ctx->error_message[0] = 0;
|
adamc@167
|
118 }
|
adamc@167
|
119
|
adamc@311
|
120 void uw_reset(uw_context ctx) {
|
adamc@311
|
121 uw_reset_keep_request(ctx);
|
adamc@311
|
122 memset(ctx->inputs, 0, uw_inputs_len * sizeof(char *));
|
adamc@144
|
123 }
|
adamc@144
|
124
|
adamc@311
|
125 void uw_db_init(uw_context);
|
adamc@311
|
126 void uw_handle(uw_context, char *);
|
adamc@167
|
127
|
adamc@311
|
128 failure_kind uw_begin_init(uw_context ctx) {
|
adamc@272
|
129 int r = setjmp(ctx->jmp_buf);
|
adamc@272
|
130
|
adamc@272
|
131 if (r == 0)
|
adamc@311
|
132 uw_db_init(ctx);
|
adamc@272
|
133
|
adamc@272
|
134 return r;
|
adamc@272
|
135 }
|
adamc@272
|
136
|
adamc@458
|
137 void uw_set_headers(uw_context ctx, char *headers) {
|
adamc@458
|
138 char *s = headers, *s2;
|
adamc@458
|
139 ctx->headers = headers;
|
adamc@458
|
140
|
adamc@458
|
141 while (s2 = strchr(s, '\r')) {
|
adamc@458
|
142 s = s2;
|
adamc@458
|
143
|
adamc@458
|
144 if (s[1] == 0)
|
adamc@458
|
145 break;
|
adamc@458
|
146
|
adamc@458
|
147 *s = 0;
|
adamc@458
|
148 s += 2;
|
adamc@458
|
149 }
|
adamc@458
|
150
|
adamc@458
|
151 ctx->headers_end = s;
|
adamc@458
|
152 }
|
adamc@458
|
153
|
adamc@458
|
154 failure_kind uw_begin(uw_context ctx, char *path) {
|
adamc@190
|
155 int r = setjmp(ctx->jmp_buf);
|
adamc@190
|
156
|
adamc@190
|
157 if (r == 0)
|
adamc@311
|
158 uw_handle(ctx, path);
|
adamc@167
|
159
|
adamc@190
|
160 return r;
|
adamc@167
|
161 }
|
adamc@167
|
162
|
adamc@311
|
163 __attribute__((noreturn)) void uw_error(uw_context ctx, failure_kind fk, const char *fmt, ...) {
|
adamc@425
|
164 cleanup *cl;
|
adamc@425
|
165
|
adamc@167
|
166 va_list ap;
|
adamc@167
|
167 va_start(ap, fmt);
|
adamc@167
|
168
|
adamc@167
|
169 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
|
adamc@167
|
170
|
adamc@425
|
171 for (cl = ctx->cleanup; cl < ctx->cleanup_front; ++cl)
|
adamc@425
|
172 cl->func(cl->arg);
|
adamc@425
|
173
|
adamc@425
|
174 ctx->cleanup_front = ctx->cleanup;
|
adamc@425
|
175
|
adamc@190
|
176 longjmp(ctx->jmp_buf, fk);
|
adamc@167
|
177 }
|
adamc@167
|
178
|
adamc@425
|
179 void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
|
adamc@425
|
180 if (ctx->cleanup_front >= ctx->cleanup_back) {
|
adamc@425
|
181 int len = ctx->cleanup_back - ctx->cleanup, newLen;
|
adamc@425
|
182 if (len == 0)
|
adamc@425
|
183 newLen = 1;
|
adamc@425
|
184 else
|
adamc@428
|
185 newLen = len * 2;
|
adamc@470
|
186 ctx->cleanup = realloc(ctx->cleanup, newLen * sizeof(cleanup));
|
adamc@425
|
187 ctx->cleanup_front = ctx->cleanup + len;
|
adamc@425
|
188 ctx->cleanup_back = ctx->cleanup + newLen;
|
adamc@425
|
189 }
|
adamc@425
|
190
|
adamc@425
|
191 ctx->cleanup_front->func = func;
|
adamc@425
|
192 ctx->cleanup_front->arg = arg;
|
adamc@425
|
193 ++ctx->cleanup_front;
|
adamc@425
|
194 }
|
adamc@425
|
195
|
adamc@425
|
196 void uw_pop_cleanup(uw_context ctx) {
|
adamc@425
|
197 if (ctx->cleanup_front == ctx->cleanup)
|
adamc@425
|
198 uw_error(ctx, FATAL, "Attempt to pop from empty cleanup action stack");
|
adamc@425
|
199
|
adamc@425
|
200 --ctx->cleanup_front;
|
adamc@425
|
201 ctx->cleanup_front->func(ctx->cleanup_front->arg);
|
adamc@425
|
202 }
|
adamc@425
|
203
|
adamc@311
|
204 char *uw_error_message(uw_context ctx) {
|
adamc@167
|
205 return ctx->error_message;
|
adamc@167
|
206 }
|
adamc@167
|
207
|
adamc@311
|
208 int uw_input_num(char*);
|
adamc@144
|
209
|
adamc@311
|
210 void uw_set_input(uw_context ctx, char *name, char *value) {
|
adamc@311
|
211 int n = uw_input_num(name);
|
adamc@144
|
212
|
adamc@169
|
213 if (n < 0)
|
adamc@311
|
214 uw_error(ctx, FATAL, "Bad input name %s", name);
|
adamc@144
|
215
|
adamc@311
|
216 if (n >= uw_inputs_len)
|
adamc@311
|
217 uw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
|
adamc@169
|
218
|
adamc@144
|
219 ctx->inputs[n] = value;
|
adamc@144
|
220
|
adamc@282
|
221 //printf("[%d] %s = %s\n", n, name, value);
|
adamc@144
|
222 }
|
adamc@144
|
223
|
adamc@311
|
224 char *uw_get_input(uw_context ctx, int n) {
|
adamc@169
|
225 if (n < 0)
|
adamc@311
|
226 uw_error(ctx, FATAL, "Negative input index %d", n);
|
adamc@311
|
227 if (n >= uw_inputs_len)
|
adamc@311
|
228 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
|
adamc@282
|
229 //printf("[%d] = %s\n", n, ctx->inputs[n]);
|
adamc@144
|
230 return ctx->inputs[n];
|
adamc@138
|
231 }
|
adamc@138
|
232
|
adamc@311
|
233 char *uw_get_optional_input(uw_context ctx, int n) {
|
adamc@190
|
234 if (n < 0)
|
adamc@311
|
235 uw_error(ctx, FATAL, "Negative input index %d", n);
|
adamc@311
|
236 if (n >= uw_inputs_len)
|
adamc@311
|
237 uw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
|
adamc@426
|
238 //printf("[%d] = %s\n", n, ctx->inputs[n]);
|
adamc@190
|
239 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
|
adamc@190
|
240 }
|
adamc@190
|
241
|
adamc@643
|
242 void uw_set_script_header(uw_context ctx, const char *s) {
|
adamc@643
|
243 ctx->script_header = s;
|
adamc@643
|
244 }
|
adamc@643
|
245
|
adamc@311
|
246 static void uw_check_heap(uw_context ctx, size_t extra) {
|
adamc@136
|
247 if (ctx->heap_back - ctx->heap_front < extra) {
|
adamc@321
|
248 size_t desired = ctx->heap_front - ctx->heap + extra, next;
|
adamc@136
|
249 char *new_heap;
|
adamc@136
|
250
|
adamc@317
|
251 next = ctx->heap_back - ctx->heap;
|
adamc@317
|
252 if (next == 0)
|
adamc@317
|
253 next = 1;
|
adamc@317
|
254 for (; next < desired; next *= 2);
|
adamc@136
|
255
|
adamc@136
|
256 new_heap = realloc(ctx->heap, next);
|
adamc@321
|
257 ctx->heap_front = new_heap + (ctx->heap_front - ctx->heap);
|
adamc@169
|
258 ctx->heap_back = new_heap + next;
|
adamc@136
|
259
|
adamc@136
|
260 if (new_heap != ctx->heap) {
|
adamc@136
|
261 ctx->heap = new_heap;
|
adamc@311
|
262 uw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
|
adamc@136
|
263 }
|
adamc@136
|
264
|
adamc@169
|
265 ctx->heap = new_heap;
|
adamc@136
|
266 }
|
adamc@136
|
267 }
|
adamc@136
|
268
|
adamc@311
|
269 void *uw_malloc(uw_context ctx, size_t len) {
|
adamc@136
|
270 void *result;
|
adamc@136
|
271
|
adamc@311
|
272 uw_check_heap(ctx, len);
|
adamc@136
|
273
|
adamc@136
|
274 result = ctx->heap_front;
|
adamc@136
|
275 ctx->heap_front += len;
|
adamc@136
|
276 return result;
|
adamc@117
|
277 }
|
adamc@117
|
278
|
adamc@323
|
279 void uw_begin_region(uw_context ctx) {
|
adamc@323
|
280 regions *r = (regions *) ctx->heap_front;
|
adamc@323
|
281
|
adamc@323
|
282 uw_check_heap(ctx, sizeof(regions));
|
adamc@323
|
283
|
adamc@323
|
284 ctx->heap_front += sizeof(regions);
|
adamc@323
|
285
|
adamc@323
|
286 r->next = ctx->regions;
|
adamc@323
|
287 ctx->regions = r;
|
adamc@323
|
288 }
|
adamc@323
|
289
|
adamc@323
|
290 void uw_end_region(uw_context ctx) {
|
adamc@323
|
291 regions *r = ctx->regions;
|
adamc@323
|
292
|
adamc@323
|
293 if (r == NULL)
|
adamc@323
|
294 uw_error(ctx, FATAL, "Region stack underflow");
|
adamc@323
|
295
|
adamc@323
|
296 ctx->heap_front = (char *) r;
|
adamc@323
|
297 ctx->regions = r->next;
|
adamc@323
|
298 }
|
adamc@323
|
299
|
adamc@324
|
300 void uw_memstats(uw_context ctx) {
|
adamc@462
|
301 printf("Headers: %d/%d\n", ctx->outHeaders_front - ctx->outHeaders, ctx->outHeaders_back - ctx->outHeaders);
|
adamc@562
|
302 printf("Script: %d/%d\n", ctx->script_front - ctx->script, ctx->script_back - ctx->script);
|
adamc@324
|
303 printf("Page: %d/%d\n", ctx->page_front - ctx->page, ctx->page_back - ctx->page);
|
adamc@324
|
304 printf("Heap: %d/%d\n", ctx->heap_front - ctx->heap, ctx->heap_back - ctx->heap);
|
adamc@324
|
305 }
|
adamc@324
|
306
|
adamc@436
|
307 int uw_really_send(int sock, const void *buf, size_t len) {
|
adamc@117
|
308 while (len > 0) {
|
adamc@436
|
309 size_t n = send(sock, buf, len, 0);
|
adamc@117
|
310
|
adamc@117
|
311 if (n < 0)
|
adamc@117
|
312 return n;
|
adamc@117
|
313
|
adamc@117
|
314 buf += n;
|
adamc@117
|
315 len -= n;
|
adamc@117
|
316 }
|
adamc@117
|
317
|
adamc@117
|
318 return 0;
|
adamc@117
|
319 }
|
adamc@117
|
320
|
adamc@311
|
321 int uw_send(uw_context ctx, int sock) {
|
adamc@462
|
322 int n = uw_really_send(sock, ctx->outHeaders, ctx->outHeaders_front - ctx->outHeaders);
|
adamc@462
|
323
|
adamc@462
|
324 if (n < 0)
|
adamc@462
|
325 return n;
|
adamc@462
|
326
|
adamc@462
|
327 n = uw_really_send(sock, "\r\n", 2);
|
adamc@462
|
328
|
adamc@462
|
329 if (n < 0)
|
adamc@462
|
330 return n;
|
adamc@462
|
331
|
adamc@464
|
332 return uw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
|
adamc@462
|
333 }
|
adamc@462
|
334
|
adamc@462
|
335 static void uw_check_headers(uw_context ctx, size_t extra) {
|
adamc@462
|
336 size_t desired = ctx->outHeaders_front - ctx->outHeaders + extra, next;
|
adamc@462
|
337 char *new_outHeaders;
|
adamc@462
|
338
|
adamc@462
|
339 next = ctx->outHeaders_back - ctx->outHeaders;
|
adamc@462
|
340 if (next < desired) {
|
adamc@462
|
341 if (next == 0)
|
adamc@462
|
342 next = 1;
|
adamc@462
|
343 for (; next < desired; next *= 2);
|
adamc@462
|
344
|
adamc@462
|
345 new_outHeaders = realloc(ctx->outHeaders, next);
|
adamc@462
|
346 ctx->outHeaders_front = new_outHeaders + (ctx->outHeaders_front - ctx->outHeaders);
|
adamc@462
|
347 ctx->outHeaders_back = new_outHeaders + next;
|
adamc@462
|
348 ctx->outHeaders = new_outHeaders;
|
adamc@462
|
349 }
|
adamc@462
|
350 }
|
adamc@462
|
351
|
adamc@462
|
352 void uw_write_header(uw_context ctx, uw_Basis_string s) {
|
adamc@462
|
353 int len = strlen(s);
|
adamc@462
|
354
|
adamc@462
|
355 uw_check_headers(ctx, len + 1);
|
adamc@462
|
356 strcpy(ctx->outHeaders_front, s);
|
adamc@462
|
357 ctx->outHeaders_front += len;
|
adamc@562
|
358 }
|
adamc@562
|
359
|
adamc@562
|
360 static void uw_check_script(uw_context ctx, size_t extra) {
|
adamc@562
|
361 size_t desired = ctx->script_front - ctx->script + extra, next;
|
adamc@562
|
362 char *new_script;
|
adamc@562
|
363
|
adamc@562
|
364 next = ctx->script_back - ctx->script;
|
adamc@562
|
365 if (next < desired) {
|
adamc@562
|
366 if (next == 0)
|
adamc@562
|
367 next = 1;
|
adamc@562
|
368 for (; next < desired; next *= 2);
|
adamc@562
|
369
|
adamc@562
|
370 new_script = realloc(ctx->script, next);
|
adamc@562
|
371 ctx->script_front = new_script + (ctx->script_front - ctx->script);
|
adamc@562
|
372 ctx->script_back = new_script + next;
|
adamc@562
|
373 ctx->script = new_script;
|
adamc@562
|
374 }
|
adamc@562
|
375 }
|
adamc@562
|
376
|
adamc@562
|
377 void uw_write_script(uw_context ctx, uw_Basis_string s) {
|
adamc@562
|
378 int len = strlen(s);
|
adamc@562
|
379
|
adamc@562
|
380 uw_check_script(ctx, len + 1);
|
adamc@562
|
381 strcpy(ctx->script_front, s);
|
adamc@562
|
382 ctx->script_front += len;
|
adamc@562
|
383 }
|
adamc@562
|
384
|
adamc@565
|
385 char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
|
adamc@565
|
386 if (ctx->script_front == ctx->script) {
|
adamc@565
|
387 char *r = uw_malloc(ctx, 1);
|
adamc@565
|
388 r[0] = 0;
|
adamc@565
|
389 return r;
|
adamc@565
|
390 } else {
|
adamc@643
|
391 char *r = uw_malloc(ctx, 41 + (ctx->script_front - ctx->script) + strlen(ctx->script_header));
|
adamc@565
|
392
|
adamc@643
|
393 sprintf(r, "%s<script>%s</script>", ctx->script_header, ctx->script);
|
adamc@565
|
394 return r;
|
adamc@565
|
395 }
|
adamc@565
|
396 }
|
adamc@565
|
397
|
adamc@574
|
398 uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
|
adamc@574
|
399 char *r, *s2;
|
adamc@574
|
400
|
adamc@574
|
401 uw_check_heap(ctx, strlen(s) * 4 + 2);
|
adamc@574
|
402
|
adamc@574
|
403 r = s2 = ctx->heap_front;
|
adamc@574
|
404 *s2++ = '"';
|
adamc@574
|
405
|
adamc@574
|
406 for (; *s; s++) {
|
adamc@574
|
407 char c = *s;
|
adamc@574
|
408
|
adamc@574
|
409 switch (c) {
|
adamc@574
|
410 case '"':
|
adamc@574
|
411 strcpy(s2, "\\\"");
|
adamc@574
|
412 s2 += 2;
|
adamc@574
|
413 break;
|
adamc@574
|
414 case '\\':
|
adamc@574
|
415 strcpy(s2, "\\\\");
|
adamc@574
|
416 s2 += 2;
|
adamc@574
|
417 break;
|
adamc@574
|
418 default:
|
adamc@574
|
419 if (isprint(c))
|
adamc@574
|
420 *s2++ = c;
|
adamc@574
|
421 else {
|
adamc@574
|
422 sprintf(s2, "\\%3o", c);
|
adamc@574
|
423 s2 += 4;
|
adamc@574
|
424 }
|
adamc@574
|
425 }
|
adamc@574
|
426 }
|
adamc@574
|
427
|
adamc@574
|
428 strcpy(s2, "\"");
|
adamc@574
|
429 ctx->heap_front = s2 + 1;
|
adamc@574
|
430 return r;
|
adamc@574
|
431 }
|
adamc@574
|
432
|
adamc@574
|
433 uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) {
|
adamc@574
|
434 char *r, *s2;
|
adamc@574
|
435
|
adamc@574
|
436 uw_check_script(ctx, strlen(s) * 4 + 2);
|
adamc@574
|
437
|
adamc@574
|
438 r = s2 = ctx->script_front;
|
adamc@574
|
439 *s2++ = '"';
|
adamc@574
|
440
|
adamc@574
|
441 for (; *s; s++) {
|
adamc@574
|
442 char c = *s;
|
adamc@574
|
443
|
adamc@574
|
444 switch (c) {
|
adamc@577
|
445 case '\'':
|
adamc@574
|
446 strcpy(s2, "\\\"");
|
adamc@574
|
447 s2 += 2;
|
adamc@574
|
448 break;
|
adamc@574
|
449 case '\\':
|
adamc@574
|
450 strcpy(s2, "\\\\");
|
adamc@574
|
451 s2 += 2;
|
adamc@574
|
452 break;
|
adamc@574
|
453 default:
|
adamc@574
|
454 if (isprint(c))
|
adamc@574
|
455 *s2++ = c;
|
adamc@574
|
456 else {
|
adamc@574
|
457 sprintf(s2, "\\%3o", c);
|
adamc@574
|
458 s2 += 4;
|
adamc@574
|
459 }
|
adamc@574
|
460 }
|
adamc@574
|
461 }
|
adamc@574
|
462
|
adamc@574
|
463 strcpy(s2, "\"");
|
adamc@574
|
464 ctx->script_front = s2 + 1;
|
adamc@574
|
465 return r;
|
adamc@574
|
466 }
|
adamc@574
|
467
|
adamc@577
|
468 uw_Basis_int uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
|
adamc@577
|
469 int len;
|
adamc@577
|
470 size_t s_len = strlen(s);
|
adamc@562
|
471
|
adamc@577
|
472 uw_check_script(ctx, 12 + INTS_MAX + s_len);
|
adamc@574
|
473 sprintf(ctx->script_front, "var s%d=sc(%n", ctx->source_count, &len);
|
adamc@562
|
474 ctx->script_front += len;
|
adamc@577
|
475 strcpy(ctx->script_front, s);
|
adamc@577
|
476 ctx->script_front += s_len;
|
adamc@577
|
477 strcpy(ctx->script_front, ");");
|
adamc@577
|
478 ctx->script_front += 2;
|
adamc@562
|
479
|
adamc@565
|
480 return ctx->source_count++;
|
adamc@117
|
481 }
|
adamc@117
|
482
|
adamc@577
|
483 uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_int n, uw_Basis_string s) {
|
adamc@577
|
484 int len;
|
adamc@577
|
485 size_t s_len = strlen(s);
|
adamc@577
|
486
|
adamc@577
|
487 uw_check_script(ctx, 6 + INTS_MAX + s_len);
|
adamc@577
|
488 sprintf(ctx->script_front, "s%d.v=%n", (int)n, &len);
|
adamc@577
|
489 ctx->script_front += len;
|
adamc@577
|
490 strcpy(ctx->script_front, s);
|
adamc@577
|
491 ctx->script_front += s_len;
|
adamc@577
|
492 strcpy(ctx->script_front, ";");
|
adamc@577
|
493 ctx->script_front++;
|
adamc@577
|
494
|
adamc@577
|
495 return uw_unit_v;
|
adamc@577
|
496 }
|
adamc@577
|
497
|
adamc@311
|
498 static void uw_check(uw_context ctx, size_t extra) {
|
adamc@321
|
499 size_t desired = ctx->page_front - ctx->page + extra, next;
|
adamc@117
|
500 char *new_page;
|
adamc@117
|
501
|
adamc@317
|
502 next = ctx->page_back - ctx->page;
|
adamc@428
|
503 if (next < desired) {
|
adamc@428
|
504 if (next == 0)
|
adamc@428
|
505 next = 1;
|
adamc@428
|
506 for (; next < desired; next *= 2);
|
adamc@117
|
507
|
adamc@428
|
508 new_page = realloc(ctx->page, next);
|
adamc@428
|
509 ctx->page_front = new_page + (ctx->page_front - ctx->page);
|
adamc@428
|
510 ctx->page_back = new_page + next;
|
adamc@428
|
511 ctx->page = new_page;
|
adamc@428
|
512 }
|
adamc@117
|
513 }
|
adamc@117
|
514
|
adamc@311
|
515 static void uw_writec_unsafe(uw_context ctx, char c) {
|
adamc@117
|
516 *(ctx->page_front)++ = c;
|
adamc@117
|
517 }
|
adamc@117
|
518
|
adamc@311
|
519 void uw_writec(uw_context ctx, char c) {
|
adamc@311
|
520 uw_check(ctx, 1);
|
adamc@311
|
521 uw_writec_unsafe(ctx, c);
|
adamc@117
|
522 }
|
adamc@117
|
523
|
adamc@311
|
524 static void uw_write_unsafe(uw_context ctx, const char* s) {
|
adamc@117
|
525 int len = strlen(s);
|
adamc@117
|
526 memcpy(ctx->page_front, s, len);
|
adamc@117
|
527 ctx->page_front += len;
|
adamc@117
|
528 }
|
adamc@117
|
529
|
adamc@311
|
530 void uw_write(uw_context ctx, const char* s) {
|
adamc@311
|
531 uw_check(ctx, strlen(s) + 1);
|
adamc@311
|
532 uw_write_unsafe(ctx, s);
|
adamc@183
|
533 *ctx->page_front = 0;
|
adamc@102
|
534 }
|
adamc@106
|
535
|
adamc@135
|
536
|
adamc@311
|
537 char *uw_Basis_attrifyInt(uw_context ctx, uw_Basis_int n) {
|
adamc@136
|
538 char *result;
|
adamc@136
|
539 int len;
|
adamc@311
|
540 uw_check_heap(ctx, INTS_MAX);
|
adamc@136
|
541 result = ctx->heap_front;
|
adamc@276
|
542 sprintf(result, "%lld%n", n, &len);
|
adamc@137
|
543 ctx->heap_front += len+1;
|
adamc@136
|
544 return result;
|
adamc@106
|
545 }
|
adamc@106
|
546
|
adamc@311
|
547 char *uw_Basis_attrifyFloat(uw_context ctx, uw_Basis_float n) {
|
adamc@136
|
548 char *result;
|
adamc@136
|
549 int len;
|
adamc@311
|
550 uw_check_heap(ctx, FLOATS_MAX);
|
adamc@136
|
551 result = ctx->heap_front;
|
adamc@136
|
552 sprintf(result, "%g%n", n, &len);
|
adamc@137
|
553 ctx->heap_front += len+1;
|
adamc@136
|
554 return result;
|
adamc@106
|
555 }
|
adamc@106
|
556
|
adamc@311
|
557 char *uw_Basis_attrifyString(uw_context ctx, uw_Basis_string s) {
|
adamc@136
|
558 int len = strlen(s);
|
adamc@136
|
559 char *result, *p;
|
adamc@311
|
560 uw_check_heap(ctx, len * 6 + 1);
|
adamc@136
|
561
|
adamc@136
|
562 result = p = ctx->heap_front;
|
adamc@136
|
563
|
adamc@136
|
564 for (; *s; s++) {
|
adamc@136
|
565 char c = *s;
|
adamc@136
|
566
|
adamc@136
|
567 if (c == '"') {
|
adamc@136
|
568 strcpy(p, """);
|
adamc@136
|
569 p += 6;
|
adamc@136
|
570 } else if (c == '&') {
|
adamc@136
|
571 strcpy(p, "&");
|
adamc@136
|
572 p += 5;
|
adamc@136
|
573 }
|
adamc@136
|
574 else if (isprint(c))
|
adamc@136
|
575 *p++ = c;
|
adamc@136
|
576 else {
|
adamc@136
|
577 int len2;
|
adamc@136
|
578 sprintf(p, "&#%d;%n", c, &len2);
|
adamc@136
|
579 p += len2;
|
adamc@136
|
580 }
|
adamc@136
|
581 }
|
adamc@136
|
582
|
adamc@137
|
583 *p++ = 0;
|
adamc@136
|
584 ctx->heap_front = p;
|
adamc@136
|
585 return result;
|
adamc@106
|
586 }
|
adamc@106
|
587
|
adamc@311
|
588 static void uw_Basis_attrifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
|
adamc@117
|
589 int len;
|
adamc@117
|
590
|
adamc@276
|
591 sprintf(ctx->page_front, "%lld%n", n, &len);
|
adamc@117
|
592 ctx->page_front += len;
|
adamc@106
|
593 }
|
adamc@106
|
594
|
adamc@428
|
595 uw_unit uw_Basis_attrifyInt_w(uw_context ctx, uw_Basis_int n) {
|
adamc@311
|
596 uw_check(ctx, INTS_MAX);
|
adamc@311
|
597 uw_Basis_attrifyInt_w_unsafe(ctx, n);
|
adamc@428
|
598
|
adamc@428
|
599 return uw_unit_v;
|
adamc@106
|
600 }
|
adamc@106
|
601
|
adamc@428
|
602 uw_unit uw_Basis_attrifyFloat_w(uw_context ctx, uw_Basis_float n) {
|
adamc@117
|
603 int len;
|
adamc@117
|
604
|
adamc@311
|
605 uw_check(ctx, FLOATS_MAX);
|
adamc@117
|
606 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@117
|
607 ctx->page_front += len;
|
adamc@428
|
608
|
adamc@428
|
609 return uw_unit_v;
|
adamc@117
|
610 }
|
adamc@117
|
611
|
adamc@428
|
612 uw_unit uw_Basis_attrifyString_w(uw_context ctx, uw_Basis_string s) {
|
adamc@311
|
613 uw_check(ctx, strlen(s) * 6);
|
adamc@117
|
614
|
adamc@106
|
615 for (; *s; s++) {
|
adamc@106
|
616 char c = *s;
|
adamc@106
|
617
|
adamc@106
|
618 if (c == '"')
|
adamc@311
|
619 uw_write_unsafe(ctx, """);
|
adamc@136
|
620 else if (c == '&')
|
adamc@311
|
621 uw_write_unsafe(ctx, "&");
|
adamc@106
|
622 else if (isprint(c))
|
adamc@311
|
623 uw_writec_unsafe(ctx, c);
|
adamc@106
|
624 else {
|
adamc@311
|
625 uw_write_unsafe(ctx, "&#");
|
adamc@311
|
626 uw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@311
|
627 uw_writec_unsafe(ctx, ';');
|
adamc@106
|
628 }
|
adamc@106
|
629 }
|
adamc@428
|
630
|
adamc@428
|
631 return uw_unit_v;
|
adamc@106
|
632 }
|
adamc@120
|
633
|
adamc@120
|
634
|
adamc@311
|
635 char *uw_Basis_urlifyInt(uw_context ctx, uw_Basis_int n) {
|
adamc@137
|
636 int len;
|
adamc@137
|
637 char *r;
|
adamc@137
|
638
|
adamc@311
|
639 uw_check_heap(ctx, INTS_MAX);
|
adamc@137
|
640 r = ctx->heap_front;
|
adamc@276
|
641 sprintf(r, "%lld%n", n, &len);
|
adamc@137
|
642 ctx->heap_front += len+1;
|
adamc@137
|
643 return r;
|
adamc@120
|
644 }
|
adamc@120
|
645
|
adamc@311
|
646 char *uw_Basis_urlifyFloat(uw_context ctx, uw_Basis_float n) {
|
adamc@137
|
647 int len;
|
adamc@137
|
648 char *r;
|
adamc@137
|
649
|
adamc@311
|
650 uw_check_heap(ctx, FLOATS_MAX);
|
adamc@137
|
651 r = ctx->heap_front;
|
adamc@137
|
652 sprintf(r, "%g%n", n, &len);
|
adamc@137
|
653 ctx->heap_front += len+1;
|
adamc@137
|
654 return r;
|
adamc@120
|
655 }
|
adamc@120
|
656
|
adamc@311
|
657 char *uw_Basis_urlifyString(uw_context ctx, uw_Basis_string s) {
|
adamc@137
|
658 char *r, *p;
|
adamc@137
|
659
|
adamc@311
|
660 uw_check_heap(ctx, strlen(s) * 3 + 1);
|
adamc@137
|
661
|
adamc@137
|
662 for (r = p = ctx->heap_front; *s; s++) {
|
adamc@137
|
663 char c = *s;
|
adamc@137
|
664
|
adamc@137
|
665 if (c == ' ')
|
adamc@137
|
666 *p++ = '+';
|
adamc@137
|
667 else if (isalnum(c))
|
adamc@137
|
668 *p++ = c;
|
adamc@137
|
669 else {
|
adamc@137
|
670 sprintf(p, "%%%02X", c);
|
adamc@137
|
671 p += 3;
|
adamc@137
|
672 }
|
adamc@137
|
673 }
|
adamc@137
|
674
|
adamc@137
|
675 *p++ = 0;
|
adamc@137
|
676 ctx->heap_front = p;
|
adamc@137
|
677 return r;
|
adamc@120
|
678 }
|
adamc@120
|
679
|
adamc@311
|
680 char *uw_Basis_urlifyBool(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
681 if (b == uw_Basis_False)
|
adamc@186
|
682 return "0";
|
adamc@186
|
683 else
|
adamc@186
|
684 return "1";
|
adamc@186
|
685 }
|
adamc@186
|
686
|
adamc@311
|
687 static void uw_Basis_urlifyInt_w_unsafe(uw_context ctx, uw_Basis_int n) {
|
adamc@120
|
688 int len;
|
adamc@120
|
689
|
adamc@276
|
690 sprintf(ctx->page_front, "%lld%n", n, &len);
|
adamc@120
|
691 ctx->page_front += len;
|
adamc@120
|
692 }
|
adamc@120
|
693
|
adamc@428
|
694 uw_unit uw_Basis_urlifyInt_w(uw_context ctx, uw_Basis_int n) {
|
adamc@311
|
695 uw_check(ctx, INTS_MAX);
|
adamc@311
|
696 uw_Basis_urlifyInt_w_unsafe(ctx, n);
|
adamc@428
|
697
|
adamc@428
|
698 return uw_unit_v;
|
adamc@120
|
699 }
|
adamc@120
|
700
|
adamc@428
|
701 uw_unit uw_Basis_urlifyFloat_w(uw_context ctx, uw_Basis_float n) {
|
adamc@120
|
702 int len;
|
adamc@120
|
703
|
adamc@311
|
704 uw_check(ctx, FLOATS_MAX);
|
adamc@120
|
705 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@120
|
706 ctx->page_front += len;
|
adamc@428
|
707
|
adamc@428
|
708 return uw_unit_v;
|
adamc@120
|
709 }
|
adamc@120
|
710
|
adamc@488
|
711 uw_Basis_string uw_Basis_urlifyTime(uw_context ctx, uw_Basis_time t) {
|
adamc@488
|
712 return uw_Basis_urlifyInt(ctx, t);
|
adamc@488
|
713 }
|
adamc@488
|
714
|
adamc@428
|
715 uw_unit uw_Basis_urlifyString_w(uw_context ctx, uw_Basis_string s) {
|
adamc@311
|
716 uw_check(ctx, strlen(s) * 3);
|
adamc@120
|
717
|
adamc@120
|
718 for (; *s; s++) {
|
adamc@120
|
719 char c = *s;
|
adamc@120
|
720
|
adamc@120
|
721 if (c == ' ')
|
adamc@311
|
722 uw_writec_unsafe(ctx, '+');
|
adamc@120
|
723 else if (isalnum(c))
|
adamc@311
|
724 uw_writec_unsafe(ctx, c);
|
adamc@120
|
725 else {
|
adamc@120
|
726 sprintf(ctx->page_front, "%%%02X", c);
|
adamc@120
|
727 ctx->page_front += 3;
|
adamc@120
|
728 }
|
adamc@120
|
729 }
|
adamc@428
|
730
|
adamc@428
|
731 return uw_unit_v;
|
adamc@120
|
732 }
|
adamc@120
|
733
|
adamc@428
|
734 uw_unit uw_Basis_urlifyBool_w(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
735 if (b == uw_Basis_False)
|
adamc@311
|
736 uw_writec(ctx, '0');
|
adamc@186
|
737 else
|
adamc@311
|
738 uw_writec(ctx, '1');
|
adamc@428
|
739
|
adamc@428
|
740 return uw_unit_v;
|
adamc@186
|
741 }
|
adamc@186
|
742
|
adamc@120
|
743
|
adamc@311
|
744 static char *uw_unurlify_advance(char *s) {
|
adamc@144
|
745 char *new_s = strchr(s, '/');
|
adamc@120
|
746
|
adamc@120
|
747 if (new_s)
|
adamc@120
|
748 *new_s++ = 0;
|
adamc@120
|
749 else
|
adamc@144
|
750 new_s = strchr(s, 0);
|
adamc@144
|
751
|
adamc@144
|
752 return new_s;
|
adamc@144
|
753 }
|
adamc@144
|
754
|
adamc@311
|
755 uw_Basis_int uw_Basis_unurlifyInt(uw_context ctx, char **s) {
|
adamc@311
|
756 char *new_s = uw_unurlify_advance(*s);
|
adamc@311
|
757 uw_Basis_int r;
|
adamc@120
|
758
|
adamc@276
|
759 r = atoll(*s);
|
adamc@120
|
760 *s = new_s;
|
adamc@120
|
761 return r;
|
adamc@120
|
762 }
|
adamc@120
|
763
|
adamc@311
|
764 uw_Basis_float uw_Basis_unurlifyFloat(uw_context ctx, char **s) {
|
adamc@311
|
765 char *new_s = uw_unurlify_advance(*s);
|
adamc@311
|
766 uw_Basis_float r;
|
adamc@120
|
767
|
adamc@120
|
768 r = atof(*s);
|
adamc@120
|
769 *s = new_s;
|
adamc@120
|
770 return r;
|
adamc@120
|
771 }
|
adamc@120
|
772
|
adamc@488
|
773 uw_Basis_time uw_Basis_unurlifyTime(uw_context ctx, char **s) {
|
adamc@488
|
774 return uw_Basis_unurlifyInt(ctx, s);
|
adamc@488
|
775 }
|
adamc@488
|
776
|
adamc@311
|
777 static uw_Basis_string uw_unurlifyString_to(uw_context ctx, char *r, char *s) {
|
adamc@144
|
778 char *s1, *s2;
|
adamc@144
|
779 int n;
|
adamc@136
|
780
|
adamc@144
|
781 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
|
adamc@136
|
782 char c = *s2;
|
adamc@136
|
783
|
adamc@136
|
784 switch (c) {
|
adamc@136
|
785 case '+':
|
adamc@136
|
786 *s1 = ' ';
|
adamc@136
|
787 break;
|
adamc@136
|
788 case '%':
|
adamc@169
|
789 if (s2[1] == 0)
|
adamc@311
|
790 uw_error(ctx, FATAL, "Missing first character of escaped URL byte");
|
adamc@169
|
791 if (s2[2] == 0)
|
adamc@311
|
792 uw_error(ctx, FATAL, "Missing second character of escaped URL byte");
|
adamc@169
|
793 if (sscanf(s2+1, "%02X", &n) != 1)
|
adamc@311
|
794 uw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
|
adamc@136
|
795 *s1 = n;
|
adamc@136
|
796 s2 += 2;
|
adamc@136
|
797 break;
|
adamc@136
|
798 default:
|
adamc@136
|
799 *s1 = c;
|
adamc@136
|
800 }
|
adamc@136
|
801 }
|
adamc@136
|
802 *s1++ = 0;
|
adamc@144
|
803 return s1;
|
adamc@144
|
804 }
|
adamc@144
|
805
|
adamc@311
|
806 uw_Basis_bool uw_Basis_unurlifyBool(uw_context ctx, char **s) {
|
adamc@311
|
807 char *new_s = uw_unurlify_advance(*s);
|
adamc@311
|
808 uw_Basis_bool r;
|
adamc@186
|
809
|
adamc@186
|
810 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
|
adamc@311
|
811 r = uw_Basis_False;
|
adamc@186
|
812 else
|
adamc@311
|
813 r = uw_Basis_True;
|
adamc@186
|
814
|
adamc@186
|
815 *s = new_s;
|
adamc@186
|
816 return r;
|
adamc@186
|
817 }
|
adamc@186
|
818
|
adamc@311
|
819 uw_Basis_string uw_Basis_unurlifyString(uw_context ctx, char **s) {
|
adamc@311
|
820 char *new_s = uw_unurlify_advance(*s);
|
adamc@144
|
821 char *r, *s1, *s2;
|
adamc@144
|
822 int len, n;
|
adamc@144
|
823
|
adamc@200
|
824 len = strlen(*s);
|
adamc@311
|
825 uw_check_heap(ctx, len + 1);
|
adamc@144
|
826
|
adamc@144
|
827 r = ctx->heap_front;
|
adamc@311
|
828 ctx->heap_front = uw_unurlifyString_to(ctx, ctx->heap_front, *s);
|
adamc@136
|
829 *s = new_s;
|
adamc@136
|
830 return r;
|
adamc@120
|
831 }
|
adamc@135
|
832
|
adamc@135
|
833
|
adamc@311
|
834 char *uw_Basis_htmlifyInt(uw_context ctx, uw_Basis_int n) {
|
adamc@286
|
835 int len;
|
adamc@286
|
836 char *r;
|
adamc@286
|
837
|
adamc@311
|
838 uw_check_heap(ctx, INTS_MAX);
|
adamc@286
|
839 r = ctx->heap_front;
|
adamc@286
|
840 sprintf(r, "%lld%n", n, &len);
|
adamc@286
|
841 ctx->heap_front += len+1;
|
adamc@286
|
842 return r;
|
adamc@286
|
843 }
|
adamc@286
|
844
|
adamc@428
|
845 uw_unit uw_Basis_htmlifyInt_w(uw_context ctx, uw_Basis_int n) {
|
adamc@286
|
846 int len;
|
adamc@286
|
847
|
adamc@311
|
848 uw_check(ctx, INTS_MAX);
|
adamc@286
|
849 sprintf(ctx->page_front, "%lld%n", n, &len);
|
adamc@286
|
850 ctx->page_front += len;
|
adamc@428
|
851
|
adamc@428
|
852 return uw_unit_v;
|
adamc@286
|
853 }
|
adamc@286
|
854
|
adamc@311
|
855 char *uw_Basis_htmlifyFloat(uw_context ctx, uw_Basis_float n) {
|
adamc@286
|
856 int len;
|
adamc@286
|
857 char *r;
|
adamc@286
|
858
|
adamc@311
|
859 uw_check_heap(ctx, FLOATS_MAX);
|
adamc@286
|
860 r = ctx->heap_front;
|
adamc@286
|
861 sprintf(r, "%g%n", n, &len);
|
adamc@286
|
862 ctx->heap_front += len+1;
|
adamc@286
|
863 return r;
|
adamc@286
|
864 }
|
adamc@286
|
865
|
adamc@428
|
866 uw_unit uw_Basis_htmlifyFloat_w(uw_context ctx, uw_Basis_float n) {
|
adamc@286
|
867 int len;
|
adamc@286
|
868
|
adamc@311
|
869 uw_check(ctx, FLOATS_MAX);
|
adamc@286
|
870 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@286
|
871 ctx->page_front += len;
|
adamc@428
|
872
|
adamc@428
|
873 return uw_unit_v;
|
adamc@286
|
874 }
|
adamc@286
|
875
|
adamc@311
|
876 char *uw_Basis_htmlifyString(uw_context ctx, uw_Basis_string s) {
|
adamc@137
|
877 char *r, *s2;
|
adamc@137
|
878
|
adamc@311
|
879 uw_check_heap(ctx, strlen(s) * 5 + 1);
|
adamc@137
|
880
|
adamc@137
|
881 for (r = s2 = ctx->heap_front; *s; s++) {
|
adamc@137
|
882 char c = *s;
|
adamc@137
|
883
|
adamc@137
|
884 switch (c) {
|
adamc@137
|
885 case '<':
|
adamc@137
|
886 strcpy(s2, "<");
|
adamc@137
|
887 s2 += 4;
|
adamc@137
|
888 break;
|
adamc@137
|
889 case '&':
|
adamc@137
|
890 strcpy(s2, "&");
|
adamc@137
|
891 s2 += 5;
|
adamc@137
|
892 break;
|
adamc@137
|
893 default:
|
adamc@137
|
894 if (isprint(c))
|
adamc@137
|
895 *s2++ = c;
|
adamc@137
|
896 else {
|
adamc@137
|
897 int len2;
|
adamc@137
|
898 sprintf(s2, "&#%d;%n", c, &len2);
|
adamc@137
|
899 s2 += len2;
|
adamc@137
|
900 }
|
adamc@137
|
901 }
|
adamc@137
|
902 }
|
adamc@137
|
903
|
adamc@137
|
904 *s2++ = 0;
|
adamc@137
|
905 ctx->heap_front = s2;
|
adamc@137
|
906 return r;
|
adamc@135
|
907 }
|
adamc@135
|
908
|
adamc@428
|
909 uw_unit uw_Basis_htmlifyString_w(uw_context ctx, uw_Basis_string s) {
|
adamc@321
|
910 uw_check(ctx, strlen(s) * 6);
|
adamc@135
|
911
|
adamc@135
|
912 for (; *s; s++) {
|
adamc@135
|
913 char c = *s;
|
adamc@135
|
914
|
adamc@135
|
915 switch (c) {
|
adamc@135
|
916 case '<':
|
adamc@311
|
917 uw_write_unsafe(ctx, "<");
|
adamc@135
|
918 break;
|
adamc@135
|
919 case '&':
|
adamc@311
|
920 uw_write_unsafe(ctx, "&");
|
adamc@135
|
921 break;
|
adamc@135
|
922 default:
|
adamc@135
|
923 if (isprint(c))
|
adamc@311
|
924 uw_writec_unsafe(ctx, c);
|
adamc@135
|
925 else {
|
adamc@311
|
926 uw_write_unsafe(ctx, "&#");
|
adamc@311
|
927 uw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@311
|
928 uw_writec_unsafe(ctx, ';');
|
adamc@135
|
929 }
|
adamc@135
|
930 }
|
adamc@135
|
931 }
|
adamc@428
|
932
|
adamc@428
|
933 return uw_unit_v;
|
adamc@135
|
934 }
|
adamc@180
|
935
|
adamc@311
|
936 uw_Basis_string uw_Basis_htmlifyBool(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
937 if (b == uw_Basis_False)
|
adamc@286
|
938 return "False";
|
adamc@286
|
939 else
|
adamc@286
|
940 return "True";
|
adamc@286
|
941 }
|
adamc@286
|
942
|
adamc@428
|
943 uw_unit uw_Basis_htmlifyBool_w(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
944 if (b == uw_Basis_False) {
|
adamc@311
|
945 uw_check(ctx, 6);
|
adamc@286
|
946 strcpy(ctx->page_front, "False");
|
adamc@286
|
947 ctx->page_front += 5;
|
adamc@286
|
948 } else {
|
adamc@311
|
949 uw_check(ctx, 5);
|
adamc@286
|
950 strcpy(ctx->page_front, "True");
|
adamc@286
|
951 ctx->page_front += 4;
|
adamc@286
|
952 }
|
adamc@428
|
953
|
adamc@428
|
954 return uw_unit_v;
|
adamc@286
|
955 }
|
adamc@286
|
956
|
adamc@436
|
957 #define TIME_FMT "%x %X"
|
adamc@438
|
958 #define TIME_FMT_PG "%Y-%m-%d %T"
|
adamc@436
|
959
|
adamc@436
|
960 uw_Basis_string uw_Basis_htmlifyTime(uw_context ctx, uw_Basis_time t) {
|
adamc@436
|
961 size_t len;
|
adamc@436
|
962 char *r;
|
adamc@436
|
963 struct tm stm;
|
adamc@436
|
964
|
adamc@436
|
965 if (localtime_r(&t, &stm)) {
|
adamc@436
|
966 uw_check_heap(ctx, TIMES_MAX);
|
adamc@436
|
967 r = ctx->heap_front;
|
adamc@436
|
968 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
|
adamc@436
|
969 ctx->heap_front += len+1;
|
adamc@436
|
970 return r;
|
adamc@436
|
971 } else
|
adamc@436
|
972 return "<i>Invalid time</i>";
|
adamc@436
|
973 }
|
adamc@436
|
974
|
adamc@436
|
975 uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
|
adamc@436
|
976 size_t len;
|
adamc@436
|
977 char *r;
|
adamc@436
|
978 struct tm stm;
|
adamc@436
|
979
|
adamc@436
|
980 if (localtime_r(&t, &stm)) {
|
adamc@436
|
981 uw_check(ctx, TIMES_MAX);
|
adamc@436
|
982 r = ctx->page_front;
|
adamc@436
|
983 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
|
adamc@436
|
984 ctx->page_front += len;
|
adamc@436
|
985 } else {
|
adamc@436
|
986 uw_check(ctx, 20);
|
adamc@436
|
987 strcpy(ctx->page_front, "<i>Invalid time</i>");
|
adamc@436
|
988 ctx->page_front += 19;
|
adamc@436
|
989 }
|
adamc@436
|
990
|
adamc@436
|
991 return uw_unit_v;
|
adamc@436
|
992 }
|
adamc@436
|
993
|
adamc@311
|
994 uw_Basis_string uw_Basis_strcat(uw_context ctx, uw_Basis_string s1, uw_Basis_string s2) {
|
adamc@180
|
995 int len = strlen(s1) + strlen(s2) + 1;
|
adamc@180
|
996 char *s;
|
adamc@180
|
997
|
adamc@311
|
998 uw_check_heap(ctx, len);
|
adamc@180
|
999
|
adamc@180
|
1000 s = ctx->heap_front;
|
adamc@180
|
1001
|
adamc@180
|
1002 strcpy(s, s1);
|
adamc@180
|
1003 strcat(s, s2);
|
adamc@180
|
1004 ctx->heap_front += len;
|
adamc@180
|
1005
|
adamc@180
|
1006 return s;
|
adamc@180
|
1007 }
|
adamc@278
|
1008
|
adamc@311
|
1009 uw_Basis_string uw_Basis_strdup(uw_context ctx, uw_Basis_string s1) {
|
adamc@278
|
1010 int len = strlen(s1) + 1;
|
adamc@278
|
1011 char *s;
|
adamc@278
|
1012
|
adamc@311
|
1013 uw_check_heap(ctx, len);
|
adamc@278
|
1014
|
adamc@278
|
1015 s = ctx->heap_front;
|
adamc@278
|
1016
|
adamc@278
|
1017 strcpy(s, s1);
|
adamc@278
|
1018 ctx->heap_front += len;
|
adamc@278
|
1019
|
adamc@278
|
1020 return s;
|
adamc@278
|
1021 }
|
adamc@280
|
1022
|
adamc@493
|
1023 uw_Basis_string uw_Basis_maybe_strdup(uw_context ctx, uw_Basis_string s1) {
|
adamc@493
|
1024 if (s1)
|
adamc@493
|
1025 return uw_Basis_strdup(ctx, s1);
|
adamc@493
|
1026 else
|
adamc@493
|
1027 return NULL;
|
adamc@493
|
1028 }
|
adamc@493
|
1029
|
adamc@280
|
1030
|
adamc@311
|
1031 char *uw_Basis_sqlifyInt(uw_context ctx, uw_Basis_int n) {
|
adamc@281
|
1032 int len;
|
adamc@281
|
1033 char *r;
|
adamc@281
|
1034
|
adamc@311
|
1035 uw_check_heap(ctx, INTS_MAX + 6);
|
adamc@281
|
1036 r = ctx->heap_front;
|
adamc@281
|
1037 sprintf(r, "%lld::int8%n", n, &len);
|
adamc@281
|
1038 ctx->heap_front += len+1;
|
adamc@281
|
1039 return r;
|
adamc@281
|
1040 }
|
adamc@281
|
1041
|
adamc@467
|
1042 char *uw_Basis_sqlifyIntN(uw_context ctx, uw_Basis_int *n) {
|
adamc@467
|
1043 if (n == NULL)
|
adamc@467
|
1044 return "NULL";
|
adamc@467
|
1045 else
|
adamc@467
|
1046 return uw_Basis_sqlifyInt(ctx, *n);
|
adamc@467
|
1047 }
|
adamc@467
|
1048
|
adamc@311
|
1049 char *uw_Basis_sqlifyFloat(uw_context ctx, uw_Basis_float n) {
|
adamc@281
|
1050 int len;
|
adamc@281
|
1051 char *r;
|
adamc@281
|
1052
|
adamc@311
|
1053 uw_check_heap(ctx, FLOATS_MAX + 8);
|
adamc@281
|
1054 r = ctx->heap_front;
|
adamc@281
|
1055 sprintf(r, "%g::float8%n", n, &len);
|
adamc@281
|
1056 ctx->heap_front += len+1;
|
adamc@281
|
1057 return r;
|
adamc@281
|
1058 }
|
adamc@281
|
1059
|
adamc@467
|
1060 char *uw_Basis_sqlifyFloatN(uw_context ctx, uw_Basis_float *n) {
|
adamc@467
|
1061 if (n == NULL)
|
adamc@467
|
1062 return "NULL";
|
adamc@467
|
1063 else
|
adamc@467
|
1064 return uw_Basis_sqlifyFloat(ctx, *n);
|
adamc@467
|
1065 }
|
adamc@467
|
1066
|
adamc@281
|
1067
|
adamc@311
|
1068 uw_Basis_string uw_Basis_sqlifyString(uw_context ctx, uw_Basis_string s) {
|
adamc@280
|
1069 char *r, *s2;
|
adamc@280
|
1070
|
adamc@311
|
1071 uw_check_heap(ctx, strlen(s) * 2 + 10);
|
adamc@280
|
1072
|
adamc@280
|
1073 r = s2 = ctx->heap_front;
|
adamc@280
|
1074 *s2++ = 'E';
|
adamc@280
|
1075 *s2++ = '\'';
|
adamc@280
|
1076
|
adamc@280
|
1077 for (; *s; s++) {
|
adamc@280
|
1078 char c = *s;
|
adamc@280
|
1079
|
adamc@280
|
1080 switch (c) {
|
adamc@280
|
1081 case '\'':
|
adamc@280
|
1082 strcpy(s2, "\\'");
|
adamc@280
|
1083 s2 += 2;
|
adamc@280
|
1084 break;
|
adamc@280
|
1085 case '\\':
|
adamc@280
|
1086 strcpy(s2, "\\\\");
|
adamc@280
|
1087 s2 += 2;
|
adamc@280
|
1088 break;
|
adamc@280
|
1089 default:
|
adamc@280
|
1090 if (isprint(c))
|
adamc@280
|
1091 *s2++ = c;
|
adamc@280
|
1092 else {
|
adamc@280
|
1093 sprintf(s2, "\\%3o", c);
|
adamc@280
|
1094 s2 += 4;
|
adamc@280
|
1095 }
|
adamc@280
|
1096 }
|
adamc@280
|
1097 }
|
adamc@280
|
1098
|
adamc@281
|
1099 strcpy(s2, "'::text");
|
adamc@281
|
1100 ctx->heap_front = s2 + 8;
|
adamc@280
|
1101 return r;
|
adamc@280
|
1102 }
|
adamc@281
|
1103
|
adamc@467
|
1104 uw_Basis_string uw_Basis_sqlifyStringN(uw_context ctx, uw_Basis_string s) {
|
adamc@467
|
1105 if (s == NULL)
|
adamc@467
|
1106 return "NULL";
|
adamc@467
|
1107 else
|
adamc@467
|
1108 return uw_Basis_sqlifyString(ctx, s);
|
adamc@467
|
1109 }
|
adamc@467
|
1110
|
adamc@311
|
1111 char *uw_Basis_sqlifyBool(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
1112 if (b == uw_Basis_False)
|
adamc@281
|
1113 return "FALSE";
|
adamc@281
|
1114 else
|
adamc@281
|
1115 return "TRUE";
|
adamc@281
|
1116 }
|
adamc@282
|
1117
|
adamc@467
|
1118 char *uw_Basis_sqlifyBoolN(uw_context ctx, uw_Basis_bool *b) {
|
adamc@467
|
1119 if (b == NULL)
|
adamc@467
|
1120 return "NULL";
|
adamc@467
|
1121 else
|
adamc@467
|
1122 return uw_Basis_sqlifyBool(ctx, *b);
|
adamc@467
|
1123 }
|
adamc@467
|
1124
|
adamc@439
|
1125 char *uw_Basis_sqlifyTime(uw_context ctx, uw_Basis_time t) {
|
adamc@439
|
1126 size_t len;
|
adamc@439
|
1127 char *r;
|
adamc@439
|
1128 struct tm stm;
|
adamc@439
|
1129
|
adamc@439
|
1130 if (localtime_r(&t, &stm)) {
|
adamc@439
|
1131 uw_check_heap(ctx, TIMES_MAX);
|
adamc@439
|
1132 r = ctx->heap_front;
|
adamc@439
|
1133 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
|
adamc@439
|
1134 ctx->heap_front += len+1;
|
adamc@439
|
1135 return r;
|
adamc@439
|
1136 } else
|
adamc@439
|
1137 return "<Invalid time>";
|
adamc@439
|
1138 }
|
adamc@439
|
1139
|
adamc@467
|
1140 char *uw_Basis_sqlifyTimeN(uw_context ctx, uw_Basis_time *t) {
|
adamc@467
|
1141 if (t == NULL)
|
adamc@467
|
1142 return "NULL";
|
adamc@467
|
1143 else
|
adamc@467
|
1144 return uw_Basis_sqlifyTime(ctx, *t);
|
adamc@467
|
1145 }
|
adamc@467
|
1146
|
adamc@311
|
1147 char *uw_Basis_ensqlBool(uw_Basis_bool b) {
|
adamc@311
|
1148 static uw_Basis_int true = 1;
|
adamc@311
|
1149 static uw_Basis_int false = 0;
|
adamc@282
|
1150
|
adamc@311
|
1151 if (b == uw_Basis_False)
|
adamc@282
|
1152 return (char *)&false;
|
adamc@282
|
1153 else
|
adamc@282
|
1154 return (char *)&true;
|
adamc@282
|
1155 }
|
adamc@284
|
1156
|
adamc@311
|
1157 uw_Basis_string uw_Basis_intToString(uw_context ctx, uw_Basis_int n) {
|
adamc@284
|
1158 int len;
|
adamc@284
|
1159 char *r;
|
adamc@284
|
1160
|
adamc@311
|
1161 uw_check_heap(ctx, INTS_MAX);
|
adamc@284
|
1162 r = ctx->heap_front;
|
adamc@284
|
1163 sprintf(r, "%lld%n", n, &len);
|
adamc@284
|
1164 ctx->heap_front += len+1;
|
adamc@284
|
1165 return r;
|
adamc@284
|
1166 }
|
adamc@285
|
1167
|
adamc@311
|
1168 uw_Basis_string uw_Basis_floatToString(uw_context ctx, uw_Basis_float n) {
|
adamc@285
|
1169 int len;
|
adamc@285
|
1170 char *r;
|
adamc@285
|
1171
|
adamc@311
|
1172 uw_check_heap(ctx, FLOATS_MAX);
|
adamc@285
|
1173 r = ctx->heap_front;
|
adamc@285
|
1174 sprintf(r, "%g%n", n, &len);
|
adamc@285
|
1175 ctx->heap_front += len+1;
|
adamc@285
|
1176 return r;
|
adamc@285
|
1177 }
|
adamc@285
|
1178
|
adamc@311
|
1179 uw_Basis_string uw_Basis_boolToString(uw_context ctx, uw_Basis_bool b) {
|
adamc@311
|
1180 if (b == uw_Basis_False)
|
adamc@285
|
1181 return "False";
|
adamc@285
|
1182 else
|
adamc@285
|
1183 return "True";
|
adamc@285
|
1184 }
|
adamc@288
|
1185
|
adamc@436
|
1186 uw_Basis_string uw_Basis_timeToString(uw_context ctx, uw_Basis_time t) {
|
adamc@436
|
1187 size_t len;
|
adamc@436
|
1188 char *r;
|
adamc@436
|
1189 struct tm stm;
|
adamc@436
|
1190
|
adamc@436
|
1191 if (localtime_r(&t, &stm)) {
|
adamc@436
|
1192 uw_check_heap(ctx, TIMES_MAX);
|
adamc@436
|
1193 r = ctx->heap_front;
|
adamc@436
|
1194 len = strftime(r, TIMES_MAX, TIME_FMT, &stm);
|
adamc@436
|
1195 ctx->heap_front += len+1;
|
adamc@436
|
1196 return r;
|
adamc@436
|
1197 } else
|
adamc@436
|
1198 return "<Invalid time>";
|
adamc@436
|
1199 }
|
adamc@288
|
1200
|
adamc@311
|
1201 uw_Basis_int *uw_Basis_stringToInt(uw_context ctx, uw_Basis_string s) {
|
adamc@288
|
1202 char *endptr;
|
adamc@311
|
1203 uw_Basis_int n = strtoll(s, &endptr, 10);
|
adamc@288
|
1204
|
adamc@288
|
1205 if (*s != '\0' && *endptr == '\0') {
|
adamc@311
|
1206 uw_Basis_int *r = uw_malloc(ctx, sizeof(uw_Basis_int));
|
adamc@288
|
1207 *r = n;
|
adamc@288
|
1208 return r;
|
adamc@288
|
1209 } else
|
adamc@288
|
1210 return NULL;
|
adamc@288
|
1211 }
|
adamc@289
|
1212
|
adamc@311
|
1213 uw_Basis_float *uw_Basis_stringToFloat(uw_context ctx, uw_Basis_string s) {
|
adamc@289
|
1214 char *endptr;
|
adamc@311
|
1215 uw_Basis_float n = strtod(s, &endptr);
|
adamc@289
|
1216
|
adamc@289
|
1217 if (*s != '\0' && *endptr == '\0') {
|
adamc@311
|
1218 uw_Basis_float *r = uw_malloc(ctx, sizeof(uw_Basis_float));
|
adamc@289
|
1219 *r = n;
|
adamc@289
|
1220 return r;
|
adamc@289
|
1221 } else
|
adamc@289
|
1222 return NULL;
|
adamc@289
|
1223 }
|
adamc@289
|
1224
|
adamc@311
|
1225 uw_Basis_bool *uw_Basis_stringToBool(uw_context ctx, uw_Basis_string s) {
|
adamc@311
|
1226 static uw_Basis_bool true = uw_Basis_True;
|
adamc@311
|
1227 static uw_Basis_bool false = uw_Basis_False;
|
adamc@289
|
1228
|
adamc@289
|
1229 if (!strcasecmp (s, "True"))
|
adamc@289
|
1230 return &true;
|
adamc@289
|
1231 else if (!strcasecmp (s, "False"))
|
adamc@289
|
1232 return &false;
|
adamc@289
|
1233 else
|
adamc@289
|
1234 return NULL;
|
adamc@289
|
1235 }
|
adamc@292
|
1236
|
adamc@436
|
1237 uw_Basis_time *uw_Basis_stringToTime(uw_context ctx, uw_Basis_string s) {
|
adamc@438
|
1238 char *dot = strchr(s, '.'), *end = strchr(s, 0);
|
adamc@436
|
1239 struct tm stm;
|
adamc@436
|
1240
|
adamc@439
|
1241 if (dot) {
|
adamc@439
|
1242 *dot = 0;
|
adamc@439
|
1243 if (strptime(s, TIME_FMT_PG, &stm) == end) {
|
adamc@439
|
1244 *dot = '.';
|
adamc@439
|
1245 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
|
adamc@439
|
1246 *r = mktime(&stm);
|
adamc@439
|
1247 return r;
|
adamc@439
|
1248 }
|
adamc@439
|
1249 else {
|
adamc@439
|
1250 *dot = '.';
|
adamc@439
|
1251 return NULL;
|
adamc@439
|
1252 }
|
adamc@436
|
1253 }
|
adamc@439
|
1254 else {
|
adamc@439
|
1255 if (strptime(s, TIME_FMT_PG, &stm) == end) {
|
adamc@439
|
1256 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
|
adamc@439
|
1257 *r = mktime(&stm);
|
adamc@439
|
1258 return r;
|
adamc@439
|
1259 }
|
adamc@439
|
1260 else if (strptime(s, TIME_FMT, &stm) == end) {
|
adamc@439
|
1261 uw_Basis_time *r = uw_malloc(ctx, sizeof(uw_Basis_time));
|
adamc@439
|
1262 *r = mktime(&stm);
|
adamc@439
|
1263 return r;
|
adamc@439
|
1264 }
|
adamc@439
|
1265 else
|
adamc@439
|
1266 return NULL;
|
adamc@439
|
1267 }
|
adamc@436
|
1268 }
|
adamc@436
|
1269
|
adamc@311
|
1270 uw_Basis_int uw_Basis_stringToInt_error(uw_context ctx, uw_Basis_string s) {
|
adamc@292
|
1271 char *endptr;
|
adamc@311
|
1272 uw_Basis_int n = strtoll(s, &endptr, 10);
|
adamc@292
|
1273
|
adamc@292
|
1274 if (*s != '\0' && *endptr == '\0')
|
adamc@292
|
1275 return n;
|
adamc@292
|
1276 else
|
adamc@311
|
1277 uw_error(ctx, FATAL, "Can't parse int: %s", s);
|
adamc@292
|
1278 }
|
adamc@293
|
1279
|
adamc@311
|
1280 uw_Basis_float uw_Basis_stringToFloat_error(uw_context ctx, uw_Basis_string s) {
|
adamc@293
|
1281 char *endptr;
|
adamc@311
|
1282 uw_Basis_float n = strtod(s, &endptr);
|
adamc@293
|
1283
|
adamc@293
|
1284 if (*s != '\0' && *endptr == '\0')
|
adamc@293
|
1285 return n;
|
adamc@293
|
1286 else
|
adamc@311
|
1287 uw_error(ctx, FATAL, "Can't parse float: %s", s);
|
adamc@293
|
1288 }
|
adamc@293
|
1289
|
adamc@311
|
1290 uw_Basis_bool uw_Basis_stringToBool_error(uw_context ctx, uw_Basis_string s) {
|
adamc@296
|
1291 if (!strcasecmp(s, "T") || !strcasecmp (s, "True"))
|
adamc@311
|
1292 return uw_Basis_True;
|
adamc@296
|
1293 else if (!strcasecmp(s, "F") || !strcasecmp (s, "False"))
|
adamc@311
|
1294 return uw_Basis_False;
|
adamc@293
|
1295 else
|
adamc@311
|
1296 uw_error(ctx, FATAL, "Can't parse bool: %s", s);
|
adamc@293
|
1297 }
|
adamc@436
|
1298
|
adamc@436
|
1299 uw_Basis_time uw_Basis_stringToTime_error(uw_context ctx, uw_Basis_string s) {
|
adamc@438
|
1300 char *dot = strchr(s, '.'), *end = strchr(s, 0);
|
adamc@436
|
1301 struct tm stm = {};
|
adamc@436
|
1302
|
adamc@438
|
1303 if (dot) {
|
adamc@438
|
1304 *dot = 0;
|
adamc@438
|
1305 if (strptime(s, TIME_FMT_PG, &stm)) {
|
adamc@438
|
1306 *dot = '.';
|
adamc@438
|
1307 return mktime(&stm);
|
adamc@438
|
1308 }
|
adamc@438
|
1309 else {
|
adamc@438
|
1310 *dot = '.';
|
adamc@438
|
1311 uw_error(ctx, FATAL, "Can't parse time: %s", s);
|
adamc@438
|
1312 }
|
adamc@438
|
1313 }
|
adamc@438
|
1314 else {
|
adamc@439
|
1315 if (strptime(s, TIME_FMT_PG, &stm) == end)
|
adamc@439
|
1316 return mktime(&stm);
|
adamc@439
|
1317 else if (strptime(s, TIME_FMT, &stm) == end)
|
adamc@438
|
1318 return mktime(&stm);
|
adamc@438
|
1319 else
|
adamc@438
|
1320 uw_error(ctx, FATAL, "Can't parse time: %s", s);
|
adamc@438
|
1321 }
|
adamc@436
|
1322 }
|
adamc@457
|
1323
|
adamc@457
|
1324 uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
|
adamc@457
|
1325 int len = strlen(h);
|
adamc@457
|
1326 char *s = ctx->headers, *p;
|
adamc@457
|
1327
|
adamc@457
|
1328 while (p = strchr(s, ':')) {
|
adamc@457
|
1329 if (p - s == len && !strncasecmp(s, h, len)) {
|
adamc@458
|
1330 return p + 2;
|
adamc@457
|
1331 } else {
|
adamc@458
|
1332 if ((s = strchr(p, 0)) && s < ctx->headers_end)
|
adamc@458
|
1333 s += 2;
|
adamc@457
|
1334 else
|
adamc@457
|
1335 return NULL;
|
adamc@457
|
1336 }
|
adamc@457
|
1337 }
|
adamc@463
|
1338 }
|
adamc@458
|
1339
|
adamc@463
|
1340 uw_Basis_string uw_Basis_get_cookie(uw_context ctx, uw_Basis_string c) {
|
adamc@463
|
1341 int len = strlen(c);
|
adamc@474
|
1342 char *s = ctx->headers, *p = ctx->outHeaders;
|
adamc@474
|
1343
|
adamc@474
|
1344 while (p = strstr(p, "\nSet-Cookie: ")) {
|
adamc@474
|
1345 char *p2;
|
adamc@474
|
1346 p += 13;
|
adamc@474
|
1347 p2 = strchr(p, '=');
|
adamc@474
|
1348
|
adamc@474
|
1349 if (p2) {
|
adamc@474
|
1350 size_t sz = strcspn(p2+1, ";\r\n");
|
adamc@474
|
1351
|
adamc@474
|
1352 if (!strncasecmp(p, c, p2 - p)) {
|
adamc@474
|
1353 char *ret = uw_malloc(ctx, sz + 1);
|
adamc@474
|
1354 memcpy(ret, p2+1, sz);
|
adamc@474
|
1355 ret[sz] = 0;
|
adamc@474
|
1356 return ret;
|
adamc@474
|
1357 }
|
adamc@474
|
1358 }
|
adamc@474
|
1359 }
|
adamc@463
|
1360
|
adamc@463
|
1361 while (p = strchr(s, ':')) {
|
adamc@476
|
1362 if (!strncasecmp(s, "Cookie: ", 8)) {
|
adamc@476
|
1363 p += 2;
|
adamc@476
|
1364 while (1) {
|
adamc@476
|
1365 if (!strncmp(p, c, len)
|
adamc@476
|
1366 && p + len < ctx->headers_end && p[len] == '=')
|
adamc@476
|
1367 return p + 1 + len;
|
adamc@476
|
1368 else if (p = strchr(p, ';'))
|
adamc@476
|
1369 p += 2;
|
adamc@476
|
1370 else if ((s = strchr(s, 0)) && s < ctx->headers_end) {
|
adamc@476
|
1371 s += 2;
|
adamc@476
|
1372 break;
|
adamc@476
|
1373 }
|
adamc@476
|
1374 else
|
adamc@476
|
1375 return NULL;
|
adamc@476
|
1376 }
|
adamc@463
|
1377 } else {
|
adamc@463
|
1378 if ((s = strchr(p, 0)) && s < ctx->headers_end)
|
adamc@463
|
1379 s += 2;
|
adamc@463
|
1380 else
|
adamc@463
|
1381 return NULL;
|
adamc@463
|
1382 }
|
adamc@463
|
1383 }
|
adamc@457
|
1384 }
|
adamc@462
|
1385
|
adamc@466
|
1386 uw_unit uw_Basis_set_cookie(uw_context ctx, uw_Basis_string prefix, uw_Basis_string c, uw_Basis_string v) {
|
adamc@462
|
1387 uw_write_header(ctx, "Set-Cookie: ");
|
adamc@462
|
1388 uw_write_header(ctx, c);
|
adamc@462
|
1389 uw_write_header(ctx, "=");
|
adamc@462
|
1390 uw_write_header(ctx, v);
|
adamc@466
|
1391 uw_write_header(ctx, "; path=");
|
adamc@466
|
1392 uw_write_header(ctx, prefix);
|
adamc@462
|
1393 uw_write_header(ctx, "\r\n");
|
adamc@462
|
1394
|
adamc@462
|
1395 return uw_unit_v;
|
adamc@462
|
1396 }
|