3838#define NGX_UPLOAD_NOMEM -2
3939#define NGX_UPLOAD_IOERROR -3
4040#define NGX_UPLOAD_SCRIPTERROR -4
41- #define NGX_UPLOAD_TOOLARGE -5
4241
4342/*
4443 * State of multipart/form-data parser
@@ -82,9 +81,7 @@ typedef struct {
8281 ngx_path_t * store_path ;
8382 ngx_uint_t store_access ;
8483 size_t buffer_size ;
85- size_t max_file_size ;
8684 size_t max_header_len ;
87- size_t max_output_body_len ;
8885 ngx_array_t * field_templates ;
8986 ngx_array_t * aggregate_field_templates ;
9087 ngx_array_t * field_filters ;
@@ -160,6 +157,8 @@ static ngx_int_t ngx_http_upload_md5_variable(ngx_http_request_t *r,
160157 ngx_http_variable_value_t * v , uintptr_t data );
161158static ngx_int_t ngx_http_upload_sha1_variable (ngx_http_request_t * r ,
162159 ngx_http_variable_value_t * v , uintptr_t data );
160+ static ngx_int_t ngx_http_upload_file_size_variable (ngx_http_request_t * r ,
161+ ngx_http_variable_value_t * v , uintptr_t data );
163162static char * ngx_http_upload_pass (ngx_conf_t * cf , ngx_command_t * cmd , void * conf );
164163
165164static ngx_int_t ngx_http_upload_start_handler (ngx_http_upload_ctx_t * u );
@@ -258,8 +257,9 @@ ngx_int_t upload_parse_content_type(ngx_http_upload_ctx_t *upload_ctx, ngx_str_t
258257 * NGX_UPLOAD_NOMEM insufficient memory
259258 * NGX_UPLOAD_IOERROR input-output error
260259 * NGX_UPLOAD_SCRIPTERROR nginx script engine failed
260+ * NGX_UPLOAD_TOOLARGE field body is too large
261261 */
262- int upload_process_buf (ngx_http_upload_ctx_t * upload_ctx , u_char * start , u_char * end );
262+ ngx_int_t upload_process_buf (ngx_http_upload_ctx_t * upload_ctx , u_char * start , u_char * end );
263263
264264static ngx_command_t ngx_http_upload_commands [] = { /* {{{ */
265265
@@ -304,16 +304,6 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
304304 offsetof(ngx_http_upload_loc_conf_t , buffer_size ),
305305 NULL },
306306
307- /*
308- * Specifies the maximal size of a file which could be uploaded
309- */
310- { ngx_string ("upload_max_file_size" ),
311- NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
312- ngx_conf_set_size_slot ,
313- NGX_HTTP_LOC_CONF_OFFSET ,
314- offsetof(ngx_http_upload_loc_conf_t , max_file_size ),
315- NULL },
316-
317307 /*
318308 * Specifies the maximal length of the part header
319309 */
@@ -324,16 +314,6 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
324314 offsetof(ngx_http_upload_loc_conf_t , max_header_len ),
325315 NULL },
326316
327- /*
328- * Specifies the maximal length of resulting body
329- */
330- { ngx_string ("upload_max_output_body_len" ),
331- NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
332- ngx_conf_set_size_slot ,
333- NGX_HTTP_LOC_CONF_OFFSET ,
334- offsetof(ngx_http_upload_loc_conf_t , max_output_body_len ),
335- NULL },
336-
337317 /*
338318 * Specifies the field to set in altered response body
339319 */
@@ -439,6 +419,10 @@ static ngx_http_variable_t ngx_http_upload_aggregate_variables[] = { /* {{{ */
439419 (uintptr_t ) "0123456789ABCDEF" ,
440420 NGX_HTTP_VAR_CHANGEABLE |NGX_HTTP_VAR_NOCACHEABLE |NGX_HTTP_VAR_NOHASH , 0 },
441421
422+ { ngx_string ("upload_file_size" ), NULL , ngx_http_upload_file_size_variable ,
423+ (uintptr_t ) offsetof(ngx_http_upload_ctx_t , output_file .offset ),
424+ NGX_HTTP_VAR_CHANGEABLE |NGX_HTTP_VAR_NOCACHEABLE |NGX_HTTP_VAR_NOHASH , 0 },
425+
442426 { ngx_null_string , NULL , NULL , 0 , 0 , 0 }
443427}; /* }}} */
444428
@@ -539,14 +523,6 @@ static ngx_int_t ngx_http_upload_body_handler(ngx_http_request_t *r) { /* {{{ */
539523 ngx_buf_t * b ;
540524 ngx_chain_t * cl ;
541525
542- if (ulcf -> max_output_body_len && ctx -> output_body_len + ctx -> boundary .len
543- + 4 > ulcf -> max_output_body_len )
544- {
545- ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 ,
546- "client has sent too large request body" );
547- return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE ;
548- }
549-
550526 ctx -> output_body_len += ctx -> boundary .len + 4 ;
551527
552528 /*
@@ -802,7 +778,7 @@ static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
802778 if (ngx_http_script_run (r , & aggregate_field_name , af [i ].field_lengths -> elts , 0 ,
803779 af [i ].field_values -> elts ) == NULL )
804780 {
805- return ;
781+ goto rollback ;
806782 }
807783 }
808784
@@ -812,20 +788,24 @@ static void ngx_http_upload_finish_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
812788 if (ngx_http_script_run (r , & aggregate_field_value , af [i ].value_lengths -> elts , 0 ,
813789 af [i ].value_values -> elts ) == NULL )
814790 {
815- return ;
791+ goto rollback ;
816792 }
817793 }
818794
819795 rc = ngx_http_upload_append_field (u , & aggregate_field_name , & aggregate_field_value );
820796
821797 if (rc != NGX_OK )
822- return ;
798+ goto rollback ;
823799 }
824800 }
825801 }
826802
827803 // Checkpoint current output chain state
828804 u -> checkpoint = u -> last ;
805+ return ;
806+
807+ rollback :
808+ ngx_http_upload_abort_handler (u );
829809} /* }}} */
830810
831811static void ngx_http_upload_abort_handler (ngx_http_upload_ctx_t * u ) { /* {{{ */
@@ -858,17 +838,10 @@ static void ngx_http_upload_abort_handler(ngx_http_upload_ctx_t *u) { /* {{{ */
858838
859839static ngx_int_t ngx_http_upload_flush_output_buffer (ngx_http_upload_ctx_t * u , u_char * buf , size_t len ) { /* {{{ */
860840 ngx_http_request_t * r = u -> request ;
861- ngx_http_upload_loc_conf_t * ulcf = ngx_http_get_module_loc_conf (r , ngx_http_upload_module );
862841 ngx_buf_t * b ;
863842 ngx_chain_t * cl ;
864843
865844 if (u -> is_file ) {
866- if (ulcf -> max_file_size && u -> output_file .offset + len > ulcf -> max_file_size ) {
867- ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 ,
868- "client has sent too large file \"%V\"" , & u -> output_file .name );
869- return NGX_UPLOAD_TOOLARGE ;
870- }
871-
872845 if (u -> md5_ctx )
873846 MD5Update (& u -> md5_ctx -> md5 , buf , len );
874847
@@ -882,14 +855,6 @@ static ngx_int_t ngx_http_upload_flush_output_buffer(ngx_http_upload_ctx_t *u, u
882855 }else
883856 return NGX_OK ;
884857 }else {
885- if (ulcf -> max_output_body_len && u -> output_body_len + len > ulcf -> max_output_body_len ) {
886- ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 ,
887- "client has sent too large field \"%V\"" , & u -> field_name );
888- return NGX_UPLOAD_TOOLARGE ;
889- }
890-
891- u -> output_body_len += len ;
892-
893858 b = ngx_create_temp_buf (u -> request -> pool , len );
894859
895860 if (b == NULL ) {
@@ -997,9 +962,7 @@ ngx_http_upload_create_loc_conf(ngx_conf_t *cf)
997962 conf -> store_access = NGX_CONF_UNSET_UINT ;
998963
999964 conf -> buffer_size = NGX_CONF_UNSET_SIZE ;
1000- conf -> max_file_size = NGX_CONF_UNSET_SIZE ;
1001965 conf -> max_header_len = NGX_CONF_UNSET_SIZE ;
1002- conf -> max_output_body_len = NGX_CONF_UNSET_SIZE ;
1003966
1004967 /*
1005968 * conf->field_templates,
@@ -1031,18 +994,10 @@ ngx_http_upload_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1031994 prev -> buffer_size ,
1032995 (size_t ) ngx_pagesize );
1033996
1034- ngx_conf_merge_size_value (conf -> max_file_size ,
1035- prev -> max_file_size ,
1036- (size_t ) 0 );
1037-
1038997 ngx_conf_merge_size_value (conf -> max_header_len ,
1039998 prev -> max_header_len ,
1040999 (size_t ) 512 );
10411000
1042- ngx_conf_merge_size_value (conf -> max_output_body_len ,
1043- prev -> max_output_body_len ,
1044- (size_t ) 256 * 1024 );
1045-
10461001 if (conf -> field_templates == NULL ) {
10471002 conf -> field_templates = prev -> field_templates ;
10481003 }
@@ -1189,6 +1144,32 @@ ngx_http_upload_sha1_variable(ngx_http_request_t *r,
11891144 return NGX_OK ;
11901145} /* }}} */
11911146
1147+ static ngx_int_t /* {{{ ngx_http_upload_file_size_variable */
1148+ ngx_http_upload_file_size_variable (ngx_http_request_t * r ,
1149+ ngx_http_variable_value_t * v , uintptr_t data )
1150+ {
1151+ ngx_http_upload_ctx_t * u ;
1152+ u_char * p ;
1153+ off_t * value ;
1154+
1155+ u = ngx_http_get_module_ctx (r , ngx_http_upload_module );
1156+
1157+ value = (off_t * ) ((char * ) u + data );
1158+
1159+ p = ngx_palloc (r -> pool , NGX_OFF_T_LEN );
1160+ if (p == NULL ) {
1161+ return NGX_ERROR ;
1162+ }
1163+
1164+ v -> len = ngx_sprintf (p , "%O" , * value ) - p ;
1165+ v -> valid = 1 ;
1166+ v -> no_cacheable = 0 ;
1167+ v -> not_found = 0 ;
1168+ v -> data = p ;
1169+
1170+ return NGX_OK ;
1171+ } /* }}} */
1172+
11921173static char * /* {{{ ngx_http_upload_set_form_field */
11931174ngx_http_upload_set_form_field (ngx_conf_t * cf , ngx_command_t * cmd , void * conf )
11941175{
@@ -1281,7 +1262,7 @@ ngx_http_upload_set_form_field(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
12811262
12821263 /*
12831264 * ngx_http_script_compile does check for final bracket earlier,
1284- * so we don't need to care about it, which simplifies things
1265+ * therefore we don't need to care about it, which simplifies things
12851266 */
12861267 if (match != NULL
12871268 && ((match - value [i ].data >= 1 && match [-1 ] == '$' )
@@ -1595,8 +1576,6 @@ ngx_http_do_read_upload_client_request_body(ngx_http_request_t *r)
15951576 return NGX_HTTP_BAD_REQUEST ;
15961577 case NGX_UPLOAD_IOERROR :
15971578 return NGX_HTTP_SERVICE_UNAVAILABLE ;
1598- case NGX_UPLOAD_TOOLARGE :
1599- return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE ;
16001579 case NGX_UPLOAD_NOMEM : case NGX_UPLOAD_SCRIPTERROR :
16011580 default :
16021581 return NGX_HTTP_INTERNAL_SERVER_ERROR ;
@@ -1676,8 +1655,6 @@ ngx_http_do_read_upload_client_request_body(ngx_http_request_t *r)
16761655 return NGX_HTTP_BAD_REQUEST ;
16771656 case NGX_UPLOAD_IOERROR :
16781657 return NGX_HTTP_SERVICE_UNAVAILABLE ;
1679- case NGX_UPLOAD_TOOLARGE :
1680- return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE ;
16811658 case NGX_UPLOAD_NOMEM : case NGX_UPLOAD_SCRIPTERROR :
16821659 default :
16831660 return NGX_HTTP_INTERNAL_SERVER_ERROR ;
@@ -1999,7 +1976,7 @@ void upload_putc(ngx_http_upload_ctx_t *upload_ctx, u_char c) { /* {{{ */
19991976 }
20001977} /* }}} */
20011978
2002- int upload_process_buf (ngx_http_upload_ctx_t * upload_ctx , u_char * start , u_char * end ) { /* {{{ */
1979+ ngx_int_t upload_process_buf (ngx_http_upload_ctx_t * upload_ctx , u_char * start , u_char * end ) { /* {{{ */
20031980
20041981 u_char * p ;
20051982 ngx_int_t rc ;
0 commit comments