1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "contrib/libxls/utils/utils_libxls.h"
16
17 #include <fstream>
18 #include <iostream>
19 #include <string>
20
21 #include "contrib/libxls/sandboxed.h"
22
GetError(LibxlsApi * api,xls_error_t error_code)23 absl::Status GetError(LibxlsApi* api, xls_error_t error_code) {
24 SAPI_ASSIGN_OR_RETURN(const char* c_errstr, api->xls_getError(error_code));
25 sapi::v::RemotePtr sapi_errstr(const_cast<char*>(c_errstr));
26 SAPI_ASSIGN_OR_RETURN(std::string errstr,
27 api->GetSandbox()->GetCString(sapi_errstr));
28
29 return absl::UnavailableError(errstr);
30 }
31
Open(LibxlsSapiSandbox * sandbox,const std::string & filename,const std::string & encode)32 absl::StatusOr<LibXlsWorkbook> LibXlsWorkbook::Open(LibxlsSapiSandbox* sandbox,
33 const std::string& filename,
34 const std::string& encode) {
35 if (sandbox == nullptr) {
36 return absl::InvalidArgumentError("Sandbox has to be defined");
37 }
38
39 LibxlsApi api(sandbox);
40
41 sapi::v::IntBase<xls_error_t> sapi_error;
42 sapi::v::CStr sapi_filename(filename.c_str());
43 sapi::v::CStr sapi_encode(encode.c_str());
44
45 SAPI_ASSIGN_OR_RETURN(
46 xlsWorkBook * wb,
47 api.xls_open_file(sapi_filename.PtrBefore(), sapi_encode.PtrBefore(),
48 sapi_error.PtrAfter()));
49
50 if (wb == nullptr) {
51 return GetError(&api, sapi_error.GetValue());
52 }
53
54 sapi::v::Struct<xlsWorkBook> sapi_wb;
55 sapi_wb.SetRemote(wb);
56 SAPI_RETURN_IF_ERROR(sandbox->TransferFromSandboxee(&sapi_wb));
57
58 return LibXlsWorkbook(sandbox, wb, sapi_wb.data().sheets.count);
59 }
60
~LibXlsWorkbook()61 LibXlsWorkbook::~LibXlsWorkbook() {
62 if (rwb_ != nullptr) {
63 sapi::v::RemotePtr sapi_rwb(rwb_);
64 LibxlsApi api(sandbox_);
65 api.xls_close_WB(&sapi_rwb).IgnoreError();
66 }
67 }
68
GetSheetCount()69 size_t LibXlsWorkbook::GetSheetCount() { return sheet_count_; }
70
OpenSheet(uint32_t index)71 absl::StatusOr<LibXlsSheet> LibXlsWorkbook::OpenSheet(uint32_t index) {
72 if (GetSheetCount() <= index) {
73 return absl::OutOfRangeError("Index out of range");
74 }
75
76 LibxlsApi api(sandbox_);
77 sapi::v::RemotePtr sapi_rwb(rwb_);
78 SAPI_ASSIGN_OR_RETURN(xlsWorkSheet * ws,
79 api.xls_getWorkSheet(&sapi_rwb, index));
80 if (ws == nullptr) {
81 return absl::UnavailableError("Unable to open sheet");
82 }
83
84 sapi::v::Struct<xlsWorkSheet> sapi_ws;
85 sapi_ws.SetRemote(ws);
86 SAPI_ASSIGN_OR_RETURN(xls_error_t error_code,
87 api.xls_parseWorkSheet(sapi_ws.PtrAfter()));
88 if (error_code != 0) {
89 return GetError(&api, error_code);
90 }
91
92 return LibXlsSheet(sandbox_, ws, sapi_ws.data().rows.lastrow + 1,
93 sapi_ws.data().rows.lastcol + 1);
94 }
95
GetRowCount() const96 size_t LibXlsSheet::GetRowCount() const { return row_; }
97
GetColCount() const98 size_t LibXlsSheet::GetColCount() const { return col_; }
99
GetStr(const sapi::v::Struct<xlsCell> & sapi_cell)100 absl::StatusOr<std::string> LibXlsSheet::GetStr(
101 const sapi::v::Struct<xlsCell>& sapi_cell) {
102 if (sapi_cell.data().str == nullptr) {
103 return "";
104 }
105
106 sapi::v::RemotePtr sapi_str(sapi_cell.data().str);
107 return sandbox_->GetCString(sapi_str);
108 }
109
GetNewCell(const sapi::v::Struct<xlsCell> & sapi_cell)110 absl::StatusOr<LibXlsCell> LibXlsSheet::GetNewCell(
111 const sapi::v::Struct<xlsCell>& sapi_cell) {
112 int id = sapi_cell.data().id;
113 double d = sapi_cell.data().d;
114
115 switch (id) {
116 case XLS_RECORD_RK:
117 case XLS_RECORD_MULRK:
118 case XLS_RECORD_NUMBER:
119 return LibXlsCell{XLS_RECORD_NUMBER, d};
120 case XLS_RECORD_BLANK:
121 return LibXlsCell{XLS_RECORD_BLANK, 0.0};
122 case XLS_RECORD_FORMULA:
123 SAPI_ASSIGN_OR_RETURN(std::string cell_str, GetStr(sapi_cell));
124 if (cell_str == "bool") {
125 return LibXlsCell{XLS_RECORD_BOOL, d > 0};
126 } else if (cell_str == "error") {
127 return LibXlsCell{XLS_RECORD_ERROR, cell_str};
128 }
129 return LibXlsCell{XLS_RECORD_STRING, cell_str};
130 }
131
132 return absl::UnavailableError("Unknown type");
133 }
134
GetCell(uint32_t row,uint32_t col)135 absl::StatusOr<LibXlsCell> LibXlsSheet::GetCell(uint32_t row, uint32_t col) {
136 if (row >= GetRowCount()) {
137 return absl::OutOfRangeError("Row out of range");
138 }
139 if (col >= GetColCount()) {
140 return absl::OutOfRangeError("Col out of range");
141 }
142
143 LibxlsApi api(sandbox_);
144 sapi::v::RemotePtr sapi_rws(rws_);
145 SAPI_ASSIGN_OR_RETURN(xlsCell * cell, api.xls_cell(&sapi_rws, row, col));
146 if (cell == nullptr) {
147 return absl::UnavailableError("Unable to get cell");
148 }
149 sapi::v::Struct<xlsCell> sapi_cell;
150 sapi_cell.SetRemote(cell);
151 SAPI_RETURN_IF_ERROR(sandbox_->TransferFromSandboxee(&sapi_cell));
152
153 return GetNewCell(sapi_cell);
154 }
155
~LibXlsSheet()156 LibXlsSheet::~LibXlsSheet() {
157 if (rws_ != nullptr) {
158 LibxlsApi api(sandbox_);
159 sapi::v::RemotePtr sapi_rws(rws_);
160 api.xls_close_WS(&sapi_rws).IgnoreError();
161 }
162 }
163