]>
Commit | Line | Data |
---|---|---|
b8151fa1 | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors |
b8151fa1 | 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. | |
b8151fa1 CT |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 16 Cache Manager API */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
b8151fa1 CT |
12 | #include "base/TextException.h" |
13 | #include "ipc/TypedMsgHdr.h" | |
14 | #include "mgr/IntParam.h" | |
b8151fa1 | 15 | #include "mgr/QueryParams.h" |
602d9612 | 16 | #include "mgr/StringParam.h" |
26e65059 AJ |
17 | #include "parser/Tokenizer.h" |
18 | #include "sbuf/StringConvert.h" | |
19 | ||
20 | #include <limits> | |
b8151fa1 | 21 | |
b8151fa1 | 22 | Mgr::QueryParam::Pointer |
22b5be72 | 23 | Mgr::QueryParams::get(const String& name) const |
b8151fa1 CT |
24 | { |
25 | Must(name.size() != 0); | |
22b5be72 | 26 | Params::const_iterator pos = find(name); |
b8151fa1 CT |
27 | return (pos == params.end() ? NULL : pos->second); |
28 | } | |
29 | ||
30 | void | |
31 | Mgr::QueryParams::pack(Ipc::TypedMsgHdr& msg) const | |
32 | { | |
33 | msg.putInt(params.size()); | |
34 | for (Params::const_iterator iter = params.begin(); iter != params.end(); ++iter) { | |
35 | Must(iter->first.size() != 0); | |
36 | msg.putString(iter->first); | |
37 | Must(iter->second != NULL); | |
38 | iter->second->pack(msg); | |
39 | } | |
40 | } | |
41 | ||
42 | void | |
43 | Mgr::QueryParams::unpack(const Ipc::TypedMsgHdr& msg) | |
44 | { | |
45 | int count = msg.getInt(); | |
46 | Must(count >= 0); | |
47 | params.clear(); | |
48 | for ( ; count > 0; --count) { | |
49 | String name; | |
50 | msg.getString(name); | |
51 | Must(name.size() != 0); | |
52 | QueryParam::Type type; | |
53 | msg.getPod(type); | |
54 | QueryParam::Pointer value = CreateParam(type); | |
55 | value->unpackValue(msg); | |
56 | params.push_back(Param(name, value)); | |
57 | } | |
58 | } | |
59 | ||
22b5be72 CT |
60 | Mgr::QueryParams::Params::const_iterator |
61 | Mgr::QueryParams::find(const String& name) const | |
b8151fa1 CT |
62 | { |
63 | Must(name.size() != 0); | |
22b5be72 | 64 | Params::const_iterator iter = params.begin(); |
b8151fa1 CT |
65 | for ( ; iter != params.end(); ++iter) { |
66 | if (name.caseCmp(iter->first) == 0) | |
67 | break; | |
68 | } | |
69 | return iter; | |
70 | } | |
71 | ||
26e65059 AJ |
72 | /** |
73 | * Parses the value part of a "param=value" URL section. | |
74 | * Value can be a comma-separated list of integers or an opaque string. | |
75 | * | |
76 | * value = *pchar | ( 1*DIGIT *( ',' 1*DIGIT ) ) | |
77 | * | |
78 | * \note opaque string may be a list with a non-integer (e.g., "1,2,3,z") | |
79 | */ | |
80 | Mgr::QueryParam::Pointer | |
81 | ParseParamValue(const SBuf &rawValue) | |
b8151fa1 | 82 | { |
26e65059 AJ |
83 | static const CharacterSet comma("comma", ","); |
84 | ||
85 | Parser::Tokenizer tok(rawValue); | |
86 | std::vector<int> array; | |
87 | int64_t intVal = 0; | |
88 | while (tok.int64(intVal, 10, false)) { | |
89 | Must(intVal >= std::numeric_limits<int>::min()); | |
90 | Must(intVal <= std::numeric_limits<int>::max()); | |
91 | array.emplace_back(intVal); | |
92 | // integer list has comma between values. | |
93 | // Require at least one potential DIGIT after the skipped ',' | |
94 | if (tok.remaining().length() > 1) | |
95 | (void)tok.skipOne(comma); | |
b8151fa1 | 96 | } |
26e65059 AJ |
97 | |
98 | if (tok.atEnd()) | |
99 | return new Mgr::IntParam(array); | |
100 | else | |
101 | return new Mgr::StringParam(SBufToString(rawValue)); | |
b8151fa1 CT |
102 | } |
103 | ||
26e65059 AJ |
104 | /** |
105 | * Syntax: | |
106 | * query = [ param *( '&' param ) ] | |
107 | * param = name '=' value | |
108 | * name = [a-zA-Z0-9]+ | |
109 | * value = *pchar | ( 1*DIGIT *( ',' 1*DIGIT ) ) | |
110 | */ | |
111 | void | |
112 | Mgr::QueryParams::Parse(Parser::Tokenizer &tok, QueryParams &aParams) | |
b8151fa1 | 113 | { |
26e65059 AJ |
114 | static const CharacterSet nameChars = CharacterSet("param-name", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT; |
115 | static const CharacterSet valueChars = CharacterSet("param-value", "&= #").complement(); | |
116 | static const CharacterSet delimChars("param-delim", "&"); | |
117 | ||
118 | while (!tok.atEnd()) { | |
119 | ||
120 | // TODO: remove '#' processing when AnyP::Uri splits 'query#fragment' properly | |
121 | // #fragment handled by caller. Do not throw. | |
122 | if (tok.remaining()[0] == '#') | |
123 | return; | |
124 | ||
125 | if (tok.skipAll(delimChars)) | |
126 | continue; | |
127 | ||
128 | SBuf nameStr; | |
129 | if (!tok.prefix(nameStr, nameChars)) | |
130 | throw TextException("invalid query parameter name", Here()); | |
131 | if (!tok.skip('=')) | |
132 | throw TextException("missing parameter value", Here()); | |
133 | ||
134 | SBuf valueStr; | |
135 | if (!tok.prefix(valueStr, valueChars)) | |
136 | throw TextException("missing or malformed parameter value", Here()); | |
137 | ||
138 | const auto name = SBufToString(nameStr); | |
139 | const auto value = ParseParamValue(valueStr); | |
140 | aParams.params.emplace_back(name, value); | |
b8151fa1 | 141 | } |
b8151fa1 CT |
142 | } |
143 | ||
144 | Mgr::QueryParam::Pointer | |
145 | Mgr::QueryParams::CreateParam(QueryParam::Type aType) | |
146 | { | |
10c40d99 | 147 | switch (aType) { |
b8151fa1 CT |
148 | case QueryParam::ptInt: |
149 | return new IntParam(); | |
150 | ||
151 | case QueryParam::ptString: | |
152 | return new StringParam(); | |
153 | ||
154 | default: | |
155 | throw TexcHere("unknown parameter type"); | |
156 | break; | |
157 | } | |
158 | return NULL; | |
159 | } |