]>
Commit | Line | Data |
---|---|---|
28204b3b | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
28204b3b | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
28204b3b FC |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 66 HTTP Header Tools */ |
10 | ||
28204b3b | 11 | #include "squid.h" |
a8842770 | 12 | #include "base/TextException.h" |
d5f18517 | 13 | #include "sbuf/SBuf.h" |
28204b3b FC |
14 | #include "SquidString.h" |
15 | #include "StrList.h" | |
16 | ||
28204b3b | 17 | void |
1c2b4465 | 18 | strListAdd(String &str, const char *item, const size_t itemSize, const char delimiter) |
28204b3b | 19 | { |
1c2b4465 CT |
20 | if (str.size()) { |
21 | const char buf[] = { delimiter, ' ' }; | |
22 | const auto bufSize = sizeof(buf); | |
23 | Must(str.canGrowBy(bufSize)); | |
24 | str.append(buf, bufSize); | |
28204b3b | 25 | } |
1c2b4465 CT |
26 | Must(str.canGrowBy(itemSize)); |
27 | str.append(item, itemSize); | |
28 | } | |
29 | ||
30 | void | |
31 | strListAdd(String *str, const char *item, const char delimiter) | |
32 | { | |
33 | assert(str); | |
34 | assert(item); | |
35 | strListAdd(*str, item, strlen(item), delimiter); | |
36 | } | |
37 | ||
38 | void | |
39 | strListAdd(String &str, const SBuf &item, char delimiter) | |
40 | { | |
41 | strListAdd(str, item.rawContent(), item.length(), delimiter); | |
28204b3b FC |
42 | } |
43 | ||
44 | /** returns true iff "m" is a member of the list */ | |
45 | int | |
d5f18517 | 46 | strListIsMember(const String * list, const SBuf &m, char del) |
28204b3b | 47 | { |
aee3523a | 48 | const char *pos = nullptr; |
28204b3b FC |
49 | const char *item; |
50 | int ilen = 0; | |
28204b3b | 51 | |
d5f18517 AJ |
52 | assert(list); |
53 | int mlen = m.plength(); | |
28204b3b | 54 | while (strListGetItem(list, del, &item, &ilen, &pos)) { |
d5f18517 | 55 | if (mlen == ilen && m.caseCmp(item, ilen) == 0) |
28204b3b FC |
56 | return 1; |
57 | } | |
58 | return 0; | |
59 | } | |
60 | ||
61 | /** returns true iff "s" is a substring of a member of the list */ | |
62 | int | |
63 | strListIsSubstr(const String * list, const char *s, char del) | |
64 | { | |
65 | assert(list && del); | |
66 | return (list->find(s) != String::npos); | |
67 | ||
68 | /** \note | |
69 | * Note: the original code with a loop is broken because it uses strstr() | |
70 | * instead of strnstr(). If 's' contains a 'del', strListIsSubstr() may | |
71 | * return true when it should not. If 's' does not contain a 'del', the | |
2f8abb64 | 72 | * implementation is equavalent to strstr()! Thus, we replace the loop with |
28204b3b FC |
73 | * strstr() above until strnstr() is available. |
74 | */ | |
75 | } | |
76 | ||
77 | /** | |
78 | * iterates through a 0-terminated string of items separated by 'del's. | |
79 | * white space around 'del' is considered to be a part of 'del' | |
80 | * like strtok, but preserves the source, and can iterate several strings at once | |
81 | * | |
82 | * returns true if next item is found. | |
83 | * init pos with NULL to start iteration. | |
84 | */ | |
85 | int | |
86 | strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos) | |
87 | { | |
88 | size_t len; | |
89 | /* ',' is always enabled as field delimiter as this is required for | |
90 | * processing merged header values properly, even if Cookie normally | |
91 | * uses ';' as delimiter. | |
92 | */ | |
93 | static char delim[3][8] = { | |
94 | "\"?,", | |
95 | "\"\\", | |
96 | " ?,\t\r\n" | |
97 | }; | |
98 | int quoted = 0; | |
99 | assert(str && item && pos); | |
100 | ||
101 | delim[0][1] = del; | |
102 | delim[2][1] = del; | |
103 | ||
104 | if (!*pos) { | |
105 | *pos = str->termedBuf(); | |
106 | ||
107 | if (!*pos) | |
108 | return 0; | |
109 | } | |
110 | ||
111 | /* skip leading whitespace and delimiters */ | |
112 | *pos += strspn(*pos, delim[2]); | |
113 | ||
114 | *item = *pos; /* remember item's start */ | |
115 | ||
116 | /* find next delimiter */ | |
117 | do { | |
118 | *pos += strcspn(*pos, delim[quoted]); | |
119 | if (**pos == '"') { | |
120 | quoted = !quoted; | |
121 | *pos += 1; | |
122 | } else if (quoted && **pos == '\\') { | |
123 | *pos += 1; | |
124 | if (**pos) | |
125 | *pos += 1; | |
126 | } else { | |
127 | break; /* Delimiter found, marking the end of this value */ | |
128 | } | |
129 | } while (**pos); | |
130 | ||
131 | len = *pos - *item; /* *pos points to del or '\0' */ | |
132 | ||
133 | /* rtrim */ | |
134 | while (len > 0 && xisspace((*item)[len - 1])) | |
135 | --len; | |
136 | ||
137 | if (ilen) | |
138 | *ilen = len; | |
139 | ||
140 | return len > 0; | |
141 | } | |
142 | ||
36c774f7 EB |
143 | SBuf |
144 | getListMember(const String &list, const char *key, const char delimiter) | |
145 | { | |
146 | const char *pos = nullptr; | |
147 | const char *item = nullptr; | |
148 | int ilen = 0; | |
149 | const auto keyLen = strlen(key); | |
150 | while (strListGetItem(&list, delimiter, &item, &ilen, &pos)) { | |
151 | if (static_cast<size_t>(ilen) > keyLen && strncmp(item, key, keyLen) == 0 && item[keyLen] == '=') | |
152 | return SBuf(item + keyLen + 1, ilen - keyLen - 1); | |
153 | } | |
154 | return SBuf(); | |
155 | } | |
156 |