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