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