@@ -125,6 +125,8 @@ typedef struct {
125125 cookie_type_e style ;
126126 char * cookie_name ;
127127 char * cookie_domain ;
128+ char * regexp_string ; /* used to compile regexp; save for debugging */
129+ regex_t * regexp ; /* used to find usertrack cookie in cookie header */
128130} cookie_dir_rec ;
129131
130132/* Make Cookie: Now we have to generate something that is going to be
@@ -193,36 +195,48 @@ static void make_cookie(request_rec *r)
193195 return ;
194196}
195197
198+ /* dcfg->regexp is "^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)",
199+ * which has three subexpressions, $0..$2 */
200+ #define NUM_SUBS 3
201+
196202static int spot_cookie (request_rec * r )
197203{
198204 cookie_dir_rec * dcfg = ap_get_module_config (r -> per_dir_config ,
199205 & usertrack_module );
200- const char * cookie ;
201- const char * value ;
206+ const char * cookie_header ;
207+ regmatch_t regm [ NUM_SUBS ] ;
202208
203209 /* Do not run in subrequests */
204210 if (!dcfg -> enabled || r -> main ) {
205211 return DECLINED ;
206212 }
207213
208- if ((cookie = apr_table_get (r -> headers_in ,
209- (dcfg -> style == CT_COOKIE2
210- ? "Cookie2"
211- : "Cookie" ))))
212- if ((value = ap_strstr_c (cookie , dcfg -> cookie_name ))) {
213- char * cookiebuf , * cookieend ;
214-
215- value += strlen (dcfg -> cookie_name ) + 1 ; /* Skip over the '=' */
216- cookiebuf = apr_pstrdup (r -> pool , value );
217- cookieend = strchr (cookiebuf , ';' );
218- if (cookieend )
219- * cookieend = '\0' ; /* Ignore anything after a ; */
220-
214+ if ((cookie_header = apr_table_get (r -> headers_in ,
215+ (dcfg -> style == CT_COOKIE2
216+ ? "Cookie2"
217+ : "Cookie" )))) {
218+ if (!ap_regexec (dcfg -> regexp , cookie_header , NUM_SUBS , regm , 0 )) {
219+ char * cookieval = NULL ;
220+ /* Our regexp,
221+ * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
222+ * only allows for $1 or $2 to be available. ($0 is always
223+ * filled with the entire matched expression, not just
224+ * the part in parentheses.) So just check for either one
225+ * and assign to cookieval if present. */
226+ if (regm [1 ].rm_so != -1 ) {
227+ cookieval = ap_pregsub (r -> pool , "$1" , cookie_header ,
228+ NUM_SUBS , regm );
229+ }
230+ if (regm [2 ].rm_so != -1 ) {
231+ cookieval = ap_pregsub (r -> pool , "$2" , cookie_header ,
232+ NUM_SUBS , regm );
233+ }
221234 /* Set the cookie in a note, for logging */
222- apr_table_setn (r -> notes , "cookie" , cookiebuf );
235+ apr_table_setn (r -> notes , "cookie" , cookieval );
223236
224237 return DECLINED ; /* There's already a cookie, no new one */
225238 }
239+ }
226240 make_cookie (r );
227241 return OK ; /* We set our cookie */
228242}
@@ -331,7 +345,26 @@ static const char *set_cookie_name(cmd_parms *cmd, void *mconfig,
331345{
332346 cookie_dir_rec * dcfg = (cookie_dir_rec * ) mconfig ;
333347
348+ /* The goal is to end up with this regexp,
349+ * ^cookie_name=([^;]+)|;[ \t]+cookie_name=([^;]+)
350+ * with cookie_name
351+ * obviously substituted with the real cookie name set by the
352+ * user in httpd.conf. */
353+ dcfg -> regexp_string = apr_pstrcat (cmd -> pool , "^" , name ,
354+ "=([^;]+)|;[ \t]+" , name ,
355+ "=([^;]+)" , NULL );
356+
334357 dcfg -> cookie_name = apr_pstrdup (cmd -> pool , name );
358+
359+ dcfg -> regexp = ap_pregcomp (cmd -> pool , dcfg -> regexp_string , REG_EXTENDED );
360+ if (dcfg -> regexp == NULL ) {
361+ return "Regular expression could not be compiled." ;
362+ }
363+ if (dcfg -> regexp -> re_nsub + 1 != NUM_SUBS ) {
364+ return apr_pstrcat (cmd -> pool , "Invalid cookie name \"" ,
365+ name , "\"" , NULL );
366+ }
367+
335368 return NULL ;
336369}
337370
0 commit comments