Skip to content

Commit

Permalink
read encrypted xlsx files
Browse files Browse the repository at this point in the history
  • Loading branch information
JanMarvin committed Jul 15, 2023
1 parent f9163e4 commit f1562e0
Show file tree
Hide file tree
Showing 30 changed files with 9,536 additions and 2 deletions.
2 changes: 2 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ Roxygen: list(markdown = TRUE)
Config/testthat/edition: 3
Config/testthat/parallel: false
Config/testthat/start-first: aaa
SystemRequirements: C++20, libarchive: libarchive-dev (deb),
libarchive-devel (rpm), libarchive (homebrew), libarchive_dev (csw)
4 changes: 4 additions & 0 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

read_encryption <- function(PATH, OUT, PASSWORD) {
invisible(.Call(`_openxlsx2_read_encryption`, PATH, OUT, PASSWORD))
}

#' Check if path is to long to be an R file path
#' @param path the file path used in file.exists()
#' @noRd
Expand Down
8 changes: 8 additions & 0 deletions R/wb_load.R
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ wb_load <- function(
stop("File does not exist.")
}

pwd <- list(...)$password

if (!is.null(pwd)) {
unencrypted_xlsx <- temp_xlsx()
read_encryption(PATH = path.expand(file), OUT = unencrypted_xlsx, PASSWORD = pwd)
file <- unencrypted_xlsx
}

## create temp dir
xmlDir <- temp_dir("_openxlsx_wb_load")

Expand Down
78 changes: 78 additions & 0 deletions configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Anticonf (tm) script by Jeroen Ooms, Jim Hester (2017)
# This script will query 'pkg-config' for the required cflags and ldflags.
# If pkg-config is unavailable or does not find the library, try setting
# INCLUDE_DIR and LIB_DIR manually via e.g:
# R CMD INSTALL --configure-vars='INCLUDE_DIR=/.../include LIB_DIR=/.../lib'

# Library settings
PKG_CONFIG_NAME="libarchive"
PKG_DEB_NAME="libarchive-dev"
PKG_RPM_NAME="libarchive-devel"
PKG_CSW_NAME="libarchive_dev"
PKG_BREW_NAME="libarchive"
PKG_TEST_HEADER="<archive.h>"
PKG_LIBS=-larchive

# Use pkg-config if available
pkg-config ${PKG_CONFIG_NAME} --atleast-version=1.0 2>/dev/null
if [ $? -eq 0 ]; then
PKGCONFIG_CFLAGS=`pkg-config --cflags ${PKG_CONFIG_NAME}`
PKGCONFIG_LIBS=`pkg-config --libs ${PKG_CONFIG_NAME}`
fi

# Note that cflags may be empty in case of success
if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]; then
echo "Found INCLUDE_DIR and/or LIB_DIR!"
PKG_CFLAGS="-I$INCLUDE_DIR $PKG_CFLAGS"
PKG_LIBS="-L$LIB_DIR $PKG_LIBS"
elif [ "$PKGCONFIG_CFLAGS" ] || [ "$PKGCONFIG_LIBS" ]; then
echo "Found pkg-config cflags and libs!"
PKG_CFLAGS=${PKGCONFIG_CFLAGS}
PKG_LIBS=${PKGCONFIG_LIBS}
elif [ `uname` = "Darwin" ]; then
test ! "$CI" && brew --version 2>/dev/null
if [ $? -eq 0 ]; then
BREWDIR=`brew --prefix`
PKG_CFLAGS="-I$BREWDIR/opt/libarchive/include"
PKG_LIBS="-L$BREWDIR/opt/libarchive/lib $PKG_LIBS"
else
curl -sfL "https://autobrew.github.io/scripts/$PKG_BREW_NAME" > autobrew
. ./autobrew
fi
fi

# Find compiler
CXX20=`${R_HOME}/bin/R CMD config CXX20`
CXX20FLAGS=`${R_HOME}/bin/R CMD config CXX20FLAGS`
CPPFLAGS=`${R_HOME}/bin/R CMD config CPPFLAGS`

# For debugging
echo "PKG_CFLAGS=$PKG_CFLAGS"
echo "PKG_LIBS=$PKG_LIBS"

# Test configuration
echo "#include $PKG_TEST_HEADER" | ${CXX20} ${CPPFLAGS} ${PKG_CFLAGS} ${CXX20FLAGS} -E -xc++ - > /dev/null

# Customize the error
if [ $? -ne 0 ]; then
echo "--------------------------- [ANTICONF] --------------------------------"
echo "Configuration failed because $PKG_CONFIG_NAME was not found. Try installing:"
echo " * deb: $PKG_DEB_NAME (Debian, Ubuntu, etc)"
echo " * rpm: $PKG_RPM_NAME (Fedora, CentOS, RHEL)"
echo " * csw: $PKG_CSW_NAME (Solaris)"
echo " * brew: $PKG_BREW_NAME (Mac OSX)"
echo "If $PKG_CONFIG_NAME is already installed, check that 'pkg-config' is in your"
echo "PATH and PKG_CONFIG_PATH contains a $PKG_CONFIG_NAME.pc file. If pkg-config"
echo "is unavailable you can set INCLUDE_DIR and LIB_DIR manually via:"
echo "R CMD INSTALL --configure-vars='INCLUDE_DIR=... LIB_DIR=...'"
echo "-------------------------- [ERROR MESSAGE] ---------------------------"
cat configure.log
echo "--------------------------------------------------------------------"
exit 1
fi

# Write to Makevars
sed -e "s|@PKG_CXXFLAGS@|$PKG_CFLAGS|" -e "s|@PKG_LIBS@|$PKG_LIBS|" src/Makevars.in > src/Makevars

# Success
exit 0
43 changes: 42 additions & 1 deletion src/Makevars
Original file line number Diff line number Diff line change
@@ -1 +1,42 @@
PKG_CPPFLAGS = -I. -I../inst/include/pugixml

#PKG_CPPFLAGS = -I. -I../inst/include/pugixml -Ixlcpp -DXLCPP_EXPORT
PKG_CXXFLAGS = -I. -Ixlcpp -I../inst/include/pugixml -DXLCPP_EXPORT

#PKG_LIBS=-Lpugixml -Lcfbf -L/usr/lib -larchive -L/usr/lib -lfmt
PKG_LIBS = -larchive -Lpugixml -Lxlcpp -lfmt

PKGROOT = ./xlcpp

OBJECTS = decrypt.o \
helper_functions.o \
load_workbook.o \
pugi.o \
strings_xml.o \
styles_xml.o \
write_file.o \
$(PKGROOT)/aes.o \
$(PKGROOT)/b64.o \
$(PKGROOT)/cfbf.o \
$(PKGROOT)/mmap.o \
$(PKGROOT)/sha1.o \
$(PKGROOT)/sha512.o \
$(PKGROOT)/xlcpp.o \
$(PKGROOT)/xlsb.o \
$(PKGROOT)/xml-reader.o \
$(PKGROOT)/xml-writer.o \
RcppExports.o

XLCPP = $(PKGROOT)/aes.cpp \
$(PKGROOT)/b64.cpp \
$(PKGROOT)/cfbf.cpp \
$(PKGROOT)/mmap.cpp \
$(PKGROOT)/sha1.cpp \
$(PKGROOT)/sha512.cpp \
$(PKGROOT)/xml-reader.cpp \
$(PKGROOT)/xml-writer.cpp \
$(PKGROOT)/xlcpp.cpp \
$(PKGROOT)/xlsb.cpp

PUGIXML = ../inst/include/pugixml/pugixml.cpp

# CXX_STD=CXX20
42 changes: 42 additions & 0 deletions src/Makevars.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

#PKG_CPPFLAGS = -I. -I../inst/include/pugixml -Ixlcpp -DXLCPP_EXPORT
PKG_CXXFLAGS = @PKG_CXXFLAGS@ -I. -Ixlcpp -I../inst/include/pugixml -DXLCPP_EXPORT

#PKG_LIBS=-Lpugixml -Lcfbf -L/usr/lib -larchive -L/usr/lib -lfmt
PKG_LIBS = @PKG_LIBS@ -Lpugixml -Lxlcpp -lfmt

PKGROOT = ./xlcpp

OBJECTS = decrypt.o \
helper_functions.o \
load_workbook.o \
pugi.o \
strings_xml.o \
styles_xml.o \
write_file.o \
$(PKGROOT)/aes.o \
$(PKGROOT)/b64.o \
$(PKGROOT)/cfbf.o \
$(PKGROOT)/mmap.o \
$(PKGROOT)/sha1.o \
$(PKGROOT)/sha512.o \
$(PKGROOT)/xlcpp.o \
$(PKGROOT)/xlsb.o \
$(PKGROOT)/xml-reader.o \
$(PKGROOT)/xml-writer.o \
RcppExports.o

XLCPP = $(PKGROOT)/aes.cpp \
$(PKGROOT)/b64.cpp \
$(PKGROOT)/cfbf.cpp \
$(PKGROOT)/mmap.cpp \
$(PKGROOT)/sha1.cpp \
$(PKGROOT)/sha512.cpp \
$(PKGROOT)/xml-reader.cpp \
$(PKGROOT)/xml-writer.cpp \
$(PKGROOT)/xlcpp.cpp \
$(PKGROOT)/xlsb.cpp

PUGIXML = ../inst/include/pugixml/pugixml.cpp

# CXX_STD=CXX20
13 changes: 13 additions & 0 deletions src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ Rcpp::Rostream<true>& Rcpp::Rcout = Rcpp::Rcpp_cout_get();
Rcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();
#endif

// read_encryption
void read_encryption(std::string PATH, std::string OUT, std::string PASSWORD);
RcppExport SEXP _openxlsx2_read_encryption(SEXP PATHSEXP, SEXP OUTSEXP, SEXP PASSWORDSEXP) {
BEGIN_RCPP
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::string >::type PATH(PATHSEXP);
Rcpp::traits::input_parameter< std::string >::type OUT(OUTSEXP);
Rcpp::traits::input_parameter< std::string >::type PASSWORD(PASSWORDSEXP);
read_encryption(PATH, OUT, PASSWORD);
return R_NilValue;
END_RCPP
}
// to_long
bool to_long(std::string path);
RcppExport SEXP _openxlsx2_to_long(SEXP pathSEXP) {
Expand Down Expand Up @@ -842,6 +854,7 @@ END_RCPP
}

static const R_CallMethodDef CallEntries[] = {
{"_openxlsx2_read_encryption", (DL_FUNC) &_openxlsx2_read_encryption, 3},
{"_openxlsx2_to_long", (DL_FUNC) &_openxlsx2_to_long, 1},
{"_openxlsx2_openxlsx2_type", (DL_FUNC) &_openxlsx2_openxlsx2_type, 1},
{"_openxlsx2_int_to_col", (DL_FUNC) &_openxlsx2_int_to_col, 1},
Expand Down
12 changes: 12 additions & 0 deletions src/decrypt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <xlcpp/xlcpp.h>

// [[Rcpp::export]]
void read_encryption(std::string PATH, std::string OUT, std::string PASSWORD) {

const std::filesystem::path path = PATH;

xlcpp::workbook wb(path, PASSWORD, OUT);

// this creates xlcpp workbook, not the unzipped xlsx file
// wb.save(OUT);
}
Loading

0 comments on commit f1562e0

Please sign in to comment.