@@ -114,6 +114,12 @@ typedef struct {
114
114
#endif
115
115
} ngx_http_upload_field_filter_t ;
116
116
117
+ typedef struct {
118
+ ngx_path_t * path ;
119
+ ngx_http_complex_value_t dynamic ;
120
+ unsigned is_dynamic :1 ;
121
+ } ngx_http_upload_path_t ;
122
+
117
123
/*
118
124
* Upload cleanup record
119
125
*/
@@ -132,8 +138,8 @@ typedef struct ngx_http_upload_cleanup_s {
132
138
typedef struct {
133
139
ngx_str_t url ;
134
140
ngx_http_complex_value_t * url_cv ;
135
- ngx_path_t * state_store_path ;
136
- ngx_path_t * store_path ;
141
+ ngx_http_upload_path_t * state_store_path ;
142
+ ngx_http_upload_path_t * store_path ;
137
143
ngx_uint_t store_access ;
138
144
size_t buffer_size ;
139
145
size_t merge_buffer_size ;
@@ -245,6 +251,8 @@ typedef struct ngx_http_upload_ctx_s {
245
251
ngx_http_upload_sha256_ctx_t * sha256_ctx ;
246
252
ngx_http_upload_sha512_ctx_t * sha512_ctx ;
247
253
uint32_t crc32 ;
254
+ ngx_path_t * store_path ;
255
+ ngx_path_t * state_store_path ;
248
256
249
257
unsigned int first_part :1 ;
250
258
unsigned int discard_data :1 ;
@@ -313,8 +321,14 @@ static char *ngx_http_upload_set_form_field(ngx_conf_t *cf, ngx_command_t *cmd,
313
321
void * conf );
314
322
static char * ngx_http_upload_add_header (ngx_conf_t * cf , ngx_command_t * cmd ,
315
323
void * conf );
324
+ static ngx_int_t ngx_http_upload_eval_path (ngx_http_request_t * r );
325
+ static ngx_int_t ngx_http_upload_eval_state_path (ngx_http_request_t * r );
316
326
static char * ngx_http_upload_pass_form_field (ngx_conf_t * cf , ngx_command_t * cmd ,
317
327
void * conf );
328
+ static char * ngx_http_upload_set_path_slot (ngx_conf_t * cf , ngx_command_t * cmd ,
329
+ void * conf );
330
+ static char * ngx_http_upload_merge_path_value (ngx_conf_t * cf , ngx_http_upload_path_t * * path , ngx_http_upload_path_t * prev ,
331
+ ngx_path_init_t * init );
318
332
static char * ngx_http_upload_cleanup (ngx_conf_t * cf , ngx_command_t * cmd ,
319
333
void * conf );
320
334
static void ngx_upload_cleanup_handler (void * data );
@@ -425,7 +439,7 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
425
439
{ ngx_string ("upload_store" ),
426
440
NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_HTTP_LMT_CONF |NGX_HTTP_LIF_CONF
427
441
|NGX_CONF_TAKE1234 ,
428
- ngx_conf_set_path_slot ,
442
+ ngx_http_upload_set_path_slot ,
429
443
NGX_HTTP_LOC_CONF_OFFSET ,
430
444
offsetof(ngx_http_upload_loc_conf_t , store_path ),
431
445
NULL },
@@ -435,7 +449,7 @@ static ngx_command_t ngx_http_upload_commands[] = { /* {{{ */
435
449
*/
436
450
{ ngx_string ("upload_state_store" ),
437
451
NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1234 ,
438
- ngx_conf_set_path_slot ,
452
+ ngx_http_upload_set_path_slot ,
439
453
NGX_HTTP_LOC_CONF_OFFSET ,
440
454
offsetof(ngx_http_upload_loc_conf_t , state_store_path ),
441
455
NULL },
@@ -841,6 +855,20 @@ ngx_http_upload_handler(ngx_http_request_t *r)
841
855
return rc ;
842
856
}
843
857
858
+ rc = ngx_http_upload_eval_path (r );
859
+
860
+ if (rc != NGX_OK ) {
861
+ upload_shutdown_ctx (u );
862
+ return rc ;
863
+ }
864
+
865
+ rc = ngx_http_upload_eval_state_path (r );
866
+
867
+ if (rc != NGX_OK ) {
868
+ upload_shutdown_ctx (u );
869
+ return rc ;
870
+ }
871
+
844
872
if (ngx_http_upload_test_expect (r ) != NGX_OK ) {
845
873
upload_shutdown_ctx (u );
846
874
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
@@ -896,6 +924,68 @@ static ngx_int_t ngx_http_upload_add_headers(ngx_http_request_t *r, ngx_http_upl
896
924
return NGX_OK ;
897
925
} /* }}} */
898
926
927
+ static ngx_int_t /* {{{ */
928
+ ngx_http_upload_eval_path (ngx_http_request_t * r ) {
929
+ ngx_http_upload_ctx_t * u ;
930
+ ngx_http_upload_loc_conf_t * ulcf ;
931
+ ngx_str_t value ;
932
+
933
+ ulcf = ngx_http_get_module_loc_conf (r , ngx_http_upload_module );
934
+ u = ngx_http_get_module_ctx (r , ngx_http_upload_module );
935
+
936
+ if (ulcf -> store_path -> is_dynamic ) {
937
+ u -> store_path = ngx_pcalloc (r -> pool , sizeof (ngx_path_t ));
938
+ if (u -> store_path == NULL ) {
939
+ return NGX_ERROR ;
940
+ }
941
+
942
+ ngx_memcpy (u -> store_path , ulcf -> store_path -> path , sizeof (ngx_path_t ));
943
+
944
+ if (ngx_http_complex_value (r , & ulcf -> store_path -> dynamic , & value ) != NGX_OK ) {
945
+ return NGX_ERROR ;
946
+ }
947
+
948
+ u -> store_path -> name .data = value .data ;
949
+ u -> store_path -> name .len = value .len ;
950
+ }
951
+ else {
952
+ u -> store_path = ulcf -> store_path -> path ;
953
+ }
954
+
955
+ return NGX_OK ;
956
+ } /* }}} */
957
+
958
+ static ngx_int_t /* {{{ */
959
+ ngx_http_upload_eval_state_path (ngx_http_request_t * r ) {
960
+ ngx_http_upload_ctx_t * u ;
961
+ ngx_http_upload_loc_conf_t * ulcf ;
962
+ ngx_str_t value ;
963
+
964
+ ulcf = ngx_http_get_module_loc_conf (r , ngx_http_upload_module );
965
+ u = ngx_http_get_module_ctx (r , ngx_http_upload_module );
966
+
967
+ if (ulcf -> state_store_path -> is_dynamic ) {
968
+ u -> state_store_path = ngx_pcalloc (r -> pool , sizeof (ngx_path_t ));
969
+ if (u -> store_path == NULL ) {
970
+ return NGX_ERROR ;
971
+ }
972
+
973
+ ngx_memcpy (u -> state_store_path , ulcf -> state_store_path -> path , sizeof (ngx_path_t ));
974
+
975
+ if (ngx_http_complex_value (r , & ulcf -> state_store_path -> dynamic , & value ) != NGX_OK ) {
976
+ return NGX_ERROR ;
977
+ }
978
+
979
+ u -> state_store_path -> name .data = value .data ;
980
+ u -> state_store_path -> name .len = value .len ;
981
+ }
982
+ else {
983
+ u -> state_store_path = ulcf -> state_store_path -> path ;
984
+ }
985
+
986
+ return NGX_OK ;
987
+ } /* }}} */
988
+
899
989
static ngx_int_t ngx_http_upload_options_handler (ngx_http_request_t * r ) { /* {{{ */
900
990
ngx_http_upload_loc_conf_t * ulcf ;
901
991
@@ -1112,7 +1202,8 @@ static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u) { /* {{
1112
1202
ngx_http_upload_loc_conf_t * ulcf = ngx_http_get_module_loc_conf (r , ngx_http_upload_module );
1113
1203
1114
1204
ngx_file_t * file = & u -> output_file ;
1115
- ngx_path_t * path = ulcf -> store_path ;
1205
+ ngx_path_t * path = u -> store_path ;
1206
+ ngx_path_t * state_path = u -> state_store_path ;
1116
1207
uint32_t n ;
1117
1208
ngx_uint_t i ;
1118
1209
ngx_int_t rc ;
@@ -1152,28 +1243,28 @@ static ngx_int_t ngx_http_upload_start_handler(ngx_http_upload_ctx_t *u) { /* {{
1152
1243
"hashed path: %s" , file -> name .data );
1153
1244
1154
1245
if (u -> partial_content ) {
1246
+ ngx_file_t * state_file = & u -> state_file ;
1155
1247
if (u -> merge_buffer == NULL ) {
1156
1248
u -> merge_buffer = ngx_palloc (r -> pool , ulcf -> merge_buffer_size );
1157
1249
1158
1250
if (u -> merge_buffer == NULL )
1159
1251
return NGX_UPLOAD_NOMEM ;
1160
1252
}
1161
1253
1162
- u -> state_file . name .len = file -> name .len + sizeof (".state" ) - 1 ;
1163
- u -> state_file . name .data = ngx_palloc (u -> request -> pool , u -> state_file . name .len + 1 );
1254
+ state_file -> name .len = state_path -> name .len + 1 + state_path -> len + u -> session_id . len + sizeof (".state" );
1255
+ state_file -> name .data = ngx_palloc (u -> request -> pool , state_file -> name .len + 1 );
1164
1256
1165
- if (u -> state_file . name .data == NULL )
1257
+ if (state_file -> name .data == NULL )
1166
1258
return NGX_UPLOAD_NOMEM ;
1167
1259
1168
- ngx_memcpy (u -> state_file .name .data , file -> name .data , file -> name .len );
1260
+ ngx_memcpy (state_file -> name .data , state_path -> name .data , state_path -> name .len );
1261
+ (void ) ngx_sprintf (state_file -> name .data + state_path -> name .len + 1 + state_path -> len ,
1262
+ "%V.state%Z" , & u -> session_id );
1169
1263
1170
- /*
1171
- * NOTE: we add terminating zero for system calls
1172
- */
1173
- ngx_memcpy (u -> state_file .name .data + file -> name .len , ".state" , sizeof (".state" ) - 1 + 1 );
1264
+ ngx_create_hashed_filename (state_path , state_file -> name .data , state_file -> name .len );
1174
1265
1175
1266
ngx_log_debug1 (NGX_LOG_DEBUG_CORE , file -> log , 0 ,
1176
- "hashed path of state file: %s" , u -> state_file . name .data );
1267
+ "hashed path of state file: %s" , state_file -> name .data );
1177
1268
}
1178
1269
1179
1270
file -> fd = ngx_open_file (file -> name .data , NGX_FILE_WRONLY , NGX_FILE_CREATE_OR_OPEN , ulcf -> store_access );
@@ -2013,27 +2104,15 @@ ngx_http_upload_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2013
2104
}
2014
2105
2015
2106
if (conf -> url .len != 0 ) {
2016
- #if defined nginx_version && nginx_version >= 7052
2017
- ngx_conf_merge_path_value (cf ,
2107
+ ngx_http_upload_merge_path_value (cf ,
2018
2108
& conf -> store_path ,
2019
2109
prev -> store_path ,
2020
2110
& ngx_http_upload_temp_path );
2021
2111
2022
- ngx_conf_merge_path_value (cf ,
2112
+ ngx_http_upload_merge_path_value (cf ,
2023
2113
& conf -> state_store_path ,
2024
2114
prev -> state_store_path ,
2025
2115
& ngx_http_upload_temp_path );
2026
- #else
2027
- ngx_conf_merge_path_value (conf -> store_path ,
2028
- prev -> store_path ,
2029
- NGX_HTTP_PROXY_TEMP_PATH , 1 , 2 , 0 ,
2030
- ngx_garbage_collector_temp_handler , cf );
2031
-
2032
- ngx_conf_merge_path_value (conf -> state_store_path ,
2033
- prev -> state_store_path ,
2034
- NGX_HTTP_PROXY_TEMP_PATH , 1 , 2 , 0 ,
2035
- ngx_garbage_collector_temp_handler , cf );
2036
- #endif
2037
2116
}
2038
2117
2039
2118
ngx_conf_merge_uint_value (conf -> store_access ,
@@ -2874,6 +2953,138 @@ ngx_http_upload_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2874
2953
return NGX_CONF_OK ;
2875
2954
} /* }}} */
2876
2955
2956
+ static char * /* {{{ ngx_http_upload_set_path_slot */
2957
+ ngx_http_upload_set_path_slot (ngx_conf_t * cf , ngx_command_t * cmd , void * conf )
2958
+ {
2959
+ char * p = conf ;
2960
+
2961
+ ssize_t level ;
2962
+ ngx_str_t * value ;
2963
+ ngx_uint_t i , n ;
2964
+ ngx_http_upload_path_t * path , * * slot ;
2965
+ ngx_http_compile_complex_value_t ccv ;
2966
+
2967
+ slot = (ngx_http_upload_path_t * * ) (p + cmd -> offset );
2968
+
2969
+ if (* slot ) {
2970
+ return "is duplicate" ;
2971
+ }
2972
+
2973
+ path = ngx_pcalloc (cf -> pool , sizeof (ngx_http_upload_path_t ));
2974
+ if (path == NULL ) {
2975
+ return NGX_CONF_ERROR ;
2976
+ }
2977
+
2978
+ path -> path = ngx_pcalloc (cf -> pool , sizeof (ngx_path_t ));
2979
+ if (path -> path == NULL ) {
2980
+ return NGX_CONF_ERROR ;
2981
+ }
2982
+
2983
+ value = cf -> args -> elts ;
2984
+
2985
+ path -> path -> name = value [1 ];
2986
+
2987
+ if (path -> path -> name .data [path -> path -> name .len - 1 ] == '/' ) {
2988
+ path -> path -> name .len -- ;
2989
+ }
2990
+
2991
+ if (ngx_conf_full_name (cf -> cycle , & path -> path -> name , 0 ) != NGX_OK ) {
2992
+ return NULL ;
2993
+ }
2994
+
2995
+ path -> path -> len = 0 ;
2996
+ path -> path -> manager = NULL ;
2997
+ path -> path -> loader = NULL ;
2998
+ path -> path -> conf_file = cf -> conf_file -> file .name .data ;
2999
+ path -> path -> line = cf -> conf_file -> line ;
3000
+
3001
+ for (i = 0 , n = 2 ; n < cf -> args -> nelts ; i ++ , n ++ ) {
3002
+ level = ngx_atoi (value [n ].data , value [n ].len );
3003
+ if (level == NGX_ERROR || level == 0 ) {
3004
+ return "invalid value" ;
3005
+ }
3006
+
3007
+ path -> path -> level [i ] = level ;
3008
+ path -> path -> len += level + 1 ;
3009
+ }
3010
+
3011
+ while (i < 3 ) {
3012
+ path -> path -> level [i ++ ] = 0 ;
3013
+ }
3014
+
3015
+ * slot = path ;
3016
+
3017
+ if (ngx_http_script_variables_count (& value [1 ])) {
3018
+ ngx_memzero (& ccv , sizeof (ngx_http_compile_complex_value_t ));
3019
+
3020
+ ccv .cf = cf ;
3021
+ ccv .value = & value [1 ];
3022
+ ccv .complex_value = & path -> dynamic ;
3023
+
3024
+ if (ngx_http_compile_complex_value (& ccv ) != NGX_OK ) {
3025
+ return NGX_CONF_ERROR ;
3026
+ }
3027
+
3028
+ path -> is_dynamic = 1 ;
3029
+ }
3030
+ else {
3031
+ if (ngx_add_path (cf , & path -> path ) == NGX_ERROR ) {
3032
+ return NGX_CONF_ERROR ;
3033
+ }
3034
+ }
3035
+
3036
+ return NGX_CONF_OK ;
3037
+ } /* }}} */
3038
+
3039
+
3040
+ static char * /* {{{ ngx_http_upload_merge_path_value */
3041
+ ngx_http_upload_merge_path_value (ngx_conf_t * cf , ngx_http_upload_path_t * * path , ngx_http_upload_path_t * prev ,
3042
+ ngx_path_init_t * init )
3043
+ {
3044
+ if (* path ) {
3045
+ return NGX_CONF_OK ;
3046
+ }
3047
+
3048
+ if (prev ) {
3049
+ * path = prev ;
3050
+ return NGX_CONF_OK ;
3051
+ }
3052
+
3053
+ * path = ngx_palloc (cf -> pool , sizeof (ngx_http_upload_path_t ));
3054
+ if (* path == NULL ) {
3055
+ return NGX_CONF_ERROR ;
3056
+ }
3057
+
3058
+ (* path )-> path = ngx_pcalloc (cf -> pool , sizeof (ngx_path_t ));
3059
+ if ((* path )-> path == NULL ) {
3060
+ return NGX_CONF_ERROR ;
3061
+ }
3062
+
3063
+ (* path )-> path -> name = init -> name ;
3064
+
3065
+ if (ngx_conf_full_name (cf -> cycle , & (* path )-> path -> name , 0 ) != NGX_OK ) {
3066
+ return NGX_CONF_ERROR ;
3067
+ }
3068
+
3069
+ (* path )-> path -> level [0 ] = init -> level [0 ];
3070
+ (* path )-> path -> level [1 ] = init -> level [1 ];
3071
+ (* path )-> path -> level [2 ] = init -> level [2 ];
3072
+
3073
+ (* path )-> path -> len = init -> level [0 ] + (init -> level [0 ] ? 1 : 0 )
3074
+ + init -> level [1 ] + (init -> level [1 ] ? 1 : 0 )
3075
+ + init -> level [2 ] + (init -> level [2 ] ? 1 : 0 );
3076
+
3077
+ (* path )-> path -> manager = NULL ;
3078
+ (* path )-> path -> loader = NULL ;
3079
+ (* path )-> path -> conf_file = NULL ;
3080
+
3081
+ if (ngx_add_path (cf , & (* path )-> path ) != NGX_OK ) {
3082
+ return NGX_CONF_ERROR ;
3083
+ }
3084
+
3085
+ return NGX_CONF_OK ;
3086
+ } /* }}} */
3087
+
2877
3088
ngx_int_t /* {{{ ngx_http_read_upload_client_request_body */
2878
3089
ngx_http_read_upload_client_request_body (ngx_http_request_t * r ) {
2879
3090
ssize_t size , preread ;
@@ -3795,8 +4006,8 @@ ngx_http_upload_parse_range(ngx_str_t *range, ngx_http_upload_range_t *range_n)
3795
4006
return NGX_ERROR ;
3796
4007
}
3797
4008
3798
- if (range_n -> start >= range_n -> end || range_n -> start >= range_n -> total
3799
- || range_n -> end > range_n -> total )
4009
+ if (range_n -> start > range_n -> end || range_n -> start >= range_n -> total
4010
+ || range_n -> end >= range_n -> total )
3800
4011
{
3801
4012
return NGX_ERROR ;
3802
4013
}
0 commit comments