mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Sandbox uriparser
This commit is contained in:
parent
2d324bd50d
commit
74c7f66dee
|
@ -20,6 +20,7 @@ set(SAPI_CONTRIB_SANDBOXES
|
|||
libidn2
|
||||
pffft
|
||||
turbojpeg
|
||||
uriparser
|
||||
zopfli
|
||||
zstd
|
||||
)
|
||||
|
|
|
@ -13,6 +13,7 @@ Directory | Project
|
|||
`libidn2/` | libidn2 - GNU IDN library | [www.gnu.org/software/libidn/#libidn2](https://www.gnu.org/software/libidn/#libidn2) | CMake
|
||||
`pffft/` | PFFFT - a pretty fast Fourier Transform | [bitbucket.org/jpommier/pffft.git](https://bitbucket.org/jpommier/pffft.git) | CMake
|
||||
`turbojpeg/` | High-level JPEG library | [libjpeg-turbo.org/About/TurboJPEG](https://libjpeg-turbo.org/About/TurboJPEG) | CMake
|
||||
`uriparser/` | uriparser - Strictly RFC 3986 compliant URI parsing and handling library | [github.com/uriparser/uriparser](https://github.com/uriparser/uriparser.git) | CMake
|
||||
`zopfli` | Zopfli - Compression Algorithm | [github.com/google/zopfli](https://github.com/google/zopfli) | CMake
|
||||
`zstd/` | Zstandard - Fast real-time compression algorithm | [github.com/facebook/zstd](https://github.com/facebook/zstd) | CMake
|
||||
|
||||
|
|
83
contrib/uriparser/CMakeLists.txt
Normal file
83
contrib/uriparser/CMakeLists.txt
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13..3.22)
|
||||
|
||||
project(sapi_uriparser CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
if(NOT TARGET sapi::sapi)
|
||||
set(SAPI_ROOT "../.." CACHE PATH "Path to the Sandboxed API source tree")
|
||||
add_subdirectory("${SAPI_ROOT}"
|
||||
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
|
||||
EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
set(HIDE_SYMBOLS OFF CACHE BOOL "" FORCE)
|
||||
set(URIPARSER_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||
set(URIPARSER_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(URIPARSER_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
|
||||
FetchContent_Declare(uriparser
|
||||
GIT_REPOSITORY https://github.com/uriparser/uriparser
|
||||
GIT_TAG e0dc98b767aadb86c6510c1b25e575084eeb803c
|
||||
PATCH_COMMAND patch < "${CMAKE_SOURCE_DIR}/patches/uriparser.cmake.patch"
|
||||
)
|
||||
FetchContent_MakeAvailable(uriparser)
|
||||
|
||||
configure_file(uri.gen.h.in uri.gen.h)
|
||||
|
||||
add_sapi_library(
|
||||
sapi_uriparser
|
||||
|
||||
FUNCTIONS
|
||||
uriParseUriA
|
||||
uriEscapeA
|
||||
|
||||
uriAddBaseUriA
|
||||
uriRemoveBaseUriA
|
||||
|
||||
uriToStringA
|
||||
uriToStringCharsRequiredA
|
||||
|
||||
uriNormalizeSyntaxMaskRequiredA
|
||||
uriNormalizeSyntaxExA
|
||||
|
||||
uriDissectQueryMallocA
|
||||
uriFreeQueryListA
|
||||
|
||||
uriFreeUriMembersA
|
||||
|
||||
INPUTS
|
||||
"${CMAKE_BINARY_DIR}/uri.gen.h"
|
||||
|
||||
LIBRARY uriparser
|
||||
LIBRARY_NAME Uriparser
|
||||
NAMESPACE ""
|
||||
)
|
||||
add_library(sapi_contrib::uriparser ALIAS sapi_uriparser)
|
||||
target_include_directories(sapi_uriparser INTERFACE
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
"${SAPI_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
if(SAPI_ENABLE_EXAMPLES)
|
||||
add_subdirectory(example)
|
||||
endif()
|
||||
|
||||
if(SAPI_ENABLE_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
28
contrib/uriparser/example/CMakeLists.txt
Normal file
28
contrib/uriparser/example/CMakeLists.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_executable(
|
||||
sapi_miniuriparser
|
||||
|
||||
main.cc
|
||||
../utils/utils_uriparser.cc
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
sapi_miniuriparser PRIVATE
|
||||
|
||||
sapi_uriparser
|
||||
sapi::sapi
|
||||
absl::flags_parse
|
||||
)
|
116
contrib/uriparser/example/main.cc
Normal file
116
contrib/uriparser/example/main.cc
Normal file
|
@ -0,0 +1,116 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/flags/parse.h"
|
||||
#include "contrib/uriparser/sandboxed.h"
|
||||
#include "contrib/uriparser/utils/utils_uriparser.h"
|
||||
|
||||
void Print(const char* name, absl::StatusOr<std::string> r) {
|
||||
if (!r.ok()) {
|
||||
std::cerr << "Unable to fetch " << name << "\n";
|
||||
std::cerr << r.status() << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if (r.value().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << name << ": " << *r << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string prog_name(argv[0]);
|
||||
google::InitGoogleLogging(argv[0]);
|
||||
std::vector<char*> args = absl::ParseCommandLine(argc, argv);
|
||||
|
||||
if (args.size() < 2) {
|
||||
std::cerr << "Usage:\n " << prog_name << " URI ...\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
UriparserSapiSandbox sandbox;
|
||||
if (!sandbox.Init().ok()) {
|
||||
std::cerr << "Unable to start sandbox\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int retval = EXIT_SUCCESS;
|
||||
for (int i = 1; i < args.size(); ++i) {
|
||||
UriParser uri(&sandbox, args[i]);
|
||||
if (!uri.GetStatus().ok()) {
|
||||
std::cerr << "Unable to parse: " << args[i] << "\n";
|
||||
std::cerr << uri.GetStatus() << "\n";
|
||||
retval = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
|
||||
Print("scheme", uri.GetScheme());
|
||||
Print("user info", uri.GetUserInfo());
|
||||
Print("host", uri.GetHostText());
|
||||
Print("host IP", uri.GetHostIP());
|
||||
Print("port", uri.GetPortText());
|
||||
Print("query", uri.GetQuery());
|
||||
Print("fragment", uri.GetFragment());
|
||||
|
||||
absl::StatusOr<std::vector<std::string>> path = uri.GetPath();
|
||||
if (!path.ok()) {
|
||||
std::cerr << "Unable to get path.\n";
|
||||
std::cerr << path.status() << "\n";
|
||||
retval = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (!path->empty()) {
|
||||
std::cout << "pathSeq: \n";
|
||||
for (const auto& s : path.value()) {
|
||||
std::cout << " - " << s << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
absl::StatusOr<absl::btree_map<std::string, std::string>> query_map;
|
||||
query_map = uri.GetQueryElements();
|
||||
if (!query_map.ok()) {
|
||||
std::cerr << "Unable to get query.\n";
|
||||
std::cerr << query_map.status() << "\n";
|
||||
retval = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (!query_map->empty()) {
|
||||
std::cout << "Query elements: \n";
|
||||
for (const auto& mp : query_map.value()) {
|
||||
std::cout << " - " << mp.first << ": " << mp.second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!uri.NormalizeSyntax().ok()) {
|
||||
std::cerr << "Unable to normalize: " << args[i] << "\n";
|
||||
continue;
|
||||
}
|
||||
absl::StatusOr<std::string> newuris = uri.GetUri();
|
||||
if (!newuris.ok()) {
|
||||
std::cerr << "Unable to reconstruct path.\n";
|
||||
std::cerr << newuris.status() << "\n";
|
||||
retval = EXIT_FAILURE;
|
||||
continue;
|
||||
}
|
||||
std::cout << "Normalized path: " << newuris.value() << "\n";
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
23
contrib/uriparser/patches/uriparser.cmake.patch
Normal file
23
contrib/uriparser/patches/uriparser.cmake.patch
Normal file
|
@ -0,0 +1,23 @@
|
|||
--- CMakeLists.txt
|
||||
+++ CMakeLists.txt
|
||||
@@ -59,6 +59,7 @@ include(GNUInstallDirs)
|
||||
# Configuration
|
||||
#
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (rather than static ones)" ON)
|
||||
+option(HIDE_SYMBOLS "Build a libraries with hidden symbols unless they're specifically exported" ON)
|
||||
option(URIPARSER_BUILD_DOCS "Build API documentation (requires Doxygen, Graphviz, and (optional) Qt's qhelpgenerator)" ON)
|
||||
option(URIPARSER_BUILD_TESTS "Build test suite (requires GTest >=1.8.0)" ON)
|
||||
option(URIPARSER_BUILD_TOOLS "Build tools (e.g. CLI \"uriparse\")" ON)
|
||||
@@ -104,10 +105,12 @@ endmacro()
|
||||
#
|
||||
set(URIPARSER_EXTRA_COMPILE_FLAGS)
|
||||
|
||||
+if(HIDE_SYMBOLS)
|
||||
check_c_compiler_flag("-fvisibility=hidden" URIPARSER_COMPILER_SUPPORTS_VISIBILITY)
|
||||
if(URIPARSER_COMPILER_SUPPORTS_VISIBILITY)
|
||||
set(URIPARSER_EXTRA_COMPILE_FLAGS "${URIPARSER_EXTRA_COMPILE_FLAGS} -fvisibility=hidden")
|
||||
endif()
|
||||
+endif(HIDE_SYMBOLS)
|
||||
|
||||
#
|
||||
# config.h
|
39
contrib/uriparser/sandboxed.h
Normal file
39
contrib/uriparser/sandboxed.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CONTRIB_URIPARSER_SANDBOXED_H_
|
||||
#define CONTRIB_URIPARSER_SANDBOXED_H_
|
||||
|
||||
#include <libgen.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "sapi_uriparser.sapi.h" // NOLINT(build/include)
|
||||
|
||||
class UriparserSapiSandbox : public UriparserSandbox {
|
||||
public:
|
||||
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||
sandbox2::PolicyBuilder*) override {
|
||||
return sandbox2::PolicyBuilder()
|
||||
.AllowDynamicStartup()
|
||||
.AllowRead()
|
||||
.AllowWrite()
|
||||
.AllowSystemMalloc()
|
||||
.AllowExit()
|
||||
.BuildOrDie();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CONTRIB_URIPARSER_SANDBOXED_H_
|
32
contrib/uriparser/test/CMakeLists.txt
Normal file
32
contrib/uriparser/test/CMakeLists.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Copyright 2022 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(
|
||||
sapi_uriparser_test
|
||||
|
||||
test_uriparser.cc
|
||||
../utils/utils_uriparser.cc
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(
|
||||
sapi_uriparser_test PRIVATE
|
||||
|
||||
sapi_uriparser
|
||||
sapi::test_main
|
||||
)
|
||||
|
||||
gtest_discover_tests(sapi_uriparser_test)
|
535
contrib/uriparser/test/test_uriparser.cc
Normal file
535
contrib/uriparser/test/test_uriparser.cc
Normal file
|
@ -0,0 +1,535 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "contrib/uriparser/sandboxed.h"
|
||||
#include "contrib/uriparser/utils/utils_uriparser.h"
|
||||
#include "sandboxed_api/util/path.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
#include "sandboxed_api/util/temp_file.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using ::sapi::IsOk;
|
||||
|
||||
const struct TestVariant {
|
||||
std::string test;
|
||||
std::string uri;
|
||||
std::string uriescaped;
|
||||
std::string scheme;
|
||||
std::string userinfo;
|
||||
std::string hosttext;
|
||||
std::string hostip;
|
||||
std::string porttext;
|
||||
std::string query;
|
||||
std::string fragment;
|
||||
std::string normalized;
|
||||
std::string add_base_example;
|
||||
std::string remove_base_example;
|
||||
std::vector<std::string> path_elements;
|
||||
std::map<std::string, std::string> query_elements;
|
||||
} TestData[] = {
|
||||
{
|
||||
.test = "http://www.example.com/",
|
||||
.uri = "http://www.example.com/",
|
||||
.uriescaped = "http%3A%2F%2Fwww.example.com%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "www.example.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://www.example.com/",
|
||||
.add_base_example = "http://www.example.com/",
|
||||
.remove_base_example = "./",
|
||||
},
|
||||
{
|
||||
.test = "https://github.com/google/sandboxed-api/",
|
||||
.uri = "https://github.com/google/sandboxed-api/",
|
||||
.uriescaped = "https%3A%2F%2Fgithub.com%2Fgoogle%2Fsandboxed-api%2F",
|
||||
.scheme = "https",
|
||||
.userinfo = "",
|
||||
.hosttext = "github.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "https://github.com/google/sandboxed-api/",
|
||||
.add_base_example = "https://github.com/google/sandboxed-api/",
|
||||
.remove_base_example = "https://github.com/google/sandboxed-api/",
|
||||
.path_elements = {
|
||||
"google",
|
||||
"sandboxed-api"
|
||||
},
|
||||
},
|
||||
{
|
||||
.test = "mailto:test@example.com",
|
||||
.uri = "mailto:test@example.com",
|
||||
.uriescaped = "mailto%3Atest%40example.com",
|
||||
.scheme = "mailto",
|
||||
.userinfo = "",
|
||||
.hosttext = "",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "mailto:test@example.com",
|
||||
.add_base_example = "mailto:test@example.com",
|
||||
.remove_base_example = "mailto:test@example.com",
|
||||
.path_elements = {"test@example.com"},
|
||||
},
|
||||
{
|
||||
.test = "file:///bin/bash",
|
||||
.uri = "file:///bin/bash",
|
||||
.uriescaped = "file%3A%2F%2F%2Fbin%2Fbash",
|
||||
.scheme = "file",
|
||||
.userinfo = "",
|
||||
.hosttext = "",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "file:///bin/bash",
|
||||
.add_base_example = "file:///bin/bash",
|
||||
.remove_base_example = "file:///bin/bash",
|
||||
.path_elements = {
|
||||
"bin",
|
||||
"bash",
|
||||
},
|
||||
},
|
||||
{
|
||||
.test = "http://www.example.com/name%20with%20spaces/",
|
||||
.uri = "http://www.example.com/name%20with%20spaces/",
|
||||
.uriescaped =
|
||||
"http%3A%2F%2Fwww.example.com%2Fname%2520with%2520spaces%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "www.example.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://www.example.com/name%20with%20spaces/",
|
||||
.add_base_example = "http://www.example.com/name%20with%20spaces/",
|
||||
.remove_base_example = "name%20with%20spaces/",
|
||||
.path_elements = {
|
||||
"name%20with%20spaces",
|
||||
},
|
||||
},
|
||||
{
|
||||
.test = "http://abcdefg@localhost/",
|
||||
.uri = "http://abcdefg@localhost/",
|
||||
.uriescaped = "http%3A%2F%2Fabcdefg%40localhost%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "abcdefg",
|
||||
.hosttext = "localhost",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://abcdefg@localhost/",
|
||||
.add_base_example = "http://abcdefg@localhost/",
|
||||
.remove_base_example = "//abcdefg@localhost/",
|
||||
},
|
||||
{
|
||||
.test = "https://localhost:123/",
|
||||
.uri = "https://localhost:123/",
|
||||
.uriescaped = "https%3A%2F%2Flocalhost%3A123%2F",
|
||||
.scheme = "https",
|
||||
.userinfo = "",
|
||||
.hosttext = "localhost",
|
||||
.hostip = "",
|
||||
.porttext = "123",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "https://localhost:123/",
|
||||
.add_base_example = "https://localhost:123/",
|
||||
.remove_base_example = "https://localhost:123/",
|
||||
},
|
||||
{
|
||||
.test = "http://[::1]/",
|
||||
.uri = "http://[0000:0000:0000:0000:0000:0000:0000:0001]/",
|
||||
.uriescaped = "http%3A%2F%2F%5B0000%3A0000%3A0000%3A0000%3A0000%3A0000%"
|
||||
"3A0000%3A0001%5D%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "::1",
|
||||
.hostip = "::1",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://[0000:0000:0000:0000:0000:0000:0000:0001]/",
|
||||
.add_base_example = "http://[0000:0000:0000:0000:0000:0000:0000:0001]/",
|
||||
.remove_base_example = "//[0000:0000:0000:0000:0000:0000:0000:0001]/",
|
||||
},
|
||||
{
|
||||
.test = "http://a/b/c/d;p?q",
|
||||
.uri = "http://a/b/c/d;p?q",
|
||||
.uriescaped = "http%3A%2F%2Fa%2Fb%2Fc%2Fd%3Bp%3Fq",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "a",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "q",
|
||||
.fragment = "",
|
||||
.normalized = "http://a/b/c/d;p?q",
|
||||
.add_base_example = "http://a/b/c/d;p?q",
|
||||
.remove_base_example = "//a/b/c/d;p?q",
|
||||
.path_elements = {
|
||||
"b",
|
||||
"c",
|
||||
"d;p"
|
||||
},
|
||||
.query_elements = {
|
||||
{"q", ""}
|
||||
},
|
||||
},
|
||||
{
|
||||
.test = "http://a/b/c/../d;p?q",
|
||||
.uri = "http://a/b/c/../d;p?q",
|
||||
.uriescaped = "http%3A%2F%2Fa%2Fb%2Fc%2F..%2Fd%3Bp%3Fq",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "a",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "q",
|
||||
.fragment = "",
|
||||
.normalized = "http://a/b/d;p?q",
|
||||
.add_base_example = "http://a/b/d;p?q",
|
||||
.remove_base_example = "//a/b/c/../d;p?q",
|
||||
.path_elements = {
|
||||
"b",
|
||||
"c",
|
||||
"..",
|
||||
"d;p"
|
||||
},
|
||||
.query_elements = {
|
||||
{"q", ""}
|
||||
}
|
||||
},
|
||||
{
|
||||
.test = "http://example.com/abc/def/",
|
||||
.uri = "http://example.com/abc/def/",
|
||||
.uriescaped = "http%3A%2F%2Fexample.com%2Fabc%2Fdef%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "example.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://example.com/abc/def/",
|
||||
.add_base_example = "http://example.com/abc/def/",
|
||||
.remove_base_example = "//example.com/abc/def/",
|
||||
.path_elements = {
|
||||
"abc",
|
||||
"def",
|
||||
},
|
||||
},
|
||||
{
|
||||
.test = "http://example.com/?abc",
|
||||
.uri = "http://example.com/?abc",
|
||||
.uriescaped = "http%3A%2F%2Fexample.com%2F%3Fabc",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "example.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "abc",
|
||||
.fragment = "",
|
||||
.normalized = "http://example.com/?abc",
|
||||
.add_base_example = "http://example.com/?abc",
|
||||
.remove_base_example = "//example.com/?abc",
|
||||
.query_elements = {
|
||||
{"abc", ""}
|
||||
}
|
||||
},
|
||||
{
|
||||
.test = "http://[vA.123456]/",
|
||||
.uri = "http://[vA.123456]/",
|
||||
.uriescaped = "http%3A%2F%2F%5BvA.123456%5D%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "vA.123456",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://[va.123456]/",
|
||||
.add_base_example = "http://[vA.123456]/",
|
||||
.remove_base_example = "//[vA.123456]/",
|
||||
},
|
||||
{
|
||||
.test = "http://8.8.8.8/",
|
||||
.uri = "http://8.8.8.8/",
|
||||
.uriescaped = "http%3A%2F%2F8.8.8.8%2F",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "8.8.8.8",
|
||||
.hostip = "8.8.8.8",
|
||||
.porttext = "",
|
||||
.query = "",
|
||||
.fragment = "",
|
||||
.normalized = "http://8.8.8.8/",
|
||||
.add_base_example = "http://8.8.8.8/",
|
||||
.remove_base_example = "//8.8.8.8/",
|
||||
},
|
||||
{
|
||||
.test = "http://www.example.com/?abc",
|
||||
.uri = "http://www.example.com/?abc",
|
||||
.uriescaped = "http%3A%2F%2Fwww.example.com%2F%3Fabc",
|
||||
.scheme = "http",
|
||||
.userinfo = "",
|
||||
.hosttext = "www.example.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "abc",
|
||||
.fragment = "",
|
||||
.normalized = "http://www.example.com/?abc",
|
||||
.add_base_example = "http://www.example.com/?abc",
|
||||
.remove_base_example = "./?abc",
|
||||
.query_elements = {
|
||||
{"abc", ""}
|
||||
}
|
||||
},
|
||||
{
|
||||
.test = "https://google.com?q=asd&x=y&zxc=asd",
|
||||
.uri = "https://google.com?q=asd&x=y&zxc=asd",
|
||||
.uriescaped = "https%3A%2F%2Fgoogle.com%3Fq%3Dasd%26x%3Dy%26zxc%3Dasd",
|
||||
.scheme = "https",
|
||||
.userinfo = "",
|
||||
.hosttext = "google.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "q=asd&x=y&zxc=asd",
|
||||
.fragment = "",
|
||||
.normalized = "https://google.com?q=asd&x=y&zxc=asd",
|
||||
.add_base_example = "https://google.com?q=asd&x=y&zxc=asd",
|
||||
.remove_base_example = "https://google.com?q=asd&x=y&zxc=asd",
|
||||
.query_elements = {
|
||||
{"q", "asd"},
|
||||
{"x", "y"},
|
||||
{"zxc", "asd"}
|
||||
}
|
||||
},
|
||||
{
|
||||
.test = "https://google.com?q=asd#newplace",
|
||||
.uri = "https://google.com?q=asd#newplace",
|
||||
.uriescaped = "https%3A%2F%2Fgoogle.com%3Fq%3Dasd%23newplace",
|
||||
.scheme = "https",
|
||||
.userinfo = "",
|
||||
.hosttext = "google.com",
|
||||
.hostip = "",
|
||||
.porttext = "",
|
||||
.query = "q=asd",
|
||||
.fragment = "newplace",
|
||||
.normalized = "https://google.com?q=asd#newplace",
|
||||
.add_base_example = "https://google.com?q=asd#newplace",
|
||||
.remove_base_example = "https://google.com?q=asd#newplace",
|
||||
.query_elements = {
|
||||
{"q", "asd"}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
class UriParserBase : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
std::unique_ptr<UriparserSapiSandbox> sandbox_;
|
||||
};
|
||||
|
||||
class UriParserTestData : public UriParserBase,
|
||||
public testing::WithParamInterface<TestVariant> {};
|
||||
|
||||
void UriParserBase::SetUp() {
|
||||
sandbox_ = std::make_unique<UriparserSapiSandbox>();
|
||||
ASSERT_THAT(sandbox_->Init(), IsOk());
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestUri) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetUri());
|
||||
ASSERT_EQ(ret, tv.uri);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestUriEscaped) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetUriEscaped(true, true));
|
||||
ASSERT_EQ(ret, tv.uriescaped);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestScheme) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetScheme());
|
||||
ASSERT_EQ(ret, tv.scheme);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestUserInfo) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetUserInfo());
|
||||
ASSERT_EQ(ret, tv.userinfo);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestHostText) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetHostText());
|
||||
ASSERT_EQ(ret, tv.hosttext);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestHostIP) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetHostIP());
|
||||
ASSERT_EQ(ret, tv.hostip);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestPortText) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetPortText());
|
||||
ASSERT_EQ(ret, tv.porttext);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestQuery) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetQuery());
|
||||
ASSERT_EQ(ret, tv.query);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestFragment) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetFragment());
|
||||
ASSERT_EQ(ret, tv.fragment);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestNormalize) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
ASSERT_THAT(uri.NormalizeSyntax(), IsOk());
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret, uri.GetUri());
|
||||
ASSERT_EQ(ret, tv.normalized);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestMultiple) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
std::string ret;
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(ret, uri.GetQuery());
|
||||
ASSERT_EQ(ret, tv.query);
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(ret, uri.GetHostIP());
|
||||
ASSERT_EQ(ret, tv.hostip);
|
||||
|
||||
ASSERT_THAT(uri.NormalizeSyntax(), IsOk());
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(ret, uri.GetUri());
|
||||
ASSERT_EQ(ret, tv.normalized);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestAddBaseExample) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::string ret,
|
||||
uri.GetUriWithBase("http://www.example.com"));
|
||||
ASSERT_EQ(ret, tv.add_base_example);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestRemoveBaseExample) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(
|
||||
std::string ret, uri.GetUriWithoutBase("http://www.example.com", false));
|
||||
ASSERT_EQ(ret, tv.remove_base_example);
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestPath) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(std::vector<std::string> ret, uri.GetPath());
|
||||
ASSERT_EQ(ret.size(), tv.path_elements.size());
|
||||
for (int i = 0; i < ret.size(); ++i) {
|
||||
ASSERT_EQ(ret[i], tv.path_elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(UriParserTestData, TestQueryElements) {
|
||||
const TestVariant& tv = GetParam();
|
||||
|
||||
UriParser uri(sandbox_.get(), tv.test);
|
||||
ASSERT_THAT(uri.GetStatus(), IsOk());
|
||||
|
||||
SAPI_ASSERT_OK_AND_ASSIGN(auto ret, uri.GetQueryElements());
|
||||
ASSERT_EQ(ret.size(), tv.query_elements.size());
|
||||
for (auto orig : tv.query_elements) {
|
||||
ASSERT_NE(ret.find(orig.first), ret.end());
|
||||
ASSERT_EQ(ret[orig.first], orig.second);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(UriParserBase, UriParserTestData,
|
||||
testing::ValuesIn(TestData));
|
||||
|
||||
} // namespace
|
21
contrib/uriparser/uri.gen.h.in
Normal file
21
contrib/uriparser/uri.gen.h.in
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This header ensure that we are getting ascii structures.
|
||||
// The generator dosen't handle well redefined macros like
|
||||
// URI_TYPE.
|
||||
|
||||
#define URI_PASS_ANSI
|
||||
#define URI_ENABLE_ANSI
|
||||
#include "${uriparser_SOURCE_DIR}/include/uriparser/Uri.h"
|
286
contrib/uriparser/utils/utils_uriparser.cc
Normal file
286
contrib/uriparser/utils/utils_uriparser.cc
Normal file
|
@ -0,0 +1,286 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "contrib/uriparser/utils/utils_uriparser.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "absl/cleanup/cleanup.h"
|
||||
|
||||
UriParser::~UriParser() {
|
||||
if (GetStatus().ok()) {
|
||||
api_.uriFreeUriMembersA(uri_.PtrBefore()).IgnoreError();
|
||||
}
|
||||
};
|
||||
|
||||
absl::Status UriParser::GetStatus() { return status_; }
|
||||
|
||||
absl::Status UriParser::ParseUri() {
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->Allocate(&uri_, true));
|
||||
|
||||
sapi::v::Struct<UriParserStateA> state;
|
||||
state.mutable_data()->uri = reinterpret_cast<UriUriA*>(uri_.GetRemote());
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
int ret, api_.uriParseUriA(state.PtrBefore(), c_uri_.PtrBefore()));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to parse uri");
|
||||
}
|
||||
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&uri_));
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::FetchUriText(UriTextRangeA* ptr) {
|
||||
if (ptr == nullptr) {
|
||||
return "";
|
||||
}
|
||||
if (ptr->first == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t size = ptr->afterLast - ptr->first;
|
||||
|
||||
// Sometimes uriparser dosen't allocate new memory
|
||||
// and sometimes it does.
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
std::string uri,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr(const_cast<char*>(ptr->first))));
|
||||
|
||||
return uri.substr(0, size);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetScheme() {
|
||||
return FetchUriText(&uri_.mutable_data()->scheme);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUserInfo() {
|
||||
return FetchUriText(&uri_.mutable_data()->userInfo);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetHostText() {
|
||||
return FetchUriText(&uri_.mutable_data()->hostText);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetHostIP() {
|
||||
char ipstr[INET6_ADDRSTRLEN] = "";
|
||||
|
||||
UriHostDataA* data = &uri_.mutable_data()->hostData;
|
||||
|
||||
if (uri_.mutable_data()->hostData.ip4) {
|
||||
sapi::v::Struct<UriIp4> ip4;
|
||||
ip4.SetRemote(uri_.mutable_data()->hostData.ip4);
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&ip4));
|
||||
inet_ntop(AF_INET, ip4.mutable_data()->data, ipstr, sizeof(ipstr));
|
||||
} else if (uri_.mutable_data()->hostData.ip6) {
|
||||
sapi::v::Struct<UriIp6> ip6;
|
||||
ip6.SetRemote(uri_.mutable_data()->hostData.ip6);
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&ip6));
|
||||
inet_ntop(AF_INET6, ip6.mutable_data()->data, ipstr, sizeof(ipstr));
|
||||
}
|
||||
|
||||
return std::string(ipstr);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetPortText() {
|
||||
return FetchUriText(&uri_.mutable_data()->portText);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetQuery() {
|
||||
return FetchUriText(&uri_.mutable_data()->query);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetFragment() {
|
||||
return FetchUriText(&uri_.mutable_data()->fragment);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::vector<std::string>> UriParser::GetPath() {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
UriPathSegmentA* pathHead = uri_.mutable_data()->pathHead;
|
||||
if (pathHead == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
sapi::v::Struct<UriPathSegmentA> path_segment;
|
||||
path_segment.SetRemote(pathHead);
|
||||
|
||||
while (path_segment.GetRemote() != nullptr) {
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&path_segment));
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(std::string seg,
|
||||
FetchUriText(&path_segment.mutable_data()->text));
|
||||
if (!seg.empty()) {
|
||||
ret.push_back(seg);
|
||||
}
|
||||
|
||||
path_segment.SetRemote(path_segment.mutable_data()->next);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
absl::Status UriParser::NormalizeSyntax() {
|
||||
SAPI_ASSIGN_OR_RETURN(int dirty_parts,
|
||||
api_.uriNormalizeSyntaxMaskRequiredA(uri_.PtrNone()));
|
||||
|
||||
return NormalizeSyntax(dirty_parts);
|
||||
}
|
||||
|
||||
absl::Status UriParser::NormalizeSyntax(int norm_mask) {
|
||||
SAPI_ASSIGN_OR_RETURN(int ret,
|
||||
api_.uriNormalizeSyntaxExA(uri_.PtrAfter(), norm_mask));
|
||||
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to normalize");
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUri() { return GetUri(&uri_); }
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUri(sapi::v::Struct<UriUriA>* uri) {
|
||||
sapi::v::Int size;
|
||||
int ret;
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
ret, api_.uriToStringCharsRequiredA(uri->PtrNone(), size.PtrAfter()));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to get size");
|
||||
}
|
||||
|
||||
sapi::v::Array<char> buf(size.GetValue() + 1);
|
||||
sapi::v::NullPtr null_ptr;
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(ret, api_.uriToStringA(buf.PtrAfter(), uri->PtrNone(),
|
||||
buf.GetSize(), &null_ptr));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to Recomposing URI");
|
||||
}
|
||||
|
||||
return std::string(buf.GetData());
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUriEscaped(bool space_to_plus,
|
||||
bool normalize_breaks) {
|
||||
SAPI_ASSIGN_OR_RETURN(std::string uri, GetUri());
|
||||
|
||||
// Be sure to allocate *6 times* the space of the input buffer for
|
||||
// *6 times* for _normalizeBreaks == URI_TRUE_
|
||||
int space = uri.length() * 6 + 1;
|
||||
|
||||
sapi::v::Array<char> bufout(space);
|
||||
sapi::v::ConstCStr bufin(uri.c_str());
|
||||
|
||||
SAPI_RETURN_IF_ERROR(api_.uriEscapeA(bufin.PtrBefore(), bufout.PtrAfter(),
|
||||
space_to_plus, normalize_breaks));
|
||||
|
||||
return std::string(bufout.GetData());
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUriWithBase(const std::string& base) {
|
||||
UriParser base_uri(sandbox_, base);
|
||||
|
||||
sapi::v::Struct<UriUriA> newuri;
|
||||
SAPI_ASSIGN_OR_RETURN(int ret,
|
||||
api_.uriAddBaseUriA(newuri.PtrAfter(), uri_.PtrNone(),
|
||||
base_uri.uri_.PtrBefore()));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to add base");
|
||||
}
|
||||
absl::Cleanup newuri_cleanup = [this, &newuri] {
|
||||
api_.uriFreeUriMembersA(newuri.PtrNone()).IgnoreError();
|
||||
};
|
||||
|
||||
return GetUri(&newuri);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> UriParser::GetUriWithoutBase(
|
||||
const std::string& base, bool domain_root_mode) {
|
||||
UriParser base_uri(sandbox_, base);
|
||||
|
||||
sapi::v::Struct<UriUriA> newuri;
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
int ret,
|
||||
api_.uriRemoveBaseUriA(newuri.PtrAfter(), uri_.PtrNone(),
|
||||
base_uri.uri_.PtrBefore(), domain_root_mode));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to remove base");
|
||||
}
|
||||
absl::Cleanup newuri_cleanup = [this, &newuri] {
|
||||
api_.uriFreeUriMembersA(newuri.PtrNone()).IgnoreError();
|
||||
};
|
||||
|
||||
return GetUri(&newuri);
|
||||
}
|
||||
|
||||
absl::StatusOr<absl::btree_map<std::string, std::string>>
|
||||
UriParser::GetQueryElements() {
|
||||
absl::btree_map<std::string, std::string> outquery;
|
||||
|
||||
if (uri_.mutable_data()->query.first == nullptr) {
|
||||
return outquery;
|
||||
}
|
||||
|
||||
sapi::v::Array<void*> query_ptr(1);
|
||||
sapi::v::Int query_count;
|
||||
sapi::v::RemotePtr first(const_cast<char*>(uri_.mutable_data()->query.first));
|
||||
sapi::v::RemotePtr afterLast(
|
||||
const_cast<char*>(uri_.mutable_data()->query.afterLast));
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(
|
||||
int ret,
|
||||
api_.uriDissectQueryMallocA(query_ptr.PtrAfter(), query_count.PtrAfter(),
|
||||
&first, &afterLast));
|
||||
if (ret != 0) {
|
||||
return absl::UnavailableError("Unable to get query list");
|
||||
}
|
||||
absl::Cleanup query_list_cleanup = [this, &query_ptr] {
|
||||
sapi::v::RemotePtr rptr(query_ptr[0]);
|
||||
api_.uriFreeQueryListA(&rptr).IgnoreError();
|
||||
};
|
||||
|
||||
sapi::v::Struct<UriQueryListA> obj;
|
||||
obj.SetRemote(query_ptr[0]);
|
||||
|
||||
for (int i = 0; i < query_count.GetValue(); ++i) {
|
||||
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&obj));
|
||||
obj.SetRemote(nullptr);
|
||||
|
||||
void* key_p = const_cast<char*>(obj.mutable_data()->key);
|
||||
void* value_p = const_cast<char*>(obj.mutable_data()->value);
|
||||
|
||||
SAPI_ASSIGN_OR_RETURN(std::string key_s,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr(key_p)));
|
||||
std::string value_s;
|
||||
if (value_p != nullptr) {
|
||||
SAPI_ASSIGN_OR_RETURN(value_s,
|
||||
sandbox_->GetCString(sapi::v::RemotePtr(value_p)));
|
||||
} else {
|
||||
value_s = "";
|
||||
}
|
||||
outquery[key_s] = value_s;
|
||||
obj.SetRemote(obj.mutable_data()->next);
|
||||
}
|
||||
obj.SetRemote(nullptr);
|
||||
|
||||
return outquery;
|
||||
}
|
66
contrib/uriparser/utils/utils_uriparser.h
Normal file
66
contrib/uriparser/utils/utils_uriparser.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CONTRIB_URIPARSER_UTILS_UTILS_ZIP_H_
|
||||
#define CONTRIB_URIPARSER_UTILS_UTILS_ZIP_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "contrib/uriparser/sandboxed.h"
|
||||
#include "sandboxed_api/util/status_macros.h"
|
||||
|
||||
class UriParser {
|
||||
public:
|
||||
UriParser(UriparserSandbox* sandbox, const std::string& uri)
|
||||
: sandbox_(CHECK_NOTNULL(sandbox)), api_(sandbox_), c_uri_(uri.c_str()) {
|
||||
status_ = ParseUri();
|
||||
};
|
||||
|
||||
~UriParser();
|
||||
|
||||
absl::Status GetStatus();
|
||||
absl::Status NormalizeSyntax();
|
||||
absl::Status NormalizeSyntax(int norm_mask);
|
||||
|
||||
absl::StatusOr<std::string> GetUri();
|
||||
absl::StatusOr<std::string> GetUriWithBase(const std::string& base);
|
||||
absl::StatusOr<std::string> GetUriWithoutBase(const std::string& base,
|
||||
bool domain_root_mode);
|
||||
absl::StatusOr<std::string> GetScheme();
|
||||
absl::StatusOr<std::string> GetUserInfo();
|
||||
absl::StatusOr<std::string> GetHostText();
|
||||
absl::StatusOr<std::string> GetHostIP();
|
||||
absl::StatusOr<std::string> GetPortText();
|
||||
absl::StatusOr<std::string> GetQuery();
|
||||
absl::StatusOr<std::string> GetFragment();
|
||||
absl::StatusOr<std::string> GetUriEscaped(bool space_to_plus,
|
||||
bool normalize_breaks);
|
||||
absl::StatusOr<std::vector<std::string>> GetPath();
|
||||
absl::StatusOr<absl::btree_map<std::string, std::string>> GetQueryElements();
|
||||
|
||||
protected:
|
||||
absl::StatusOr<std::string> FetchUriText(UriTextRangeA* ptr);
|
||||
absl::StatusOr<std::string> GetUri(sapi::v::Struct<UriUriA>* uri);
|
||||
absl::Status ParseUri();
|
||||
sapi::v::Struct<UriUriA> uri_;
|
||||
|
||||
private:
|
||||
UriparserSandbox* sandbox_;
|
||||
UriparserApi api_;
|
||||
sapi::v::ConstCStr c_uri_; // We have to keep a orginal string in sandbox
|
||||
absl::Status status_;
|
||||
};
|
||||
|
||||
#endif // CONTRIB_URIARSER_UTILS_UTILS_ZIP_H_
|
Loading…
Reference in New Issue
Block a user