agoo 2.15.10 → 2.15.11

Sign up to get free protection for your applications and to get access to all the features.
data/ext/agoo/page.c CHANGED
@@ -10,58 +10,58 @@
10
10
  #include "dtime.h"
11
11
  #include "page.h"
12
12
 
13
- #define PAGE_RECHECK_TIME 5.0
13
+ #define PAGE_RECHECK_TIME 5.0
14
14
 
15
- #define MAX_KEY_UNIQ 9
16
- #define MAX_KEY_LEN 1024
17
- #define PAGE_BUCKET_SIZE 1024
18
- #define PAGE_BUCKET_MASK 1023
15
+ #define MAX_KEY_UNIQ 9
16
+ #define MAX_KEY_LEN 1024
17
+ #define PAGE_BUCKET_SIZE 1024
18
+ #define PAGE_BUCKET_MASK 1023
19
19
 
20
- #define MAX_MIME_KEY_LEN 15
21
- #define MIME_BUCKET_SIZE 64
22
- #define MIME_BUCKET_MASK 63
20
+ #define MAX_MIME_KEY_LEN 15
21
+ #define MIME_BUCKET_SIZE 64
22
+ #define MIME_BUCKET_MASK 63
23
23
 
24
24
  typedef struct _slot {
25
- struct _slot *next;
26
- char key[MAX_KEY_LEN + 1];
27
- agooPage value;
28
- uint64_t hash;
29
- int klen;
25
+ struct _slot *next;
26
+ char key[MAX_KEY_LEN + 1];
27
+ agooPage value;
28
+ uint64_t hash;
29
+ int klen;
30
30
  } *Slot;
31
31
 
32
32
  typedef struct _headRule {
33
- struct _headRule *next;
34
- char *path;
35
- char *mime;
36
- char *key;
37
- char *value;
38
- int len; // length of key + value + ': ' + '\r\n'
33
+ struct _headRule *next;
34
+ char *path;
35
+ char *mime;
36
+ char *key;
37
+ char *value;
38
+ int len; // length of key + value + ': ' + '\r\n'
39
39
  } *HeadRule;
40
40
 
41
41
  typedef struct _mimeSlot {
42
- struct _mimeSlot *next;
43
- char key[MAX_MIME_KEY_LEN + 1];
44
- char *value;
45
- uint64_t hash;
46
- int klen;
42
+ struct _mimeSlot *next;
43
+ char key[MAX_MIME_KEY_LEN + 1];
44
+ char *value;
45
+ uint64_t hash;
46
+ int klen;
47
47
  } *MimeSlot;
48
48
 
49
49
  typedef struct _cache {
50
- Slot buckets[PAGE_BUCKET_SIZE];
51
- Slot ruckets[PAGE_BUCKET_SIZE];
52
- MimeSlot muckets[MIME_BUCKET_SIZE];
53
- char *root;
54
- agooGroup groups;
55
- HeadRule head_rules;
50
+ Slot buckets[PAGE_BUCKET_SIZE];
51
+ Slot ruckets[PAGE_BUCKET_SIZE];
52
+ MimeSlot muckets[MIME_BUCKET_SIZE];
53
+ char *root;
54
+ agooGroup groups;
55
+ HeadRule head_rules;
56
56
  } *Cache;
57
57
 
58
58
  typedef struct _mime {
59
- const char *suffix;
60
- const char *type;
59
+ const char *suffix;
60
+ const char *type;
61
61
  } *Mime;
62
62
 
63
63
  // These are used for the initial load.
64
- static struct _mime mime_map[] = {
64
+ static struct _mime mime_map[] = {
65
65
  { "asc", "text/plain" },
66
66
  { "avi", "video/x-msvideo" },
67
67
  { "bin", "application/octet-stream" },
@@ -108,8 +108,8 @@ static struct _mime mime_map[] = {
108
108
  { NULL, NULL }
109
109
  };
110
110
 
111
- static const char page_fmt[] = "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n";
112
- static const char page_min_fmt[] = "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n";
111
+ static const char page_fmt[] = "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n";
112
+ static const char page_min_fmt[] = "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n";
113
113
  // 0123456789abcdef0123456789abcdef
114
114
  static const char hex_map[] = "\
115
115
  ................................\
@@ -121,7 +121,7 @@ static const char hex_map[] = "\
121
121
  ................................\
122
122
  ................................";
123
123
 
124
- static struct _cache cache = {
124
+ static struct _cache cache = {
125
125
  .buckets = {0},
126
126
  .ruckets = {0},
127
127
  .muckets = {0},
@@ -147,15 +147,15 @@ parse_percent_seq(const char *seq) {
147
147
 
148
148
  static uint64_t
149
149
  calc_hash(const char *key, int *lenp) {
150
- int len = 0;
151
- int klen = *lenp;
152
- uint64_t h = 0;
153
- const uint8_t *k = (const uint8_t*)key;
150
+ int len = 0;
151
+ int klen = *lenp;
152
+ uint64_t h = 0;
153
+ const uint8_t *k = (const uint8_t*)key;
154
154
 
155
155
  for (; len < klen; k++) {
156
- // fast, just spread it out
157
- h = 77 * h + (*k - 0x2D);
158
- len++;
156
+ // fast, just spread it out
157
+ h = 77 * h + (*k - 0x2D);
158
+ len++;
159
159
  }
160
160
  *lenp = len;
161
161
 
@@ -180,94 +180,94 @@ get_mime_bucketp(uint64_t h) {
180
180
 
181
181
  const char*
182
182
  mime_get(const char *key) {
183
- int klen = (int)strlen(key);
184
- int len = klen;
185
- int64_t h = calc_hash(key, &len);
186
- MimeSlot *bucket = get_mime_bucketp(h);
187
- MimeSlot s;
188
- const char *v = NULL;
183
+ int klen = (int)strlen(key);
184
+ int len = klen;
185
+ int64_t h = calc_hash(key, &len);
186
+ MimeSlot *bucket = get_mime_bucketp(h);
187
+ MimeSlot s;
188
+ const char *v = NULL;
189
189
 
190
190
  for (s = *bucket; NULL != s; s = s->next) {
191
- if (h == (int64_t)s->hash && len == (int)s->klen &&
192
- ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
193
- v = s->value;
194
- break;
195
- }
191
+ if (h == (int64_t)s->hash && len == (int)s->klen &&
192
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
193
+ v = s->value;
194
+ break;
195
+ }
196
196
  }
197
197
  return v;
198
198
  }
199
199
 
200
200
  agooPage
201
201
  cache_get(const char *key, int klen) {
202
- int len = klen;
203
- int64_t h = calc_hash(key, &len);
204
- Slot *bucket = get_bucketp(h);
205
- Slot s;
206
- agooPage v = NULL;
202
+ int len = klen;
203
+ int64_t h = calc_hash(key, &len);
204
+ Slot *bucket = get_bucketp(h);
205
+ Slot s;
206
+ agooPage v = NULL;
207
207
 
208
208
  for (s = *bucket; NULL != s; s = s->next) {
209
- if (h == (int64_t)s->hash && len == (int)s->klen &&
210
- ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
211
- v = s->value;
212
- break;
213
- }
209
+ if (h == (int64_t)s->hash && len == (int)s->klen &&
210
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
211
+ v = s->value;
212
+ break;
213
+ }
214
214
  }
215
215
  return v;
216
216
  }
217
217
 
218
218
  agooPage
219
219
  cache_root_get(const char *key, int klen) {
220
- int len = klen;
221
- int64_t h = calc_hash(key, &len);
222
- Slot *bucket = get_rucketp(h);
223
- Slot s;
224
- agooPage v = NULL;
220
+ int len = klen;
221
+ int64_t h = calc_hash(key, &len);
222
+ Slot *bucket = get_rucketp(h);
223
+ Slot s;
224
+ agooPage v = NULL;
225
225
 
226
226
  for (s = *bucket; NULL != s; s = s->next) {
227
- if (h == (int64_t)s->hash && len == (int)s->klen &&
228
- ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
229
- v = s->value;
230
- break;
231
- }
227
+ if (h == (int64_t)s->hash && len == (int)s->klen &&
228
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
229
+ v = s->value;
230
+ break;
231
+ }
232
232
  }
233
233
  return v;
234
234
  }
235
235
 
236
236
  int
237
237
  mime_set(agooErr err, const char *key, const char *value) {
238
- int klen = (int)strlen(key);
239
- int len = klen;
240
- int64_t h = calc_hash(key, &len);
241
- MimeSlot *bucket = get_mime_bucketp(h);
242
- MimeSlot s;
238
+ int klen = (int)strlen(key);
239
+ int len = klen;
240
+ int64_t h = calc_hash(key, &len);
241
+ MimeSlot *bucket = get_mime_bucketp(h);
242
+ MimeSlot s;
243
243
 
244
244
  if (MAX_MIME_KEY_LEN < len) {
245
- return agoo_err_set(err, AGOO_ERR_ARG, "%s is too long for a file extension. Maximum is %d", key, MAX_MIME_KEY_LEN);
245
+ return agoo_err_set(err, AGOO_ERR_ARG, "%s is too long for a file extension. Maximum is %d", key, MAX_MIME_KEY_LEN);
246
246
  }
247
247
  for (s = *bucket; NULL != s; s = s->next) {
248
- if (h == (int64_t)s->hash && len == s->klen &&
249
- ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, len))) {
248
+ if (h == (int64_t)s->hash && len == s->klen &&
249
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, len))) {
250
250
 
251
- AGOO_FREE(s->value);
252
- if (NULL == (s->value = AGOO_STRDUP(value))) {
253
- return agoo_err_set(err, AGOO_ERR_ARG, "out of memory adding %s", key);
254
- }
255
- return AGOO_ERR_OK;
256
- }
251
+ AGOO_FREE(s->value);
252
+ if (NULL == (s->value = AGOO_STRDUP(value))) {
253
+ return agoo_err_set(err, AGOO_ERR_ARG, "out of memory adding %s", key);
254
+ }
255
+ return AGOO_ERR_OK;
256
+ }
257
257
  }
258
258
  if (NULL == (s = (MimeSlot)AGOO_MALLOC(sizeof(struct _mimeSlot)))) {
259
- return AGOO_ERR_MEM(err, "mime key and value");
259
+ return AGOO_ERR_MEM(err, "mime key and value");
260
260
  }
261
261
  s->hash = h;
262
262
  s->klen = len;
263
263
  if (NULL == key) {
264
- *s->key = '\0';
264
+ *s->key = '\0';
265
265
  } else {
266
- strcpy(s->key, key);
266
+ strcpy(s->key, key);
267
267
  }
268
268
  if (NULL == (s->value = AGOO_STRDUP(value))) {
269
- AGOO_FREE(s);
270
- return AGOO_ERR_MEM(err, "mime key and value");
269
+ AGOO_FREE(s);
270
+ return AGOO_ERR_MEM(err, "mime key and value");
271
271
  }
272
272
  s->next = *bucket;
273
273
  *bucket = s;
@@ -277,33 +277,33 @@ mime_set(agooErr err, const char *key, const char *value) {
277
277
 
278
278
  static agooPage
279
279
  bucket_set(Slot *bucket, int64_t h, const char *key, int klen, agooPage value) {
280
- Slot s;
281
- agooPage old = NULL;
280
+ Slot s;
281
+ agooPage old = NULL;
282
282
 
283
283
  if (MAX_KEY_LEN < klen) {
284
- return value;
284
+ return value;
285
285
  }
286
286
  for (s = *bucket; NULL != s; s = s->next) {
287
- if (h == (int64_t)s->hash && klen == s->klen &&
288
- ((0 <= klen && klen <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
287
+ if (h == (int64_t)s->hash && klen == s->klen &&
288
+ ((0 <= klen && klen <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
289
289
 
290
- old = s->value;
291
- // replace
292
- s->value = value;
290
+ old = s->value;
291
+ // replace
292
+ s->value = value;
293
293
 
294
- return old;
295
- }
294
+ return old;
295
+ }
296
296
  }
297
297
  if (NULL == (s = (Slot)AGOO_MALLOC(sizeof(struct _slot)))) {
298
- return value;
298
+ return value;
299
299
  }
300
300
  s->hash = h;
301
301
  s->klen = klen;
302
302
  if (NULL == key) {
303
- *s->key = '\0';
303
+ *s->key = '\0';
304
304
  } else {
305
- strncpy(s->key, key, klen);
306
- s->key[klen] = '\0';
305
+ strncpy(s->key, key, klen);
306
+ s->key[klen] = '\0';
307
307
  }
308
308
  s->value = value;
309
309
  s->next = *bucket;
@@ -314,32 +314,32 @@ bucket_set(Slot *bucket, int64_t h, const char *key, int klen, agooPage value) {
314
314
 
315
315
  static agooPage
316
316
  cache_set(const char *key, int klen, agooPage value) {
317
- int len = klen;
318
- int64_t h = calc_hash(key, &len);
319
- Slot *bucket = get_bucketp(h);
317
+ int len = klen;
318
+ int64_t h = calc_hash(key, &len);
319
+ Slot *bucket = get_bucketp(h);
320
320
 
321
321
  return bucket_set(bucket, h, key, len, value);
322
322
  }
323
323
 
324
324
  static agooPage
325
325
  cache_root_set(const char *key, int klen, agooPage value) {
326
- int len = klen;
327
- int64_t h = calc_hash(key, &len);
328
- Slot *bucket = get_rucketp(h);
326
+ int len = klen;
327
+ int64_t h = calc_hash(key, &len);
328
+ Slot *bucket = get_rucketp(h);
329
329
 
330
330
  return bucket_set(bucket, h, key, len, value);
331
331
  }
332
332
 
333
333
  int
334
334
  agoo_pages_init(agooErr err) {
335
- Mime m;
335
+ Mime m;
336
336
 
337
337
  memset(&cache, 0, sizeof(struct _cache));
338
338
  if (NULL == (cache.root = AGOO_STRDUP("."))) {
339
- return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
339
+ return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
340
340
  }
341
341
  for (m = mime_map; NULL != m->suffix; m++) {
342
- mime_set(err, m->suffix, m->type);
342
+ mime_set(err, m->suffix, m->type);
343
343
  }
344
344
  return err->code;
345
345
  }
@@ -348,11 +348,11 @@ int
348
348
  agoo_pages_set_root(agooErr err, const char *root) {
349
349
  AGOO_FREE(cache.root);
350
350
  if (NULL == root) {
351
- cache.root = NULL;
351
+ cache.root = NULL;
352
352
  } else {
353
- if (NULL == (cache.root = AGOO_STRDUP(root))) {
354
- return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
355
- }
353
+ if (NULL == (cache.root = AGOO_STRDUP(root))) {
354
+ return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
355
+ }
356
356
  }
357
357
  return AGOO_ERR_OK;
358
358
  }
@@ -360,8 +360,8 @@ agoo_pages_set_root(agooErr err, const char *root) {
360
360
  static void
361
361
  agoo_page_destroy(agooPage p) {
362
362
  if (NULL != p->resp) {
363
- agoo_text_release(p->resp);
364
- p->resp = NULL;
363
+ agoo_text_release(p->resp);
364
+ p->resp = NULL;
365
365
  }
366
366
  AGOO_FREE(p->path);
367
367
  AGOO_FREE(p);
@@ -369,86 +369,86 @@ agoo_page_destroy(agooPage p) {
369
369
 
370
370
  void
371
371
  agoo_pages_cleanup() {
372
- Slot *sp = cache.buckets;
373
- Slot s;
374
- Slot n;
375
- MimeSlot *mp = cache.muckets;
376
- MimeSlot sm;
377
- MimeSlot m;
378
- HeadRule hr;
379
- int i;
372
+ Slot *sp = cache.buckets;
373
+ Slot s;
374
+ Slot n;
375
+ MimeSlot *mp = cache.muckets;
376
+ MimeSlot sm;
377
+ MimeSlot m;
378
+ HeadRule hr;
379
+ int i;
380
380
 
381
381
  for (i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
382
- for (s = *sp; NULL != s; s = n) {
383
- n = s->next;
384
- agoo_page_destroy(s->value);
385
- AGOO_FREE(s);
386
- }
387
- *sp = NULL;
382
+ for (s = *sp; NULL != s; s = n) {
383
+ n = s->next;
384
+ agoo_page_destroy(s->value);
385
+ AGOO_FREE(s);
386
+ }
387
+ *sp = NULL;
388
388
  }
389
389
  for (sp = cache.ruckets, i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
390
- for (s = *sp; NULL != s; s = n) {
391
- n = s->next;
392
- agoo_page_destroy(s->value);
393
- AGOO_FREE(s);
394
- }
395
- *sp = NULL;
390
+ for (s = *sp; NULL != s; s = n) {
391
+ n = s->next;
392
+ agoo_page_destroy(s->value);
393
+ AGOO_FREE(s);
394
+ }
395
+ *sp = NULL;
396
396
  }
397
397
  for (i = MIME_BUCKET_SIZE; 0 < i; i--, mp++) {
398
- for (sm = *mp; NULL != sm; sm = m) {
399
- m = sm->next;
400
- AGOO_FREE(sm->value);
401
- AGOO_FREE(sm);
402
- }
403
- *mp = NULL;
398
+ for (sm = *mp; NULL != sm; sm = m) {
399
+ m = sm->next;
400
+ AGOO_FREE(sm->value);
401
+ AGOO_FREE(sm);
402
+ }
403
+ *mp = NULL;
404
404
  }
405
405
  while (NULL != (hr = cache.head_rules)) {
406
- cache.head_rules = hr->next;
407
- AGOO_FREE(hr->path);
408
- AGOO_FREE(hr->mime);
409
- AGOO_FREE(hr->key);
410
- AGOO_FREE(hr->value);
411
- AGOO_FREE(hr);
406
+ cache.head_rules = hr->next;
407
+ AGOO_FREE(hr->path);
408
+ AGOO_FREE(hr->mime);
409
+ AGOO_FREE(hr->key);
410
+ AGOO_FREE(hr->value);
411
+ AGOO_FREE(hr);
412
412
  }
413
413
  AGOO_FREE(cache.root);
414
414
  }
415
415
 
416
416
  static const char*
417
417
  path_mime(const char *path) {
418
- const char *suffix = path + strlen(path) - 1;
419
- const char *mime = NULL;
418
+ const char *suffix = path + strlen(path) - 1;
419
+ const char *mime = NULL;
420
420
 
421
421
  for (; '.' != *suffix; suffix--) {
422
- if (suffix <= path) {
423
- suffix = NULL;
424
- break;
425
- }
422
+ if (suffix <= path) {
423
+ suffix = NULL;
424
+ break;
425
+ }
426
426
  }
427
427
  if (suffix <= path) {
428
- suffix = NULL;
428
+ suffix = NULL;
429
429
  }
430
430
  if (NULL != suffix) {
431
- suffix++;
432
- mime = mime_get(suffix);
431
+ suffix++;
432
+ mime = mime_get(suffix);
433
433
  }
434
434
  return mime;
435
435
  }
436
436
 
437
437
  static const char*
438
438
  path_suffix(const char *path) {
439
- const char *suffix = path + strlen(path) - 1;
439
+ const char *suffix = path + strlen(path) - 1;
440
440
 
441
441
  for (; '.' != *suffix; suffix--) {
442
- if (suffix <= path) {
443
- suffix = NULL;
444
- break;
445
- }
442
+ if (suffix <= path) {
443
+ suffix = NULL;
444
+ break;
445
+ }
446
446
  }
447
447
  if (suffix <= path) {
448
- suffix = NULL;
448
+ suffix = NULL;
449
449
  }
450
450
  if (NULL != suffix) {
451
- suffix++;
451
+ suffix++;
452
452
  }
453
453
  return suffix;
454
454
  }
@@ -456,141 +456,141 @@ path_suffix(const char *path) {
456
456
  static bool
457
457
  path_match(const char *pat, const char *path) {
458
458
  if (NULL == pat) {
459
- return true;
459
+ return true;
460
460
  }
461
461
  if (NULL == path) {
462
- return '*' == *pat && '*' == pat[1] && '\0' == pat[2];
462
+ return '*' == *pat && '*' == pat[1] && '\0' == pat[2];
463
463
  }
464
464
  if ('/' == *path) {
465
- path++;
465
+ path++;
466
466
  }
467
467
  for (; '\0' != *pat && '\0' != *path; pat++) {
468
- if (*path == *pat) {
469
- path++;
470
- } else if ('*' == *pat) {
471
- if ('*' == *(pat + 1)) {
472
- return true;
473
- }
474
- for (; '\0' != *path && '/' != *path; path++) {
475
- }
476
- } else {
477
- break;
478
- }
468
+ if (*path == *pat) {
469
+ path++;
470
+ } else if ('*' == *pat) {
471
+ if ('*' == *(pat + 1)) {
472
+ return true;
473
+ }
474
+ for (; '\0' != *path && '/' != *path; path++) {
475
+ }
476
+ } else {
477
+ break;
478
+ }
479
479
  }
480
480
  return '\0' == *pat && '\0' == *path;
481
481
  }
482
482
 
483
483
  static bool
484
484
  head_rule_match(HeadRule rule, const char *path, const char *mime) {
485
- const char *suffix = NULL;
485
+ const char *suffix = NULL;
486
486
 
487
487
  if (NULL != path) {
488
- suffix = path_suffix(path);
488
+ suffix = path_suffix(path);
489
489
  }
490
490
  return path_match(rule->path, path) &&
491
- (NULL == rule->mime || 0 == strcmp(rule->mime, mime) ||
492
- (NULL != suffix && 0 == strcmp(rule->mime, suffix)));
491
+ (NULL == rule->mime || 0 == strcmp(rule->mime, mime) ||
492
+ (NULL != suffix && 0 == strcmp(rule->mime, suffix)));
493
493
  }
494
494
 
495
495
  // The page resp points to the page resp msg to save memory and reduce
496
496
  // allocations.
497
497
  agooPage
498
498
  agoo_page_create(const char *path) {
499
- agooPage p = (agooPage)AGOO_MALLOC(sizeof(struct _agooPage));
499
+ agooPage p = (agooPage)AGOO_MALLOC(sizeof(struct _agooPage));
500
500
 
501
501
  if (NULL != p) {
502
- p->resp = NULL;
503
- if (NULL == path) {
504
- p->path = NULL;
505
- } else {
506
- if (NULL == (p->path = AGOO_STRDUP(path))) {
507
- AGOO_FREE(p);
508
- return NULL;
509
- }
510
- }
511
- p->mtime = 0;
512
- p->last_check = 0.0;
513
- p->immutable = false;
502
+ p->resp = NULL;
503
+ if (NULL == path) {
504
+ p->path = NULL;
505
+ } else {
506
+ if (NULL == (p->path = AGOO_STRDUP(path))) {
507
+ AGOO_FREE(p);
508
+ return NULL;
509
+ }
510
+ }
511
+ p->mtime = 0;
512
+ p->last_check = 0.0;
513
+ p->immutable = false;
514
514
  }
515
515
  return p;
516
516
  }
517
517
 
518
518
  agooPage
519
519
  agoo_page_immutable(agooErr err, const char *path, const char *content, int clen) {
520
- agooPage p = (agooPage)AGOO_MALLOC(sizeof(struct _agooPage));
521
- const char *mime = path_mime(path);
522
- char *rel_path = NULL;
523
- long msize;
524
- int cnt;
525
- int plen = 0;
526
- long hlen = 0;
527
- HeadRule hr;
520
+ agooPage p = (agooPage)AGOO_MALLOC(sizeof(struct _agooPage));
521
+ const char *mime = path_mime(path);
522
+ char *rel_path = NULL;
523
+ long msize;
524
+ int cnt;
525
+ int plen = 0;
526
+ long hlen = 0;
527
+ HeadRule hr;
528
528
 
529
529
  if (NULL == p) {
530
- AGOO_ERR_MEM(err, "Page");
531
- return NULL;
530
+ AGOO_ERR_MEM(err, "Page");
531
+ return NULL;
532
532
  }
533
533
  if (NULL == path) {
534
- p->path = NULL;
534
+ p->path = NULL;
535
535
  } else {
536
- if (NULL == (p->path = AGOO_STRDUP(path))) {
537
- AGOO_FREE(p);
538
- return NULL;
539
- }
540
- plen = (int)strlen(path);
541
- if (NULL != cache.root) {
542
- int rlen = (int)strlen(cache.root);
543
-
544
- if (0 == strncmp(cache.root, p->path, rlen) && '/' == p->path[rlen]) {
545
- rel_path = p->path + rlen + 1;
546
- } else {
547
- rel_path = NULL;
548
- }
549
- }
536
+ if (NULL == (p->path = AGOO_STRDUP(path))) {
537
+ AGOO_FREE(p);
538
+ return NULL;
539
+ }
540
+ plen = (int)strlen(path);
541
+ if (NULL != cache.root) {
542
+ int rlen = (int)strlen(cache.root);
543
+
544
+ if (0 == strncmp(cache.root, p->path, rlen) && '/' == p->path[rlen]) {
545
+ rel_path = p->path + rlen + 1;
546
+ } else {
547
+ rel_path = NULL;
548
+ }
549
+ }
550
550
  }
551
551
  p->mtime = 0;
552
552
  p->last_check = 0.0;
553
553
  p->immutable = true;
554
554
 
555
555
  if (NULL == mime) {
556
- mime = "text/html";
556
+ mime = "text/html";
557
557
  }
558
558
  if (0 == clen) {
559
- clen = (int)strlen(content);
559
+ clen = (int)strlen(content);
560
560
  }
561
561
  for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
562
- if (head_rule_match(hr, rel_path, mime)) {
563
- hlen += hr->len;
564
- }
562
+ if (head_rule_match(hr, rel_path, mime)) {
563
+ hlen += hr->len;
564
+ }
565
565
  }
566
566
  // Format size plus space for the length, the mime type, and some
567
567
  // padding. Then add the content length.
568
568
  msize = sizeof(page_fmt) + 60 + clen;
569
569
  if (NULL == (p->resp = agoo_text_allocate((int)msize))) {
570
- AGOO_ERR_MEM(err, "Page content");
571
- AGOO_FREE(p);
572
- return NULL;
570
+ AGOO_ERR_MEM(err, "Page content");
571
+ AGOO_FREE(p);
572
+ return NULL;
573
573
  }
574
574
  if (0 < hlen) {
575
- bool has_ct;
576
-
577
- cnt = sprintf(p->resp->text, page_min_fmt, (long)clen); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
578
- for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
579
- if (head_rule_match(hr, rel_path, mime)) {
580
- cnt += sprintf(p->resp->text + cnt, "%s: %s\r\n", hr->key, hr->value);
581
- if (0 == strcasecmp("Content-Type", hr->key)) {
582
- has_ct = true;
583
- }
584
- }
585
- }
586
- if (!has_ct) {
587
- cnt += sprintf(p->resp->text + cnt, "Content-Type: %s\r\n\r\n", mime);
588
- } else {
589
- strcpy(p->resp->text + cnt, "\r\n");
590
- cnt += 2;
591
- }
575
+ bool has_ct;
576
+
577
+ cnt = sprintf(p->resp->text, page_min_fmt, (long)clen); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
578
+ for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
579
+ if (head_rule_match(hr, rel_path, mime)) {
580
+ cnt += sprintf(p->resp->text + cnt, "%s: %s\r\n", hr->key, hr->value);
581
+ if (0 == strcasecmp("Content-Type", hr->key)) {
582
+ has_ct = true;
583
+ }
584
+ }
585
+ }
586
+ if (!has_ct) {
587
+ cnt += sprintf(p->resp->text + cnt, "Content-Type: %s\r\n\r\n", mime);
588
+ } else {
589
+ strcpy(p->resp->text + cnt, "\r\n");
590
+ cnt += 2;
591
+ }
592
592
  } else {
593
- cnt = sprintf(p->resp->text, page_fmt, mime, (long)clen);
593
+ cnt = sprintf(p->resp->text, page_fmt, mime, (long)clen);
594
594
  }
595
595
  msize = cnt + clen;
596
596
  memcpy(p->resp->text + cnt, content, clen);
@@ -611,19 +611,19 @@ close_return_false(FILE *f) {
611
611
 
612
612
  static bool
613
613
  update_contents(agooPage p) {
614
- const char *mime = path_mime(p->path);
615
- char path[1024];
616
- char *rel_path = NULL;
617
- int plen = (int)strlen(p->path);
618
- long size;
619
- struct stat fattr;
620
- long msize;
621
- long hlen = 0;
622
- int cnt;
623
- struct stat fs;
624
- agooText t;
625
- FILE *f = fopen(p->path, "rb");
626
- HeadRule hr;
614
+ const char *mime = path_mime(p->path);
615
+ char path[1024];
616
+ char *rel_path = NULL;
617
+ int plen = (int)strlen(p->path);
618
+ long size;
619
+ struct stat fattr;
620
+ long msize;
621
+ long hlen = 0;
622
+ int cnt;
623
+ struct stat fs;
624
+ agooText t;
625
+ FILE *f = fopen(p->path, "rb");
626
+ HeadRule hr;
627
627
 
628
628
  strncpy(path, p->path, sizeof(path));
629
629
  path[sizeof(path) - 1] = '\0';
@@ -631,104 +631,104 @@ update_contents(agooPage p) {
631
631
  // fstat is called to get the file mode and verify it is a regular file or
632
632
  // a symlink.
633
633
  if (NULL != f) {
634
- if (0 == fstat(fileno(f), &fs)) {
635
- if (!S_ISREG(fs.st_mode) && !S_ISLNK(fs.st_mode)) {
636
- fclose(f);
637
- f = NULL;
638
- }
639
- } else {
640
- return close_return_false(f);
641
- }
634
+ if (0 == fstat(fileno(f), &fs)) {
635
+ if (!S_ISREG(fs.st_mode) && !S_ISLNK(fs.st_mode)) {
636
+ fclose(f);
637
+ f = NULL;
638
+ }
639
+ } else {
640
+ return close_return_false(f);
641
+ }
642
642
  }
643
643
  if (NULL == f) {
644
- // If not found how about with a /index.html added?
645
- if (NULL == mime) {
646
- int cnt;
647
-
648
- if ('/' == p->path[plen - 1]) {
649
- cnt = snprintf(path, sizeof(path), "%sindex.html", p->path);
650
- } else {
651
- cnt = snprintf(path, sizeof(path), "%s/index.html", p->path);
652
- }
653
- if ((int)sizeof(path) < cnt) {
654
- return false;
655
- }
656
- if (NULL == (f = fopen(path, "rb"))) {
657
- return false;
658
- }
659
- mime = "text/html";
660
- } else {
661
- return false;
662
- }
644
+ // If not found how about with a /index.html added?
645
+ if (NULL == mime) {
646
+ int cnt;
647
+
648
+ if ('/' == p->path[plen - 1]) {
649
+ cnt = snprintf(path, sizeof(path), "%sindex.html", p->path);
650
+ } else {
651
+ cnt = snprintf(path, sizeof(path), "%s/index.html", p->path);
652
+ }
653
+ if ((int)sizeof(path) < cnt) {
654
+ return false;
655
+ }
656
+ if (NULL == (f = fopen(path, "rb"))) {
657
+ return false;
658
+ }
659
+ mime = "text/html";
660
+ } else {
661
+ return false;
662
+ }
663
663
  }
664
664
  if (NULL == mime) {
665
- mime = "text/html";
665
+ mime = "text/html";
666
666
  }
667
667
  if (0 != fseek(f, 0, SEEK_END)) {
668
- return close_return_false(f);
668
+ return close_return_false(f);
669
669
  }
670
670
  if (0 > (size = ftell(f))) {
671
- return close_return_false(f);
671
+ return close_return_false(f);
672
672
  }
673
673
  rewind(f);
674
674
 
675
675
  if (NULL != cache.root) {
676
- int rlen = (int)strlen(cache.root);
676
+ int rlen = (int)strlen(cache.root);
677
677
 
678
- if (0 == strncmp(cache.root, path, rlen) && '/' == path[rlen]) {
679
- rel_path = path + rlen + 1;
680
- }
678
+ if (0 == strncmp(cache.root, path, rlen) && '/' == path[rlen]) {
679
+ rel_path = path + rlen + 1;
680
+ }
681
681
  }
682
682
  for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
683
- if (head_rule_match(hr, rel_path, mime)) {
684
- hlen += hr->len;
685
- }
683
+ if (head_rule_match(hr, rel_path, mime)) {
684
+ hlen += hr->len;
685
+ }
686
686
  }
687
687
  // Format size plus space for the length, the mime type, and some
688
688
  // padding. Then add the header rule and content length.
689
689
  msize = sizeof(page_fmt) + 60 + size + hlen;
690
690
  if (NULL == (t = agoo_text_allocate((int)msize))) {
691
- return close_return_false(f);
691
+ return close_return_false(f);
692
692
  }
693
693
  if (0 < hlen) {
694
- bool has_ct = false;
695
-
696
- cnt = sprintf(t->text, page_min_fmt, size); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
697
- for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
698
- if (head_rule_match(hr, rel_path, mime)) {
699
- cnt += sprintf(t->text + cnt, "%s: %s\r\n", hr->key, hr->value);
700
- if (0 == strcasecmp("Content-Type", hr->key)) {
701
- has_ct = true;
702
- }
703
- }
704
- }
705
- if (!has_ct) {
706
- cnt += sprintf(t->text + cnt, "Content-Type: %s\r\n\r\n", mime);
707
- } else {
708
- strcpy(t->text + cnt, "\r\n");
709
- cnt += 2;
710
- }
694
+ bool has_ct = false;
695
+
696
+ cnt = sprintf(t->text, page_min_fmt, size); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
697
+ for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
698
+ if (head_rule_match(hr, rel_path, mime)) {
699
+ cnt += sprintf(t->text + cnt, "%s: %s\r\n", hr->key, hr->value);
700
+ if (0 == strcasecmp("Content-Type", hr->key)) {
701
+ has_ct = true;
702
+ }
703
+ }
704
+ }
705
+ if (!has_ct) {
706
+ cnt += sprintf(t->text + cnt, "Content-Type: %s\r\n\r\n", mime);
707
+ } else {
708
+ strcpy(t->text + cnt, "\r\n");
709
+ cnt += 2;
710
+ }
711
711
  } else {
712
- cnt = sprintf(t->text, page_fmt, mime, size);
712
+ cnt = sprintf(t->text, page_fmt, mime, size);
713
713
  }
714
714
  msize = cnt + size;
715
715
  if (0 < size) {
716
- if (size != (long)fread(t->text + cnt, 1, size, f)) {
717
- agoo_text_release(t);
718
- return close_return_false(f);
719
- }
716
+ if (size != (long)fread(t->text + cnt, 1, size, f)) {
717
+ agoo_text_release(t);
718
+ return close_return_false(f);
719
+ }
720
720
  }
721
721
  fclose(f);
722
722
  t->text[msize] = '\0';
723
723
  t->len = msize;
724
724
  if (0 == stat(p->path, &fattr)) {
725
- p->mtime = fattr.st_mtime;
725
+ p->mtime = fattr.st_mtime;
726
726
  } else {
727
- p->mtime = 0;
727
+ p->mtime = 0;
728
728
  }
729
729
  if (NULL != p->resp) {
730
- agoo_text_release(p->resp);
731
- p->resp = NULL;
730
+ agoo_text_release(p->resp);
731
+ p->resp = NULL;
732
732
  }
733
733
  p->resp = t;
734
734
  agoo_text_ref(p->resp);
@@ -739,73 +739,73 @@ update_contents(agooPage p) {
739
739
 
740
740
  static void
741
741
  agoo_page_remove(agooPage p) {
742
- int len = (int)strlen(p->path);
743
- int64_t h = calc_hash(p->path, &len);
744
- Slot *bucket = get_bucketp(h);
745
- Slot s;
746
- Slot prev = NULL;
742
+ int len = (int)strlen(p->path);
743
+ int64_t h = calc_hash(p->path, &len);
744
+ Slot *bucket = get_bucketp(h);
745
+ Slot s;
746
+ Slot prev = NULL;
747
747
 
748
748
  for (s = *bucket; NULL != s; s = s->next) {
749
- if (h == (int64_t)s->hash && len == (int)s->klen &&
750
- ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, p->path, len))) {
749
+ if (h == (int64_t)s->hash && len == (int)s->klen &&
750
+ ((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, p->path, len))) {
751
751
 
752
- if (NULL == prev) {
753
- *bucket = s->next;
754
- } else {
755
- prev->next = s->next;
756
- }
757
- agoo_page_destroy(s->value);
758
- AGOO_FREE(s);
752
+ if (NULL == prev) {
753
+ *bucket = s->next;
754
+ } else {
755
+ prev->next = s->next;
756
+ }
757
+ agoo_page_destroy(s->value);
758
+ AGOO_FREE(s);
759
759
 
760
- break;
761
- }
762
- prev = s;
760
+ break;
761
+ }
762
+ prev = s;
763
763
  }
764
764
  }
765
765
 
766
766
  static agooPage
767
767
  page_check(agooErr err, agooPage page) {
768
768
  if (!page->immutable) {
769
- double now = dtime();
770
-
771
- if (page->last_check + PAGE_RECHECK_TIME < now) {
772
- struct stat fattr;
773
-
774
- if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
775
- update_contents(page);
776
- if (NULL == page->resp) {
777
- agoo_page_remove(page);
778
- agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
779
- return NULL;
780
- }
781
- }
782
- page->last_check = now;
783
- }
769
+ double now = dtime();
770
+
771
+ if (page->last_check + PAGE_RECHECK_TIME < now) {
772
+ struct stat fattr;
773
+
774
+ if (0 == stat(page->path, &fattr) && page->mtime != fattr.st_mtime) {
775
+ update_contents(page);
776
+ if (NULL == page->resp) {
777
+ agoo_page_remove(page);
778
+ agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
779
+ return NULL;
780
+ }
781
+ }
782
+ page->last_check = now;
783
+ }
784
784
  }
785
785
  return page;
786
786
  }
787
787
 
788
788
  agooPage
789
789
  agoo_page_get(agooErr err, const char *path, int plen, const char *root) {
790
- agooPage page = NULL;
790
+ agooPage page = NULL;
791
791
 
792
792
  if (NULL != strstr(path, "../")) {
793
- return NULL;
793
+ return NULL;
794
794
  }
795
795
  if (NULL != root) {
796
- char full_path[2048];
797
- char *s = stpcpy(full_path, root);
798
-
799
- if (NULL != strstr(path, "../")) {
800
- return NULL;
801
- }
802
- if ((int)sizeof(full_path) <= plen + (s - full_path)) {
803
- AGOO_ERR_MEM(err, "Page path");
804
- return NULL;
805
- }
806
- if ('/' != *root && '/' != *(s - 1) && '/' != *path) {
807
- *s++ = '/';
808
- }
796
+ char full_path[2048];
797
+ char *s = stpcpy(full_path, root);
798
+
799
+ if (NULL != strstr(path, "../")) {
800
+ return NULL;
801
+ }
802
+ if ((int)sizeof(full_path) <= plen + (s - full_path)) {
803
+ AGOO_ERR_MEM(err, "Page path");
804
+ return NULL;
805
+ }
806
+ if ('/' != *(s - 1) && '/' != *path) {
807
+ *s++ = '/';
808
+ }
809
809
  // TBD if path has % then ...
810
810
  if (NULL != memchr(path, '%', plen)) {
811
811
  const char *pend = path + plen;
@@ -823,44 +823,44 @@ agoo_page_get(agooErr err, const char *path, int plen, const char *root) {
823
823
  strncpy(s, path, plen);
824
824
  s += plen;
825
825
  }
826
- *s = '\0';
826
+ *s = '\0';
827
827
  plen = (int)(s - full_path);
828
- if (NULL == (page = cache_root_get(full_path, plen))) {
829
- if (NULL != cache.root) {
830
- agooPage old;
831
-
832
- if (NULL == (page = agoo_page_create(full_path))) {
833
- AGOO_ERR_MEM(err, "Page");
834
- return NULL;
835
- }
836
- if (!update_contents(page) || NULL == page->resp) {
837
- agoo_page_destroy(page);
838
- agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
839
- return NULL;
840
- }
841
- if (NULL != (old = cache_root_set(full_path, plen, page))) {
842
- agoo_page_destroy(old);
843
- }
844
- }
845
- } else {
846
- page = page_check(err, page);
847
- }
828
+ if (NULL == (page = cache_root_get(full_path, plen))) {
829
+ if (NULL != cache.root) {
830
+ agooPage old;
831
+
832
+ if (NULL == (page = agoo_page_create(full_path))) {
833
+ AGOO_ERR_MEM(err, "Page");
834
+ return NULL;
835
+ }
836
+ if (!update_contents(page) || NULL == page->resp) {
837
+ agoo_page_destroy(page);
838
+ agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
839
+ return NULL;
840
+ }
841
+ if (NULL != (old = cache_root_set(full_path, plen, page))) {
842
+ agoo_page_destroy(old);
843
+ }
844
+ }
845
+ } else {
846
+ page = page_check(err, page);
847
+ }
848
848
  } else {
849
- if (NULL == (page = cache_get(path, plen))) {
849
+ if (NULL == (page = cache_get(path, plen))) {
850
850
  bool has_percent = NULL != memchr(path, '%', plen);
851
851
 
852
- if (NULL != cache.root || has_percent) {
853
- agooPage old;
854
- char full_path[2048];
855
- char *s = stpcpy(full_path, cache.root);
856
-
857
- if ('/' != *cache.root && '/' != *path) {
858
- *s++ = '/';
859
- }
860
- if ((int)sizeof(full_path) <= plen + (s - full_path)) {
861
- AGOO_ERR_MEM(err, "Page path");
862
- return NULL;
863
- }
852
+ if (NULL != cache.root || has_percent) {
853
+ agooPage old;
854
+ char full_path[2048];
855
+ char *s = stpcpy(full_path, cache.root);
856
+
857
+ if ('/' != *(s - 1) && '/' != *path) {
858
+ *s++ = '/';
859
+ }
860
+ if ((int)sizeof(full_path) <= plen + (s - full_path)) {
861
+ AGOO_ERR_MEM(err, "Page path");
862
+ return NULL;
863
+ }
864
864
  if (has_percent) {
865
865
  const char *pend = path + plen;
866
866
  const char *pp = path;
@@ -878,150 +878,150 @@ agoo_page_get(agooErr err, const char *path, int plen, const char *root) {
878
878
  strncpy(s, path, plen);
879
879
  s[plen] = '\0';
880
880
  }
881
- if (NULL == (page = agoo_page_create(full_path))) { // TBD full_path or original path?
882
- AGOO_ERR_MEM(err, "Page");
883
- return NULL;
884
- }
881
+ if (NULL == (page = agoo_page_create(full_path))) { // TBD full_path or original path?
882
+ AGOO_ERR_MEM(err, "Page");
883
+ return NULL;
884
+ }
885
885
  plen = (int)strlen(full_path);
886
- if (!update_contents(page) || NULL == page->resp) {
887
- agoo_page_destroy(page);
888
- agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
889
- return NULL;
890
- }
886
+ if (!update_contents(page) || NULL == page->resp) {
887
+ agoo_page_destroy(page);
888
+ agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
889
+ return NULL;
890
+ }
891
891
  // Cache key is the original path/plen.
892
- if (NULL != (old = cache_set(path, plen, page))) {
893
- agoo_page_destroy(old);
894
- }
895
- }
896
- } else {
897
- page = page_check(err, page);
898
- }
892
+ if (NULL != (old = cache_set(path, plen, page))) {
893
+ agoo_page_destroy(old);
894
+ }
895
+ }
896
+ } else {
897
+ page = page_check(err, page);
898
+ }
899
899
  }
900
900
  return page;
901
901
  }
902
902
 
903
903
  agooPage
904
904
  agoo_group_get(agooErr err, const char *path, int plen) {
905
- agooPage page = NULL;
906
- agooGroup g = NULL;
907
- char full_path[2048];
908
- char *s = NULL;
909
- agooDir d;
905
+ agooPage page = NULL;
906
+ agooGroup g = NULL;
907
+ char full_path[2048];
908
+ char *s = NULL;
909
+ agooDir d;
910
910
 
911
911
  if (NULL != strstr(path, "../")) {
912
- return NULL;
912
+ return NULL;
913
913
  }
914
914
  for (g = cache.groups; NULL != g; g = g->next) {
915
- if (g->plen < plen && 0 == strncmp(path, g->path, g->plen) && '/' == path[g->plen]) {
916
- break;
917
- }
915
+ if (g->plen < plen && 0 == strncmp(path, g->path, g->plen) && '/' == path[g->plen]) {
916
+ break;
917
+ }
918
918
  }
919
919
  if (NULL == g) {
920
- return NULL;
920
+ return NULL;
921
921
  }
922
922
  for (d = g->dirs; NULL != d; d = d->next) {
923
- if ((int)sizeof(full_path) <= d->plen + plen) {
924
- continue;
925
- }
926
- s = stpcpy(full_path, d->path);
927
- strncpy(s, path + g->plen, plen - g->plen);
928
- s += plen - g->plen;
929
- *s = '\0';
930
- if (NULL != (page = cache_get(full_path, (int)(s - full_path)))) {
931
- break;
932
- }
923
+ if ((int)sizeof(full_path) <= d->plen + plen) {
924
+ continue;
925
+ }
926
+ s = stpcpy(full_path, d->path);
927
+ strncpy(s, path + g->plen, plen - g->plen);
928
+ s += plen - g->plen;
929
+ *s = '\0';
930
+ if (NULL != (page = cache_get(full_path, (int)(s - full_path)))) {
931
+ break;
932
+ }
933
933
  }
934
934
  if (NULL == page) {
935
- for (d = g->dirs; NULL != d; d = d->next) {
936
- if ((int)sizeof(full_path) <= d->plen + plen) {
937
- continue;
938
- }
939
- s = stpcpy(full_path, d->path);
940
- strncpy(s, path + g->plen, plen - g->plen);
941
- s += plen - g->plen;
942
- *s = '\0';
943
- if (0 == access(full_path, R_OK)) {
944
- break;
945
- }
946
- }
947
- if (NULL == d) {
948
- return NULL;
949
- }
950
- plen = (int)(s - full_path);
951
- path = full_path;
952
- if (NULL == (page = cache_get(path, plen))) {
953
- agooPage old;
954
-
955
- if (NULL == (page = agoo_page_create(path))) {
956
- AGOO_ERR_MEM(err, "Page");
957
- return NULL;
958
- }
959
- if (!update_contents(page) || NULL == page->resp) {
960
- agoo_page_destroy(page);
961
- agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
962
- return NULL;
963
- }
964
- if (NULL != (old = cache_set(path, plen, page))) {
965
- agoo_page_destroy(old);
966
- }
967
- }
968
- return page;
935
+ for (d = g->dirs; NULL != d; d = d->next) {
936
+ if ((int)sizeof(full_path) <= d->plen + plen) {
937
+ continue;
938
+ }
939
+ s = stpcpy(full_path, d->path);
940
+ strncpy(s, path + g->plen, plen - g->plen);
941
+ s += plen - g->plen;
942
+ *s = '\0';
943
+ if (0 == access(full_path, R_OK)) {
944
+ break;
945
+ }
946
+ }
947
+ if (NULL == d) {
948
+ return NULL;
949
+ }
950
+ plen = (int)(s - full_path);
951
+ path = full_path;
952
+ if (NULL == (page = cache_get(path, plen))) {
953
+ agooPage old;
954
+
955
+ if (NULL == (page = agoo_page_create(path))) {
956
+ AGOO_ERR_MEM(err, "Page");
957
+ return NULL;
958
+ }
959
+ if (!update_contents(page) || NULL == page->resp) {
960
+ agoo_page_destroy(page);
961
+ agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
962
+ return NULL;
963
+ }
964
+ if (NULL != (old = cache_set(path, plen, page))) {
965
+ agoo_page_destroy(old);
966
+ }
967
+ }
968
+ return page;
969
969
  }
970
970
  return page_check(err, page);
971
971
  }
972
972
 
973
973
  agooGroup
974
974
  agoo_group_create(const char *path) {
975
- agooGroup g = (agooGroup)AGOO_MALLOC(sizeof(struct _agooGroup));
975
+ agooGroup g = (agooGroup)AGOO_MALLOC(sizeof(struct _agooGroup));
976
976
 
977
977
  if (NULL != g) {
978
- if (NULL == (g->path = AGOO_STRDUP(path))) {
979
- AGOO_FREE(g);
980
- return NULL;
981
- }
982
- g->plen = (int)strlen(path);
983
- g->dirs = NULL;
984
- g->next = cache.groups;
985
- cache.groups = g;
978
+ if (NULL == (g->path = AGOO_STRDUP(path))) {
979
+ AGOO_FREE(g);
980
+ return NULL;
981
+ }
982
+ g->plen = (int)strlen(path);
983
+ g->dirs = NULL;
984
+ g->next = cache.groups;
985
+ cache.groups = g;
986
986
  }
987
987
  return g;
988
988
  }
989
989
 
990
990
  agooDir
991
991
  agoo_group_add(agooErr err, agooGroup g, const char *dir) {
992
- agooDir d = (agooDir)AGOO_MALLOC(sizeof(struct _agooDir));
992
+ agooDir d = (agooDir)AGOO_MALLOC(sizeof(struct _agooDir));
993
993
 
994
994
  if (NULL != d) {
995
- if (NULL == (d->path = AGOO_STRDUP(dir))) {
996
- AGOO_ERR_MEM(err, "Group");
997
- return NULL;
998
- }
999
- d->plen = (int)strlen(dir);
1000
- d->next = g->dirs;
1001
- g->dirs = d;
995
+ if (NULL == (d->path = AGOO_STRDUP(dir))) {
996
+ AGOO_ERR_MEM(err, "Group");
997
+ return NULL;
998
+ }
999
+ d->plen = (int)strlen(dir);
1000
+ d->next = g->dirs;
1001
+ g->dirs = d;
1002
1002
  }
1003
1003
  return d;
1004
1004
  }
1005
1005
 
1006
1006
  int
1007
1007
  agoo_header_rule(agooErr err, const char *path, const char *mime, const char *key, const char *value) {
1008
- HeadRule hr;
1008
+ HeadRule hr;
1009
1009
 
1010
1010
  if (0 == strcasecmp("Content-Length", key)) {
1011
- return agoo_err_set(err, AGOO_ERR_ARG, "Can not mask Content-Length with a header rule.");
1011
+ return agoo_err_set(err, AGOO_ERR_ARG, "Can not mask Content-Length with a header rule.");
1012
1012
  }
1013
1013
  if (NULL == (hr = (HeadRule)AGOO_CALLOC(1, sizeof(struct _headRule)))) {
1014
- return AGOO_ERR_MEM(err, "Header Rule");
1014
+ return AGOO_ERR_MEM(err, "Header Rule");
1015
1015
  }
1016
1016
  if (NULL == (hr->path = AGOO_STRDUP(path)) ||
1017
- NULL == (hr->key = AGOO_STRDUP(key)) ||
1018
- NULL == (hr->value = AGOO_STRDUP(value))) {
1019
- goto ERROR;
1017
+ NULL == (hr->key = AGOO_STRDUP(key)) ||
1018
+ NULL == (hr->value = AGOO_STRDUP(value))) {
1019
+ goto ERROR;
1020
1020
  }
1021
1021
  if ('*' == *mime && '\0' == mime[1]) {
1022
- hr->mime = NULL;
1022
+ hr->mime = NULL;
1023
1023
  } else if (NULL == (hr->mime = AGOO_STRDUP(mime))) {
1024
- goto ERROR;
1024
+ goto ERROR;
1025
1025
  }
1026
1026
  hr->len = (int)strlen(hr->key) + (int)strlen(hr->value) + 4;
1027
1027
  hr->next = cache.head_rules;