aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-12-06 23:40:21 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-12-19 18:13:44 +0300
commit1e7ad3010da7d2be1afe219da0ba84dd129f9c4e (patch)
tree3c44eee03a349aac2c862ed666bbfcb2497e3221
parent38b46a2fd1cf24270e6deab2bb64c381938b95a9 (diff)
downloadlibmicrohttpd-1e7ad3010da7d2be1afe219da0ba84dd129f9c4e.tar.gz
libmicrohttpd-1e7ad3010da7d2be1afe219da0ba84dd129f9c4e.zip
Refactored cookies parsing.
The new code is more compact as duplicated code was removed. Added testing for various cookies parsing strictness levels.
-rw-r--r--src/microhttpd/connection.c299
-rw-r--r--src/testcurl/Makefile.am14
-rw-r--r--src/testcurl/test_parse_cookies.c540
3 files changed, 614 insertions, 239 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 960c22db..16c5fb93 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -2829,146 +2829,6 @@ enum _MHD_ParseCookie
2829/** 2829/**
2830 * Parse the cookies string (see RFC 6265). 2830 * Parse the cookies string (see RFC 6265).
2831 * 2831 *
2832 * Parsing may fail if the string is not formed strictly as defined by RFC 6265.
2833 *
2834 * @param str the string to parse, without leading whitespaces
2835 * @param str_len the size of the @a str, not including mandatory
2836 * zero-termination
2837 * @param connection the connection to add parsed cookies
2838 * @return #MHD_PARSE_COOKIE_OK for success, error code otherwise
2839 */
2840static enum _MHD_ParseCookie
2841parse_cookies_string_strict (char *str,
2842 size_t str_len,
2843 struct MHD_Connection *connection)
2844{
2845 size_t i;
2846
2847 i = 0;
2848 while (i < str_len)
2849 {
2850 size_t name_start;
2851 size_t name_len;
2852 size_t value_start;
2853 size_t value_len;
2854 bool val_quoted;
2855 /* 'i' must point to the first char of cookie-name */
2856 name_start = i;
2857 /* Find the end of the cookie-name */
2858 do
2859 {
2860 const char l = str[i];
2861 if (('=' == l) || (' ' == l) || ('\t' == l) || ('"' == l) || (',' == l) ||
2862 (';' == l) || (0 == l))
2863 break;
2864 } while (str_len > ++i);
2865 if ((str_len == i) || ('=' != str[i]) || (name_start == i))
2866 return MHD_PARSE_COOKIE_MALFORMED; /* Incomplete cookie name */
2867 name_len = i - name_start;
2868 /* 'i' must point to the '=' char */
2869 mhd_assert ('=' == str[i]);
2870 i++;
2871 /* 'i' must point to the first char of cookie-value */
2872 if (str_len == i)
2873 {
2874 value_start = 0;
2875 value_len = 0;
2876#ifdef _DEBUG
2877 val_quoted = false; /* This assignment used in assert */
2878#endif
2879 }
2880 else
2881 {
2882 bool valid_cookie;
2883 val_quoted = ('"' == str[i]);
2884 if (val_quoted)
2885 i++;
2886 value_start = i;
2887 /* Find the end of the cookie-value */
2888 while (str_len > i)
2889 {
2890 const char l = str[i];
2891 if ((';' == l) || ('"' == l) || (' ' == l) || ('\t' == l)
2892 || (',' == l) || ('\\' == l) || (0 == l))
2893 break;
2894 i++;
2895 }
2896 value_len = i - value_start;
2897 if (val_quoted)
2898 {
2899 if ((str_len == i) || ('"' != str[i]))
2900 return MHD_PARSE_COOKIE_MALFORMED; /* Incomplete cookie value, no closing quote */
2901 i++;
2902 }
2903 if (str_len == i)
2904 valid_cookie = true;
2905 else if (';' == str[i])
2906 valid_cookie = true;
2907 else if ((' ' == str[i]) || ('\t' == str[i]))
2908 { /* Optional whitespace at the end of the string? */
2909 while (str_len > ++i)
2910 {
2911 if ((' ' != str[i]) && ('\t' != str[i]))
2912 break;
2913 }
2914 if (str_len == i)
2915 valid_cookie = true;
2916 else
2917 valid_cookie = false;
2918 }
2919 else
2920 valid_cookie = false;
2921
2922 if (! valid_cookie)
2923 return MHD_PARSE_COOKIE_MALFORMED; /* Garbage at the end of the cookie value */
2924 }
2925 mhd_assert (0 != name_len);
2926 str[name_start + name_len] = 0; /* Zero-terminate the name */
2927 if (0 != value_len)
2928 {
2929 mhd_assert (0 == str[i] || ';' == str[i]);
2930 mhd_assert (! val_quoted || ';' == str[i]);
2931 str[value_start + value_len] = 0; /* Zero-terminate the value */
2932 if (MHD_NO ==
2933 MHD_set_connection_value_n_nocheck_ (connection,
2934 MHD_COOKIE_KIND,
2935 str + name_start,
2936 name_len,
2937 str + value_start,
2938 value_len))
2939 return MHD_PARSE_COOKIE_NO_MEMORY;
2940 }
2941 else
2942 {
2943 if (MHD_NO ==
2944 MHD_set_connection_value_n_nocheck_ (connection,
2945 MHD_COOKIE_KIND,
2946 str + name_start,
2947 name_len,
2948 "",
2949 0))
2950 return MHD_PARSE_COOKIE_NO_MEMORY;
2951 }
2952 if (str_len > i)
2953 {
2954 mhd_assert (0 == str[i] || ';' == str[i]);
2955 mhd_assert (! val_quoted || ';' == str[i]);
2956 mhd_assert (';' != str[i] || val_quoted || 0 == value_len);
2957 i++;
2958 if (str_len == i)
2959 return MHD_PARSE_COOKIE_MALFORMED; /* No cookie name after semicolon */
2960 if (' ' != str[i])
2961 return MHD_PARSE_COOKIE_MALFORMED; /* No space after semicolon */
2962 i++;
2963 }
2964 }
2965 return MHD_PARSE_COOKIE_OK;
2966}
2967
2968
2969/**
2970 * Parse the cookies string (see RFC 6265).
2971 *
2972 * Try to parse the cookies string even if it is not strictly formed 2832 * Try to parse the cookies string even if it is not strictly formed
2973 * as specified by RFC 6265. 2833 * as specified by RFC 6265.
2974 * 2834 *
@@ -2979,12 +2839,22 @@ parse_cookies_string_strict (char *str,
2979 * @return #MHD_PARSE_COOKIE_OK for success, error code otherwise 2839 * @return #MHD_PARSE_COOKIE_OK for success, error code otherwise
2980 */ 2840 */
2981static enum _MHD_ParseCookie 2841static enum _MHD_ParseCookie
2982parse_cookies_string_lenient (char *str, 2842parse_cookies_string (char *str,
2983 size_t str_len, 2843 const size_t str_len,
2984 struct MHD_Connection *connection) 2844 struct MHD_Connection *connection)
2985{ 2845{
2986 size_t i; 2846 size_t i;
2987 bool non_strict; 2847 bool non_strict;
2848 /* Skip extra whitespaces and empty cookies */
2849 const bool allow_wsp_empty = (0 >= connection->daemon->strict_for_client);
2850 /* Allow whitespaces around '=' character */
2851 const bool wsp_around_eq = (0 > connection->daemon->strict_for_client);
2852 /* Allow whitespaces in quoted cookie value */
2853 const bool wsp_in_quoted = (0 >= connection->daemon->strict_for_client);
2854 /* Allow tab as space after semicolon between cookies */
2855 const bool tab_as_sp = (0 >= connection->daemon->strict_for_client);
2856 /* Allow no space after semicolon between cookies */
2857 const bool allow_no_space = (0 >= connection->daemon->strict_for_client);
2988 2858
2989 non_strict = false; 2859 non_strict = false;
2990 i = 0; 2860 i = 0;
@@ -2998,6 +2868,8 @@ parse_cookies_string_lenient (char *str,
2998 /* Skip any whitespaces and empty cookies */ 2868 /* Skip any whitespaces and empty cookies */
2999 while (' ' == str[i] || '\t' == str[i] || ';' == str[i]) 2869 while (' ' == str[i] || '\t' == str[i] || ';' == str[i])
3000 { 2870 {
2871 if (! allow_wsp_empty)
2872 return MHD_PARSE_COOKIE_MALFORMED;
3001 non_strict = true; 2873 non_strict = true;
3002 i++; 2874 i++;
3003 if (i == str_len) 2875 if (i == str_len)
@@ -3017,6 +2889,8 @@ parse_cookies_string_lenient (char *str,
3017 /* Skip any whitespaces */ 2889 /* Skip any whitespaces */
3018 while (str_len > i && (' ' == str[i] || '\t' == str[i])) 2890 while (str_len > i && (' ' == str[i] || '\t' == str[i]))
3019 { 2891 {
2892 if (! wsp_around_eq)
2893 return MHD_PARSE_COOKIE_MALFORMED;
3020 non_strict = true; 2894 non_strict = true;
3021 i++; 2895 i++;
3022 } 2896 }
@@ -3028,6 +2902,8 @@ parse_cookies_string_lenient (char *str,
3028 /* Skip any whitespaces */ 2902 /* Skip any whitespaces */
3029 while (str_len > i && (' ' == str[i] || '\t' == str[i])) 2903 while (str_len > i && (' ' == str[i] || '\t' == str[i]))
3030 { 2904 {
2905 if (! wsp_around_eq)
2906 return MHD_PARSE_COOKIE_MALFORMED;
3031 non_strict = true; 2907 non_strict = true;
3032 i++; 2908 i++;
3033 } 2909 }
@@ -3058,6 +2934,8 @@ parse_cookies_string_lenient (char *str,
3058 { 2934 {
3059 if (! val_quoted) 2935 if (! val_quoted)
3060 break; 2936 break;
2937 if (! wsp_in_quoted)
2938 return MHD_PARSE_COOKIE_MALFORMED;
3061 non_strict = true; 2939 non_strict = true;
3062 } 2940 }
3063 i++; 2941 i++;
@@ -3070,10 +2948,19 @@ parse_cookies_string_lenient (char *str,
3070 i++; 2948 i++;
3071 } 2949 }
3072 /* Skip any whitespaces */ 2950 /* Skip any whitespaces */
3073 while (str_len > i && (' ' == str[i] || '\t' == str[i])) 2951 if ((str_len > i) && ((' ' == str[i]) || ('\t' == str[i])))
3074 { 2952 {
3075 non_strict = true; 2953 do
3076 i++; 2954 {
2955 i++;
2956 } while (str_len > i && (' ' == str[i] || '\t' == str[i]));
2957 /* Whitespace at the end? */
2958 if (str_len > i)
2959 {
2960 if (! allow_wsp_empty)
2961 return MHD_PARSE_COOKIE_MALFORMED;
2962 non_strict = true;
2963 }
3077 } 2964 }
3078 if (str_len == i) 2965 if (str_len == i)
3079 valid_cookie = true; 2966 valid_cookie = true;
@@ -3118,11 +3005,29 @@ parse_cookies_string_lenient (char *str,
3118 mhd_assert (';' != str[i] || val_quoted || non_strict || 0 == value_len); 3005 mhd_assert (';' != str[i] || val_quoted || non_strict || 0 == value_len);
3119 i++; 3006 i++;
3120 if (str_len == i) 3007 if (str_len == i)
3121 non_strict = true; /* No cookie name after semicolon */ 3008 { /* No next cookie after semicolon */
3009 if (! allow_wsp_empty)
3010 return MHD_PARSE_COOKIE_MALFORMED;
3011 non_strict = true;
3012 }
3122 else if (' ' != str[i]) 3013 else if (' ' != str[i])
3123 non_strict = true; /* No space after semicolon */ 3014 {/* No space after semicolon */
3015 if (('\t' == str[i]) && tab_as_sp)
3016 i++;
3017 else if (! allow_no_space)
3018 return MHD_PARSE_COOKIE_MALFORMED;
3019 non_strict = true;
3020 }
3124 else 3021 else
3022 {
3125 i++; 3023 i++;
3024 if (str_len == i)
3025 {
3026 if (! allow_wsp_empty)
3027 return MHD_PARSE_COOKIE_MALFORMED;
3028 non_strict = true;
3029 }
3030 }
3126 } 3031 }
3127 } 3032 }
3128 return non_strict? MHD_PARSE_COOKIE_OK_LAX : MHD_PARSE_COOKIE_OK; 3033 return non_strict? MHD_PARSE_COOKIE_OK_LAX : MHD_PARSE_COOKIE_OK;
@@ -3141,8 +3046,10 @@ parse_cookie_header (struct MHD_Connection *connection)
3141 const char *hdr; 3046 const char *hdr;
3142 size_t hdr_len; 3047 size_t hdr_len;
3143 char *cpy; 3048 char *cpy;
3144 bool strict_parsing;
3145 size_t i; 3049 size_t i;
3050 enum _MHD_ParseCookie parse_res;
3051 const struct MHD_HTTP_Req_Header *const saved_tail =
3052 connection->rq.headers_received_tail;
3146 3053
3147 if (MHD_NO == 3054 if (MHD_NO ==
3148 MHD_lookup_connection_value_n (connection, 3055 MHD_lookup_connection_value_n (connection,
@@ -3159,25 +3066,61 @@ parse_cookie_header (struct MHD_Connection *connection)
3159 cpy = MHD_connection_alloc_memory_ (connection, 3066 cpy = MHD_connection_alloc_memory_ (connection,
3160 hdr_len + 1); 3067 hdr_len + 1);
3161 if (NULL == cpy) 3068 if (NULL == cpy)
3162 return MHD_PARSE_COOKIE_NO_MEMORY; 3069 parse_res = MHD_PARSE_COOKIE_NO_MEMORY;
3163 3070 else
3164 memcpy (cpy, 3071 {
3165 hdr, 3072 memcpy (cpy,
3166 hdr_len); 3073 hdr,
3167 cpy[hdr_len] = '\0'; 3074 hdr_len);
3075 cpy[hdr_len] = '\0';
3076
3077 i = 0;
3078 /* Skip all initial whitespaces */
3079 while (i < hdr_len && (' ' == cpy[i] || '\t' == cpy[i]))
3080 i++;
3168 3081
3169 /* TODO: add individual configuration */ 3082 parse_res = parse_cookies_string (cpy + i, hdr_len - i, connection);
3170 strict_parsing = (0 < connection->daemon->strict_for_client); 3083 }
3171 i = 0;
3172 /* Skip all initial whitespaces */
3173 while (i < hdr_len && (' ' == cpy[i] || '\t' == cpy[i]))
3174 i++;
3175 3084
3176 /* 'i' points to the first non-whitespace char or to the end of the string */ 3085 switch (parse_res)
3177 if (strict_parsing) 3086 {
3178 return parse_cookies_string_strict (cpy + i, hdr_len - i, connection); 3087 case MHD_PARSE_COOKIE_OK:
3088 break;
3089 case MHD_PARSE_COOKIE_OK_LAX:
3090#ifdef HAVE_MESSAGES
3091 if (saved_tail != connection->rq.headers_received_tail)
3092 MHD_DLOG (connection->daemon,
3093 _ ("The Cookie header has been parsed, but it is not fully "
3094 "compliant with the standard.\n"));
3095#endif /* HAVE_MESSAGES */
3096 break;
3097 case MHD_PARSE_COOKIE_MALFORMED:
3098#ifdef HAVE_MESSAGES
3099 if (saved_tail != connection->rq.headers_received_tail)
3100 MHD_DLOG (connection->daemon,
3101 _ ("The Cookie header has been only partially parsed as it "
3102 "contains malformed data.\n"));
3103 else
3104 MHD_DLOG (connection->daemon,
3105 _ ("The Cookie header has malformed data.\n"));
3106#endif /* HAVE_MESSAGES */
3107 break;
3108 case MHD_PARSE_COOKIE_NO_MEMORY:
3109#ifdef HAVE_MESSAGES
3110 MHD_DLOG (connection->daemon,
3111 _ ("Not enough memory in the connection pool to "
3112 "parse client cookies!\n"));
3113#endif /* HAVE_MESSAGES */
3114 break;
3115 default:
3116 mhd_assert (0);
3117 break;
3118 }
3119#ifndef HAVE_MESSAGES
3120 (void) saved_tail; /* Mute compiler warning */
3121#endif /* ! HAVE_MESSAGES */
3179 3122
3180 return parse_cookies_string_lenient (cpy + i, hdr_len - i, connection); 3123 return parse_res;
3181} 3124}
3182 3125
3183 3126
@@ -3946,37 +3889,13 @@ parse_connection_headers (struct MHD_Connection *connection)
3946 size_t val_len; 3889 size_t val_len;
3947 3890
3948#ifdef COOKIE_SUPPORT 3891#ifdef COOKIE_SUPPORT
3949 enum _MHD_ParseCookie cookie_res; 3892 if (MHD_PARSE_COOKIE_NO_MEMORY == parse_cookie_header (connection))
3950
3951 cookie_res = parse_cookie_header (connection);
3952 if (MHD_PARSE_COOKIE_NO_MEMORY == cookie_res)
3953 { 3893 {
3954#ifdef HAVE_MESSAGES
3955 MHD_DLOG (connection->daemon,
3956 _ ("Not enough memory in pool to parse cookies!\n"));
3957#endif
3958 transmit_error_response_static (connection, 3894 transmit_error_response_static (connection,
3959 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 3895 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
3960 REQUEST_TOO_BIG); 3896 REQUEST_TOO_BIG);
3961 return; 3897 return;
3962 } 3898 }
3963 else if (MHD_PARSE_COOKIE_OK_LAX == cookie_res)
3964 {
3965#ifdef HAVE_MESSAGES
3966 MHD_DLOG (connection->daemon,
3967 _ ("The Cookie header has been parsed, but is not fully "
3968 "compliant with the standard.\n"));
3969#endif
3970 (void) 0; /* Mute compiler warning */
3971 }
3972 else if (MHD_PARSE_COOKIE_MALFORMED == cookie_res)
3973 {
3974#ifdef HAVE_MESSAGES
3975 MHD_DLOG (connection->daemon,
3976 _ ("The Cookie header has malformed data.\n"));
3977#endif
3978 (void) 0; /* Mute compiler warning */
3979 }
3980#endif /* COOKIE_SUPPORT */ 3899#endif /* COOKIE_SUPPORT */
3981 if ( (1 <= connection->daemon->strict_for_client) && 3900 if ( (1 <= connection->daemon->strict_for_client) &&
3982 (MHD_IS_HTTP_VER_1_1_COMPAT (connection->rq.http_ver)) && 3901 (MHD_IS_HTTP_VER_1_1_COMPAT (connection->rq.http_ver)) &&
diff --git a/src/testcurl/Makefile.am b/src/testcurl/Makefile.am
index 010ec2ef..0d190f9d 100644
--- a/src/testcurl/Makefile.am
+++ b/src/testcurl/Makefile.am
@@ -144,8 +144,9 @@ check_PROGRAMS = \
144 144
145if ENABLE_COOKIE 145if ENABLE_COOKIE
146check_PROGRAMS += \ 146check_PROGRAMS += \
147 test_parse_cookies \ 147 test_parse_cookies_strict_p1 \
148 test_parse_cookies_nonstrict 148 test_parse_cookies_strict_zero \
149 test_parse_cookies_strict_n1
149endif 150endif
150 151
151if HEAVY_TESTS 152if HEAVY_TESTS
@@ -467,11 +468,14 @@ test_post_SOURCES = \
467test_process_headers_SOURCES = \ 468test_process_headers_SOURCES = \
468 test_process_headers.c mhd_has_in_name.h 469 test_process_headers.c mhd_has_in_name.h
469 470
470test_parse_cookies_SOURCES = \ 471test_parse_cookies_strict_zero_SOURCES = \
471 test_parse_cookies.c mhd_has_in_name.h mhd_has_param.h 472 test_parse_cookies.c mhd_has_in_name.h mhd_has_param.h
472 473
473test_parse_cookies_nonstrict_SOURCES = \ 474test_parse_cookies_strict_p1_SOURCES = \
474 $(test_parse_cookies_SOURCES) 475 $(test_parse_cookies_strict_zero_SOURCES)
476
477test_parse_cookies_strict_n1_SOURCES = \
478 $(test_parse_cookies_strict_zero_SOURCES)
475 479
476test_process_arguments_SOURCES = \ 480test_process_arguments_SOURCES = \
477 test_process_arguments.c mhd_has_in_name.h 481 test_process_arguments.c mhd_has_in_name.h
diff --git a/src/testcurl/test_parse_cookies.c b/src/testcurl/test_parse_cookies.c
index 987ddbf4..308b751e 100644
--- a/src/testcurl/test_parse_cookies.c
+++ b/src/testcurl/test_parse_cookies.c
@@ -189,7 +189,7 @@ _mhdErrorExit_func (const char *errDesc, const char *funcName, int lineNum)
189 189
190 190
191/* Could be increased to facilitate debugging */ 191/* Could be increased to facilitate debugging */
192#define TIMEOUTS_VAL 5 192#define TIMEOUTS_VAL 500000
193 193
194#define EXPECTED_URI_BASE_PATH "/" 194#define EXPECTED_URI_BASE_PATH "/"
195 195
@@ -203,6 +203,9 @@ _mhdErrorExit_func (const char *errDesc, const char *funcName, int lineNum)
203 "<html><head><title>libmicrohttpd test page</title></head>" \ 203 "<html><head><title>libmicrohttpd test page</title></head>" \
204 "<body>Success!</body></html>" 204 "<body>Success!</body></html>"
205 205
206#define PAGE_ERROR \
207 "<html><body>Cookies parsing error</body></html>"
208
206 209
207#ifndef MHD_STATICSTR_LEN_ 210#ifndef MHD_STATICSTR_LEN_
208/** 211/**
@@ -234,19 +237,293 @@ struct strct_test_data
234{ 237{
235 unsigned int line_num; 238 unsigned int line_num;
236 const char *header_str; 239 const char *header_str;
237 unsigned int num_cookies_non_strict; 240 unsigned int num_cookies_strict_p2; /* Reserved */
238 unsigned int num_cookies_strict; 241 unsigned int num_cookies_strict_p1;
242 unsigned int num_cookies_strict_zero;
243 unsigned int num_cookies_strict_n1;
239 struct strct_cookie cookies[5]; 244 struct strct_cookie cookies[5];
240}; 245};
241 246
242static const struct strct_test_data test_data[] = { 247static const struct strct_test_data test_data[] = {
243 { 248 {
244 __LINE__, 249 __LINE__,
250 "name1=value1",
251 1,
252 1,
253 1,
254 1,
255 {
256 COOKIE_ ("name1", "value1"),
257 COOKIE_NULL,
258 COOKIE_NULL,
259 COOKIE_NULL,
260 COOKIE_NULL
261 }
262 },
263 {
264 __LINE__,
265 "name1=value1;",
266 1,
267 1,
268 1,
269 1,
270 {
271 COOKIE_ ("name1", "value1"),
272 COOKIE_NULL,
273 COOKIE_NULL,
274 COOKIE_NULL,
275 COOKIE_NULL
276 }
277 },
278 {
279 __LINE__,
280 "name1=value1; ",
281 0,
282 1,
283 1,
284 1,
285 {
286 COOKIE_ ("name1", "value1"),
287 COOKIE_NULL,
288 COOKIE_NULL,
289 COOKIE_NULL,
290 COOKIE_NULL
291 }
292 },
293 {
294 __LINE__,
295 "; name1=value1",
296 0,
297 0,
298 1,
299 1,
300 {
301 COOKIE_ ("name1", "value1"),
302 COOKIE_NULL,
303 COOKIE_NULL,
304 COOKIE_NULL,
305 COOKIE_NULL
306 }
307 },
308 {
309 __LINE__,
310 ";name1=value1",
311 0,
312 0,
313 1,
314 1,
315 {
316 COOKIE_ ("name1", "value1"),
317 COOKIE_NULL,
318 COOKIE_NULL,
319 COOKIE_NULL,
320 COOKIE_NULL
321 }
322 },
323 {
324 __LINE__,
325 "name1=value1 ",
326 1,
327 1,
328 1,
329 1,
330 {
331 COOKIE_ ("name1", "value1"),
332 COOKIE_NULL,
333 COOKIE_NULL,
334 COOKIE_NULL,
335 COOKIE_NULL
336 }
337 },
338 {
339 __LINE__,
340 "name1=value1 ;",
341 0,
342 0,
343 1,
344 1,
345 {
346 COOKIE_ ("name1", "value1"),
347 COOKIE_NULL,
348 COOKIE_NULL,
349 COOKIE_NULL,
350 COOKIE_NULL
351 }
352 },
353 {
354 __LINE__,
355 "name1=value1 ; ",
356 0,
357 0,
358 1,
359 1,
360 {
361 COOKIE_ ("name1", "value1"),
362 COOKIE_NULL,
363 COOKIE_NULL,
364 COOKIE_NULL,
365 COOKIE_NULL
366 }
367 },
368 {
369 __LINE__,
370 "name2=\"value 2\"",
371 0,
372 0,
373 1,
374 1,
375 {
376 COOKIE_ ("name2", "value 2"),
377 COOKIE_NULL,
378 COOKIE_NULL,
379 COOKIE_NULL,
380 COOKIE_NULL
381 }
382 },
383 {
384 __LINE__,
385 "name1=value1;\tname2=value2",
386 0,
387 1,
388 2,
389 2,
390 {
391 COOKIE_ ("name1", "value1"),
392 COOKIE_ ("name2", "value2"),
393 COOKIE_NULL,
394 COOKIE_NULL,
395 COOKIE_NULL
396 }
397 },
398 {
399 __LINE__,
400 "name1=value1; name1=value1",
401 2,
402 2,
403 2,
404 2,
405 {
406 COOKIE_ ("name1", "value1"),
407 COOKIE_ ("name1", "value1"),
408 COOKIE_NULL,
409 COOKIE_NULL,
410 COOKIE_NULL
411 }
412 },
413 {
414 __LINE__,
415 "name1=value1; name2=value2",
416 2,
417 2,
418 2,
419 2,
420 {
421 COOKIE_ ("name1", "value1"),
422 COOKIE_ ("name2", "value2"),
423 COOKIE_NULL,
424 COOKIE_NULL,
425 COOKIE_NULL
426 }
427 },
428 {
429 __LINE__,
430 "name1=value1; name2=value2",
431 2,
432 2,
433 2,
434 2,
435 {
436 COOKIE_ ("name1", "value1"),
437 COOKIE_ ("name2", "value2"),
438 COOKIE_NULL,
439 COOKIE_NULL,
440 COOKIE_NULL
441 }
442 },
443 {
444 __LINE__,
445 "name1=value1; name2=value2",
446 2,
447 2,
448 2,
449 2,
450 {
451 COOKIE_ ("name1", "value1"),
452 COOKIE_ ("name2", "value2"),
453 COOKIE_NULL,
454 COOKIE_NULL,
455 COOKIE_NULL
456 }
457 },
458 {
459 __LINE__,
460 "name1=value1; name2=value2",
461 2,
462 2,
463 2,
464 2,
465 {
466 COOKIE_ ("name1", "value1"),
467 COOKIE_ ("name2", "value2"),
468 COOKIE_NULL,
469 COOKIE_NULL,
470 COOKIE_NULL
471 }
472 },
473 {
474 __LINE__,
475 "name1=value1; name2=value2",
476 2,
477 2,
478 2,
479 2,
480 {
481 COOKIE_ ("name1", "value1"),
482 COOKIE_ ("name2", "value2"),
483 COOKIE_NULL,
484 COOKIE_NULL,
485 COOKIE_NULL
486 }
487 },
488 {
489 __LINE__,
490 "name1=value1; name2=value2",
491 2,
492 2,
493 2,
494 2,
495 {
496 COOKIE_ ("name1", "value1"),
497 COOKIE_ ("name2", "value2"),
498 COOKIE_NULL,
499 COOKIE_NULL,
500 COOKIE_NULL
501 }
502 },
503 {
504 __LINE__,
505 "name1=value1; name2=value2",
506 2,
507 2,
508 2,
509 2,
510 {
511 COOKIE_ ("name1", "value1"),
512 COOKIE_ ("name2", "value2"),
513 COOKIE_NULL,
514 COOKIE_NULL,
515 COOKIE_NULL
516 }
517 },
518 {
519 __LINE__,
245 "name1=var1; name2=var2; name3=; " \ 520 "name1=var1; name2=var2; name3=; " \
246 "name4=\"var4 with spaces\"; " \ 521 "name4=\"var4 with spaces\"; " \
247 "name5=var_with_=_char", 522 "name5=var_with_=_char",
248 5,
249 0, 523 0,
524 3,
525 5,
526 5,
250 { 527 {
251 COOKIE_ ("name1", "var1"), 528 COOKIE_ ("name1", "var1"),
252 COOKIE_ ("name2", "var2"), 529 COOKIE_ ("name2", "var2"),
@@ -260,8 +537,10 @@ static const struct strct_test_data test_data[] = {
260 "name1=var1;name2=var2;name3=;" \ 537 "name1=var1;name2=var2;name3=;" \
261 "name4=\"var4 with spaces\";" \ 538 "name4=\"var4 with spaces\";" \
262 "name5=var_with_=_char", 539 "name5=var_with_=_char",
263 5,
264 0, 540 0,
541 1,
542 5,
543 5,
265 { 544 {
266 COOKIE_ ("name1", "var1"), 545 COOKIE_ ("name1", "var1"),
267 COOKIE_ ("name2", "var2"), 546 COOKIE_ ("name2", "var2"),
@@ -275,8 +554,10 @@ static const struct strct_test_data test_data[] = {
275 "name1=var1; name2=var2; name3=; " \ 554 "name1=var1; name2=var2; name3=; " \
276 "name4=\"var4 with spaces\"; " \ 555 "name4=\"var4 with spaces\"; " \
277 "name5=var_with_=_char\t \t", 556 "name5=var_with_=_char\t \t",
278 5,
279 0, 557 0,
558 1,
559 5,
560 5,
280 { 561 {
281 COOKIE_ ("name1", "var1"), 562 COOKIE_ ("name1", "var1"),
282 COOKIE_ ("name2", "var2"), 563 COOKIE_ ("name2", "var2"),
@@ -290,8 +571,10 @@ static const struct strct_test_data test_data[] = {
290 "name1=var1;;name2=var2;;name3=;;" \ 571 "name1=var1;;name2=var2;;name3=;;" \
291 "name4=\"var4 with spaces\";;" \ 572 "name4=\"var4 with spaces\";;" \
292 "name5=var_with_=_char;\t \t", 573 "name5=var_with_=_char;\t \t",
293 5,
294 0, 574 0,
575 1,
576 5,
577 5,
295 { 578 {
296 COOKIE_ ("name1", "var1"), 579 COOKIE_ ("name1", "var1"),
297 COOKIE_ ("name2", "var2"), 580 COOKIE_ ("name2", "var2"),
@@ -305,14 +588,16 @@ static const struct strct_test_data test_data[] = {
305 "name3=; name1=var1; name2=var2; " \ 588 "name3=; name1=var1; name2=var2; " \
306 "name5=var_with_=_char;" \ 589 "name5=var_with_=_char;" \
307 "name4=\"var4 with spaces\"", 590 "name4=\"var4 with spaces\"",
308 5,
309 0, 591 0,
592 4,
593 5,
594 5,
310 { 595 {
311 COOKIE_ ("name1", "var1"), 596 COOKIE_ ("name1", "var1"),
312 COOKIE_ ("name2", "var2"), 597 COOKIE_ ("name2", "var2"),
313 COOKIE_ ("name3", ""), 598 COOKIE_ ("name3", ""),
314 COOKIE_ ("name4", "var4 with spaces"), 599 COOKIE_ ("name5", "var_with_=_char"),
315 COOKIE_ ("name5", "var_with_=_char") 600 COOKIE_ ("name4", "var4 with spaces")
316 } 601 }
317 }, 602 },
318 { 603 {
@@ -320,14 +605,16 @@ static const struct strct_test_data test_data[] = {
320 "name2=var2; name1=var1; " \ 605 "name2=var2; name1=var1; " \
321 "name5=var_with_=_char; name3=; " \ 606 "name5=var_with_=_char; name3=; " \
322 "name4=\"var4 with spaces\";", 607 "name4=\"var4 with spaces\";",
323 5,
324 0, 608 0,
609 4,
610 5,
611 5,
325 { 612 {
326 COOKIE_ ("name1", "var1"), 613 COOKIE_ ("name1", "var1"),
327 COOKIE_ ("name2", "var2"), 614 COOKIE_ ("name2", "var2"),
328 COOKIE_ ("name3", ""), 615 COOKIE_ ("name3", ""),
329 COOKIE_ ("name4", "var4 with spaces"), 616 COOKIE_ ("name5", "var_with_=_char"),
330 COOKIE_ ("name5", "var_with_=_char") 617 COOKIE_ ("name4", "var4 with spaces")
331 } 618 }
332 }, 619 },
333 { 620 {
@@ -335,14 +622,16 @@ static const struct strct_test_data test_data[] = {
335 "name2=var2; name1=var1; " \ 622 "name2=var2; name1=var1; " \
336 "name5=var_with_=_char; " \ 623 "name5=var_with_=_char; " \
337 "name4=\"var4 with spaces\"; name3=", 624 "name4=\"var4 with spaces\"; name3=",
338 5,
339 0, 625 0,
626 3,
627 5,
628 5,
340 { 629 {
341 COOKIE_ ("name1", "var1"), 630 COOKIE_ ("name1", "var1"),
342 COOKIE_ ("name2", "var2"), 631 COOKIE_ ("name2", "var2"),
632 COOKIE_ ("name5", "var_with_=_char"),
343 COOKIE_ ("name3", ""), 633 COOKIE_ ("name3", ""),
344 COOKIE_ ("name4", "var4 with spaces"), 634 COOKIE_ ("name4", "var4 with spaces")
345 COOKIE_ ("name5", "var_with_=_char")
346 } 635 }
347 }, 636 },
348 { 637 {
@@ -350,8 +639,10 @@ static const struct strct_test_data test_data[] = {
350 "name2=var2; name1=var1; " \ 639 "name2=var2; name1=var1; " \
351 "name4=\"var4 with spaces\"; " \ 640 "name4=\"var4 with spaces\"; " \
352 "name5=var_with_=_char; name3=;", 641 "name5=var_with_=_char; name3=;",
353 5,
354 0, 642 0,
643 2,
644 5,
645 5,
355 { 646 {
356 COOKIE_ ("name1", "var1"), 647 COOKIE_ ("name1", "var1"),
357 COOKIE_ ("name2", "var2"), 648 COOKIE_ ("name2", "var2"),
@@ -365,8 +656,10 @@ static const struct strct_test_data test_data[] = {
365 ";;;;;;;;name1=var1; name2=var2; name3=; " \ 656 ";;;;;;;;name1=var1; name2=var2; name3=; " \
366 "name4=\"var4 with spaces\"; " \ 657 "name4=\"var4 with spaces\"; " \
367 "name5=var_with_=_char", 658 "name5=var_with_=_char",
368 5,
369 0, 659 0,
660 0,
661 5,
662 5,
370 { 663 {
371 COOKIE_ ("name1", "var1"), 664 COOKIE_ ("name1", "var1"),
372 COOKIE_ ("name2", "var2"), 665 COOKIE_ ("name2", "var2"),
@@ -380,8 +673,10 @@ static const struct strct_test_data test_data[] = {
380 "name1=var1; name2=var2; name3=; " \ 673 "name1=var1; name2=var2; name3=; " \
381 "name4=\"var4 with spaces\"; ; ; ; ; " \ 674 "name4=\"var4 with spaces\"; ; ; ; ; " \
382 "name5=var_with_=_char", 675 "name5=var_with_=_char",
383 5,
384 0, 676 0,
677 3,
678 5,
679 5,
385 { 680 {
386 COOKIE_ ("name1", "var1"), 681 COOKIE_ ("name1", "var1"),
387 COOKIE_ ("name2", "var2"), 682 COOKIE_ ("name2", "var2"),
@@ -395,8 +690,10 @@ static const struct strct_test_data test_data[] = {
395 "name1=var1; name2=var2; name3=; " \ 690 "name1=var1; name2=var2; name3=; " \
396 "name4=\"var4 with spaces\"; " \ 691 "name4=\"var4 with spaces\"; " \
397 "name5=var_with_=_char;;;;;;;;", 692 "name5=var_with_=_char;;;;;;;;",
398 5,
399 0, 693 0,
694 3,
695 5,
696 5,
400 { 697 {
401 COOKIE_ ("name1", "var1"), 698 COOKIE_ ("name1", "var1"),
402 COOKIE_ ("name2", "var2"), 699 COOKIE_ ("name2", "var2"),
@@ -408,16 +705,18 @@ static const struct strct_test_data test_data[] = {
408 { 705 {
409 __LINE__, 706 __LINE__,
410 "name1=var1; name2=var2; " \ 707 "name1=var1; name2=var2; " \
411 "name4=\"var4 with spaces\"" \ 708 "name4=\"var4 with spaces\";" \
412 "name5=var_with_=_char; ; ; ; ; name3=", 709 "name5=var_with_=_char; ; ; ; ; name3=",
413 5,
414 0, 710 0,
711 2,
712 5,
713 5,
415 { 714 {
416 COOKIE_ ("name1", "var1"), 715 COOKIE_ ("name1", "var1"),
417 COOKIE_ ("name2", "var2"), 716 COOKIE_ ("name2", "var2"),
717 COOKIE_ ("name5", "var_with_=_char"),
418 COOKIE_ ("name3", ""), 718 COOKIE_ ("name3", ""),
419 COOKIE_ ("name4", "var4 with spaces"), 719 COOKIE_ ("name4", "var4 with spaces")
420 COOKIE_ ("name5", "var_with_=_char")
421 } 720 }
422 }, 721 },
423 { 722 {
@@ -425,8 +724,10 @@ static const struct strct_test_data test_data[] = {
425 "name5=var_with_=_char ;" \ 724 "name5=var_with_=_char ;" \
426 "name1=var1; name2=var2; name3=; " \ 725 "name1=var1; name2=var2; name3=; " \
427 "name4=\"var4 with spaces\" ", 726 "name4=\"var4 with spaces\" ",
428 5,
429 0, 727 0,
728 0,
729 5,
730 5,
430 { 731 {
431 COOKIE_ ("name1", "var1"), 732 COOKIE_ ("name1", "var1"),
432 COOKIE_ ("name2", "var2"), 733 COOKIE_ ("name2", "var2"),
@@ -439,14 +740,106 @@ static const struct strct_test_data test_data[] = {
439 __LINE__, 740 __LINE__,
440 "name5=var_with_=_char; name4=\"var4 with spaces\";" \ 741 "name5=var_with_=_char; name4=\"var4 with spaces\";" \
441 "name1=var1; name2=var2; name3=", 742 "name1=var1; name2=var2; name3=",
442 5,
443 0, 743 0,
744 1,
745 5,
746 5,
444 { 747 {
748 COOKIE_ ("name5", "var_with_=_char"),
445 COOKIE_ ("name1", "var1"), 749 COOKIE_ ("name1", "var1"),
446 COOKIE_ ("name2", "var2"), 750 COOKIE_ ("name2", "var2"),
447 COOKIE_ ("name3", ""), 751 COOKIE_ ("name3", ""),
448 COOKIE_ ("name4", "var4 with spaces"), 752 COOKIE_ ("name4", "var4 with spaces")
449 COOKIE_ ("name5", "var_with_=_char") 753 }
754 },
755 {
756 __LINE__,
757 "name1 = value1",
758 0,
759 0,
760 0,
761 1,
762 {
763 COOKIE_ ("name1", "value1"),
764 COOKIE_NULL,
765 COOKIE_NULL,
766 COOKIE_NULL,
767 COOKIE_NULL
768 }
769 },
770 {
771 __LINE__,
772 "name1\t=\tvalue1",
773 0,
774 0,
775 0,
776 1,
777 {
778 COOKIE_ ("name1", "value1"),
779 COOKIE_NULL,
780 COOKIE_NULL,
781 COOKIE_NULL,
782 COOKIE_NULL
783 }
784 },
785 {
786 __LINE__,
787 "name1\t = \tvalue1",
788 0,
789 0,
790 0,
791 1,
792 {
793 COOKIE_ ("name1", "value1"),
794 COOKIE_NULL,
795 COOKIE_NULL,
796 COOKIE_NULL,
797 COOKIE_NULL
798 }
799 },
800 {
801 __LINE__,
802 "name1 = value1; name2 =\tvalue2",
803 0,
804 0,
805 0,
806 2,
807 {
808 COOKIE_ ("name1", "value1"),
809 COOKIE_ ("name2", "value2"),
810 COOKIE_NULL,
811 COOKIE_NULL,
812 COOKIE_NULL
813 }
814 },
815 {
816 __LINE__,
817 "name1=value1; name2 =\tvalue2",
818 0,
819 1,
820 1,
821 2,
822 {
823 COOKIE_ ("name1", "value1"),
824 COOKIE_ ("name2", "value2"),
825 COOKIE_NULL,
826 COOKIE_NULL,
827 COOKIE_NULL
828 }
829 },
830 {
831 __LINE__,
832 "name1 = value1; name2=value2",
833 0,
834 0,
835 0,
836 2,
837 {
838 COOKIE_ ("name1", "value1"),
839 COOKIE_ ("name2", "value2"),
840 COOKIE_NULL,
841 COOKIE_NULL,
842 COOKIE_NULL
450 } 843 }
451 }, 844 },
452 { 845 {
@@ -454,6 +847,8 @@ static const struct strct_test_data test_data[] = {
454 "", 847 "",
455 0, 848 0,
456 0, 849 0,
850 0,
851 0,
457 { 852 {
458 COOKIE_NULL, 853 COOKIE_NULL,
459 COOKIE_NULL, 854 COOKIE_NULL,
@@ -467,6 +862,8 @@ static const struct strct_test_data test_data[] = {
467 " ", 862 " ",
468 0, 863 0,
469 0, 864 0,
865 0,
866 0,
470 { 867 {
471 COOKIE_NULL, 868 COOKIE_NULL,
472 COOKIE_NULL, 869 COOKIE_NULL,
@@ -480,6 +877,8 @@ static const struct strct_test_data test_data[] = {
480 "\t", 877 "\t",
481 0, 878 0,
482 0, 879 0,
880 0,
881 0,
483 { 882 {
484 COOKIE_NULL, 883 COOKIE_NULL,
485 COOKIE_NULL, 884 COOKIE_NULL,
@@ -493,6 +892,8 @@ static const struct strct_test_data test_data[] = {
493 "var=,", 892 "var=,",
494 0, 893 0,
495 0, 894 0,
895 0,
896 0,
496 { 897 {
497 COOKIE_NULL, 898 COOKIE_NULL,
498 COOKIE_NULL, 899 COOKIE_NULL,
@@ -506,6 +907,8 @@ static const struct strct_test_data test_data[] = {
506 "var=\"\\ \"", 907 "var=\"\\ \"",
507 0, 908 0,
508 0, 909 0,
910 0,
911 0,
509 { 912 {
510 COOKIE_NULL, 913 COOKIE_NULL,
511 COOKIE_NULL, 914 COOKIE_NULL,
@@ -519,6 +922,8 @@ static const struct strct_test_data test_data[] = {
519 "var=value space", 922 "var=value space",
520 0, 923 0,
521 0, 924 0,
925 0,
926 0,
522 { 927 {
523 COOKIE_NULL, 928 COOKIE_NULL,
524 COOKIE_NULL, 929 COOKIE_NULL,
@@ -532,6 +937,8 @@ static const struct strct_test_data test_data[] = {
532 "var=value\ttab", 937 "var=value\ttab",
533 0, 938 0,
534 0, 939 0,
940 0,
941 0,
535 { 942 {
536 COOKIE_NULL, 943 COOKIE_NULL,
537 COOKIE_NULL, 944 COOKIE_NULL,
@@ -545,6 +952,8 @@ static const struct strct_test_data test_data[] = {
545 "=", 952 "=",
546 0, 953 0,
547 0, 954 0,
955 0,
956 0,
548 { 957 {
549 COOKIE_NULL, 958 COOKIE_NULL,
550 COOKIE_NULL, 959 COOKIE_NULL,
@@ -558,6 +967,8 @@ static const struct strct_test_data test_data[] = {
558 "====", 967 "====",
559 0, 968 0,
560 0, 969 0,
970 0,
971 0,
561 { 972 {
562 COOKIE_NULL, 973 COOKIE_NULL,
563 COOKIE_NULL, 974 COOKIE_NULL,
@@ -571,6 +982,8 @@ static const struct strct_test_data test_data[] = {
571 ";=", 982 ";=",
572 0, 983 0,
573 0, 984 0,
985 0,
986 0,
574 { 987 {
575 COOKIE_NULL, 988 COOKIE_NULL,
576 COOKIE_NULL, 989 COOKIE_NULL,
@@ -584,6 +997,8 @@ static const struct strct_test_data test_data[] = {
584 "var", 997 "var",
585 0, 998 0,
586 0, 999 0,
1000 0,
1001 0,
587 { 1002 {
588 COOKIE_NULL, 1003 COOKIE_NULL,
589 COOKIE_NULL, 1004 COOKIE_NULL,
@@ -597,6 +1012,8 @@ static const struct strct_test_data test_data[] = {
597 "=;", 1012 "=;",
598 0, 1013 0,
599 0, 1014 0,
1015 0,
1016 0,
600 { 1017 {
601 COOKIE_NULL, 1018 COOKIE_NULL,
602 COOKIE_NULL, 1019 COOKIE_NULL,
@@ -610,6 +1027,8 @@ static const struct strct_test_data test_data[] = {
610 "= ;", 1027 "= ;",
611 0, 1028 0,
612 0, 1029 0,
1030 0,
1031 0,
613 { 1032 {
614 COOKIE_NULL, 1033 COOKIE_NULL,
615 COOKIE_NULL, 1034 COOKIE_NULL,
@@ -623,6 +1042,8 @@ static const struct strct_test_data test_data[] = {
623 ";= ;", 1042 ";= ;",
624 0, 1043 0,
625 0, 1044 0,
1045 0,
1046 0,
626 { 1047 {
627 COOKIE_NULL, 1048 COOKIE_NULL,
628 COOKIE_NULL, 1049 COOKIE_NULL,
@@ -636,7 +1057,10 @@ static const struct strct_test_data test_data[] = {
636/* Global parameters */ 1057/* Global parameters */
637static int verbose; 1058static int verbose;
638static int oneone; /**< If false use HTTP/1.0 for requests*/ 1059static int oneone; /**< If false use HTTP/1.0 for requests*/
639static int use_non_strict; 1060static int use_strict_n1;
1061static int use_strict_zero;
1062static int use_strict_p1;
1063static int strict_level;
640 1064
641static void 1065static void
642test_global_init (void) 1066test_global_init (void)
@@ -700,12 +1124,19 @@ ahcCheck (void *cls,
700 struct MHD_Response *response; 1124 struct MHD_Response *response;
701 enum MHD_Result ret; 1125 enum MHD_Result ret;
702 struct ahc_cls_type *const param = (struct ahc_cls_type *) cls; 1126 struct ahc_cls_type *const param = (struct ahc_cls_type *) cls;
703 const unsigned int expected_num_cookies = 1127 unsigned int expected_num_cookies;
704 use_non_strict ? param->check->num_cookies_non_strict :
705 param->check->num_cookies_strict;
706 unsigned int i; 1128 unsigned int i;
707 int cookie_failed; 1129 int cookie_failed;
708 1130
1131 if (use_strict_p1)
1132 expected_num_cookies = param->check->num_cookies_strict_p1;
1133 else if (use_strict_zero)
1134 expected_num_cookies = param->check->num_cookies_strict_zero;
1135 else if (use_strict_n1)
1136 expected_num_cookies = param->check->num_cookies_strict_n1;
1137 else
1138 externalErrorExit ();
1139
709 if (NULL == param) 1140 if (NULL == param)
710 mhdErrorExitDesc ("cls parameter is NULL"); 1141 mhdErrorExitDesc ("cls parameter is NULL");
711 1142
@@ -813,7 +1244,17 @@ ahcCheck (void *cls,
813 cookie_failed = 1; 1244 cookie_failed = 1;
814 } 1245 }
815 if (cookie_failed) 1246 if (cookie_failed)
816 return MHD_NO; /* Break connection */ 1247 {
1248 response =
1249 MHD_create_response_from_buffer_static (MHD_STATICSTR_LEN_ (PAGE_ERROR),
1250 PAGE_ERROR);
1251 ret = MHD_queue_response (connection,
1252 MHD_HTTP_BAD_REQUEST,
1253 response);
1254 MHD_destroy_response (response);
1255
1256 return ret;
1257 }
817 1258
818 if (&marker != *req_cls) 1259 if (&marker != *req_cls)
819 { 1260 {
@@ -1057,7 +1498,6 @@ check_result (CURLcode curl_code, CURL *c, long expected_code,
1057 struct CBC *pcbc) 1498 struct CBC *pcbc)
1058{ 1499{
1059 long code; 1500 long code;
1060 unsigned int ret;
1061 1501
1062 if (CURLE_OK != curl_code) 1502 if (CURLE_OK != curl_code)
1063 { 1503 {
@@ -1079,15 +1519,15 @@ check_result (CURLcode curl_code, CURL *c, long expected_code,
1079 if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code)) 1519 if (CURLE_OK != curl_easy_getinfo (c, CURLINFO_RESPONSE_CODE, &code))
1080 libcurlErrorExit (); 1520 libcurlErrorExit ();
1081 1521
1082 ret = 1;
1083 if (expected_code != code) 1522 if (expected_code != code)
1084 { 1523 {
1085 fprintf (stderr, "The response has wrong HTTP code: %ld\tExpected: %ld.\n", 1524 fprintf (stderr, "### The response has wrong HTTP code: %ld\t"
1525 "Expected: %ld.\n",
1086 code, expected_code); 1526 code, expected_code);
1087 ret = 0; 1527 return 0;
1088 } 1528 }
1089 else if (verbose) 1529 else if (verbose)
1090 printf ("The response has expected HTTP code: %ld\n", expected_code); 1530 printf ("### The response has expected HTTP code: %ld\n", expected_code);
1091 1531
1092 if (pcbc->pos != MHD_STATICSTR_LEN_ (PAGE)) 1532 if (pcbc->pos != MHD_STATICSTR_LEN_ (PAGE))
1093 { 1533 {
@@ -1105,7 +1545,7 @@ check_result (CURLcode curl_code, CURL *c, long expected_code,
1105 fflush (stderr); 1545 fflush (stderr);
1106 fflush (stdout); 1546 fflush (stdout);
1107 1547
1108 return ret; 1548 return 1;
1109} 1549}
1110 1550
1111 1551
@@ -1125,13 +1565,13 @@ testExternalPolling (void)
1125 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 1565 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
1126 port = 0; 1566 port = 0;
1127 else 1567 else
1128 port = 1340 + oneone ? 0 : 1 + use_non_strict ? 0 : 2; 1568 port = 1340 + oneone ? 0 : 6 + (uint16_t) (1 + strict_level);
1129 1569
1130 d = MHD_start_daemon (MHD_USE_ERROR_LOG, 1570 d = MHD_start_daemon (MHD_USE_ERROR_LOG,
1131 port, NULL, NULL, 1571 port, NULL, NULL,
1132 &ahcCheck, &ahc_param, 1572 &ahcCheck, &ahc_param,
1133 MHD_OPTION_STRICT_FOR_CLIENT, 1573 MHD_OPTION_STRICT_FOR_CLIENT,
1134 (int) (use_non_strict ? 0 : 1), 1574 (int) (strict_level),
1135 MHD_OPTION_END); 1575 MHD_OPTION_END);
1136 if (d == NULL) 1576 if (d == NULL)
1137 return 1; 1577 return 1;
@@ -1167,13 +1607,13 @@ testExternalPolling (void)
1167 MHD_HTTP_OK, &cbc)) 1607 MHD_HTTP_OK, &cbc))
1168 { 1608 {
1169 if (verbose) 1609 if (verbose)
1170 printf ("Got expected response for the check at line %u.\n", 1610 printf ("### Got expected response for the check at line %u.\n",
1171 test_data[i].line_num); 1611 test_data[i].line_num);
1172 fflush (stdout); 1612 fflush (stdout);
1173 } 1613 }
1174 else 1614 else
1175 { 1615 {
1176 fprintf (stderr, "FAILED request for the check at line %u.\n", 1616 fprintf (stderr, "### FAILED request for the check at line %u.\n",
1177 test_data[i].line_num); 1617 test_data[i].line_num);
1178 fflush (stderr); 1618 fflush (stderr);
1179 failed = 1; 1619 failed = 1;
@@ -1200,7 +1640,19 @@ main (int argc, char *const *argv)
1200 has_param (argc, argv, "-s") || 1640 has_param (argc, argv, "-s") ||
1201 has_param (argc, argv, "--silent")); 1641 has_param (argc, argv, "--silent"));
1202 oneone = ! has_in_name (argv[0], "10"); 1642 oneone = ! has_in_name (argv[0], "10");
1203 use_non_strict = has_in_name (argv[0], "_nonstrict"); 1643 use_strict_n1 = has_in_name (argv[0], "_strict_n1");
1644 use_strict_zero = has_in_name (argv[0], "_strict_zero");
1645 use_strict_p1 = has_in_name (argv[0], "_strict_p1");
1646 if (1 != ((use_strict_n1 ? 1 : 0) + (use_strict_zero ? 1 : 0)
1647 + (use_strict_p1 ? 1 : 0)))
1648 return 99;
1649
1650 if (use_strict_n1)
1651 strict_level = -1;
1652 else if (use_strict_zero)
1653 strict_level = 0;
1654 else if (use_strict_p1)
1655 strict_level = 1;
1204 1656
1205 test_global_init (); 1657 test_global_init ();
1206 1658