diff --git a/src/util/UriQueryParser.cxx b/src/util/UriQueryParser.cxx new file mode 100644 index 000000000..f75fec733 --- /dev/null +++ b/src/util/UriQueryParser.cxx @@ -0,0 +1,49 @@ +/* + * Copyright 2008-2019 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "UriQueryParser.hxx" +#include "IterableSplitString.hxx" + +StringView +UriFindRawQueryParameter(StringView query_string, StringView name) noexcept +{ + for (StringView i : IterableSplitString(query_string, '&')) { + if (i.StartsWith(name)) { + if (i.size == name.size) + return ""; + + if (i[name.size] == '=') { + i.skip_front(name.size + 1); + return i; + } + } + } + + return nullptr; +} diff --git a/src/util/UriQueryParser.hxx b/src/util/UriQueryParser.hxx new file mode 100644 index 000000000..b098e5f06 --- /dev/null +++ b/src/util/UriQueryParser.hxx @@ -0,0 +1,48 @@ +/* + * Copyright 2008-2019 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef URI_QUERY_PARSER_HXX +#define URI_QUERY_PARSER_HXX + +#include "Compiler.h" + +struct StringView; + +/** + * Find the first query parameter with the given name and return its + * raw value (without unescaping). + * + * @return the raw value (pointing into the #query_string parameter) + * or nullptr if the parameter does not exist + */ +gcc_pure +StringView +UriFindRawQueryParameter(StringView query_string, StringView name) noexcept; + +#endif diff --git a/src/util/meson.build b/src/util/meson.build index da42d4362..9b1e261d7 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -18,6 +18,7 @@ util = static_library( 'FormatString.cxx', 'Tokenizer.cxx', 'UriExtract.cxx', + 'UriQueryParser.cxx', 'UriRelative.cxx', 'UriUtil.cxx', 'LazyRandomEngine.cxx', diff --git a/test/TestUriQueryParser.cxx b/test/TestUriQueryParser.cxx new file mode 100644 index 000000000..9455f0664 --- /dev/null +++ b/test/TestUriQueryParser.cxx @@ -0,0 +1,34 @@ +/* + * Unit tests for src/util/ + */ + +#include "util/UriQueryParser.hxx" +#include "util/StringView.hxx" + +#include + +static bool +operator==(StringView a, StringView b) +{ + if (a.IsNull() || b.IsNull()) + return a.IsNull() == b.IsNull(); + + return a.Equals(b); +} + +TEST(UriQueryParser, UriFindRawQueryParameter) +{ + const char *q = "foo=1&bar=2"ed=%20%00+%%&empty1&empty2="; + EXPECT_EQ(UriFindRawQueryParameter(q, "doesntexist"), + (const char *)nullptr); + EXPECT_EQ(UriFindRawQueryParameter(q, "foo"), + "1"); + EXPECT_EQ(UriFindRawQueryParameter(q, "bar"), + "2"); + EXPECT_EQ(UriFindRawQueryParameter(q, "quoted"), + "%20%00+%%"); + EXPECT_EQ(UriFindRawQueryParameter(q, "empty1"), + ""); + EXPECT_EQ(UriFindRawQueryParameter(q, "empty2"), + ""); +} diff --git a/test/meson.build b/test/meson.build index 4a146dcf9..66f7e88d0 100644 --- a/test/meson.build +++ b/test/meson.build @@ -38,6 +38,7 @@ test('TestUtil', executable( 'TestMimeType.cxx', 'TestSplitString.cxx', 'TestUriExtract.cxx', + 'TestUriQueryParser.cxx', 'TestUriUtil.cxx', 'test_byte_reverse.cxx', include_directories: inc,