mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Merge pull request #160 from oshogbo:libxls
PiperOrigin-RevId: 443307436 Change-Id: Ic2550e45cf3f55cac9fcfce37cf669c6a6f9fc96
This commit is contained in:
commit
d8d7d74ae2
|
@ -18,6 +18,7 @@ set(SAPI_CONTRIB_SANDBOXES
|
||||||
hunspell
|
hunspell
|
||||||
jsonnet
|
jsonnet
|
||||||
libidn2
|
libidn2
|
||||||
|
libxls
|
||||||
libzip
|
libzip
|
||||||
pffft
|
pffft
|
||||||
turbojpeg
|
turbojpeg
|
||||||
|
|
|
@ -11,6 +11,7 @@ Directory | Project
|
||||||
`hunspell/` | Hunspell - The most popular spellchecking library | [github.com/hunspell/hunspell](https://github.com/hunspell/hunspell) | CMake
|
`hunspell/` | Hunspell - The most popular spellchecking library | [github.com/hunspell/hunspell](https://github.com/hunspell/hunspell) | CMake
|
||||||
`jsonnet/` | Jsonnet - The Data Templating Language | [github.com/google/jsonnet](https://github.com/google/jsonnet) | CMake
|
`jsonnet/` | Jsonnet - The Data Templating Language | [github.com/google/jsonnet](https://github.com/google/jsonnet) | CMake
|
||||||
`libidn2/` | libidn2 - GNU IDN library | [www.gnu.org/software/libidn/#libidn2](https://www.gnu.org/software/libidn/#libidn2) | CMake
|
`libidn2/` | libidn2 - GNU IDN library | [www.gnu.org/software/libidn/#libidn2](https://www.gnu.org/software/libidn/#libidn2) | CMake
|
||||||
|
`libxls/` | libxls - Read binary Excel files from C/C++ | [https://github.com/libxls/libxls](https://github.com/libxls/libxls) | CMake
|
||||||
`libzip/` | libzip - operations on zip archives | [github.com/nih-at/libzip](https://github.com/nih-at/libzip) | CMake
|
`libzip/` | libzip - operations on zip archives | [github.com/nih-at/libzip](https://github.com/nih-at/libzip) | CMake
|
||||||
`pffft/` | PFFFT - a pretty fast Fourier Transform | [bitbucket.org/jpommier/pffft.git](https://bitbucket.org/jpommier/pffft.git) | 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
|
`turbojpeg/` | High-level JPEG library | [libjpeg-turbo.org/About/TurboJPEG](https://libjpeg-turbo.org/About/TurboJPEG) | CMake
|
||||||
|
|
117
contrib/libxls/CMakeLists.txt
Normal file
117
contrib/libxls/CMakeLists.txt
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# 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_libxls C CXX)
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
FetchContent_Declare(libxls
|
||||||
|
GIT_REPOSITORY https://github.com/libxls/libxls.git
|
||||||
|
GIT_TAG 448240067919707eb95fb009f76f3fdb439b1427
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_GetProperties(libxls)
|
||||||
|
if(NOT libxls_POPULATED)
|
||||||
|
FetchContent_Populate(libxls)
|
||||||
|
set(libxls_STATUS_FILE "${libxls_SOURCE_DIR}/config.status")
|
||||||
|
if(EXISTS "${libxls_STATUS_FILE}")
|
||||||
|
file(SHA256 "${libxls_STATUS_FILE}" _sapi_CONFIG_STATUS)
|
||||||
|
endif()
|
||||||
|
if(NOT _sapi_CONFIG_STATUS STREQUAL "${libxls_CONFIG_STATUS}")
|
||||||
|
message("-- Configuring libxls...")
|
||||||
|
execute_process(
|
||||||
|
COMMAND autoreconf -i
|
||||||
|
WORKING_DIRECTORY "${libxls_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE _sapi_libxls_autoreconf_result
|
||||||
|
)
|
||||||
|
if(NOT _sapi_libxls_autoreconf_result EQUAL "0")
|
||||||
|
message(FATAL_ERROR "Configuration for libxls failed: "
|
||||||
|
"${_sapi_libxls_autoreconf_result}")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ./configure --disable-dependency-tracking
|
||||||
|
--disable-shared
|
||||||
|
--quiet
|
||||||
|
WORKING_DIRECTORY "${libxls_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE _sapi_libxls_config_result
|
||||||
|
)
|
||||||
|
if(NOT _sapi_libxls_config_result EQUAL "0")
|
||||||
|
message(FATAL_ERROR "Configuration for libxls failed: "
|
||||||
|
"${_sapi_libxls_config_result}")
|
||||||
|
endif()
|
||||||
|
file(SHA256 "${libxls_SOURCE_DIR}/config.status" _sapi_CONFIG_STATUS)
|
||||||
|
set(libxls_CONFIG_STATUS "${_sapi_CONFIG_STATUS}" CACHE INTERNAL "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(libxls STATIC
|
||||||
|
"${libxls_SOURCE_DIR}/src/endian.c"
|
||||||
|
"${libxls_SOURCE_DIR}/src/locale.c"
|
||||||
|
"${libxls_SOURCE_DIR}/src/ole.c"
|
||||||
|
"${libxls_SOURCE_DIR}/src/xls.c"
|
||||||
|
"${libxls_SOURCE_DIR}/src/xlstool.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(libxls PUBLIC
|
||||||
|
"${libxls_SOURCE_DIR}"
|
||||||
|
"${libxls_SOURCE_DIR}/include"
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file(xls.gen.h.in xls.gen.h)
|
||||||
|
|
||||||
|
add_sapi_library(
|
||||||
|
sapi_libxls
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
xls_open_file
|
||||||
|
|
||||||
|
xls_getWorkSheet
|
||||||
|
xls_parseWorkSheet
|
||||||
|
|
||||||
|
xls_cell
|
||||||
|
|
||||||
|
xls_close_WS
|
||||||
|
xls_close_WB
|
||||||
|
|
||||||
|
xls_getError
|
||||||
|
|
||||||
|
INPUTS
|
||||||
|
"${CMAKE_BINARY_DIR}/xls.gen.h"
|
||||||
|
|
||||||
|
LIBRARY libxls
|
||||||
|
LIBRARY_NAME Libxls
|
||||||
|
NAMESPACE ""
|
||||||
|
)
|
||||||
|
add_library(sapi_contrib::libxls ALIAS sapi_libxls)
|
||||||
|
target_include_directories(sapi_libxls INTERFACE
|
||||||
|
"${PROJECT_BINARY_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(SAPI_ENABLE_EXAMPLES)
|
||||||
|
add_subdirectory(example)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SAPI_ENABLE_TESTS)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
14
contrib/libxls/README.md
Normal file
14
contrib/libxls/README.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# libxls Sandboxed API
|
||||||
|
|
||||||
|
This directory contains a ready-made sandbox for the
|
||||||
|
[libxls](https://github.com/libxls/libxls) library.
|
||||||
|
|
||||||
|
The libxls library uses Autotools and a special macro package for its
|
||||||
|
configuration. This means that on Debian based systems, the package
|
||||||
|
`autoconf-archive` needs to be installed or the configuration phase
|
||||||
|
will fail with the following error:
|
||||||
|
|
||||||
|
```
|
||||||
|
./configure: line 16126: syntax error near unexpected token `,'
|
||||||
|
./configure: line 16126: `AX_CXX_COMPILE_STDCXX_11(, optional)'
|
||||||
|
```
|
24
contrib/libxls/example/CMakeLists.txt
Normal file
24
contrib/libxls/example/CMakeLists.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# 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_minixls
|
||||||
|
main.cc
|
||||||
|
../utils/utils_libxls.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(sapi_minixls
|
||||||
|
PRIVATE sapi_libxls
|
||||||
|
absl::flags_parse
|
||||||
|
sapi::sapi
|
||||||
|
)
|
89
contrib/libxls/example/main.cc
Normal file
89
contrib/libxls/example/main.cc
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
// 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 <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/flags/flag.h"
|
||||||
|
#include "absl/flags/parse.h"
|
||||||
|
#include "contrib/libxls/sandboxed.h"
|
||||||
|
#include "contrib/libxls/utils/utils_libxls.h"
|
||||||
|
|
||||||
|
ABSL_FLAG(uint32_t, sheet, 0, "sheet number");
|
||||||
|
|
||||||
|
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 << " INPUT\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibxlsSapiSandbox sandbox(args[1]);
|
||||||
|
if (!sandbox.Init().ok()) {
|
||||||
|
std::cerr << "Unable to start sandbox\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsWorkbook> wb = LibXlsWorkbook::Open(&sandbox, args[1]);
|
||||||
|
|
||||||
|
uint32_t nr_sheet = absl::GetFlag(FLAGS_sheet);
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsSheet> sheet = wb->OpenSheet(nr_sheet);
|
||||||
|
if (!sheet.ok()) {
|
||||||
|
std::cerr << "Unable to switch sheet: ";
|
||||||
|
std::cerr << sheet.status() << "\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t row = 0; row < sheet->GetRowCount(); ++row) {
|
||||||
|
for (size_t col = 0; col < sheet->GetColCount(); ++col) {
|
||||||
|
absl::StatusOr<LibXlsCell> cell = sheet->GetCell(row, col);
|
||||||
|
if (!cell.ok()) {
|
||||||
|
std::cerr << "Unable to get cell: ";
|
||||||
|
std::cerr << cell.status() << "\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
switch (cell->type) {
|
||||||
|
case XLS_RECORD_NUMBER:
|
||||||
|
std::cout << std::setw(16) << std::get<double>(cell->value) << " | ";
|
||||||
|
break;
|
||||||
|
case XLS_RECORD_STRING:
|
||||||
|
std::cout << std::setw(16) << std::get<std::string>(cell->value)
|
||||||
|
<< " | ";
|
||||||
|
break;
|
||||||
|
case XLS_RECORD_BOOL:
|
||||||
|
std::cout << std::setw(16) << std::get<bool>(cell->value) << " | ";
|
||||||
|
break;
|
||||||
|
case XLS_RECORD_BLANK:
|
||||||
|
std::cout << std::setw(16) << " | ";
|
||||||
|
break;
|
||||||
|
case XLS_RECORD_ERROR:
|
||||||
|
std::cout << "error"
|
||||||
|
<< "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
BIN
contrib/libxls/files/t1.xls
Normal file
BIN
contrib/libxls/files/t1.xls
Normal file
Binary file not shown.
BIN
contrib/libxls/files/t2.xls
Normal file
BIN
contrib/libxls/files/t2.xls
Normal file
Binary file not shown.
BIN
contrib/libxls/files/t3.xls
Normal file
BIN
contrib/libxls/files/t3.xls
Normal file
Binary file not shown.
48
contrib/libxls/sandboxed.h
Normal file
48
contrib/libxls/sandboxed.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// 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_LIBXLS_SANDBOXED_H_
|
||||||
|
#define CONTRIB_LIBXLS_SANDBOXED_H_
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "sapi_libxls.sapi.h" // NOLINT(build/include)
|
||||||
|
|
||||||
|
class LibxlsSapiSandbox : public LibxlsSandbox {
|
||||||
|
public:
|
||||||
|
explicit LibxlsSapiSandbox(std::string filename)
|
||||||
|
: filename_(std::move(filename)) {}
|
||||||
|
|
||||||
|
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
|
||||||
|
sandbox2::PolicyBuilder*) override {
|
||||||
|
return sandbox2::PolicyBuilder()
|
||||||
|
.AllowDynamicStartup()
|
||||||
|
.AllowOpen()
|
||||||
|
.AllowRead()
|
||||||
|
.AllowWrite()
|
||||||
|
.AllowSystemMalloc()
|
||||||
|
.AllowExit()
|
||||||
|
.AllowSyscall(__NR_recvmsg)
|
||||||
|
.AddFile(filename_)
|
||||||
|
.BuildOrDie();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string filename_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTRIB_LIBXLS_SANDBOXED_H_
|
28
contrib/libxls/test/CMakeLists.txt
Normal file
28
contrib/libxls/test/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.
|
||||||
|
|
||||||
|
include(GoogleTest)
|
||||||
|
|
||||||
|
add_executable(sapi_libxls_test
|
||||||
|
libxls_test.cc
|
||||||
|
../utils/utils_libxls.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(sapi_libxls_test
|
||||||
|
PRIVATE sapi_libxls
|
||||||
|
sapi::temp_file
|
||||||
|
sapi::test_main
|
||||||
|
)
|
||||||
|
|
||||||
|
gtest_discover_tests(sapi_libxls_test PROPERTIES ENVIRONMENT "TEST_FILES_DIR=${PROJECT_SOURCE_DIR}/files")
|
143
contrib/libxls/test/libxls_test.cc
Normal file
143
contrib/libxls/test/libxls_test.cc
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
// 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/libxls/sandboxed.h"
|
||||||
|
#include "contrib/libxls/utils/utils_libxls.h"
|
||||||
|
#undef FILE // TODO(cblichmann): Artifact from generated header
|
||||||
|
|
||||||
|
#include "sandboxed_api/util/path.h"
|
||||||
|
#include "sandboxed_api/util/status_matchers.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::sapi::IsOk;
|
||||||
|
using ::testing::Not;
|
||||||
|
|
||||||
|
struct Sheet {
|
||||||
|
int count_row;
|
||||||
|
int count_col;
|
||||||
|
double values[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct TestCase {
|
||||||
|
std::string filename;
|
||||||
|
size_t sheet_count;
|
||||||
|
struct Sheet sheet[2];
|
||||||
|
} kTestData[] = {
|
||||||
|
{
|
||||||
|
.filename = "t1.xls",
|
||||||
|
.sheet_count = 1,
|
||||||
|
.sheet =
|
||||||
|
{
|
||||||
|
{.count_row = 4,
|
||||||
|
.count_col = 2,
|
||||||
|
.values =
|
||||||
|
{
|
||||||
|
{1, 2, 0, 0},
|
||||||
|
{3, 4, 0, 0},
|
||||||
|
{5, 6, 0, 0},
|
||||||
|
{7, 8, 0, 0},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.filename = "t2.xls",
|
||||||
|
.sheet_count = 2,
|
||||||
|
.sheet =
|
||||||
|
{
|
||||||
|
{.count_row = 2,
|
||||||
|
.count_col = 3,
|
||||||
|
.values =
|
||||||
|
{
|
||||||
|
{1, 2, 3, 0},
|
||||||
|
{4, 5, 6, 0},
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
}},
|
||||||
|
{.count_row = 2,
|
||||||
|
.count_col = 2,
|
||||||
|
.values =
|
||||||
|
{
|
||||||
|
{9, 8, 0, 0},
|
||||||
|
{7, 6, 0, 0},
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibXlsBase : public testing::Test {
|
||||||
|
protected:
|
||||||
|
std::string GetTestFilePath(const std::string& filename) {
|
||||||
|
return sapi::file::JoinPath(test_dir_, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() override;
|
||||||
|
|
||||||
|
const char* test_dir_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibXlsTestFiles : public LibXlsBase,
|
||||||
|
public testing::WithParamInterface<TestCase> {};
|
||||||
|
|
||||||
|
void LibXlsBase::SetUp() {
|
||||||
|
test_dir_ = getenv("TEST_FILES_DIR");
|
||||||
|
ASSERT_NE(test_dir_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(LibXlsTestFiles, TestValues) {
|
||||||
|
const TestCase& tv = GetParam();
|
||||||
|
std::string test_file_path = GetTestFilePath(tv.filename);
|
||||||
|
|
||||||
|
LibxlsSapiSandbox sandbox(test_file_path);
|
||||||
|
SAPI_ASSERT_OK(sandbox.Init());
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsWorkbook wb,
|
||||||
|
LibXlsWorkbook::Open(&sandbox, test_file_path));
|
||||||
|
ASSERT_EQ(wb.GetSheetCount(), tv.sheet_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < tv.sheet_count; ++i) {
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsSheet sheet, wb.OpenSheet(i));
|
||||||
|
ASSERT_EQ(sheet.GetRowCount(), tv.sheet[i].count_row);
|
||||||
|
ASSERT_EQ(sheet.GetColCount(), tv.sheet[i].count_col);
|
||||||
|
for (size_t row = 0; row < sheet.GetRowCount(); ++row) {
|
||||||
|
for (size_t col = 0; col < sheet.GetColCount(); ++col) {
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsCell cell, sheet.GetCell(row, col));
|
||||||
|
ASSERT_EQ(cell.type, XLS_RECORD_NUMBER);
|
||||||
|
ASSERT_EQ(std::get<double>(cell.value), tv.sheet[i].values[row][col]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(LibXlsBase, LibXlsTestFiles,
|
||||||
|
testing::ValuesIn(kTestData));
|
||||||
|
|
||||||
|
TEST_F(LibXlsBase, TestFormula) {
|
||||||
|
std::string test_file_path = GetTestFilePath("t3.xls");
|
||||||
|
|
||||||
|
LibxlsSapiSandbox sandbox(test_file_path);
|
||||||
|
SAPI_ASSERT_OK(sandbox.Init());
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsWorkbook wb,
|
||||||
|
LibXlsWorkbook::Open(&sandbox, test_file_path));
|
||||||
|
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsSheet sheet, wb.OpenSheet(0));
|
||||||
|
SAPI_ASSERT_OK_AND_ASSIGN(LibXlsCell cell, sheet.GetCell(0, 0));
|
||||||
|
ASSERT_EQ(cell.type, XLS_RECORD_STRING);
|
||||||
|
ASSERT_EQ(std::get<std::string>(cell.value), "10.000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
162
contrib/libxls/utils/utils_libxls.cc
Normal file
162
contrib/libxls/utils/utils_libxls.cc
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
// 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/libxls/utils/utils_libxls.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "contrib/libxls/sandboxed.h"
|
||||||
|
|
||||||
|
absl::Status GetError(LibxlsApi* api, xls_error_t error_code) {
|
||||||
|
SAPI_ASSIGN_OR_RETURN(const char* c_errstr, api->xls_getError(error_code));
|
||||||
|
sapi::v::RemotePtr sapi_errstr(const_cast<char*>(c_errstr));
|
||||||
|
SAPI_ASSIGN_OR_RETURN(std::string errstr,
|
||||||
|
api->GetSandbox()->GetCString(sapi_errstr));
|
||||||
|
|
||||||
|
return absl::UnavailableError(errstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsWorkbook> LibXlsWorkbook::Open(LibxlsSapiSandbox* sandbox,
|
||||||
|
const std::string& filename,
|
||||||
|
const std::string& encode) {
|
||||||
|
if (sandbox == nullptr) {
|
||||||
|
return absl::InvalidArgumentError("Sandbox has to be defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
LibxlsApi api(sandbox);
|
||||||
|
|
||||||
|
sapi::v::IntBase<xls_error_t> sapi_error;
|
||||||
|
sapi::v::CStr sapi_filename(filename.c_str());
|
||||||
|
sapi::v::CStr sapi_encode(encode.c_str());
|
||||||
|
|
||||||
|
SAPI_ASSIGN_OR_RETURN(
|
||||||
|
xlsWorkBook * wb,
|
||||||
|
api.xls_open_file(sapi_filename.PtrBefore(), sapi_encode.PtrBefore(),
|
||||||
|
sapi_error.PtrAfter()));
|
||||||
|
|
||||||
|
if (wb == nullptr) {
|
||||||
|
return GetError(&api, sapi_error.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::v::Struct<xlsWorkBook> sapi_wb;
|
||||||
|
sapi_wb.SetRemote(wb);
|
||||||
|
SAPI_RETURN_IF_ERROR(sandbox->TransferFromSandboxee(&sapi_wb));
|
||||||
|
|
||||||
|
return LibXlsWorkbook(sandbox, wb, sapi_wb.data().sheets.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
LibXlsWorkbook::~LibXlsWorkbook() {
|
||||||
|
if (rwb_ != nullptr) {
|
||||||
|
sapi::v::RemotePtr sapi_rwb(rwb_);
|
||||||
|
LibxlsApi api(sandbox_);
|
||||||
|
api.xls_close_WB(&sapi_rwb).IgnoreError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LibXlsWorkbook::GetSheetCount() { return sheet_count_; }
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsSheet> LibXlsWorkbook::OpenSheet(uint32_t index) {
|
||||||
|
if (GetSheetCount() <= index) {
|
||||||
|
return absl::OutOfRangeError("Index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
LibxlsApi api(sandbox_);
|
||||||
|
sapi::v::RemotePtr sapi_rwb(rwb_);
|
||||||
|
SAPI_ASSIGN_OR_RETURN(xlsWorkSheet * ws,
|
||||||
|
api.xls_getWorkSheet(&sapi_rwb, index));
|
||||||
|
if (ws == nullptr) {
|
||||||
|
return absl::UnavailableError("Unable to open sheet");
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::v::Struct<xlsWorkSheet> sapi_ws;
|
||||||
|
sapi_ws.SetRemote(ws);
|
||||||
|
SAPI_ASSIGN_OR_RETURN(xls_error_t error_code,
|
||||||
|
api.xls_parseWorkSheet(sapi_ws.PtrAfter()));
|
||||||
|
if (error_code != 0) {
|
||||||
|
return GetError(&api, error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LibXlsSheet(sandbox_, ws, sapi_ws.data().rows.lastrow + 1,
|
||||||
|
sapi_ws.data().rows.lastcol + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LibXlsSheet::GetRowCount() const { return row_; }
|
||||||
|
|
||||||
|
size_t LibXlsSheet::GetColCount() const { return col_; }
|
||||||
|
|
||||||
|
absl::StatusOr<std::string> LibXlsSheet::GetStr(
|
||||||
|
const sapi::v::Struct<xlsCell>& sapi_cell) {
|
||||||
|
if (sapi_cell.data().str == nullptr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
sapi::v::RemotePtr sapi_str(sapi_cell.data().str);
|
||||||
|
return sandbox_->GetCString(sapi_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsCell> LibXlsSheet::GetNewCell(
|
||||||
|
const sapi::v::Struct<xlsCell>& sapi_cell) {
|
||||||
|
int id = sapi_cell.data().id;
|
||||||
|
double d = sapi_cell.data().d;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case XLS_RECORD_RK:
|
||||||
|
case XLS_RECORD_MULRK:
|
||||||
|
case XLS_RECORD_NUMBER:
|
||||||
|
return LibXlsCell{XLS_RECORD_NUMBER, d};
|
||||||
|
case XLS_RECORD_BLANK:
|
||||||
|
return LibXlsCell{XLS_RECORD_BLANK, 0.0};
|
||||||
|
case XLS_RECORD_FORMULA:
|
||||||
|
SAPI_ASSIGN_OR_RETURN(std::string cell_str, GetStr(sapi_cell));
|
||||||
|
if (cell_str == "bool") {
|
||||||
|
return LibXlsCell{XLS_RECORD_BOOL, d > 0};
|
||||||
|
} else if (cell_str == "error") {
|
||||||
|
return LibXlsCell{XLS_RECORD_ERROR, cell_str};
|
||||||
|
}
|
||||||
|
return LibXlsCell{XLS_RECORD_STRING, cell_str};
|
||||||
|
}
|
||||||
|
|
||||||
|
return absl::UnavailableError("Unknown type");
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<LibXlsCell> LibXlsSheet::GetCell(uint32_t row, uint32_t col) {
|
||||||
|
if (row >= GetRowCount()) {
|
||||||
|
return absl::OutOfRangeError("Row out of range");
|
||||||
|
}
|
||||||
|
if (col >= GetColCount()) {
|
||||||
|
return absl::OutOfRangeError("Col out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
LibxlsApi api(sandbox_);
|
||||||
|
sapi::v::RemotePtr sapi_rws(rws_);
|
||||||
|
SAPI_ASSIGN_OR_RETURN(xlsCell * cell, api.xls_cell(&sapi_rws, row, col));
|
||||||
|
if (cell == nullptr) {
|
||||||
|
return absl::UnavailableError("Unable to get cell");
|
||||||
|
}
|
||||||
|
sapi::v::Struct<xlsCell> sapi_cell;
|
||||||
|
sapi_cell.SetRemote(cell);
|
||||||
|
SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&sapi_cell));
|
||||||
|
|
||||||
|
return GetNewCell(sapi_cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
LibXlsSheet::~LibXlsSheet() {
|
||||||
|
if (rws_ != nullptr) {
|
||||||
|
LibxlsApi api(sandbox_);
|
||||||
|
sapi::v::RemotePtr sapi_rws(rws_);
|
||||||
|
api.xls_close_WS(&sapi_rws).IgnoreError();
|
||||||
|
}
|
||||||
|
}
|
110
contrib/libxls/utils/utils_libxls.h
Normal file
110
contrib/libxls/utils/utils_libxls.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
// 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_LIBXLS_UTILS_UTILS_LIBXLS_H_
|
||||||
|
#define CONTRIB_LIBXLS_UTILS_UTILS_LIBXLS_H_
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "contrib/libxls/sandboxed.h"
|
||||||
|
|
||||||
|
#define XLS_RECORD_FORMULA 0x0006
|
||||||
|
#define XLS_RECORD_MULRK 0x00BD
|
||||||
|
#define XLS_RECORD_BLANK 0x0201
|
||||||
|
#define XLS_RECORD_NUMBER 0x0203
|
||||||
|
#define XLS_RECORD_STRING 0x0207
|
||||||
|
#define XLS_RECORD_RK 0x027E
|
||||||
|
#define XLS_RECORD_BOOL 0x9998
|
||||||
|
#define XLS_RECORD_ERROR 0x9999
|
||||||
|
|
||||||
|
struct LibXlsCell {
|
||||||
|
int type;
|
||||||
|
std::variant<double, bool, std::string> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibXlsSheet {
|
||||||
|
public:
|
||||||
|
size_t GetRowCount() const;
|
||||||
|
size_t GetColCount() const;
|
||||||
|
absl::StatusOr<LibXlsCell> GetCell(uint32_t row, uint32_t col);
|
||||||
|
|
||||||
|
~LibXlsSheet();
|
||||||
|
|
||||||
|
LibXlsSheet(LibXlsSheet&& other) { *this = std::move(other); }
|
||||||
|
|
||||||
|
LibXlsSheet& operator=(LibXlsSheet&& other) {
|
||||||
|
using std::swap;
|
||||||
|
|
||||||
|
if (this != &other) {
|
||||||
|
swap(sandbox_, other.sandbox_);
|
||||||
|
swap(rws_, other.rws_);
|
||||||
|
swap(row_, other.row_);
|
||||||
|
swap(col_, other.col_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class LibXlsWorkbook;
|
||||||
|
|
||||||
|
LibXlsSheet(LibxlsSapiSandbox* sandbox, xlsWorkSheet* rws, size_t row,
|
||||||
|
size_t col)
|
||||||
|
: sandbox_(CHECK_NOTNULL(sandbox)), rws_(rws), row_(row), col_(col) {}
|
||||||
|
|
||||||
|
absl::StatusOr<std::string> GetStr(const sapi::v::Struct<xlsCell>& sapi_cell);
|
||||||
|
absl::StatusOr<LibXlsCell> GetNewCell(
|
||||||
|
const sapi::v::Struct<xlsCell>& sapi_cell);
|
||||||
|
|
||||||
|
LibxlsSapiSandbox* sandbox_;
|
||||||
|
xlsWorkSheet* rws_ = nullptr;
|
||||||
|
size_t row_;
|
||||||
|
size_t col_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LibXlsWorkbook {
|
||||||
|
public:
|
||||||
|
static absl::StatusOr<LibXlsWorkbook> Open(
|
||||||
|
LibxlsSapiSandbox* sandbox, const std::string& filename,
|
||||||
|
const std::string& encode = "UTF-8");
|
||||||
|
|
||||||
|
size_t GetSheetCount();
|
||||||
|
absl::StatusOr<LibXlsSheet> OpenSheet(uint32_t index);
|
||||||
|
|
||||||
|
~LibXlsWorkbook();
|
||||||
|
|
||||||
|
LibXlsWorkbook(LibXlsWorkbook&& other) { *this = std::move(other); }
|
||||||
|
|
||||||
|
LibXlsWorkbook& operator=(LibXlsWorkbook&& other) {
|
||||||
|
using std::swap;
|
||||||
|
|
||||||
|
if (this != &other) {
|
||||||
|
swap(sandbox_, other.sandbox_);
|
||||||
|
swap(rwb_, other.rwb_);
|
||||||
|
swap(sheet_count_, other.sheet_count_);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
LibXlsWorkbook(LibxlsSapiSandbox* sandbox, xlsWorkBook* rwb, size_t count)
|
||||||
|
: sandbox_(CHECK_NOTNULL(sandbox)),
|
||||||
|
rwb_(CHECK_NOTNULL(rwb)),
|
||||||
|
sheet_count_(count) {}
|
||||||
|
|
||||||
|
LibxlsSapiSandbox* sandbox_;
|
||||||
|
xlsWorkBook* rwb_ = nullptr;
|
||||||
|
size_t sheet_count_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTRIB_LIBXLS_UTILS_UTILS_LIBXLS_H_
|
27
contrib/libxls/xls.gen.h.in
Normal file
27
contrib/libxls/xls.gen.h.in
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// 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_LIBXLS_XLS_GEN_H_
|
||||||
|
#define CONTRIB_LIBXLS_XLS_GEN_H_
|
||||||
|
|
||||||
|
// Workaround for libclang based interface generator
|
||||||
|
#define FILE void
|
||||||
|
#undef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#include "${libxls_SOURCE_DIR}/include/xls.h"
|
||||||
|
}
|
||||||
|
#define __cplusplus
|
||||||
|
#undef FILE
|
||||||
|
|
||||||
|
#endif // CONTRIB_LIBXLS_XLS_GEN_H_
|
Loading…
Reference in New Issue
Block a user