Преглед на файлове

Changes:

 * First version
tags/v0.3
Brice Figureau преди 18 години
ревизия
2c65cbd551
променени са 7 файла, в които са добавени 1622 реда и са изтрити 0 реда
  1. 3
    0
      CHANGES
  2. 25
    0
      LICENSE
  3. 217
    0
      README
  4. 3
    0
      config
  5. 852
    0
      ngx_http_uploadprogress_module.c
  6. 503
    0
      prj/project.tmproj
  7. 19
    0
      prj/tmtags

+ 3
- 0
CHANGES Целия файл

@@ -0,0 +1,3 @@
1
+nginx_upload_progress release 0.1                                   3 Oct 2007
2
+
3
+ * public release

+ 25
- 0
LICENSE Целия файл

@@ -0,0 +1,25 @@
1
+/* 
2
+ * Copyright (C) 2007 Brice FIGUREAU
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ *    notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ *    notice, this list of conditions and the following disclaimer in the
11
+ *    documentation and/or other materials provided with the distribution.
12
+ *
13
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
+ * SUCH DAMAGE.
24
+ *
25
+ */

+ 217
- 0
README Целия файл

@@ -0,0 +1,217 @@
1
+Nginx Upload Progress Module
2
+============================
3
+
4
+
5
+Introduction
6
+============
7
+
8
+nginx_uploadprogress_module is an implementation of an upload progress system, that monitors
9
+RFC1867 POST upload as they are transmitted to upstream servers.
10
+
11
+It works by tracking the uploads proxied by Nginx to upstream servers without 
12
+analysing the uploaded content and offers a web API to report upload progress in JSON format.
13
+It works because Nginx acts as an accelerator of an upstream server, storing uploaded POST content
14
+on disk, before transmitting it to the upstream server. Each individual POST upload request
15
+should contain a progress unique identifier.
16
+
17
+This module is Copyright (c) 2007 Brice Figureau, and is licensed under the BSD license (see LICENSE).
18
+ * rbtree and shm_zone code is based on Igor Sysoev limit_zone Nginx module.
19
+ * expire header code is based on Igor Sysoev header_filter Nginx module.
20
+
21
+The JSON idea and the mechanism idea are based on Lighttpd mod_uploadprogress:
22
+http://blog.lighttpd.net/articles/2006/08/01/mod_uploadprogress-is-back
23
+
24
+
25
+WARNINGS: 
26
+ * this software has never been tested under load. It only passed a few lab tests.
27
+ * it is not intended to be deployed on *production systems*.
28
+ * when compiled with --with-debug, this module will produce high number of log messages.
29
+
30
+
31
+Installation
32
+============
33
+
34
+nginx_uploadprogress_module has been tested with Nginx 0.6.1, 0.6.12 and 0.6.13.
35
+
36
+Download the Nginx sources from http://nginx.net/ and unpack it.
37
+
38
+To build Nginx, change to the directory which contains the Nginx
39
+sources, and run the configuration script making sure to add the path
40
+to the nginx_uploadprogress_module sources using the --add-module option: ::
41
+
42
+ $ ./configure --add-module=/path/to/nginx_uploadprogress_module/
43
+
44
+Now you can build and install the software:
45
+
46
+ $ make
47
+
48
+and as root:
49
+
50
+ $ make install 
51
+ 
52
+ 
53
+Configuration
54
+=============
55
+
56
+Each upload request should be assigned a unique identifier. This unique identifier will be used
57
+to store the request and reference it to report.
58
+This identifier can be transmitted either as a GET argument or as an HTTP header whose name is X-Progress-ID.
59
+
60
+upload_progress
61
++++++++++++++++
62
+	:Syntax: upload_progress <zone_name> <zone_size>
63
+	:Default: none
64
+	:Context: http
65
+	:Description:
66
+	This directive enables the upload progress module and reserve <zone_size> bytes to the <zone_name> which
67
+	will be used to store the per-connection tracking information.
68
+	
69
+track_uploads
70
++++++++++++++
71
+	:Syntax: track_uploads <zone_name>
72
+	:Default: none
73
+	:Context: location
74
+	:Description:
75
+	This directive enables tracking uploads for the current location. Each POST landing in this location will register
76
+	the request in the <zone_name> upload progress tracker.
77
+	Since Nginx doesn't support yet RFC 1867 upload, the location must be a proxy_pass or fastcgi location.
78
+	The POST _must_ have a query parameter called X-Progress-ID (or an HTTP header of the same name) whose value is the
79
+	unique identifier used to get progress information. If the POST has no such information, the upload will not be tracked.
80
+	
81
+report_uploads
82
+++++++++++++++
83
+	:Syntax: report_uploads <zone_name>
84
+	:Default: none
85
+	:Context: location
86
+	:Description:
87
+	This directive allows a location to report the upload progress that is tracked by track_uploads for <zone_name>.
88
+	The returned document is a JSON text with the possible 4 results:
89
+	  * the upload request hasn't been registered yet or is unknown:			 
90
+				new Object({ 'state' : 'starting' })
91
+				
92
+		* the upload request has ended:
93
+				new Object({ 'state' : 'done' })
94
+		
95
+		* the upload request generated an HTTP 413 error (Request entity too large):
96
+				new Object({ 'state' : 'error', 'status' : 413 })
97
+		
98
+		* the upload request is in progress:
99
+				new Object({ 'state' : 'uploading', 'received' : <size_received>, 'size' : <total_size>})
100
+				
101
+	The HTTP request to this location must have a X-Progress-ID parameter or HTTP header containing a valid
102
+	unique identifier of an inprogress upload.
103
+				
104
+
105
+Configuration Example:
106
++++++++++++++++++++++
107
+
108
+http {
109
+	
110
+	# reserve 1MB under the name 'proxied' to track uploads
111
+	upload_progress proxied 1m;
112
+
113
+  server {
114
+		listen       127.0.0.1 default;
115
+		server_name  _ *;
116
+		
117
+		root /path/to/root;
118
+		
119
+		location / {
120
+			# proxy to upstream server
121
+			proxy_pass http://127.0.0.1;
122
+			proxy_redirect default;
123
+			
124
+			# track uploads in the 'proxied' zone
125
+			track_uploads proxied;
126
+		}
127
+		
128
+		location ^~ /progress {
129
+			# report uploads tracked in the 'proxied' zone
130
+			report_uploads proxied;
131
+		}
132
+}
133
+	
134
+
135
+Usage Example
136
+=============
137
+
138
+(based on Lighttd mod_uploadprogress module example):
139
+
140
+First we need a upload form:
141
+
142
+  <form id="upload" enctype="multipart/form-data" 
143
+    action="/upload.php" method="post" 
144
+    onsubmit="openProgressBar(); return true;">
145
+  <input type="hidden" name="MAX_FILE_SIZE" value="30000000"  />
146
+  <input name="userfile" type="file" label="fileupload" />
147
+  <input type="submit" value="Send File" />
148
+  </form>
149
+
150
+And a progress bar to visualize the progress:
151
+
152
+  <div>
153
+   <div id="progress" style="width: 400px; border: 1px solid black">
154
+    <div id="progressbar" 
155
+       style="width: 1px; background-color: black; border: 1px solid white">
156
+     &nbsp;
157
+    </div>
158
+   </div>
159
+   <div id="tp">(progress)</div>
160
+  </div>
161
+
162
+Then we need to generate the Unique Identifier and launch the upload on submit
163
+action. This also will start the ajax progress report mechanism.
164
+
165
+ interval = null;
166
+
167
+function openProgressBar() {
168
+ /* generate random progress-id */
169
+ uuid = "";
170
+ for (i = 0; i < 32; i++) {
171
+  uuid += Math.floor(Math.random() * 16).toString(16);
172
+ }
173
+ /* patch the form-action tag to include the progress-id */
174
+ document.getElementById("upload").action="/upload.php?X-Progress-ID=" + uuid;
175
+
176
+ /* call the progress-updater every 1000ms */
177
+ interval = window.setInterval(
178
+   function () {
179
+     fetch(uuid);
180
+   },
181
+   1000
182
+ );
183
+}
184
+
185
+function fetch(uuid) {
186
+ req = new XMLHttpRequest();
187
+ req.open("GET", "/progress", 1);
188
+ req.setRequestHeader("X-Progress-ID", uuid);
189
+ req.onreadystatechange = function () {
190
+  if (req.readyState == 4) {
191
+   if (req.status == 200) {
192
+    /* poor-man JSON parser */
193
+    var upload = eval(req.responseText);
194
+
195
+    document.getElementById('tp').innerHTML = upload.state;
196
+
197
+    /* change the width if the inner progress-bar */
198
+    if (upload.state == 'done' || upload.state == 'uploading') {
199
+     bar = document.getElementById('progressbar');
200
+     w = 400 * upload.received / upload.size;
201
+     bar.style.width = w + 'px';
202
+    }
203
+    /* we are done, stop the interval */
204
+    if (upload.state == 'done') {
205
+     window.clearTimeout(interval);
206
+    }
207
+   }
208
+  }
209
+ }
210
+ req.send(null);
211
+}
212
+
213
+
214
+
215
+
216
+
217
+

+ 3
- 0
config Целия файл

@@ -0,0 +1,3 @@
1
+ngx_addon_name=ngx_http_uploadprogress_module
2
+HTTP_MODULES="$HTTP_MODULES ngx_http_uploadprogress_module"
3
+NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_uploadprogress_module.c"

+ 852
- 0
ngx_http_uploadprogress_module.c Целия файл

@@ -0,0 +1,852 @@
1
+
2
+/*
3
+ * Copyright (C) 2007 Brice Figureau
4
+ */
5
+
6
+#include <ngx_config.h>
7
+#include <ngx_core.h>
8
+#include <ngx_http.h>
9
+
10
+typedef struct {
11
+    u_char              color;
12
+ 		ngx_http_request_t *r;
13
+    u_char              len;
14
+    u_char              data[1];
15
+} ngx_http_uploadprogress_node_t;
16
+
17
+
18
+typedef struct {
19
+    ngx_shm_zone_t     *shm_zone;
20
+    ngx_rbtree_node_t  *node;
21
+} ngx_http_uploadprogress_cleanup_t;
22
+
23
+typedef struct {
24
+    ngx_rbtree_t       *rbtree;
25
+} ngx_http_uploadprogress_ctx_t;
26
+
27
+typedef struct {
28
+    ngx_shm_zone_t     *shm_zone;
29
+		u_char							track;
30
+} ngx_http_uploadprogress_conf_t;
31
+
32
+static ngx_int_t ngx_http_reportuploads_handler(ngx_http_request_t *r);
33
+static ngx_int_t ngx_http_reportuploads_handler(ngx_http_request_t *r);
34
+static void ngx_http_uploadprogress_cleanup(void *data);
35
+static char *ngx_http_report_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
36
+static ngx_int_t ngx_http_uploadprogress_init_zone(ngx_shm_zone_t *shm_zone, void *data);
37
+static ngx_int_t ngx_http_uploadprogress_init(ngx_conf_t *cf);
38
+static void *ngx_http_uploadprogress_create_loc_conf(ngx_conf_t *cf);
39
+static char *ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
40
+static char *ngx_http_track_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
41
+static char *ngx_http_report_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
42
+static char *ngx_http_upload_progress(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
43
+
44
+static ngx_command_t  ngx_http_uploadprogress_commands[] = {
45
+
46
+  { ngx_string("upload_progress"),
47
+    NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
48
+    ngx_http_upload_progress,
49
+    0,
50
+    0,
51
+    NULL },
52
+
53
+  { ngx_string("track_uploads"),
54
+	  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
55
+	  ngx_http_track_uploads,
56
+	  NGX_HTTP_LOC_CONF_OFFSET,
57
+    0,
58
+    NULL },
59
+
60
+  { ngx_string("report_uploads"),
61
+    NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
62
+    ngx_http_report_uploads,
63
+    NGX_HTTP_LOC_CONF_OFFSET,
64
+    0,
65
+    NULL },
66
+
67
+		ngx_null_command
68
+};
69
+
70
+
71
+static ngx_http_module_t  ngx_http_uploadprogress_module_ctx = {
72
+    NULL,                          /* preconfiguration */
73
+    ngx_http_uploadprogress_init,  /* postconfiguration */
74
+
75
+    NULL,  /* create main configuration */
76
+    NULL,    /* init main configuration */
77
+
78
+    NULL,                          /* create server configuration */
79
+    NULL,                          /* merge server configuration */
80
+
81
+    ngx_http_uploadprogress_create_loc_conf,          /* create location configuration */
82
+    ngx_http_uploadprogress_merge_loc_conf            /* merge location configuration */
83
+};
84
+
85
+
86
+ngx_module_t  ngx_http_uploadprogress_module = {
87
+    NGX_MODULE_V1,
88
+    &ngx_http_uploadprogress_module_ctx,      /* module context */
89
+    ngx_http_uploadprogress_commands,         /* module directives */
90
+    NGX_HTTP_MODULE,               /* module type */
91
+    NULL,                          /* init master */
92
+    NULL,                          /* init module */
93
+    NULL,                          /* init process */
94
+    NULL,                          /* init thread */
95
+    NULL,                          /* exit thread */
96
+    NULL,                          /* exit process */
97
+    NULL,                          /* exit master */
98
+    NGX_MODULE_V1_PADDING
99
+};
100
+
101
+static ngx_str_t x_progress_id = ngx_string("X-Progress-ID");
102
+
103
+static ngx_str_t*
104
+get_tracking_id(ngx_http_request_t *r)
105
+{
106
+	u_char										 *p,*start_p;
107
+	ngx_uint_t i;
108
+  ngx_list_part_t              *part;
109
+  ngx_table_elt_t              *header;
110
+	ngx_str_t										 *ret;
111
+
112
+  part = &r->headers_in.headers.part;
113
+  header = part->elts;
114
+
115
+  for (i = 0; /* void */; i++) {
116
+
117
+      if (i >= part->nelts) {
118
+          if (part->next == NULL) {
119
+              break;
120
+          }
121
+
122
+          part = part->next;
123
+          header = part->elts;
124
+          i = 0;
125
+      }
126
+
127
+			if (header[i].key.len == x_progress_id.len && ngx_strncmp(header[i].key.data, x_progress_id.data,header[i].key.len) == 0)
128
+			{
129
+				ret = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
130
+				ret->data = header[i].value.data;
131
+				ret->len = header[i].value.len;
132
+				return ret;
133
+			}
134
+  }
135
+
136
+	/* not found, check as a reaquest arg */
137
+	if (r->args.len) {
138
+		p = (u_char *) ngx_strstr(r->args.data, "X-Progress-ID=");
139
+
140
+		if (p) {
141
+			start_p = p += 14;
142
+	    while (p < r->args.data + r->args.len) {
143
+	        if (*p++ != '&') {
144
+	            continue;
145
+	        }
146
+			}
147
+			
148
+			ret = ngx_pcalloc(r->pool, sizeof(ngx_str_t));
149
+			ret->data = start_p;
150
+			ret->len = p-start_p;
151
+			return ret;
152
+		}
153
+	}
154
+
155
+	return NULL;
156
+}
157
+
158
+
159
+/* This generates the response for the report */
160
+static ngx_int_t
161
+ngx_http_reportuploads_handler(ngx_http_request_t *r)
162
+{
163
+	ngx_str_t		 *id;
164
+  ngx_buf_t    *b;
165
+  ngx_chain_t   out;
166
+	ngx_http_request_t								 *orig;
167
+  ngx_int_t                       rc, size;
168
+  uint32_t                        hash;
169
+  ngx_slab_pool_t                *shpool;
170
+  ngx_rbtree_node_t              *node, *sentinel;
171
+	ngx_http_uploadprogress_conf_t     *lzcf;
172
+  ngx_http_uploadprogress_ctx_t      *ctx;
173
+  ngx_http_uploadprogress_node_t     *lz;
174
+  ngx_table_elt_t  *expires, *cc, **ccp;
175
+
176
+  if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
177
+      return NGX_HTTP_NOT_ALLOWED;
178
+  }
179
+
180
+  rc = ngx_http_discard_request_body(r);
181
+
182
+  if (rc != NGX_OK) {
183
+      return rc;
184
+  }
185
+
186
+	/* get the tracking id if any */
187
+	id = get_tracking_id(r);
188
+
189
+
190
+	if ( id == NULL )
191
+	{
192
+	  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
193
+	                 "reportuploads handler cant find id");
194
+    return NGX_DECLINED;
195
+	}
196
+	
197
+  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
198
+                 "reportuploads handler found id: %V", id);
199
+
200
+  lzcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
201
+
202
+  if (lzcf->shm_zone == NULL) {
203
+	  	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
204
+	                 "reportuploads no shm_zone for id: %V", id);
205
+      return NGX_DECLINED;
206
+  }
207
+
208
+	orig = NULL;
209
+  ctx = lzcf->shm_zone->data;
210
+	
211
+  hash = ngx_crc32_short(id->data, id->len);
212
+
213
+	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
214
+               "reportuploads trying to find block with hash %08XD for id: %V", hash, id);
215
+
216
+	/* get the original connection of the upload */
217
+  shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr;
218
+  ngx_shmtx_lock(&shpool->mutex);
219
+
220
+	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
221
+               "reportuploads in mutex lock for hash %08XD for id: %V", hash, id);
222
+
223
+  node = ctx->rbtree->root;
224
+  sentinel = ctx->rbtree->sentinel;
225
+
226
+	ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
227
+               "reportuploads root %p, sentinel %p for id: %V", node,sentinel, id);
228
+
229
+  while (node != sentinel) {
230
+
231
+      if (hash < node->key) {
232
+          node = node->left;
233
+          continue;
234
+      }
235
+
236
+      if (hash > node->key) {
237
+          node = node->right;
238
+          continue;
239
+      }
240
+
241
+			ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
242
+		               "reportuploads found matching hash %08XD, node %p for id: %V", hash, node, id);
243
+
244
+      /* hash == node->key */
245
+
246
+      do {
247
+          lz = (ngx_http_uploadprogress_node_t *) &node->color;
248
+
249
+          rc = ngx_memn2cmp(id->data, lz->data, id->len, (size_t) lz->len);
250
+
251
+          if (rc == 0) {
252
+						/* found the right one */
253
+						/* lz contains the right node*/
254
+						ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
255
+					               "reportuploads found request: %p", lz->r);
256
+						orig = lz->r;
257
+						goto found;
258
+          }
259
+
260
+					ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
261
+				               "reportuploads oops not the same : lz %V != id %V", lz, id);
262
+
263
+
264
+          node = (rc < 0) ? node->left : node->right;
265
+
266
+      } while (node != sentinel && hash == node->key);
267
+
268
+			lz = NULL;
269
+			
270
+			/* couldn't find one */
271
+			ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
272
+		               "reportuploads not matching request");
273
+  }
274
+
275
+found:
276
+	ngx_shmtx_unlock(&shpool->mutex);
277
+
278
+	/* send the output */
279
+  r->headers_out.content_type.len = sizeof("text/javascript") - 1;
280
+  r->headers_out.content_type.data = (u_char *) "text/javascript";
281
+
282
+	/* no-cache */
283
+
284
+  expires = r->headers_out.expires;
285
+
286
+  if (expires == NULL) {
287
+
288
+      expires = ngx_list_push(&r->headers_out.headers);
289
+      if (expires == NULL) {
290
+          return NGX_HTTP_INTERNAL_SERVER_ERROR;
291
+      }
292
+
293
+      r->headers_out.expires = expires;
294
+
295
+      expires->hash = 1;
296
+      expires->key.len = sizeof("Expires") - 1;
297
+      expires->key.data = (u_char *) "Expires";
298
+  }
299
+
300
+  len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
301
+  expires->value.len = len - 1;
302
+
303
+  ccp = r->headers_out.cache_control.elts;
304
+  if (ccp == NULL) {
305
+
306
+      if (ngx_array_init(&r->headers_out.cache_control, r->pool,
307
+                         1, sizeof(ngx_table_elt_t *))
308
+          != NGX_OK)
309
+      {
310
+          return NGX_HTTP_INTERNAL_SERVER_ERROR;
311
+      }
312
+
313
+      ccp = ngx_array_push(&r->headers_out.cache_control);
314
+      if (ccp == NULL) {
315
+          return NGX_HTTP_INTERNAL_SERVER_ERROR;
316
+      }
317
+
318
+      cc = ngx_list_push(&r->headers_out.headers);
319
+      if (cc == NULL) {
320
+          return NGX_HTTP_INTERNAL_SERVER_ERROR;
321
+      }
322
+
323
+      cc->hash = 1;
324
+      cc->key.len = sizeof("Cache-Control") - 1;
325
+      cc->key.data = (u_char *) "Cache-Control";
326
+
327
+      *ccp = cc;
328
+
329
+  } else {
330
+      for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
331
+          ccp[i]->hash = 0;
332
+      }
333
+
334
+      cc = ccp[0];
335
+  }
336
+
337
+  expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
338
+
339
+  cc->value.len = sizeof("no-cache") - 1;
340
+  cc->value.data = (u_char *) "no-cache";
341
+
342
+
343
+  if (r->method == NGX_HTTP_HEAD) {
344
+      r->headers_out.status = NGX_HTTP_OK;
345
+
346
+      rc = ngx_http_send_header(r);
347
+
348
+      if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
349
+          return rc;
350
+      }
351
+  }
352
+
353
+	if ( orig == NULL )
354
+	{
355
+		if (lz != NULL )
356
+		{
357
+			size = sizeof("new Object({ 'state' : 'done' })\r\n");
358
+  	}
359
+		else
360
+		{
361
+			size = sizeof("new Object({ 'state' : 'starting' })\r\n");
362
+  	}
363
+	}
364
+	else if ( orig->err_status == 413)
365
+	{
366
+		size = sizeof("new Object({ 'state' : 'error', 'status' : 413 })\r\n");
367
+	}
368
+	else
369
+	{
370
+		size = sizeof("new Object({ 'state' : 'uploading', 'received' : ") + NGX_INT_T_LEN + sizeof(" })\r\n");
371
+		size += sizeof(", 'size' : ") + NGX_INT_T_LEN;
372
+	}
373
+
374
+  b = ngx_create_temp_buf(r->pool, size);
375
+  if (b == NULL) {
376
+      return NGX_HTTP_INTERNAL_SERVER_ERROR;
377
+  }
378
+
379
+  out.buf = b;
380
+  out.next = NULL;
381
+	
382
+	if (orig == NULL)
383
+	{
384
+		if (lz == NULL )
385
+		{
386
+			b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'starting' })\r\n",
387
+		                       sizeof("new Object({ 'state' : 'starting' })\r\n") - 1);
388
+			ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
389
+											               "reportuploads returning starting");
390
+		}
391
+		else 
392
+		{
393
+			b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'done' })\r\n",
394
+		                       sizeof("new Object({ 'state' : 'done' })\r\n") - 1);
395
+			ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
396
+		               "reportuploads returning done");
397
+		}
398
+	}
399
+	else if ( orig->err_status == 413)
400
+	{
401
+		b->last = ngx_cpymem(b->last, "new Object({ 'state' : 'error', 'status' : 413 })\r\n",
402
+	                       sizeof("new Object({ 'state' : 'error', 'status' : 413 })\r\n") - 1);
403
+		ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
404
+	               "reportuploads returning error 413");
405
+	}
406
+	else
407
+	{
408
+		b->last = ngx_cpymem(b->last,"new Object({ 'state' : 'uploading', 'received' : ", 
409
+			sizeof("new Object({ 'state' : 'uploading', 'received' : ")-1 );
410
+			
411
+		b->last = ngx_sprintf(b->last, "%uO, 'size' : %uO })\r\n", (orig->headers_in.content_length_n - orig->request_body->rest), orig->headers_in.content_length_n);
412
+
413
+		ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
414
+	               "reportuploads returning %uO / %uO", (orig->headers_in.content_length_n - orig->request_body->rest), orig->headers_in.content_length_n);
415
+
416
+	}
417
+
418
+	// force no caching for proxy
419
+	
420
+
421
+	r->headers_out.status = NGX_HTTP_OK;
422
+	r->headers_out.content_length_n = b->last - b->pos;
423
+
424
+	b->last_buf = 1;
425
+	rc = ngx_http_send_header(r);
426
+
427
+	if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
428
+	    return rc;
429
+	}
430
+
431
+	return ngx_http_output_filter(r, &out);;
432
+}
433
+
434
+/* 
435
+This is the post read phase. It registers the upload connection in the rb tree
436
+*/
437
+static ngx_int_t
438
+ngx_http_uploadprogress_handler(ngx_http_request_t *r)
439
+{
440
+  size_t                          n;
441
+	ngx_str_t 												 *id;
442
+  ngx_int_t                       rc;
443
+  uint32_t                        hash;
444
+  ngx_slab_pool_t                *shpool;
445
+  ngx_rbtree_node_t              *node, *sentinel;
446
+	ngx_http_uploadprogress_conf_t     *lzcf;
447
+  ngx_http_uploadprogress_ctx_t      *ctx;
448
+  ngx_http_uploadprogress_node_t     *lz;
449
+	ngx_http_uploadprogress_cleanup_t	 *lzcln;
450
+  ngx_pool_cleanup_t             *cln;
451
+
452
+	id = get_tracking_id(r);
453
+	if ( id == NULL )
454
+	{
455
+		ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
456
+             "trackuploads no id found in POST upload req");
457
+		return NGX_DECLINED;
458
+	}
459
+	
460
+	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
461
+           "trackuploads id found: %V", id);
462
+
463
+  lzcf = ngx_http_get_module_loc_conf(r, ngx_http_uploadprogress_module);
464
+
465
+  if (!lzcf->track) {
466
+	  	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
467
+	                 "trackuploads not tracking in this location for id: %V", id);
468
+      return NGX_DECLINED;
469
+  }
470
+
471
+  if (lzcf->shm_zone == NULL) {
472
+  	ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
473
+                 "trackuploads no shm_zone for id: %V", id);
474
+      return NGX_DECLINED;
475
+  }
476
+
477
+  ctx = lzcf->shm_zone->data;
478
+	
479
+  hash = ngx_crc32_short(id->data, id->len);
480
+
481
+	ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
482
+               "trackuploads hash %08XD for id: %V",hash, id);
483
+
484
+  cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_uploadprogress_cleanup_t));
485
+  if (cln == NULL) {
486
+      return NGX_HTTP_INTERNAL_SERVER_ERROR;
487
+  }
488
+
489
+  shpool = (ngx_slab_pool_t *) lzcf->shm_zone->shm.addr;
490
+
491
+  ngx_shmtx_lock(&shpool->mutex);
492
+
493
+  node = ctx->rbtree->root;
494
+  sentinel = ctx->rbtree->sentinel;
495
+
496
+  while (node != sentinel) {
497
+
498
+      if (hash < node->key) {
499
+          node = node->left;
500
+          continue;
501
+      }
502
+
503
+      if (hash > node->key) {
504
+          node = node->right;
505
+          continue;
506
+      }
507
+
508
+      /* hash == node->key */
509
+
510
+      do {
511
+          lz = (ngx_http_uploadprogress_node_t *) &node->color;
512
+
513
+          rc = ngx_memn2cmp(id->data, lz->data, id->len, (size_t) lz->len);
514
+
515
+          if (rc == 0) {
516
+							ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
517
+					               "trackuploads already registered: %V",id);
518
+							/* oops found already one */
519
+              ngx_shmtx_unlock(&shpool->mutex);
520
+
521
+              return NGX_HTTP_SERVICE_UNAVAILABLE;
522
+          }
523
+
524
+          node = (rc < 0) ? node->left : node->right;
525
+
526
+      } while (node != sentinel && hash == node->key);
527
+
528
+      break;
529
+  }
530
+
531
+  n = offsetof(ngx_rbtree_node_t, color)
532
+      + offsetof(ngx_http_uploadprogress_node_t, data)
533
+      + id->len;
534
+
535
+  node = ngx_slab_alloc_locked(shpool, n);
536
+  if (node == NULL) {
537
+      ngx_shmtx_unlock(&shpool->mutex);
538
+      return NGX_HTTP_SERVICE_UNAVAILABLE;
539
+  }
540
+
541
+  lz = (ngx_http_uploadprogress_node_t *) &node->color;
542
+
543
+  node->key = hash;
544
+  lz->len = (u_char) id->len;
545
+	lz->r = r;
546
+  ngx_memcpy(lz->data, id->data, id->len);
547
+
548
+  ngx_rbtree_insert(ctx->rbtree, node);
549
+  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
550
+                 "trackuploads: %08XD", node->key);
551
+
552
+  ngx_shmtx_unlock(&shpool->mutex);
553
+
554
+  cln->handler = ngx_http_uploadprogress_cleanup;
555
+  lzcln = cln->data;
556
+
557
+  lzcln->shm_zone = lzcf->shm_zone;
558
+  lzcln->node = node;
559
+
560
+  return NGX_DECLINED;
561
+}
562
+
563
+static void
564
+ngx_http_uploadprogress_rbtree_insert_value(ngx_rbtree_node_t *temp,
565
+    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
566
+{
567
+    ngx_http_uploadprogress_node_t  *lzn, *lznt;
568
+
569
+    for ( ;; ) {
570
+
571
+        if (node->key < temp->key) {
572
+
573
+            if (temp->left == sentinel) {
574
+                temp->left = node;
575
+                break;
576
+            }
577
+
578
+            temp = temp->left;
579
+
580
+        } else if (node->key > temp->key) {
581
+
582
+            if (temp->right == sentinel) {
583
+                temp->right = node;
584
+                break;
585
+            }
586
+
587
+            temp = temp->right;
588
+
589
+        } else { /* node->key == temp->key */
590
+
591
+            lzn = (ngx_http_uploadprogress_node_t *) &node->color;
592
+            lznt = (ngx_http_uploadprogress_node_t *) &temp->color;
593
+
594
+            if (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) {
595
+
596
+                if (temp->left == sentinel) {
597
+                    temp->left = node;
598
+                    break;
599
+                }
600
+
601
+                temp = temp->left;
602
+
603
+            } else {
604
+
605
+                if (temp->right == sentinel) {
606
+                    temp->right = node;
607
+                    break;
608
+                }
609
+
610
+                temp = temp->right;
611
+            }
612
+        }
613
+    }
614
+
615
+    node->parent = temp;
616
+    node->left = sentinel;
617
+    node->right = sentinel;
618
+    ngx_rbt_red(node);
619
+}
620
+
621
+/*
622
+removes the expired node from the upload rbtree
623
+*/
624
+static void
625
+ngx_http_uploadprogress_cleanup(void *data)
626
+{
627
+    ngx_http_uploadprogress_cleanup_t  *lzcln = data;
628
+
629
+    ngx_slab_pool_t             *shpool;
630
+    ngx_rbtree_node_t           *node;
631
+    ngx_http_uploadprogress_ctx_t   *ctx;
632
+    ngx_http_uploadprogress_node_t  *lz;
633
+
634
+		ngx_log_debug0(NGX_LOG_DEBUG_HTTP, lzcln->shm_zone->shm.log, 0,
635
+	           "uploadprogress cleanup called");
636
+
637
+    ctx = lzcln->shm_zone->data;
638
+    shpool = (ngx_slab_pool_t *) lzcln->shm_zone->shm.addr;
639
+    node = lzcln->node;
640
+    lz = (ngx_http_uploadprogress_node_t *) &node->color;
641
+
642
+    ngx_shmtx_lock(&shpool->mutex);
643
+
644
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, lzcln->shm_zone->shm.log, 0,
645
+                   "upload progress cleanup: %08XD", node->key);
646
+
647
+    ngx_rbtree_delete(ctx->rbtree, node);
648
+    ngx_slab_free_locked(shpool, node);
649
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, lzcln->shm_zone->shm.log, 0,
650
+			"upload progress cleanup node removed: %08XD", node->key);
651
+    ngx_shmtx_unlock(&shpool->mutex);
652
+}
653
+
654
+static ngx_int_t
655
+ngx_http_uploadprogress_init_zone(ngx_shm_zone_t *shm_zone, void *data)
656
+{
657
+    ngx_http_uploadprogress_ctx_t  *octx = data;
658
+
659
+    ngx_slab_pool_t            *shpool;
660
+    ngx_rbtree_node_t          *sentinel;
661
+    ngx_http_uploadprogress_ctx_t  *ctx;
662
+
663
+    ctx = shm_zone->data;
664
+
665
+    if (octx) {
666
+        ctx->rbtree = octx->rbtree;
667
+        return NGX_OK;
668
+    }
669
+
670
+    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
671
+
672
+    ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
673
+    if (ctx->rbtree == NULL) {
674
+        return NGX_ERROR;
675
+    }
676
+
677
+    sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
678
+    if (sentinel == NULL) {
679
+        return NGX_ERROR;
680
+    }
681
+
682
+    ngx_rbtree_sentinel_init(sentinel);
683
+
684
+    ctx->rbtree->root = sentinel;
685
+    ctx->rbtree->sentinel = sentinel;
686
+    ctx->rbtree->insert = ngx_http_uploadprogress_rbtree_insert_value;
687
+
688
+    return NGX_OK;
689
+}
690
+
691
+
692
+static ngx_int_t
693
+ngx_http_uploadprogress_init(ngx_conf_t *cf)
694
+{
695
+    ngx_http_handler_pt        *h;
696
+    ngx_http_core_main_conf_t  *cmcf;
697
+
698
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
699
+
700
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
701
+    if (h == NULL) {
702
+        return NGX_ERROR;
703
+    }
704
+
705
+    *h = ngx_http_uploadprogress_handler;
706
+    return NGX_OK;
707
+}
708
+
709
+static void *
710
+ngx_http_uploadprogress_create_loc_conf(ngx_conf_t *cf)
711
+{
712
+    ngx_http_uploadprogress_conf_t  *conf;
713
+
714
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uploadprogress_conf_t));
715
+    if (conf == NULL) {
716
+        return NGX_CONF_ERROR;
717
+    }
718
+    return conf;
719
+}
720
+
721
+
722
+static char *
723
+ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
724
+{
725
+  ngx_http_uploadprogress_conf_t *prev = parent;
726
+  ngx_http_uploadprogress_conf_t *conf = child;
727
+
728
+  if (conf->shm_zone == NULL) {
729
+      *conf = *prev;
730
+  }
731
+
732
+  return NGX_CONF_OK;
733
+}
734
+
735
+
736
+static char *
737
+ngx_http_upload_progress(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
738
+{
739
+    ssize_t                     n;
740
+    ngx_str_t                  *value;
741
+    ngx_shm_zone_t             *shm_zone;
742
+    ngx_http_uploadprogress_ctx_t  *ctx;
743
+
744
+    value = cf->args->elts;
745
+
746
+	  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
747
+	                 "ngx_upload_progress name: %V", &value[1]);
748
+
749
+    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_uploadprogress_ctx_t));
750
+    if (ctx == NULL) {
751
+        return NGX_CONF_ERROR;
752
+    }
753
+
754
+    n = ngx_parse_size(&value[2]);
755
+
756
+    if (n == NGX_ERROR) {
757
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
758
+                           "invalid size of track_uploads \"%V\"", &value[2]);
759
+        return NGX_CONF_ERROR;
760
+    }
761
+
762
+    if (n < (ngx_int_t) (8 * ngx_pagesize)) {
763
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
764
+                           "track_uploads \"%V\" is too small", &value[1]);
765
+        return NGX_CONF_ERROR;
766
+    }
767
+
768
+    shm_zone = ngx_shared_memory_add(cf, &value[1], n,
769
+                                     &ngx_http_uploadprogress_module);
770
+    if (shm_zone == NULL) {
771
+        return NGX_CONF_ERROR;
772
+    }
773
+
774
+	  ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
775
+	                 "ngx_upload_progress name: %V, szhm_zone: %p", value[1], shm_zone);
776
+
777
+    if (shm_zone->data) {
778
+        ctx = shm_zone->data;
779
+
780
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
781
+                        "track_uploads \"%V\" is already created",
782
+                        &value[1]);
783
+        return NGX_CONF_ERROR;
784
+    }
785
+
786
+    shm_zone->init = ngx_http_uploadprogress_init_zone;
787
+    shm_zone->data = ctx;
788
+
789
+    return NGX_CONF_OK;
790
+}
791
+
792
+static char *
793
+ngx_http_track_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
794
+{
795
+    ngx_http_uploadprogress_conf_t  *lzcf = conf;
796
+    ngx_str_t  *value;
797
+
798
+	  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
799
+	                 "ngx_track_uploads in");
800
+
801
+    value = cf->args->elts;
802
+
803
+		ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
804
+		                 "ngx_track_uploads name: %V", value[1]);
805
+
806
+    lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
807
+                                           &ngx_http_uploadprogress_module);
808
+    if (lzcf->shm_zone == NULL) {
809
+        return NGX_CONF_ERROR;
810
+    }
811
+
812
+		lzcf->track = (u_char)1;
813
+
814
+	  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
815
+	                 "ngx_track_uploads name: %V,szhm_zone: %p", value[1], lzcf->shm_zone);
816
+
817
+    return NGX_CONF_OK;
818
+}
819
+
820
+
821
+static char *
822
+ngx_http_report_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
823
+{
824
+    ngx_http_uploadprogress_conf_t  *lzcf = conf;
825
+    ngx_http_core_loc_conf_t  *clcf;
826
+    ngx_str_t  *value;
827
+
828
+	  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
829
+	                 "ngx_report_uploads in");
830
+
831
+    value = cf->args->elts;
832
+
833
+	  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
834
+	                 "ngx_report_uploads name: %V", value[1]);
835
+
836
+    lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
837
+                                           &ngx_http_uploadprogress_module);
838
+    if (lzcf->shm_zone == NULL) {
839
+        return NGX_CONF_ERROR;
840
+    }
841
+
842
+	  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
843
+	                 "ngx_report_uploads name: %V, szhm_zone: %p", value[1], lzcf->shm_zone);
844
+
845
+		lzcf->track = (u_char)0;
846
+
847
+		/* install our report handler */
848
+    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
849
+    clcf->handler = ngx_http_reportuploads_handler;
850
+
851
+    return NGX_CONF_OK;
852
+}

+ 503
- 0
prj/project.tmproj Целия файл

@@ -0,0 +1,503 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+<plist version="1.0">
4
+<dict>
5
+	<key>currentDocument</key>
6
+	<string>ngx_http_merge_module.c</string>
7
+	<key>documents</key>
8
+	<array>
9
+		<dict>
10
+			<key>children</key>
11
+			<array>
12
+				<dict>
13
+					<key>filename</key>
14
+					<string>config</string>
15
+					<key>lastUsed</key>
16
+					<date>2007-05-18T11:20:50Z</date>
17
+				</dict>
18
+				<dict>
19
+					<key>filename</key>
20
+					<string>ngx_http_merge_module.c</string>
21
+					<key>lastUsed</key>
22
+					<date>2007-05-18T16:52:53Z</date>
23
+					<key>selected</key>
24
+					<true/>
25
+				</dict>
26
+			</array>
27
+			<key>expanded</key>
28
+			<true/>
29
+			<key>name</key>
30
+			<string>nginx_merge_module</string>
31
+		</dict>
32
+		<dict>
33
+			<key>children</key>
34
+			<array>
35
+				<dict>
36
+					<key>filename</key>
37
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_flv_module.c</string>
38
+					<key>lastUsed</key>
39
+					<date>2007-05-18T11:26:07Z</date>
40
+				</dict>
41
+				<dict>
42
+					<key>filename</key>
43
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_access_module.c</string>
44
+					<key>lastUsed</key>
45
+					<date>2007-05-18T14:04:10Z</date>
46
+				</dict>
47
+				<dict>
48
+					<key>filename</key>
49
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_auth_basic_module.c</string>
50
+					<key>lastUsed</key>
51
+					<date>2007-05-18T14:04:08Z</date>
52
+				</dict>
53
+				<dict>
54
+					<key>filename</key>
55
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_autoindex_module.c</string>
56
+					<key>lastUsed</key>
57
+					<date>2007-05-18T14:04:05Z</date>
58
+				</dict>
59
+				<dict>
60
+					<key>filename</key>
61
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_browser_module.c</string>
62
+					<key>lastUsed</key>
63
+					<date>2007-05-18T14:04:03Z</date>
64
+				</dict>
65
+				<dict>
66
+					<key>filename</key>
67
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_dav_module.c</string>
68
+					<key>lastUsed</key>
69
+					<date>2007-05-18T14:50:24Z</date>
70
+				</dict>
71
+				<dict>
72
+					<key>filename</key>
73
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_static_module.c</string>
74
+					<key>lastUsed</key>
75
+					<date>2007-05-18T16:51:16Z</date>
76
+				</dict>
77
+				<dict>
78
+					<key>filename</key>
79
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_addition_filter_module.c</string>
80
+					<key>lastUsed</key>
81
+					<date>2007-05-18T14:55:43Z</date>
82
+				</dict>
83
+				<dict>
84
+					<key>filename</key>
85
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_charset_filter_module.c</string>
86
+				</dict>
87
+				<dict>
88
+					<key>filename</key>
89
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_chunked_filter_module.c</string>
90
+				</dict>
91
+				<dict>
92
+					<key>filename</key>
93
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_empty_gif_module.c</string>
94
+					<key>lastUsed</key>
95
+					<date>2007-05-18T16:50:19Z</date>
96
+				</dict>
97
+				<dict>
98
+					<key>filename</key>
99
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_fastcgi_module.c</string>
100
+				</dict>
101
+				<dict>
102
+					<key>filename</key>
103
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_geo_module.c</string>
104
+					<key>lastUsed</key>
105
+					<date>2007-05-18T14:49:52Z</date>
106
+				</dict>
107
+				<dict>
108
+					<key>filename</key>
109
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_gzip_filter_module.c</string>
110
+					<key>lastUsed</key>
111
+					<date>2007-05-18T16:50:47Z</date>
112
+				</dict>
113
+				<dict>
114
+					<key>filename</key>
115
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_headers_filter_module.c</string>
116
+					<key>lastUsed</key>
117
+					<date>2007-05-18T14:19:14Z</date>
118
+				</dict>
119
+				<dict>
120
+					<key>filename</key>
121
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_index_module.c</string>
122
+					<key>lastUsed</key>
123
+					<date>2007-05-18T14:10:29Z</date>
124
+				</dict>
125
+				<dict>
126
+					<key>filename</key>
127
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_limit_zone_module.c</string>
128
+				</dict>
129
+				<dict>
130
+					<key>filename</key>
131
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_log_module.c</string>
132
+				</dict>
133
+				<dict>
134
+					<key>filename</key>
135
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_map_module.c</string>
136
+				</dict>
137
+				<dict>
138
+					<key>filename</key>
139
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_memcached_module.c</string>
140
+					<key>lastUsed</key>
141
+					<date>2007-05-18T14:49:23Z</date>
142
+				</dict>
143
+				<dict>
144
+					<key>filename</key>
145
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_not_modified_filter_module.c</string>
146
+				</dict>
147
+				<dict>
148
+					<key>filename</key>
149
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_proxy_module.c</string>
150
+					<key>lastUsed</key>
151
+					<date>2007-05-18T14:18:36Z</date>
152
+				</dict>
153
+				<dict>
154
+					<key>filename</key>
155
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_range_filter_module.c</string>
156
+				</dict>
157
+				<dict>
158
+					<key>filename</key>
159
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_realip_module.c</string>
160
+				</dict>
161
+				<dict>
162
+					<key>filename</key>
163
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_referer_module.c</string>
164
+				</dict>
165
+				<dict>
166
+					<key>filename</key>
167
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_rewrite_module.c</string>
168
+				</dict>
169
+				<dict>
170
+					<key>filename</key>
171
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_ssi_filter_module.c</string>
172
+					<key>lastUsed</key>
173
+					<date>2007-05-18T15:34:37Z</date>
174
+				</dict>
175
+				<dict>
176
+					<key>filename</key>
177
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_ssi_filter_module.h</string>
178
+				</dict>
179
+				<dict>
180
+					<key>filename</key>
181
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_ssl_module.c</string>
182
+				</dict>
183
+				<dict>
184
+					<key>filename</key>
185
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_ssl_module.h</string>
186
+				</dict>
187
+				<dict>
188
+					<key>filename</key>
189
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_stub_status_module.c</string>
190
+					<key>lastUsed</key>
191
+					<date>2007-05-18T16:52:53Z</date>
192
+				</dict>
193
+				<dict>
194
+					<key>filename</key>
195
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_upstream_ip_hash_module.c</string>
196
+				</dict>
197
+				<dict>
198
+					<key>filename</key>
199
+					<string>../nginx-0.5.15/src/http/modules/ngx_http_userid_filter_module.c</string>
200
+				</dict>
201
+				<dict>
202
+					<key>filename</key>
203
+					<string>../nginx-0.5.15/src/http/ngx_http_core_module.c</string>
204
+					<key>lastUsed</key>
205
+					<date>2007-05-18T16:51:26Z</date>
206
+				</dict>
207
+			</array>
208
+			<key>expanded</key>
209
+			<true/>
210
+			<key>name</key>
211
+			<string>nginx</string>
212
+		</dict>
213
+	</array>
214
+	<key>fileHierarchyDrawerWidth</key>
215
+	<integer>250</integer>
216
+	<key>metaData</key>
217
+	<dict>
218
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_addition_filter_module.c</key>
219
+		<dict>
220
+			<key>caret</key>
221
+			<dict>
222
+				<key>column</key>
223
+				<integer>21</integer>
224
+				<key>line</key>
225
+				<integer>37</integer>
226
+			</dict>
227
+			<key>columnSelection</key>
228
+			<false/>
229
+			<key>firstVisibleColumn</key>
230
+			<integer>0</integer>
231
+			<key>firstVisibleLine</key>
232
+			<integer>112</integer>
233
+			<key>selectFrom</key>
234
+			<dict>
235
+				<key>column</key>
236
+				<integer>18</integer>
237
+				<key>line</key>
238
+				<integer>37</integer>
239
+			</dict>
240
+			<key>selectTo</key>
241
+			<dict>
242
+				<key>column</key>
243
+				<integer>32</integer>
244
+				<key>line</key>
245
+				<integer>37</integer>
246
+			</dict>
247
+		</dict>
248
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_dav_module.c</key>
249
+		<dict>
250
+			<key>caret</key>
251
+			<dict>
252
+				<key>column</key>
253
+				<integer>0</integer>
254
+				<key>line</key>
255
+				<integer>1209</integer>
256
+			</dict>
257
+			<key>firstVisibleColumn</key>
258
+			<integer>0</integer>
259
+			<key>firstVisibleLine</key>
260
+			<integer>691</integer>
261
+		</dict>
262
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_empty_gif_module.c</key>
263
+		<dict>
264
+			<key>caret</key>
265
+			<dict>
266
+				<key>column</key>
267
+				<integer>0</integer>
268
+				<key>line</key>
269
+				<integer>0</integer>
270
+			</dict>
271
+			<key>firstVisibleColumn</key>
272
+			<integer>0</integer>
273
+			<key>firstVisibleLine</key>
274
+			<integer>0</integer>
275
+		</dict>
276
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_geo_module.c</key>
277
+		<dict>
278
+			<key>caret</key>
279
+			<dict>
280
+				<key>column</key>
281
+				<integer>0</integer>
282
+				<key>line</key>
283
+				<integer>0</integer>
284
+			</dict>
285
+			<key>firstVisibleColumn</key>
286
+			<integer>0</integer>
287
+			<key>firstVisibleLine</key>
288
+			<integer>207</integer>
289
+		</dict>
290
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_gzip_filter_module.c</key>
291
+		<dict>
292
+			<key>caret</key>
293
+			<dict>
294
+				<key>column</key>
295
+				<integer>0</integer>
296
+				<key>line</key>
297
+				<integer>130</integer>
298
+			</dict>
299
+			<key>columnSelection</key>
300
+			<false/>
301
+			<key>firstVisibleColumn</key>
302
+			<integer>0</integer>
303
+			<key>firstVisibleLine</key>
304
+			<integer>104</integer>
305
+			<key>selectFrom</key>
306
+			<dict>
307
+				<key>column</key>
308
+				<integer>0</integer>
309
+				<key>line</key>
310
+				<integer>126</integer>
311
+			</dict>
312
+			<key>selectTo</key>
313
+			<dict>
314
+				<key>column</key>
315
+				<integer>0</integer>
316
+				<key>line</key>
317
+				<integer>130</integer>
318
+			</dict>
319
+		</dict>
320
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_memcached_module.c</key>
321
+		<dict>
322
+			<key>caret</key>
323
+			<dict>
324
+				<key>column</key>
325
+				<integer>0</integer>
326
+				<key>line</key>
327
+				<integer>24</integer>
328
+			</dict>
329
+			<key>firstVisibleColumn</key>
330
+			<integer>0</integer>
331
+			<key>firstVisibleLine</key>
332
+			<integer>378</integer>
333
+		</dict>
334
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_ssi_filter_module.c</key>
335
+		<dict>
336
+			<key>caret</key>
337
+			<dict>
338
+				<key>column</key>
339
+				<integer>15</integer>
340
+				<key>line</key>
341
+				<integer>1885</integer>
342
+			</dict>
343
+			<key>columnSelection</key>
344
+			<false/>
345
+			<key>firstVisibleColumn</key>
346
+			<integer>0</integer>
347
+			<key>firstVisibleLine</key>
348
+			<integer>2004</integer>
349
+			<key>selectFrom</key>
350
+			<dict>
351
+				<key>column</key>
352
+				<integer>12</integer>
353
+				<key>line</key>
354
+				<integer>1885</integer>
355
+			</dict>
356
+			<key>selectTo</key>
357
+			<dict>
358
+				<key>column</key>
359
+				<integer>15</integer>
360
+				<key>line</key>
361
+				<integer>1885</integer>
362
+			</dict>
363
+		</dict>
364
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_static_module.c</key>
365
+		<dict>
366
+			<key>caret</key>
367
+			<dict>
368
+				<key>column</key>
369
+				<integer>36</integer>
370
+				<key>line</key>
371
+				<integer>90</integer>
372
+			</dict>
373
+			<key>columnSelection</key>
374
+			<false/>
375
+			<key>firstVisibleColumn</key>
376
+			<integer>0</integer>
377
+			<key>firstVisibleLine</key>
378
+			<integer>9</integer>
379
+			<key>selectFrom</key>
380
+			<dict>
381
+				<key>column</key>
382
+				<integer>15</integer>
383
+				<key>line</key>
384
+				<integer>90</integer>
385
+			</dict>
386
+			<key>selectTo</key>
387
+			<dict>
388
+				<key>column</key>
389
+				<integer>36</integer>
390
+				<key>line</key>
391
+				<integer>90</integer>
392
+			</dict>
393
+		</dict>
394
+		<key>../nginx-0.5.15/src/http/modules/ngx_http_stub_status_module.c</key>
395
+		<dict>
396
+			<key>caret</key>
397
+			<dict>
398
+				<key>column</key>
399
+				<integer>0</integer>
400
+				<key>line</key>
401
+				<integer>22</integer>
402
+			</dict>
403
+			<key>columnSelection</key>
404
+			<false/>
405
+			<key>firstVisibleColumn</key>
406
+			<integer>0</integer>
407
+			<key>firstVisibleLine</key>
408
+			<integer>5</integer>
409
+			<key>selectFrom</key>
410
+			<dict>
411
+				<key>column</key>
412
+				<integer>0</integer>
413
+				<key>line</key>
414
+				<integer>17</integer>
415
+			</dict>
416
+			<key>selectTo</key>
417
+			<dict>
418
+				<key>column</key>
419
+				<integer>0</integer>
420
+				<key>line</key>
421
+				<integer>22</integer>
422
+			</dict>
423
+		</dict>
424
+		<key>../nginx-0.5.15/src/http/ngx_http_core_module.c</key>
425
+		<dict>
426
+			<key>caret</key>
427
+			<dict>
428
+				<key>column</key>
429
+				<integer>55</integer>
430
+				<key>line</key>
431
+				<integer>2637</integer>
432
+			</dict>
433
+			<key>firstVisibleColumn</key>
434
+			<integer>0</integer>
435
+			<key>firstVisibleLine</key>
436
+			<integer>2606</integer>
437
+		</dict>
438
+		<key>config</key>
439
+		<dict>
440
+			<key>caret</key>
441
+			<dict>
442
+				<key>column</key>
443
+				<integer>70</integer>
444
+				<key>line</key>
445
+				<integer>2</integer>
446
+			</dict>
447
+			<key>columnSelection</key>
448
+			<false/>
449
+			<key>firstVisibleColumn</key>
450
+			<integer>0</integer>
451
+			<key>firstVisibleLine</key>
452
+			<integer>0</integer>
453
+			<key>selectFrom</key>
454
+			<dict>
455
+				<key>column</key>
456
+				<integer>47</integer>
457
+				<key>line</key>
458
+				<integer>2</integer>
459
+			</dict>
460
+			<key>selectTo</key>
461
+			<dict>
462
+				<key>column</key>
463
+				<integer>70</integer>
464
+				<key>line</key>
465
+				<integer>2</integer>
466
+			</dict>
467
+		</dict>
468
+		<key>ngx_http_merge_module.c</key>
469
+		<dict>
470
+			<key>caret</key>
471
+			<dict>
472
+				<key>column</key>
473
+				<integer>1</integer>
474
+				<key>line</key>
475
+				<integer>91</integer>
476
+			</dict>
477
+			<key>firstVisibleColumn</key>
478
+			<integer>0</integer>
479
+			<key>firstVisibleLine</key>
480
+			<integer>228</integer>
481
+		</dict>
482
+	</dict>
483
+	<key>openDocuments</key>
484
+	<array>
485
+		<string>config</string>
486
+		<string>ngx_http_merge_module.c</string>
487
+		<string>../nginx-0.5.15/src/http/ngx_http_core_module.c</string>
488
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_stub_status_module.c</string>
489
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_static_module.c</string>
490
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_empty_gif_module.c</string>
491
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_ssi_filter_module.c</string>
492
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_memcached_module.c</string>
493
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_geo_module.c</string>
494
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_dav_module.c</string>
495
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_addition_filter_module.c</string>
496
+		<string>../nginx-0.5.15/src/http/modules/ngx_http_gzip_filter_module.c</string>
497
+	</array>
498
+	<key>showFileHierarchyDrawer</key>
499
+	<true/>
500
+	<key>windowFrame</key>
501
+	<string>{{299, 34}, {713, 684}}</string>
502
+</dict>
503
+</plist>

+ 19
- 0
prj/tmtags Целия файл

@@ -0,0 +1,19 @@
1
+!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
2
+!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
3
+!_TAG_PROGRAM_AUTHOR	Darren Hiebert	/dhiebert@users.sourceforge.net/
4
+!_TAG_PROGRAM_NAME	Exuberant Ctags	//
5
+!_TAG_PROGRAM_URL	http://ctags.sourceforge.net	/official site/
6
+!_TAG_PROGRAM_VERSION	5.5.4	//
7
+get_tracking_id	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^get_tracking_id(ngx_http_request_t *r)$/;"	function	line:68
8
+ngx_http_reportuploads	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_reportuploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)$/;"	function	line:221
9
+ngx_http_reportuploads_handler	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_reportuploads_handler(ngx_http_request_t *r)$/;"	function	line:99
10
+ngx_http_rewrite_loc_conf_t	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^} ngx_http_rewrite_loc_conf_t;$/;"	typedef	line:13
11
+ngx_http_uploadprogress_commands	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^static ngx_command_t  ngx_http_uploadprogress_commands[] = {$/;"	variable	line:15
12
+ngx_http_uploadprogress_create_loc_conf	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_uploadprogress_create_loc_conf(ngx_conf_t *cf)$/;"	function	line:209
13
+ngx_http_uploadprogress_handler	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_uploadprogress_handler(ngx_http_request_t *r)$/;"	function	line:156
14
+ngx_http_uploadprogress_init	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_uploadprogress_init(ngx_conf_t *cf)$/;"	function	line:191
15
+ngx_http_uploadprogress_merge_loc_conf	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)$/;"	function	line:234
16
+ngx_http_uploadprogress_module	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^ngx_module_t  ngx_http_uploadprogress_module = {$/;"	variable	line:51
17
+ngx_http_uploadprogress_module_ctx	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^static ngx_http_module_t  ngx_http_uploadprogress_module_ctx = {$/;"	variable	line:36
18
+report_upload	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^    ngx_flag_t    report_upload;$/;"	member	line:12
19
+track_upload	/Users/brice/devl/nginx_uploadprogress_module/ngx_http_uploadprogress_module.c	/^    ngx_flag_t    track_upload;$/;"	member	line:11

Loading…
Отказ
Запис