~ubuntu-branches/ubuntu/precise/nginx/precise-updates

« back to all changes in this revision

Viewing changes to debian/modules/nginx-cache-purge/ngx_cache_purge_module.c

  • Committer: Package Import Robot
  • Author(s): Cyril Lavier, Cyril Lavier, Kartik Mistry
  • Date: 2012-04-13 16:58:59 UTC
  • mfrom: (4.2.48 sid)
  • Revision ID: package-import@ubuntu.com-20120413165859-ef6fkd11mudyaspr
Tags: 1.1.19-1
[Cyril Lavier]
* New upstream release.
  + Fixed a buffer overflow in the ngx_http_mp4_module. See: CVE-2012-2089
    for more details.
* debian/copyright:
  + Updated licenses.
* debian/nginx-extras.postinst, debian/nginx-full.postinst,
  debian/nginx-light.postinst, debian/nginx-naxsi.postinst:
  + Removing the debug markers. (Closes: #667894)
* debian/control, debian/rules, debian/copyright,
  debian/modules/nginx-dav-ext-module:
  + Added nginx-dav-ext-module in full and extras.
* debian/modules/naxsi:
  + Updated naxsi to the SVN snapshot (r280) to fix the licence issue with
    OpenSSL.

[Kartik Mistry]
* Misc cleanups in debian/control, debian/copyright.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009-2011, FRiCKLE <info@frickle.com>
 
3
 * Copyright (c) 2009-2011, Piotr Sikora <piotr.sikora@frickle.com>
 
4
 * All rights reserved.
 
5
 *
 
6
 * This project was fully funded by yo.se.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY FRiCKLE PIOTR SIKORA AND CONTRIBUTORS
 
18
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
19
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
20
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FRiCKLE PIOTR
 
21
 * SIKORA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
27
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
28
 */
 
29
 
 
30
#include <nginx.h>
 
31
#include <ngx_config.h>
 
32
#include <ngx_core.h>
 
33
#include <ngx_http.h>
 
34
 
 
35
 
 
36
#if (NGX_HTTP_CACHE)
 
37
 
 
38
# if (NGX_HTTP_FASTCGI)
 
39
char       *ngx_http_fastcgi_cache_purge_conf(ngx_conf_t *cf,
 
40
                ngx_command_t *cmd, void *conf);
 
41
ngx_int_t   ngx_http_fastcgi_cache_purge_handler(ngx_http_request_t *r);
 
42
# endif /* NGX_HTTP_FASTCGI */
 
43
 
 
44
# if (NGX_HTTP_PROXY)
 
45
char       *ngx_http_proxy_cache_purge_conf(ngx_conf_t *cf,
 
46
                ngx_command_t *cmd, void *conf);
 
47
ngx_int_t   ngx_http_proxy_cache_purge_handler(ngx_http_request_t *r);
 
48
# endif /* NGX_HTTP_PROXY */
 
49
 
 
50
# if (NGX_HTTP_SCGI)
 
51
char       *ngx_http_scgi_cache_purge_conf(ngx_conf_t *cf,
 
52
                ngx_command_t *cmd, void *conf);
 
53
ngx_int_t   ngx_http_scgi_cache_purge_handler(ngx_http_request_t *r);
 
54
# endif /* NGX_HTTP_SCGI */
 
55
 
 
56
# if (NGX_HTTP_UWSGI)
 
57
char       *ngx_http_uwsgi_cache_purge_conf(ngx_conf_t *cf,
 
58
                ngx_command_t *cmd, void *conf);
 
59
ngx_int_t   ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r);
 
60
# endif /* NGX_HTTP_UWSGI */
 
61
 
 
62
ngx_int_t   ngx_http_cache_purge_init(ngx_http_request_t *r,
 
63
    ngx_http_file_cache_t *cache, ngx_http_complex_value_t *cache_key);
 
64
void        ngx_http_cache_purge_handler(ngx_http_request_t *r);
 
65
 
 
66
ngx_int_t   ngx_http_file_cache_purge(ngx_http_request_t *r);
 
67
 
 
68
static ngx_command_t  ngx_http_cache_purge_module_commands[] = {
 
69
 
 
70
# if (NGX_HTTP_FASTCGI)
 
71
    { ngx_string("fastcgi_cache_purge"),
 
72
      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
 
73
      ngx_http_fastcgi_cache_purge_conf,
 
74
      NGX_HTTP_LOC_CONF_OFFSET,
 
75
      0,
 
76
      NULL },
 
77
# endif /* NGX_HTTP_FASTCGI */
 
78
 
 
79
# if (NGX_HTTP_PROXY)
 
80
    { ngx_string("proxy_cache_purge"),
 
81
      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
 
82
      ngx_http_proxy_cache_purge_conf,
 
83
      NGX_HTTP_LOC_CONF_OFFSET,
 
84
      0,
 
85
      NULL },
 
86
# endif /* NGX_HTTP_PROXY */
 
87
 
 
88
# if (NGX_HTTP_SCGI)
 
89
    { ngx_string("scgi_cache_purge"),
 
90
      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
 
91
      ngx_http_scgi_cache_purge_conf,
 
92
      NGX_HTTP_LOC_CONF_OFFSET,
 
93
      0,
 
94
      NULL },
 
95
# endif /* NGX_HTTP_SCGI */
 
96
 
 
97
# if (NGX_HTTP_UWSGI)
 
98
    { ngx_string("uwsgi_cache_purge"),
 
99
      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
 
100
      ngx_http_uwsgi_cache_purge_conf,
 
101
      NGX_HTTP_LOC_CONF_OFFSET,
 
102
      0,
 
103
      NULL },
 
104
# endif /* NGX_HTTP_UWSGI */
 
105
 
 
106
      ngx_null_command
 
107
};
 
108
 
 
109
static ngx_http_module_t  ngx_http_cache_purge_module_ctx = {
 
110
    NULL,  /* preconfiguration */
 
111
    NULL,  /* postconfiguration */
 
112
 
 
113
    NULL,  /* create main configuration */
 
114
    NULL,  /* init main configuration */
 
115
 
 
116
    NULL,  /* create server configuration */
 
117
    NULL,  /* merge server configuration */
 
118
 
 
119
    NULL,  /* create location configuration */
 
120
    NULL   /* merge location configuration */
 
121
};
 
122
 
 
123
ngx_module_t  ngx_http_cache_purge_module = {
 
124
    NGX_MODULE_V1,
 
125
    &ngx_http_cache_purge_module_ctx,      /* module context */
 
126
    ngx_http_cache_purge_module_commands,  /* module directives */
 
127
    NGX_HTTP_MODULE,                       /* module type */
 
128
    NULL,                                  /* init master */
 
129
    NULL,                                  /* init module */
 
130
    NULL,                                  /* init process */
 
131
    NULL,                                  /* init thread */
 
132
    NULL,                                  /* exit thread */
 
133
    NULL,                                  /* exit process */
 
134
    NULL,                                  /* exit master */
 
135
    NGX_MODULE_V1_PADDING
 
136
};
 
137
 
 
138
static char ngx_http_cache_purge_success_page_top[] =
 
139
"<html>" CRLF
 
140
"<head><title>Successful purge</title></head>" CRLF
 
141
"<body bgcolor=\"white\">" CRLF
 
142
"<center><h1>Successful purge</h1>" CRLF
 
143
;
 
144
 
 
145
static char ngx_http_cache_purge_success_page_tail[] =
 
146
CRLF "</center>" CRLF
 
147
"<hr><center>" NGINX_VER "</center>" CRLF
 
148
"</body>" CRLF
 
149
"</html>" CRLF
 
150
;
 
151
 
 
152
# if (NGX_HTTP_FASTCGI)
 
153
extern ngx_module_t  ngx_http_fastcgi_module;
 
154
 
 
155
typedef struct {
 
156
    ngx_http_upstream_conf_t       upstream;
 
157
 
 
158
    ngx_str_t                      index;
 
159
 
 
160
    ngx_array_t                   *flushes;
 
161
    ngx_array_t                   *params_len;
 
162
    ngx_array_t                   *params;
 
163
    ngx_array_t                   *params_source;
 
164
    ngx_array_t                   *catch_stderr;
 
165
 
 
166
    ngx_array_t                   *fastcgi_lengths;
 
167
    ngx_array_t                   *fastcgi_values;
 
168
 
 
169
#  if defined(nginx_version) && (nginx_version >= 8040)
 
170
    ngx_hash_t                     headers_hash;
 
171
    ngx_uint_t                     header_params;
 
172
#  endif /* nginx_version >= 8040 */
 
173
 
 
174
    ngx_http_complex_value_t       cache_key;
 
175
 
 
176
#  if (NGX_PCRE)
 
177
    ngx_regex_t                   *split_regex;
 
178
    ngx_str_t                      split_name;
 
179
#  endif /* NGX_PCRE */
 
180
} ngx_http_fastcgi_loc_conf_t;
 
181
 
 
182
char *
 
183
ngx_http_fastcgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd,
 
184
    void *conf)
 
185
{
 
186
    ngx_http_compile_complex_value_t   ccv;
 
187
    ngx_http_core_loc_conf_t          *clcf;
 
188
    ngx_http_fastcgi_loc_conf_t       *flcf;
 
189
    ngx_str_t                         *value;
 
190
 
 
191
    flcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_fastcgi_module);
 
192
 
 
193
    /* check for duplicates / collisions */
 
194
    if (flcf->upstream.cache != NGX_CONF_UNSET_PTR
 
195
        && flcf->upstream.cache != NULL)
 
196
    {
 
197
        return "is either duplicate or collides with \"fastcgi_cache\"";
 
198
    }
 
199
 
 
200
    if (flcf->upstream.upstream || flcf->fastcgi_lengths) {
 
201
        return "is incompatible with \"fastcgi_pass\"";
 
202
    }
 
203
 
 
204
    if (flcf->upstream.store > 0 || flcf->upstream.store_lengths) {
 
205
        return "is incompatible with \"fastcgi_store\"";
 
206
    }
 
207
 
 
208
    value = cf->args->elts;
 
209
 
 
210
    /* set fastcgi_cache part */
 
211
    flcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
 
212
                                                 &ngx_http_fastcgi_module);
 
213
    if (flcf->upstream.cache == NULL) {
 
214
        return NGX_CONF_ERROR;
 
215
    }
 
216
 
 
217
    /* set fastcgi_cache_key part */
 
218
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
219
 
 
220
    ccv.cf = cf;
 
221
    ccv.value = &value[2];
 
222
    ccv.complex_value = &flcf->cache_key;
 
223
 
 
224
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
 
225
        return NGX_CONF_ERROR;
 
226
    }
 
227
 
 
228
    /* set handler */
 
229
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
230
 
 
231
    clcf->handler = ngx_http_fastcgi_cache_purge_handler;
 
232
 
 
233
    return NGX_CONF_OK;
 
234
}
 
235
 
 
236
ngx_int_t
 
237
ngx_http_fastcgi_cache_purge_handler(ngx_http_request_t *r)
 
238
{
 
239
    ngx_http_fastcgi_loc_conf_t  *flcf;
 
240
 
 
241
    flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
 
242
 
 
243
    if (ngx_http_cache_purge_init(r, flcf->upstream.cache->data,
 
244
                                  &flcf->cache_key)
 
245
        != NGX_OK)
 
246
    {
 
247
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
248
    }
 
249
 
 
250
#  if defined(nginx_version) && (nginx_version >= 8011)
 
251
    r->main->count++;
 
252
#  endif
 
253
 
 
254
    ngx_http_cache_purge_handler(r);
 
255
 
 
256
    return NGX_DONE;
 
257
}
 
258
# endif /* NGX_HTTP_FASTCGI */
 
259
 
 
260
# if (NGX_HTTP_PROXY)
 
261
extern ngx_module_t  ngx_http_proxy_module;
 
262
 
 
263
typedef struct {
 
264
    ngx_str_t                      key_start;
 
265
    ngx_str_t                      schema;
 
266
    ngx_str_t                      host_header;
 
267
    ngx_str_t                      port;
 
268
    ngx_str_t                      uri;
 
269
} ngx_http_proxy_vars_t;
 
270
 
 
271
typedef struct {
 
272
    ngx_http_upstream_conf_t       upstream;
 
273
 
 
274
    ngx_array_t                   *flushes;
 
275
    ngx_array_t                   *body_set_len;
 
276
    ngx_array_t                   *body_set;
 
277
    ngx_array_t                   *headers_set_len;
 
278
    ngx_array_t                   *headers_set;
 
279
    ngx_hash_t                     headers_set_hash;
 
280
 
 
281
    ngx_array_t                   *headers_source;
 
282
#  if defined(nginx_version) && (nginx_version < 8040)
 
283
    ngx_array_t                   *headers_names;
 
284
#  endif /* nginx_version < 8040 */
 
285
 
 
286
    ngx_array_t                   *proxy_lengths;
 
287
    ngx_array_t                   *proxy_values;
 
288
 
 
289
    ngx_array_t                   *redirects;
 
290
 
 
291
    ngx_str_t                      body_source;
 
292
 
 
293
    ngx_str_t                      method;
 
294
    ngx_str_t                      location;
 
295
    ngx_str_t                      url;
 
296
 
 
297
    ngx_http_complex_value_t       cache_key;
 
298
 
 
299
    ngx_http_proxy_vars_t          vars;
 
300
 
 
301
    ngx_flag_t                     redirect;
 
302
 
 
303
    ngx_uint_t                     headers_hash_max_size;
 
304
    ngx_uint_t                     headers_hash_bucket_size;
 
305
} ngx_http_proxy_loc_conf_t;
 
306
 
 
307
char *
 
308
ngx_http_proxy_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
309
{
 
310
    ngx_http_compile_complex_value_t   ccv;
 
311
    ngx_http_core_loc_conf_t          *clcf;
 
312
    ngx_http_proxy_loc_conf_t         *plcf;
 
313
    ngx_str_t                         *value;
 
314
 
 
315
    plcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_proxy_module);
 
316
 
 
317
    /* check for duplicates / collisions */
 
318
    if (plcf->upstream.cache != NGX_CONF_UNSET_PTR
 
319
        && plcf->upstream.cache != NULL)
 
320
    {
 
321
        return "is either duplicate or collides with \"proxy_cache\"";
 
322
    }
 
323
 
 
324
    if (plcf->upstream.upstream || plcf->proxy_lengths) {
 
325
        return "is incompatible with \"proxy_pass\"";
 
326
    }
 
327
 
 
328
    if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) {
 
329
        return "is incompatible with \"proxy_store\"";
 
330
    }
 
331
 
 
332
    value = cf->args->elts;
 
333
 
 
334
    /* set proxy_cache part */
 
335
    plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
 
336
                                                 &ngx_http_proxy_module);
 
337
    if (plcf->upstream.cache == NULL) {
 
338
        return NGX_CONF_ERROR;
 
339
    }
 
340
 
 
341
    /* set proxy_cache_key part */
 
342
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
343
 
 
344
    ccv.cf = cf;
 
345
    ccv.value = &value[2];
 
346
    ccv.complex_value = &plcf->cache_key;
 
347
 
 
348
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
 
349
        return NGX_CONF_ERROR;
 
350
    }
 
351
 
 
352
    /* set handler */
 
353
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
354
 
 
355
    clcf->handler = ngx_http_proxy_cache_purge_handler;
 
356
 
 
357
    return NGX_CONF_OK;
 
358
}
 
359
 
 
360
ngx_int_t
 
361
ngx_http_proxy_cache_purge_handler(ngx_http_request_t *r)
 
362
{
 
363
    ngx_http_proxy_loc_conf_t  *plcf;
 
364
 
 
365
    plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
 
366
 
 
367
    if (ngx_http_cache_purge_init(r, plcf->upstream.cache->data,
 
368
                                  &plcf->cache_key)
 
369
        != NGX_OK)
 
370
    {
 
371
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
372
    }
 
373
 
 
374
#  if defined(nginx_version) && (nginx_version >= 8011)
 
375
    r->main->count++;
 
376
#  endif
 
377
 
 
378
    ngx_http_cache_purge_handler(r);
 
379
 
 
380
    return NGX_DONE;
 
381
}
 
382
# endif /* NGX_HTTP_PROXY */
 
383
 
 
384
# if (NGX_HTTP_SCGI)
 
385
extern ngx_module_t  ngx_http_scgi_module;
 
386
 
 
387
typedef struct {
 
388
    ngx_http_upstream_conf_t   upstream;
 
389
 
 
390
    ngx_array_t               *flushes;
 
391
    ngx_array_t               *params_len;
 
392
    ngx_array_t               *params;
 
393
    ngx_array_t               *params_source;
 
394
 
 
395
    ngx_hash_t                 headers_hash;
 
396
    ngx_uint_t                 header_params;
 
397
 
 
398
    ngx_array_t               *scgi_lengths;
 
399
    ngx_array_t               *scgi_values;
 
400
 
 
401
    ngx_http_complex_value_t   cache_key;
 
402
} ngx_http_scgi_loc_conf_t;
 
403
 
 
404
char *
 
405
ngx_http_scgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
406
{
 
407
    ngx_http_compile_complex_value_t   ccv;
 
408
    ngx_http_core_loc_conf_t          *clcf;
 
409
    ngx_http_scgi_loc_conf_t          *slcf;
 
410
    ngx_str_t                         *value;
 
411
 
 
412
    slcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_scgi_module);
 
413
 
 
414
    /* check for duplicates / collisions */
 
415
    if (slcf->upstream.cache != NGX_CONF_UNSET_PTR
 
416
        && slcf->upstream.cache != NULL)
 
417
    {
 
418
        return "is either duplicate or collides with \"scgi_cache\"";
 
419
    }
 
420
 
 
421
    if (slcf->upstream.upstream || slcf->scgi_lengths) {
 
422
        return "is incompatible with \"scgi_pass\"";
 
423
    }
 
424
 
 
425
    if (slcf->upstream.store > 0 || slcf->upstream.store_lengths) {
 
426
        return "is incompatible with \"scgi_store\"";
 
427
    }
 
428
 
 
429
    value = cf->args->elts;
 
430
 
 
431
    /* set scgi_cache part */
 
432
    slcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
 
433
                                                 &ngx_http_scgi_module);
 
434
    if (slcf->upstream.cache == NULL) {
 
435
        return NGX_CONF_ERROR;
 
436
    }
 
437
 
 
438
    /* set scgi_cache_key part */
 
439
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
440
 
 
441
    ccv.cf = cf;
 
442
    ccv.value = &value[2];
 
443
    ccv.complex_value = &slcf->cache_key;
 
444
 
 
445
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
 
446
        return NGX_CONF_ERROR;
 
447
    }
 
448
 
 
449
    /* set handler */
 
450
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
451
 
 
452
    clcf->handler = ngx_http_scgi_cache_purge_handler;
 
453
 
 
454
    return NGX_CONF_OK;
 
455
}
 
456
 
 
457
ngx_int_t
 
458
ngx_http_scgi_cache_purge_handler(ngx_http_request_t *r)
 
459
{
 
460
    ngx_http_scgi_loc_conf_t  *slcf;
 
461
 
 
462
    slcf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);
 
463
 
 
464
    if (ngx_http_cache_purge_init(r, slcf->upstream.cache->data,
 
465
                                  &slcf->cache_key)
 
466
        != NGX_OK)
 
467
    {
 
468
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
469
    }
 
470
 
 
471
#  if defined(nginx_version) && (nginx_version >= 8011)
 
472
    r->main->count++;
 
473
#  endif
 
474
 
 
475
    ngx_http_cache_purge_handler(r);
 
476
 
 
477
    return NGX_DONE;
 
478
}
 
479
# endif /* NGX_HTTP_SCGI */
 
480
 
 
481
# if (NGX_HTTP_UWSGI)
 
482
extern ngx_module_t  ngx_http_uwsgi_module;
 
483
 
 
484
typedef struct {
 
485
    ngx_http_upstream_conf_t   upstream;
 
486
 
 
487
    ngx_array_t               *flushes;
 
488
    ngx_array_t               *params_len;
 
489
    ngx_array_t               *params;
 
490
    ngx_array_t               *params_source;
 
491
 
 
492
    ngx_hash_t                 headers_hash;
 
493
    ngx_uint_t                 header_params;
 
494
 
 
495
    ngx_array_t               *uwsgi_lengths;
 
496
    ngx_array_t               *uwsgi_values;
 
497
 
 
498
    ngx_http_complex_value_t   cache_key;
 
499
 
 
500
    ngx_str_t                  uwsgi_string;
 
501
 
 
502
    ngx_uint_t                 modifier1;
 
503
    ngx_uint_t                 modifier2;
 
504
} ngx_http_uwsgi_loc_conf_t;
 
505
 
 
506
char *
 
507
ngx_http_uwsgi_cache_purge_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
508
{
 
509
    ngx_http_compile_complex_value_t   ccv;
 
510
    ngx_http_core_loc_conf_t          *clcf;
 
511
    ngx_http_uwsgi_loc_conf_t         *ulcf;
 
512
    ngx_str_t                         *value;
 
513
 
 
514
    ulcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_uwsgi_module);
 
515
 
 
516
    /* check for duplicates / collisions */
 
517
    if (ulcf->upstream.cache != NGX_CONF_UNSET_PTR
 
518
        && ulcf->upstream.cache != NULL)
 
519
    {
 
520
        return "is either duplicate or collides with \"uwsgi_cache\"";
 
521
    }
 
522
 
 
523
    if (ulcf->upstream.upstream || ulcf->uwsgi_lengths) {
 
524
        return "is incompatible with \"uwsgi_pass\"";
 
525
    }
 
526
 
 
527
    if (ulcf->upstream.store > 0 || ulcf->upstream.store_lengths) {
 
528
        return "is incompatible with \"uwsgi_store\"";
 
529
    }
 
530
 
 
531
    value = cf->args->elts;
 
532
 
 
533
    /* set uwsgi_cache part */
 
534
    ulcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
 
535
                                                 &ngx_http_uwsgi_module);
 
536
    if (ulcf->upstream.cache == NULL) {
 
537
        return NGX_CONF_ERROR;
 
538
    }
 
539
 
 
540
    /* set uwsgi_cache_key part */
 
541
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
542
 
 
543
    ccv.cf = cf;
 
544
    ccv.value = &value[2];
 
545
    ccv.complex_value = &ulcf->cache_key;
 
546
 
 
547
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
 
548
        return NGX_CONF_ERROR;
 
549
    }
 
550
 
 
551
    /* set handler */
 
552
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
553
 
 
554
    clcf->handler = ngx_http_uwsgi_cache_purge_handler;
 
555
 
 
556
    return NGX_CONF_OK;
 
557
}
 
558
 
 
559
ngx_int_t
 
560
ngx_http_uwsgi_cache_purge_handler(ngx_http_request_t *r)
 
561
{
 
562
    ngx_http_uwsgi_loc_conf_t  *ulcf;
 
563
 
 
564
    ulcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
 
565
 
 
566
    if (ngx_http_cache_purge_init(r, ulcf->upstream.cache->data,
 
567
                                  &ulcf->cache_key)
 
568
        != NGX_OK)
 
569
    {
 
570
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
571
    }
 
572
 
 
573
#  if defined(nginx_version) && (nginx_version >= 8011)
 
574
    r->main->count++;
 
575
#  endif
 
576
 
 
577
    ngx_http_cache_purge_handler(r);
 
578
 
 
579
    return NGX_DONE;
 
580
}
 
581
# endif /* NGX_HTTP_UWSGI */
 
582
 
 
583
ngx_int_t
 
584
ngx_http_cache_purge_send_response(ngx_http_request_t *r)
 
585
{
 
586
    ngx_chain_t   out;
 
587
    ngx_buf_t    *b;
 
588
    ngx_str_t    *key;
 
589
    ngx_int_t     rc;
 
590
    size_t        len;
 
591
 
 
592
    key = r->cache->keys.elts;
 
593
 
 
594
    len = sizeof(ngx_http_cache_purge_success_page_top) - 1
 
595
          + sizeof(ngx_http_cache_purge_success_page_tail) - 1
 
596
          + sizeof("<br>Key : ") - 1 + sizeof(CRLF "<br>Path: ") - 1
 
597
          + key[0].len + r->cache->file.name.len;
 
598
 
 
599
    r->headers_out.content_type.len = sizeof("text/html") - 1;
 
600
    r->headers_out.content_type.data = (u_char *) "text/html";
 
601
    r->headers_out.status = NGX_HTTP_OK;
 
602
    r->headers_out.content_length_n = len;
 
603
 
 
604
    if (r->method == NGX_HTTP_HEAD) {
 
605
        rc = ngx_http_send_header(r);
 
606
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
 
607
            return rc;
 
608
        }
 
609
    }
 
610
 
 
611
    b = ngx_create_temp_buf(r->pool, len);
 
612
    if (b == NULL) {
 
613
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
 
614
    }
 
615
 
 
616
    out.buf = b;
 
617
    out.next = NULL;
 
618
 
 
619
    b->last = ngx_cpymem(b->last, ngx_http_cache_purge_success_page_top,
 
620
                         sizeof(ngx_http_cache_purge_success_page_top) - 1);
 
621
    b->last = ngx_cpymem(b->last, "<br>Key : ", sizeof("<br>Key : ") - 1);
 
622
    b->last = ngx_cpymem(b->last, key[0].data, key[0].len);
 
623
    b->last = ngx_cpymem(b->last, CRLF "<br>Path: ",
 
624
                         sizeof(CRLF "<br>Path: ") - 1);
 
625
    b->last = ngx_cpymem(b->last, r->cache->file.name.data,
 
626
                         r->cache->file.name.len);
 
627
    b->last = ngx_cpymem(b->last, ngx_http_cache_purge_success_page_tail,
 
628
                         sizeof(ngx_http_cache_purge_success_page_tail) - 1);
 
629
    b->last_buf = 1;
 
630
 
 
631
    rc = ngx_http_send_header(r);
 
632
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
 
633
       return rc;
 
634
    }
 
635
 
 
636
    return ngx_http_output_filter(r, &out);
 
637
}
 
638
 
 
639
ngx_int_t
 
640
ngx_http_cache_purge_init(ngx_http_request_t *r, ngx_http_file_cache_t *cache,
 
641
    ngx_http_complex_value_t *cache_key)
 
642
{
 
643
    ngx_http_cache_t  *c;
 
644
    ngx_str_t         *key;
 
645
    ngx_int_t          rc;
 
646
 
 
647
    rc = ngx_http_discard_request_body(r);
 
648
    if (rc != NGX_OK) {
 
649
        return NGX_ERROR;
 
650
    }
 
651
 
 
652
    c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
 
653
    if (c == NULL) {
 
654
        return NGX_ERROR;
 
655
    }
 
656
 
 
657
    rc = ngx_array_init(&c->keys, r->pool, 1, sizeof(ngx_str_t));
 
658
    if (rc != NGX_OK) {
 
659
        return NGX_ERROR;
 
660
    }
 
661
 
 
662
    key = ngx_array_push(&c->keys);
 
663
    if (key == NULL) {
 
664
        return NGX_ERROR;
 
665
    }
 
666
 
 
667
    rc = ngx_http_complex_value(r, cache_key, key);
 
668
    if (rc != NGX_OK) {
 
669
        return NGX_ERROR;
 
670
    }
 
671
 
 
672
    r->cache = c;
 
673
    c->body_start = ngx_pagesize;
 
674
    c->file_cache = cache;
 
675
    c->file.log = r->connection->log;
 
676
 
 
677
    ngx_http_file_cache_create_key(r);
 
678
 
 
679
    return NGX_OK;
 
680
}
 
681
 
 
682
void
 
683
ngx_http_cache_purge_handler(ngx_http_request_t *r)
 
684
{
 
685
    ngx_int_t  rc;
 
686
 
 
687
#  if (NGX_HAVE_FILE_AIO)
 
688
    if (r->aio) {
 
689
        return;
 
690
    }
 
691
#  endif
 
692
 
 
693
    rc = ngx_http_file_cache_purge(r);
 
694
 
 
695
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
696
                   "http file cache purge: %i, \"%s\"",
 
697
                   rc, r->cache->file.name.data);
 
698
 
 
699
    switch (rc) {
 
700
    case NGX_OK:
 
701
        r->write_event_handler = ngx_http_request_empty_handler;
 
702
        ngx_http_finalize_request(r, ngx_http_cache_purge_send_response(r));
 
703
        return;
 
704
    case NGX_DECLINED:
 
705
        ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
 
706
        return;
 
707
#  if (NGX_HAVE_FILE_AIO)
 
708
    case NGX_AGAIN:
 
709
        r->write_event_handler = ngx_http_cache_purge_handler;
 
710
        return;
 
711
#  endif
 
712
    default:
 
713
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
 
714
    }
 
715
}
 
716
 
 
717
ngx_int_t
 
718
ngx_http_file_cache_purge(ngx_http_request_t *r)
 
719
{
 
720
    ngx_http_file_cache_t  *cache;
 
721
    ngx_http_cache_t       *c;
 
722
 
 
723
    switch (ngx_http_file_cache_open(r)) {
 
724
    case NGX_OK:
 
725
    case NGX_HTTP_CACHE_STALE:
 
726
#  if defined(nginx_version) \
 
727
      && ((nginx_version >= 8001) \
 
728
          || ((nginx_version < 8000) && (nginx_version >= 7060)))
 
729
    case NGX_HTTP_CACHE_UPDATING:
 
730
#  endif
 
731
        break;
 
732
    case NGX_DECLINED:
 
733
        return NGX_DECLINED;
 
734
#  if (NGX_HAVE_FILE_AIO)
 
735
    case NGX_AGAIN:
 
736
        return NGX_AGAIN;
 
737
#  endif
 
738
    default:
 
739
        return NGX_ERROR;
 
740
    }
 
741
 
 
742
    c = r->cache;
 
743
    cache = c->file_cache;
 
744
 
 
745
    /*
 
746
     * delete file from disk but *keep* in-memory node,
 
747
     * because other requests might still point to it.
 
748
     */
 
749
 
 
750
    ngx_shmtx_lock(&cache->shpool->mutex);
 
751
 
 
752
    if (!c->node->exists) {
 
753
        /* race between concurrent purges, backoff */
 
754
        ngx_shmtx_unlock(&cache->shpool->mutex);
 
755
        return NGX_DECLINED;
 
756
    }
 
757
 
 
758
#  if defined(nginx_version) && (nginx_version >= 1000001)
 
759
    cache->sh->size -= c->node->fs_size;
 
760
    c->node->fs_size = 0;
 
761
#  else
 
762
    cache->sh->size -= (c->node->length + cache->bsize - 1) / cache->bsize;
 
763
    c->node->length = 0;
 
764
#  endif
 
765
 
 
766
    c->node->exists = 0;
 
767
#  if defined(nginx_version) \
 
768
      && ((nginx_version >= 8001) \
 
769
          || ((nginx_version < 8000) && (nginx_version >= 7060)))
 
770
    c->node->updating = 0;
 
771
#  endif
 
772
 
 
773
    ngx_shmtx_unlock(&cache->shpool->mutex);
 
774
 
 
775
    if (ngx_delete_file(c->file.name.data) == NGX_FILE_ERROR) {
 
776
        /* entry in error log is enough, don't notice client */
 
777
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
 
778
                      ngx_delete_file_n " \"%s\" failed", c->file.name.data);
 
779
    }
 
780
 
 
781
    /* file deleted from cache */
 
782
    return NGX_OK;
 
783
}
 
784
 
 
785
#else /* !NGX_HTTP_CACHE */
 
786
 
 
787
static ngx_http_module_t  ngx_http_cache_purge_module_ctx = {
 
788
    NULL,  /* preconfiguration */
 
789
    NULL,  /* postconfiguration */
 
790
 
 
791
    NULL,  /* create main configuration */
 
792
    NULL,  /* init main configuration */
 
793
 
 
794
    NULL,  /* create server configuration */
 
795
    NULL,  /* merge server configuration */
 
796
 
 
797
    NULL,  /* create location configuration */
 
798
    NULL,  /* merge location configuration */
 
799
};
 
800
 
 
801
ngx_module_t  ngx_http_cache_purge_module = {
 
802
    NGX_MODULE_V1,
 
803
    &ngx_http_cache_purge_module_ctx,  /* module context */
 
804
    NULL,                              /* module directives */
 
805
    NGX_HTTP_MODULE,                   /* module type */
 
806
    NULL,                              /* init master */
 
807
    NULL,                              /* init module */
 
808
    NULL,                              /* init process */
 
809
    NULL,                              /* init thread */
 
810
    NULL,                              /* exit thread */
 
811
    NULL,                              /* exit process */
 
812
    NULL,                              /* exit master */
 
813
    NGX_MODULE_V1_PADDING
 
814
};
 
815
 
 
816
#endif /* NGX_HTTP_CACHE */