@@ -23,7 +23,7 @@ typedef struct query_param {
23
23
* @param ctx The Varnish context.
24
24
* @param result The array of query parameters.
25
25
* @param query_str The query string to tokenize.
26
- * @return The number of query parameters.
26
+ * @return The number of query parameters or -1 on error .
27
27
*/
28
28
static int tokenize_querystring (VRT_CTX , query_param_t * * result ,
29
29
char * query_str ) {
@@ -72,6 +72,131 @@ static int tokenize_querystring(VRT_CTX, query_param_t **result,
72
72
return no_param ;
73
73
}
74
74
75
+ /**
76
+ * Tokenize and parse the filter parameters from params_in into filter_params
77
+ * array.
78
+ * @param ctx Varnish context
79
+ * @param params_in Comma-separated filter parameter names
80
+ * @param filter_params Output array of parameter names
81
+ * @param num_filter_params Output number of parsed filter parameters
82
+ * @return 0 on success, -1 on error
83
+ */
84
+ static int parse_filter_params (VRT_CTX , const char * params_in ,
85
+ char * * filter_params ,
86
+ size_t * num_filter_params ) {
87
+ char * saveptr ;
88
+ char * params_copy ;
89
+ size_t count = 0 ;
90
+
91
+ if (params_in == NULL || * params_in == '\0' ) {
92
+ * num_filter_params = 0 ;
93
+ return 0 ;
94
+ }
95
+
96
+ params_copy = WS_Copy (ctx -> ws , params_in , strlen (params_in ) + 1 );
97
+ if (!params_copy ) {
98
+ VRT_fail (ctx , "WS_Copy: params_copy: out of workspace" );
99
+ return -1 ;
100
+ }
101
+
102
+ for (char * filter_name = strtok_r (params_copy , "," , & saveptr ); filter_name ;
103
+ filter_name = strtok_r (NULL , "," , & saveptr )) {
104
+
105
+ if (count >= MAX_FILTER_PARAMS ) {
106
+ VRT_fail (ctx , "Exceeded maximum number of filter parameters" );
107
+ return -1 ;
108
+ }
109
+ filter_params [count ++ ] = filter_name ;
110
+ }
111
+
112
+ * num_filter_params = count ;
113
+ return 0 ;
114
+ }
115
+
116
+ /**
117
+ * Determine if a given parameter should be included based on the exclude_params
118
+ * flag and the list of filtered parameters.
119
+ * @param param_name The query parameter name to check
120
+ * @param filter_params Array of filter parameter names
121
+ * @param num_filter_params Number of filter parameters
122
+ * @param exclude_params If true, parameters in filter_params are excluded; else
123
+ * included
124
+ * @return 1 if parameter should be included, 0 otherwise
125
+ */
126
+ static int should_include_param (const char * param_name , char * * filter_params ,
127
+ size_t num_filter_params ,
128
+ VCL_BOOL exclude_params ) {
129
+ int match = 0 ;
130
+
131
+ for (size_t i = 0 ; i < num_filter_params ; i ++ ) {
132
+ if (strcmp (param_name , filter_params [i ]) == 0 ) {
133
+ match = 1 ;
134
+ break ;
135
+ }
136
+ }
137
+
138
+ return exclude_params ? !match : match ;
139
+ }
140
+
141
+ /**
142
+ * Rebuild the query string by including or excluding parameters as per filters.
143
+ * @param ctx Varnish context
144
+ * @param uri_base The portion of the URI before the query string
145
+ * @param params The array of tokenized query parameters
146
+ * @param param_count The number of query parameters
147
+ * @param filter_params The array of filter parameter names
148
+ * @param num_filter_params The number of filter parameters
149
+ * @param exclude_params Whether to exclude or include params_in
150
+ * @return A pointer to the rebuilt URI from workspace or NULL on error
151
+ */
152
+ static char * rebuild_query_string (VRT_CTX , const char * uri_base ,
153
+ query_param_t * params , size_t param_count ,
154
+ char * * filter_params ,
155
+ size_t num_filter_params ,
156
+ VCL_BOOL exclude_params ) {
157
+ struct vsb * vsb = VSB_new_auto ();
158
+ char sep = '?' ;
159
+
160
+ if (vsb == NULL ) {
161
+ VRT_fail (ctx , "VSB_new_auto failed" );
162
+ return NULL ;
163
+ }
164
+
165
+ VSB_cat (vsb , uri_base );
166
+
167
+ for (size_t i = 0 ; i < param_count ; i ++ ) {
168
+ query_param_t * current = & params [i ];
169
+ if (should_include_param (current -> name , filter_params ,
170
+ num_filter_params , exclude_params )) {
171
+ if (current -> value && (* current -> value ) != '\0' ) {
172
+ VSB_printf (vsb , "%c%s=%s" , sep , current -> name , current -> value );
173
+ } else {
174
+ // Parameter with no value
175
+ VSB_printf (vsb , "%c%s" , sep , current -> name );
176
+ }
177
+ sep = '&' ;
178
+ }
179
+ }
180
+
181
+ if (VSB_finish (vsb ) != 0 ) {
182
+ VRT_fail (ctx , "VSB_finish failed" );
183
+ VSB_destroy (& vsb );
184
+ return NULL ;
185
+ }
186
+
187
+ const char * final_uri = VSB_data (vsb );
188
+ size_t final_len = VSB_len (vsb );
189
+ char * ws_uri = WS_Copy (ctx -> ws , final_uri , final_len + 1 );
190
+ VSB_destroy (& vsb );
191
+
192
+ if (ws_uri == NULL ) {
193
+ VRT_fail (ctx , "WS_Copy: out of workspace" );
194
+ return NULL ;
195
+ }
196
+
197
+ return ws_uri ;
198
+ }
199
+
75
200
/**
76
201
* This function modifies the query string of a URL by including or excluding
77
202
* query parameters based on the input parameters.
@@ -81,31 +206,19 @@ static int tokenize_querystring(VRT_CTX, query_param_t **result,
81
206
* @param exclude_params If true, exclude the parameters in params_in. If false,
82
207
* include the parameters in params_in.
83
208
*/
84
- VCL_STRING vmod_modifyparams (VRT_CTX , VCL_STRING uri , VCL_STRING params_in ,
85
- VCL_BOOL exclude_params ) {
86
- char * saveptr ;
87
- char * new_uri ;
88
- char * new_uri_end ;
89
- char * query_str ;
90
- char * params ;
91
- query_param_t * head ;
92
- query_param_t * current ;
93
- char * filter_params [MAX_FILTER_PARAMS ];
94
- int num_filter_params = 0 ;
95
- int i ;
96
- int no_param ;
97
- char sep = '?' ;
98
-
209
+ VCL_STRING
210
+ vmod_modifyparams (VRT_CTX , VCL_STRING uri , VCL_STRING params_in ,
211
+ VCL_BOOL exclude_params ) {
99
212
CHECK_OBJ_NOTNULL (ctx , VRT_CTX_MAGIC );
100
213
101
- // Return if the URI is NULL.
214
+ // Return if the URI is NULL
102
215
if (uri == NULL ) {
103
216
VRT_fail (ctx , "uri is NULL" );
104
217
return NULL ;
105
218
}
106
219
107
- // Check if there is a query string.
108
- query_str = strchr (uri , '?' );
220
+ // Check for existing query string
221
+ char * query_str = strchr (uri , '?' );
109
222
if (query_str == NULL ) {
110
223
char * ws_uri = WS_Copy (ctx -> ws , uri , strlen (uri ) + 1 );
111
224
if (ws_uri == NULL ) {
@@ -117,117 +230,65 @@ VCL_STRING vmod_modifyparams(VRT_CTX, VCL_STRING uri, VCL_STRING params_in,
117
230
}
118
231
119
232
size_t base_uri_len = query_str - uri ;
120
- size_t query_str_len = strlen (query_str + 1 ); // +1 to skip '?'
121
- size_t new_uri_max_len =
122
- base_uri_len + query_str_len + 2 ; // +2 for '?' and '\0'
123
-
124
- new_uri = WS_Alloc (ctx -> ws , new_uri_max_len );
125
- if (new_uri == NULL ) {
126
- VRT_fail (ctx , "WS_Alloc: new_uri: out of workspace" );
127
- return NULL ;
128
- }
233
+ char base_uri [base_uri_len + 1 ];
234
+ memcpy (base_uri , uri , base_uri_len );
235
+ base_uri [base_uri_len ] = '\0' ;
129
236
130
- memcpy (new_uri , uri , base_uri_len );
131
- new_uri [base_uri_len ] = '\0' ;
132
- new_uri_end = new_uri + base_uri_len ;
133
-
134
- // Skip past the '?' to get the query string.
237
+ // Move past the '?'
135
238
query_str = query_str + 1 ;
136
239
137
- // If there are no query params, return the base URI from workspace.
240
+ // If no query params, return base_uri
138
241
if (* query_str == '\0' ) {
139
- return new_uri ;
242
+ char * ws_uri = WS_Copy (ctx -> ws , base_uri , base_uri_len + 1 );
243
+ if (ws_uri == NULL ) {
244
+ VRT_fail (ctx , "WS_Copy: out of workspace" );
245
+ return NULL ;
246
+ }
247
+ return ws_uri ;
140
248
}
141
249
142
- // If params_in is NULL or empty, remove all query params.
143
250
if (params_in == NULL || * params_in == '\0' ) {
144
- return new_uri ;
251
+ char * ws_uri = WS_Copy (ctx -> ws , base_uri , base_uri_len + 1 );
252
+ if (!ws_uri ) {
253
+ VRT_fail (ctx , "WS_Copy: out of workspace" );
254
+ return NULL ;
255
+ }
256
+ return ws_uri ;
145
257
}
146
258
147
- // Copy the query string to the workspace.
148
259
char * query_str_copy = WS_Copy (ctx -> ws , query_str , strlen (query_str ) + 1 );
149
260
if (!query_str_copy ) {
150
261
VRT_fail (ctx , "WS_Copy: query_str_copy: out of workspace" );
151
262
return NULL ;
152
263
}
153
264
154
- // Copy the params_in to the workspace.
155
- params = WS_Copy (ctx -> ws , params_in , strlen (params_in ) + 1 );
156
- if (!params ) {
157
- VRT_fail (ctx , "WS_Copy: params: out of workspace" );
265
+ // Parse filter parameters
266
+ char * filter_params [MAX_FILTER_PARAMS ];
267
+ size_t num_filter_params = 0 ;
268
+ if (parse_filter_params (ctx , params_in , filter_params , & num_filter_params ) <
269
+ 0 ) {
158
270
return NULL ;
159
271
}
160
272
161
- // Tokenize params_in into filter_params array.
162
- num_filter_params = 0 ;
163
- for (char * filter_name = strtok_r (params , "," , & saveptr ); filter_name ;
164
- filter_name = strtok_r (NULL , "," , & saveptr )) {
165
- if (num_filter_params >= MAX_FILTER_PARAMS ) {
166
- VRT_fail (ctx , "Exceeded maximum number of filter parameters" );
167
- return NULL ;
168
- }
169
- filter_params [num_filter_params ++ ] = filter_name ;
170
- }
171
-
172
- // Tokenize the query string into parameters.
173
- no_param = tokenize_querystring (ctx , & head , query_str_copy );
273
+ query_param_t * head ;
274
+ int no_param = tokenize_querystring (ctx , & head , query_str_copy );
174
275
if (no_param < 0 ) {
175
276
VRT_fail (ctx , "tokenize_querystring failed" );
176
277
return NULL ;
177
278
}
178
279
179
280
if (no_param == 0 ) {
180
- return new_uri ;
181
- }
182
-
183
- struct vsb * vsb = VSB_new_auto ();
184
- if (vsb == NULL ) {
185
- VRT_fail (ctx , "VSB_new_auto failed" );
186
- return NULL ;
187
- }
188
-
189
- VSB_bcat (vsb , uri , base_uri_len );
190
-
191
- // Iterate through the query parameters.
192
- for (i = 0 , current = head ; i < no_param ; ++ i , ++ current ) {
193
- int match = 0 ;
194
- for (int j = 0 ; j < num_filter_params ; ++ j ) {
195
- if (strcmp (current -> name , filter_params [j ]) == 0 ) {
196
- match = 1 ;
197
- break ;
198
- }
199
- }
200
-
201
- // Include or exclude parameters based upon the argument.
202
- int include = exclude_params ? !match : match ;
203
- if (include ) {
204
- if (current -> value && (* current -> value ) != '\0' ) {
205
- VSB_printf (vsb , "%c%s=%s" , sep , current -> name , current -> value );
206
- } else {
207
- VSB_printf (vsb , "%c%s" , sep , current -> name );
208
- }
209
- sep = '&' ;
281
+ char * ws_uri = WS_Copy (ctx -> ws , base_uri , base_uri_len + 1 );
282
+ if (!ws_uri ) {
283
+ VRT_fail (ctx , "WS_Copy: out of workspace" );
284
+ return NULL ;
210
285
}
286
+ return ws_uri ;
211
287
}
212
288
213
- if (VSB_finish (vsb ) != 0 ) {
214
- VRT_fail (ctx , "VSB_finish failed" );
215
- VSB_destroy (& vsb );
216
- return NULL ;
217
- }
218
-
219
- // Copy the final URI from the VSB into the workspace
220
- const char * final_uri = VSB_data (vsb );
221
- size_t final_len = VSB_len (vsb );
222
- char * ws_uri = WS_Copy (ctx -> ws , final_uri , final_len + 1 );
223
- VSB_destroy (& vsb );
224
-
225
- if (ws_uri == NULL ) {
226
- VRT_fail (ctx , "WS_Copy: out of workspace" );
227
- return NULL ;
228
- }
229
-
230
- return ws_uri ;
289
+ return rebuild_query_string (ctx , base_uri , head , (size_t )no_param ,
290
+ filter_params , num_filter_params ,
291
+ exclude_params );
231
292
}
232
293
233
294
/**
@@ -237,7 +298,8 @@ VCL_STRING vmod_modifyparams(VRT_CTX, VCL_STRING uri, VCL_STRING params_in,
237
298
* @param params The query parameters to include.
238
299
* @return The modified URL.
239
300
*/
240
- VCL_STRING vmod_includeparams (VRT_CTX , VCL_STRING uri , VCL_STRING params ) {
301
+ VCL_STRING
302
+ vmod_includeparams (VRT_CTX , VCL_STRING uri , VCL_STRING params ) {
241
303
return vmod_modifyparams (ctx , uri , params , 0 );
242
304
}
243
305
@@ -248,6 +310,7 @@ VCL_STRING vmod_includeparams(VRT_CTX, VCL_STRING uri, VCL_STRING params) {
248
310
* @param params The query parameters to exclude.
249
311
* @return The modified URL.
250
312
*/
251
- VCL_STRING vmod_excludeparams (VRT_CTX , VCL_STRING uri , VCL_STRING params ) {
313
+ VCL_STRING
314
+ vmod_excludeparams (VRT_CTX , VCL_STRING uri , VCL_STRING params ) {
252
315
return vmod_modifyparams (ctx , uri , params , 1 );
253
316
}
0 commit comments