]> git.ipfire.org Git - thirdparty/squid.git/blame - src/mgr/QueryParams.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / mgr / QueryParams.cc
CommitLineData
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 22Mgr::QueryParam::Pointer
22b5be72 23Mgr::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
30void
31Mgr::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
42void
43Mgr::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
60Mgr::QueryParams::Params::const_iterator
61Mgr::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 */
80Mgr::QueryParam::Pointer
81ParseParamValue(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 */
111void
112Mgr::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
144Mgr::QueryParam::Pointer
145Mgr::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}