Lines 19-24
Link Here
|
19 |
#include "cache_util.h" |
19 |
#include "cache_util.h" |
20 |
#include <ap_provider.h> |
20 |
#include <ap_provider.h> |
21 |
|
21 |
|
|
|
22 |
#include "test_char.h" |
23 |
|
22 |
APLOG_USE_MODULE(cache); |
24 |
APLOG_USE_MODULE(cache); |
23 |
|
25 |
|
24 |
/* -------------------------------------------------------------- */ |
26 |
/* -------------------------------------------------------------- */ |
Lines 923-997
CACHE_DECLARE(char *)ap_cache_generate_name(apr_po
Link Here
|
923 |
} |
925 |
} |
924 |
|
926 |
|
925 |
/** |
927 |
/** |
926 |
* String tokenizer that ignores separator characters within quoted strings |
928 |
* String tokenizer per RFC 7234 section 5.2 (1#token[=["]arg["]]). |
927 |
* and escaped characters, as per RFC2616 section 2.2. |
929 |
* If any (and arg not NULL), the argument is also returned (unquoted). |
928 |
*/ |
930 |
*/ |
929 |
char *cache_strqtok(char *str, const char *sep, char **last) |
931 |
apr_status_t cache_strqtok(char *str, char **token, char **arg, char **last) |
930 |
{ |
932 |
{ |
931 |
char *token; |
933 |
#define CACHE_TOKEN_SEPS "\t ," |
932 |
int quoted = 0; |
934 |
apr_status_t rv = APR_SUCCESS; |
|
|
935 |
enum { |
936 |
IN_TOKEN, |
937 |
IN_BETWEEN, |
938 |
IN_ARGUMENT, |
939 |
IN_QUOTES |
940 |
} state = IN_TOKEN; |
941 |
char *wpos; |
933 |
|
942 |
|
934 |
if (!str) { /* subsequent call */ |
943 |
if (!str) { /* subsequent call */ |
935 |
str = *last; /* start where we left off */ |
944 |
str = *last; /* start where we left off */ |
936 |
} |
945 |
} |
937 |
|
|
|
938 |
if (!str) { /* no more tokens */ |
946 |
if (!str) { /* no more tokens */ |
939 |
return NULL; |
947 |
return APR_EOF; |
940 |
} |
948 |
} |
941 |
|
949 |
|
942 |
/* skip characters in sep (will terminate at '\0') */ |
950 |
/* skip separators (will terminate at '\0') */ |
943 |
while (*str && ap_strchr_c(sep, *str)) { |
951 |
while (*str && TEST_CHAR(*str, T_HTTP_TOKEN_STOP)) { |
|
|
952 |
if (!ap_strchr_c(CACHE_TOKEN_SEPS, *str)) { |
953 |
return APR_EINVAL; |
954 |
} |
944 |
++str; |
955 |
++str; |
945 |
} |
956 |
} |
946 |
|
|
|
947 |
if (!*str) { /* no more tokens */ |
957 |
if (!*str) { /* no more tokens */ |
948 |
return NULL; |
958 |
return APR_EOF; |
949 |
} |
959 |
} |
950 |
|
960 |
|
951 |
token = str; |
961 |
*token = str; |
|
|
962 |
if (arg) { |
963 |
*arg = NULL; |
964 |
} |
952 |
|
965 |
|
953 |
/* skip valid token characters to terminate token and |
966 |
/* skip valid token characters to terminate token and |
954 |
* prepare for the next call (will terminate at '\0) |
967 |
* prepare for the next call (will terminate at '\0) |
955 |
* on the way, ignore all quoted strings, and within |
968 |
* on the way, handle quoted strings, and within |
956 |
* quoted strings, escaped characters. |
969 |
* quoted strings, escaped characters. |
957 |
*/ |
970 |
*/ |
958 |
*last = token; |
971 |
for (wpos = str; *str; ++str) { |
959 |
while (**last) { |
972 |
switch (state) { |
960 |
if (!quoted) { |
973 |
case IN_TOKEN: |
961 |
if (**last == '\"' && !ap_strchr_c(sep, '\"')) { |
974 |
if (*str == '=') { |
962 |
quoted = 1; |
975 |
state = IN_BETWEEN; |
963 |
++*last; |
976 |
*wpos++ = '\0'; |
|
|
977 |
*arg = wpos; |
978 |
continue; |
964 |
} |
979 |
} |
965 |
else if (!ap_strchr_c(sep, **last)) { |
980 |
break; |
966 |
++*last; |
981 |
|
|
|
982 |
case IN_BETWEEN: |
983 |
if (*str == '"') { |
984 |
state = IN_QUOTES; |
985 |
continue; |
967 |
} |
986 |
} |
968 |
else { |
987 |
/* fall through */ |
969 |
break; |
988 |
state = IN_ARGUMENT; |
|
|
989 |
case IN_ARGUMENT: |
990 |
if (TEST_CHAR(*str, T_HTTP_TOKEN_STOP)) { |
991 |
goto end; |
970 |
} |
992 |
} |
971 |
} |
993 |
break; |
972 |
else { |
994 |
|
973 |
if (**last == '\"') { |
995 |
default: |
974 |
quoted = 0; |
996 |
AP_DEBUG_ASSERT(state == IN_QUOTES); |
975 |
++*last; |
997 |
if (*str == '"') { |
|
|
998 |
++str; |
999 |
goto end; |
976 |
} |
1000 |
} |
977 |
else if (**last == '\\') { |
1001 |
if (*str == '\\' && *(str + 1)) { |
978 |
++*last; |
1002 |
++str; |
979 |
if (**last) { |
|
|
980 |
++*last; |
981 |
} |
982 |
} |
1003 |
} |
983 |
else { |
1004 |
break; |
984 |
++*last; |
|
|
985 |
} |
986 |
} |
1005 |
} |
|
|
1006 |
*wpos++ = *str; |
987 |
} |
1007 |
} |
988 |
|
1008 |
end: |
989 |
if (**last) { |
1009 |
/* anything after should be trailing OWS or comma */ |
990 |
**last = '\0'; |
1010 |
for (; *str; ++str) { |
991 |
++*last; |
1011 |
if (*str == ',') { |
|
|
1012 |
++str; |
1013 |
break; |
1014 |
} |
1015 |
if (*str != '\t' && *str != ' ') { |
1016 |
rv = APR_EINVAL; |
1017 |
break; |
1018 |
} |
992 |
} |
1019 |
} |
993 |
|
1020 |
|
994 |
return token; |
1021 |
*wpos = '\0'; |
|
|
1022 |
*last = str; |
1023 |
return rv; |
995 |
} |
1024 |
} |
996 |
|
1025 |
|
997 |
/** |
1026 |
/** |
Lines 1003-1008
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1003 |
const char *cc_header, const char *pragma_header, apr_table_t *headers) |
1032 |
const char *cc_header, const char *pragma_header, apr_table_t *headers) |
1004 |
{ |
1033 |
{ |
1005 |
char *last; |
1034 |
char *last; |
|
|
1035 |
apr_status_t rv; |
1006 |
|
1036 |
|
1007 |
if (cc->parsed) { |
1037 |
if (cc->parsed) { |
1008 |
return cc->cache_control || cc->pragma; |
1038 |
return cc->cache_control || cc->pragma; |
Lines 1015-1047
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1015 |
cc->s_maxage_value = -1; |
1045 |
cc->s_maxage_value = -1; |
1016 |
|
1046 |
|
1017 |
if (pragma_header) { |
1047 |
if (pragma_header) { |
1018 |
char *header = apr_pstrdup(r->pool, pragma_header); |
1048 |
char *header = apr_pstrdup(r->pool, pragma_header), *token; |
1019 |
const char *token = cache_strqtok(header, CACHE_SEPARATOR, &last); |
1049 |
for (rv = cache_strqtok(header, &token, NULL, &last); |
1020 |
while (token) { |
1050 |
rv == APR_SUCCESS; |
|
|
1051 |
rv = cache_strqtok(NULL, &token, NULL, &last)) { |
1021 |
if (!ap_cstr_casecmp(token, "no-cache")) { |
1052 |
if (!ap_cstr_casecmp(token, "no-cache")) { |
1022 |
cc->no_cache = 1; |
1053 |
cc->no_cache = 1; |
1023 |
} |
1054 |
} |
1024 |
token = cache_strqtok(NULL, CACHE_SEPARATOR, &last); |
|
|
1025 |
} |
1055 |
} |
1026 |
cc->pragma = 1; |
1056 |
cc->pragma = 1; |
1027 |
} |
1057 |
} |
1028 |
|
1058 |
|
1029 |
if (cc_header) { |
1059 |
if (cc_header) { |
1030 |
char *endp; |
1060 |
char *header = apr_pstrdup(r->pool, cc_header), *token, *arg; |
1031 |
apr_off_t offt; |
1061 |
for (rv = cache_strqtok(header, &token, &arg, &last); |
1032 |
char *header = apr_pstrdup(r->pool, cc_header); |
1062 |
rv == APR_SUCCESS; |
1033 |
const char *token = cache_strqtok(header, CACHE_SEPARATOR, &last); |
1063 |
rv = cache_strqtok(NULL, &token, &arg, &last)) { |
1034 |
while (token) { |
1064 |
char *endp; |
|
|
1065 |
apr_off_t offt; |
1066 |
|
1035 |
switch (token[0]) { |
1067 |
switch (token[0]) { |
1036 |
case 'n': |
1068 |
case 'n': |
1037 |
case 'N': { |
1069 |
case 'N': |
1038 |
if (!ap_cstr_casecmpn(token, "no-cache", 8)) { |
1070 |
if (!ap_cstr_casecmp(token, "no-cache")) { |
1039 |
if (token[8] == '=') { |
1071 |
if (!arg) { |
|
|
1072 |
cc->no_cache = 1; |
1073 |
} |
1074 |
else { |
1040 |
cc->no_cache_header = 1; |
1075 |
cc->no_cache_header = 1; |
1041 |
} |
1076 |
} |
1042 |
else if (!token[8]) { |
|
|
1043 |
cc->no_cache = 1; |
1044 |
} |
1045 |
} |
1077 |
} |
1046 |
else if (!ap_cstr_casecmp(token, "no-store")) { |
1078 |
else if (!ap_cstr_casecmp(token, "no-store")) { |
1047 |
cc->no_store = 1; |
1079 |
cc->no_store = 1; |
Lines 1050-1062
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1050 |
cc->no_transform = 1; |
1082 |
cc->no_transform = 1; |
1051 |
} |
1083 |
} |
1052 |
break; |
1084 |
break; |
1053 |
} |
1085 |
|
1054 |
case 'm': |
1086 |
case 'm': |
1055 |
case 'M': { |
1087 |
case 'M': |
1056 |
if (!ap_cstr_casecmpn(token, "max-age", 7)) { |
1088 |
if (arg && !ap_cstr_casecmp(token, "max-age")) { |
1057 |
if (token[7] == '=' |
1089 |
if (!apr_strtoff(&offt, arg, &endp, 10) |
1058 |
&& !apr_strtoff(&offt, token + 8, &endp, 10) |
1090 |
&& endp > arg && !*endp) { |
1059 |
&& endp > token + 8 && !*endp) { |
|
|
1060 |
cc->max_age = 1; |
1091 |
cc->max_age = 1; |
1061 |
cc->max_age_value = offt; |
1092 |
cc->max_age_value = offt; |
1062 |
} |
1093 |
} |
Lines 1064-1122
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1064 |
else if (!ap_cstr_casecmp(token, "must-revalidate")) { |
1095 |
else if (!ap_cstr_casecmp(token, "must-revalidate")) { |
1065 |
cc->must_revalidate = 1; |
1096 |
cc->must_revalidate = 1; |
1066 |
} |
1097 |
} |
1067 |
else if (!ap_cstr_casecmpn(token, "max-stale", 9)) { |
1098 |
else if (!ap_cstr_casecmp(token, "max-stale")) { |
1068 |
if (token[9] == '=' |
1099 |
if (!arg) { |
1069 |
&& !apr_strtoff(&offt, token + 10, &endp, 10) |
|
|
1070 |
&& endp > token + 10 && !*endp) { |
1071 |
cc->max_stale = 1; |
1100 |
cc->max_stale = 1; |
1072 |
cc->max_stale_value = offt; |
1101 |
cc->max_stale_value = -1; |
1073 |
} |
1102 |
} |
1074 |
else if (!token[9]) { |
1103 |
else if (!apr_strtoff(&offt, arg, &endp, 10) |
|
|
1104 |
&& endp > arg && !*endp) { |
1075 |
cc->max_stale = 1; |
1105 |
cc->max_stale = 1; |
1076 |
cc->max_stale_value = -1; |
1106 |
cc->max_stale_value = offt; |
1077 |
} |
1107 |
} |
1078 |
} |
1108 |
} |
1079 |
else if (!ap_cstr_casecmpn(token, "min-fresh", 9)) { |
1109 |
else if (arg && !ap_cstr_casecmp(token, "min-fresh")) { |
1080 |
if (token[9] == '=' |
1110 |
if (!apr_strtoff(&offt, arg, &endp, 10) |
1081 |
&& !apr_strtoff(&offt, token + 10, &endp, 10) |
1111 |
&& endp > arg && !*endp) { |
1082 |
&& endp > token + 10 && !*endp) { |
|
|
1083 |
cc->min_fresh = 1; |
1112 |
cc->min_fresh = 1; |
1084 |
cc->min_fresh_value = offt; |
1113 |
cc->min_fresh_value = offt; |
1085 |
} |
1114 |
} |
1086 |
} |
1115 |
} |
1087 |
break; |
1116 |
break; |
1088 |
} |
1117 |
|
1089 |
case 'o': |
1118 |
case 'o': |
1090 |
case 'O': { |
1119 |
case 'O': |
1091 |
if (!ap_cstr_casecmp(token, "only-if-cached")) { |
1120 |
if (!ap_cstr_casecmp(token, "only-if-cached")) { |
1092 |
cc->only_if_cached = 1; |
1121 |
cc->only_if_cached = 1; |
1093 |
} |
1122 |
} |
1094 |
break; |
1123 |
break; |
1095 |
} |
1124 |
|
1096 |
case 'p': |
1125 |
case 'p': |
1097 |
case 'P': { |
1126 |
case 'P': |
1098 |
if (!ap_cstr_casecmp(token, "public")) { |
1127 |
if (!ap_cstr_casecmp(token, "public")) { |
1099 |
cc->public = 1; |
1128 |
cc->public = 1; |
1100 |
} |
1129 |
} |
1101 |
else if (!ap_cstr_casecmpn(token, "private", 7)) { |
1130 |
else if (!ap_cstr_casecmp(token, "private")) { |
1102 |
if (token[7] == '=') { |
1131 |
if (!arg) { |
|
|
1132 |
cc->private = 1; |
1133 |
} |
1134 |
else { |
1103 |
cc->private_header = 1; |
1135 |
cc->private_header = 1; |
1104 |
} |
1136 |
} |
1105 |
else if (!token[7]) { |
|
|
1106 |
cc->private = 1; |
1107 |
} |
1108 |
} |
1137 |
} |
1109 |
else if (!ap_cstr_casecmp(token, "proxy-revalidate")) { |
1138 |
else if (!ap_cstr_casecmp(token, "proxy-revalidate")) { |
1110 |
cc->proxy_revalidate = 1; |
1139 |
cc->proxy_revalidate = 1; |
1111 |
} |
1140 |
} |
1112 |
break; |
1141 |
break; |
1113 |
} |
1142 |
|
1114 |
case 's': |
1143 |
case 's': |
1115 |
case 'S': { |
1144 |
case 'S': |
1116 |
if (!ap_cstr_casecmpn(token, "s-maxage", 8)) { |
1145 |
if (arg && !ap_cstr_casecmp(token, "s-maxage")) { |
1117 |
if (token[8] == '=' |
1146 |
if (!apr_strtoff(&offt, arg, &endp, 10) |
1118 |
&& !apr_strtoff(&offt, token + 9, &endp, 10) |
1147 |
&& endp > arg && !*endp) { |
1119 |
&& endp > token + 9 && !*endp) { |
|
|
1120 |
cc->s_maxage = 1; |
1148 |
cc->s_maxage = 1; |
1121 |
cc->s_maxage_value = offt; |
1149 |
cc->s_maxage_value = offt; |
1122 |
} |
1150 |
} |
Lines 1123-1130
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1123 |
} |
1151 |
} |
1124 |
break; |
1152 |
break; |
1125 |
} |
1153 |
} |
1126 |
} |
|
|
1127 |
token = cache_strqtok(NULL, CACHE_SEPARATOR, &last); |
1128 |
} |
1154 |
} |
1129 |
cc->cache_control = 1; |
1155 |
cc->cache_control = 1; |
1130 |
} |
1156 |
} |
Lines 1139-1186
int ap_cache_control(request_rec *r, cache_control
Link Here
|
1139 |
static int cache_control_remove(request_rec *r, const char *cc_header, |
1165 |
static int cache_control_remove(request_rec *r, const char *cc_header, |
1140 |
apr_table_t *headers) |
1166 |
apr_table_t *headers) |
1141 |
{ |
1167 |
{ |
1142 |
char *last, *slast; |
1168 |
char *last, *slast, *sheader; |
1143 |
int found = 0; |
1169 |
int found = 0; |
1144 |
|
1170 |
|
1145 |
if (cc_header) { |
1171 |
if (cc_header) { |
1146 |
char *header = apr_pstrdup(r->pool, cc_header); |
1172 |
apr_status_t rv; |
1147 |
char *token = cache_strqtok(header, CACHE_SEPARATOR, &last); |
1173 |
char *header = apr_pstrdup(r->pool, cc_header), *token, *arg; |
1148 |
while (token) { |
1174 |
for (rv = cache_strqtok(header, &token, &arg, &last); |
|
|
1175 |
rv == APR_SUCCESS; |
1176 |
rv = cache_strqtok(NULL, &token, &arg, &last)) { |
1177 |
if (!arg) { |
1178 |
continue; |
1179 |
} |
1180 |
|
1149 |
switch (token[0]) { |
1181 |
switch (token[0]) { |
1150 |
case 'n': |
1182 |
case 'n': |
1151 |
case 'N': { |
1183 |
case 'N': |
1152 |
if (!ap_cstr_casecmpn(token, "no-cache", 8)) { |
1184 |
if (!ap_cstr_casecmp(token, "no-cache")) { |
1153 |
if (token[8] == '=') { |
1185 |
for (rv = cache_strqtok(arg, &sheader, NULL, &slast); |
1154 |
const char *header = cache_strqtok(token + 9, |
1186 |
rv == APR_SUCCESS; |
1155 |
CACHE_SEPARATOR "\"", &slast); |
1187 |
rv = cache_strqtok(NULL, &sheader, NULL, &slast)) { |
1156 |
while (header) { |
1188 |
apr_table_unset(headers, sheader); |
1157 |
apr_table_unset(headers, header); |
|
|
1158 |
header = cache_strqtok(NULL, CACHE_SEPARATOR "\"", |
1159 |
&slast); |
1160 |
} |
1161 |
found = 1; |
1162 |
} |
1189 |
} |
|
|
1190 |
found = 1; |
1163 |
} |
1191 |
} |
1164 |
break; |
1192 |
break; |
1165 |
} |
1193 |
|
1166 |
case 'p': |
1194 |
case 'p': |
1167 |
case 'P': { |
1195 |
case 'P': |
1168 |
if (!ap_cstr_casecmpn(token, "private", 7)) { |
1196 |
if (!ap_cstr_casecmp(token, "private")) { |
1169 |
if (token[7] == '=') { |
1197 |
for (rv = cache_strqtok(arg, &sheader, NULL, &slast); |
1170 |
const char *header = cache_strqtok(token + 8, |
1198 |
rv == APR_SUCCESS; |
1171 |
CACHE_SEPARATOR "\"", &slast); |
1199 |
rv = cache_strqtok(NULL, &sheader, NULL, &slast)) { |
1172 |
while (header) { |
1200 |
apr_table_unset(headers, sheader); |
1173 |
apr_table_unset(headers, header); |
|
|
1174 |
header = cache_strqtok(NULL, CACHE_SEPARATOR "\"", |
1175 |
&slast); |
1176 |
} |
1177 |
found = 1; |
1178 |
} |
1201 |
} |
|
|
1202 |
found = 1; |
1179 |
} |
1203 |
} |
1180 |
break; |
1204 |
break; |
1181 |
} |
1205 |
} |
1182 |
} |
|
|
1183 |
token = cache_strqtok(NULL, CACHE_SEPARATOR, &last); |
1184 |
} |
1206 |
} |
1185 |
} |
1207 |
} |
1186 |
|
1208 |
|