]> git.ipfire.org Git - thirdparty/squid.git/blame - src/StrList.cc
Log PROXY protocol v2 TLVs; fix PROXY protocol parsing bugs (#342)
[thirdparty/squid.git] / src / StrList.cc
CommitLineData
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 */
18void
19strListAdd(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 */
36int
d5f18517 37strListIsMember(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 */
53int
54strListIsSubstr(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 */
76int
77strListGetItem(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
134SBuf
135getListMember(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