Skip to content

Commit 6da7d16

Browse files
committed
Optimize Base64 writing and and some error handling
Signed-off-by: Raul Metsma <[email protected]>
1 parent 721894a commit 6da7d16

File tree

7 files changed

+67
-83
lines changed

7 files changed

+67
-83
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
container: ubuntu:${{ matrix.container }}
1515
strategy:
1616
matrix:
17-
container: ['22.04', '24.04', '24.10', '25.04']
17+
container: ['22.04', '24.04', '25.04']
1818
arch: ['amd64', 'arm64']
1919
env:
2020
DEBIAN_FRONTEND: noninteractive
@@ -59,7 +59,7 @@ jobs:
5959
- name: Prepare vcpkg
6060
uses: lukka/run-vcpkg@v11
6161
with:
62-
vcpkgGitCommitId: 4008642a50a01a7115c2406b04d5273898e7fe1c
62+
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
6363
vcpkgJsonGlob: ./vcpkg.json
6464
runVcpkgInstall: true
6565
env:
@@ -94,14 +94,12 @@ jobs:
9494
- name: Install dependencies
9595
run: |
9696
brew update
97-
brew install --formula flatbuffers swig doxygen boost [email protected]
98-
brew unlink [email protected] || true
99-
brew unlink [email protected] || true
97+
brew install --formula flatbuffers swig doxygen boost
10098
- name: Prepare vcpkg
10199
if: matrix.target != 'macos'
102100
uses: lukka/run-vcpkg@v11
103101
with:
104-
vcpkgGitCommitId: 4008642a50a01a7115c2406b04d5273898e7fe1c
102+
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
105103
vcpkgJsonGlob: ./vcpkg.json
106104
runVcpkgInstall: true
107105
env:
@@ -125,7 +123,7 @@ jobs:
125123
runs-on: ${{ matrix.image }}
126124
strategy:
127125
matrix:
128-
image: [windows-2022]
126+
image: [windows-2025]
129127
platform: [x64, arm64]
130128
env:
131129
CXXFLAGS: '/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR' # https://github.com/actions/runner-images/issues/10004
@@ -137,17 +135,14 @@ jobs:
137135
- name: Prepare vcpkg
138136
uses: lukka/run-vcpkg@v11
139137
with:
140-
vcpkgGitCommitId: 4008642a50a01a7115c2406b04d5273898e7fe1c
138+
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
141139
vcpkgJsonGlob: ./vcpkg.json
142140
runVcpkgInstall: true
143141
runVcpkgFormatString: "[`install`, `--recurse`, `--clean-after-build`, `--x-install-root`, `$[env.VCPKG_INSTALLED_DIR]`, `--triplet`, `$[env.VCPKG_DEFAULT_TRIPLET]`, `--x-feature`, `tests`]"
144142
env:
145143
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/vcpkg_installed
146144
- name: Install dependencies
147-
run: |
148-
choco install doxygen.install -y > $null
149-
Invoke-WebRequest -UserAgent "Wget" "https://sourceforge.net/projects/swig/files/swigwin/swigwin-4.3.0/swigwin-4.3.0.zip/download" -OutFile swig.zip
150-
tar xf swig.zip
145+
run: winget install --silent --accept-source-agreements --accept-package-agreements swig doxygen
151146
- uses: actions/setup-java@v4
152147
with:
153148
distribution: 'temurin'
@@ -156,7 +151,7 @@ jobs:
156151
run: |
157152
cmake -A ${{ matrix.platform }} -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo `
158153
"-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}/scripts/buildsystems/vcpkg.cmake" `
159-
"-DSWIG_EXECUTABLE=${{ github.workspace }}/swigwin-4.3.0/swig.exe" `
154+
-DSWIG_EXECUTABLE=(Get-Item $env:LOCALAPPDATA\Microsoft\WinGet\Links\swig.exe).Target `
160155
-DVCPKG_TARGET_TRIPLET=${{ env.VCPKG_DEFAULT_TRIPLET }} `
161156
-DVCPKG_MANIFEST_FEATURES=tests `
162157
-DCMAKE_INSTALL_LIBDIR=bin

cdoc/Crypto.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ Crypto::hkdf(const std::vector<uint8_t> &key, const std::vector<uint8_t> &salt,
407407
SSL_FAILED(EVP_PKEY_CTX_hkdf_mode(ctx.get(), mode), "EVP_PKEY_CTX_hkdf_mode") ||
408408
SSL_FAILED(EVP_PKEY_CTX_set_hkdf_md(ctx.get(), EVP_sha256()), "EVP_PKEY_CTX_set_hkdf_md") ||
409409
SSL_FAILED(EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), key.data(), int(key.size())), "EVP_PKEY_CTX_set1_hkdf_key") ||
410-
SSL_FAILED(EVP_PKEY_CTX_set1_hkdf_salt(ctx.get(), salt.data(), int(salt.size())), "EVP_PKEY_CTX_set1_hkdf_salt") ||
411-
SSL_FAILED(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data(), int(info.size())), "EVP_PKEY_CTX_add1_hkdf_info") ||
410+
(!salt.empty() && SSL_FAILED(EVP_PKEY_CTX_set1_hkdf_salt(ctx.get(), salt.data(), int(salt.size())), "EVP_PKEY_CTX_set1_hkdf_salt")) ||
411+
(!info.empty() && SSL_FAILED(EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data(), int(info.size())), "EVP_PKEY_CTX_add1_hkdf_info")) ||
412412
SSL_FAILED(EVP_PKEY_derive(ctx.get(), out.data(), &outlen), "EVP_PKEY_derive"))
413413
return {};
414414

cdoc/DDocWriter.cpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,27 @@ using namespace libcdoc;
2525
* @brief DDOCWriter is used for storing multiple files.
2626
*/
2727

28-
struct DDOCWriter::Private
29-
{
30-
static const NS DDOC;
31-
int fileCount = 0;
32-
};
33-
34-
const XMLWriter::NS DDOCWriter::Private::DDOC{ "", "http://www.sk.ee/DigiDoc/v1.3.0#" };
28+
const XMLWriter::NS DDOCWriter::DDOC{ "", "http://www.sk.ee/DigiDoc/v1.3.0#" };
3529

3630
/**
3731
* DDOCWriter constructor.
3832
* @param file File to be created
3933
*/
4034
DDOCWriter::DDOCWriter(const std::string &file)
4135
: XMLWriter(file)
42-
, d(new Private)
4336
{
44-
writeStartElement(Private::DDOC, "SignedDoc", {{"format", "DIGIDOC-XML"}, {"version", "1.3"}});
37+
writeStartElement(DDOC, "SignedDoc", {{"format", "DIGIDOC-XML"}, {"version", "1.3"}});
4538
}
4639

4740
DDOCWriter::DDOCWriter(std::vector<uint8_t>& vec)
48-
: XMLWriter(vec),
49-
d(new Private)
41+
: XMLWriter(vec)
5042
{
51-
writeStartElement(Private::DDOC, "SignedDoc", {{"format", "DIGIDOC-XML"}, {"version", "1.3"}});
43+
writeStartElement(DDOC, "SignedDoc", {{"format", "DIGIDOC-XML"}, {"version", "1.3"}});
5244
}
5345

5446
DDOCWriter::~DDOCWriter()
5547
{
56-
writeEndElement(Private::DDOC); // SignedDoc
57-
delete d;
48+
writeEndElement(DDOC); // SignedDoc
5849
}
5950

6051
/**
@@ -63,12 +54,12 @@ DDOCWriter::~DDOCWriter()
6354
* @param mime File mime type
6455
* @param data File content
6556
*/
66-
void DDOCWriter::addFile(const std::string &file, const std::string &mime, const std::vector<unsigned char> &data)
57+
uint64_t DDOCWriter::addFile(const std::string &file, const std::string &mime, const std::vector<unsigned char> &data)
6758
{
68-
writeBase64Element(Private::DDOC, "DataFile", data, {
59+
return writeBase64Element(DDOC, "DataFile", data, {
6960
{"ContentType", "EMBEDDED_BASE64"},
7061
{"Filename", file},
71-
{"Id", "D" + std::to_string(d->fileCount++)},
62+
{"Id", "D" + std::to_string(fileCount++)},
7263
{"MimeType", mime},
7364
{"Size", std::to_string(data.size())}
7465
});

cdoc/DDocWriter.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ class DDOCWriter: public XMLWriter
2929
DDOCWriter(std::vector<uint8_t>& vec);
3030
~DDOCWriter();
3131

32-
void addFile(const std::string &name, const std::string &mime, const std::vector<unsigned char> &data);
32+
uint64_t addFile(const std::string &name, const std::string &mime, const std::vector<unsigned char> &data);
3333

3434
private:
3535
DDOCWriter(const DDOCWriter &) = delete;
3636
DDOCWriter &operator=(const DDOCWriter &) = delete;
37-
struct Private;
38-
Private *d;
37+
int fileCount = 0;
38+
39+
static const NS DDOC;
3940
};
4041

4142
}

cdoc/XmlWriter.cpp

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@
1818

1919
#include "XmlWriter.h"
2020

21-
#include "Utils.h"
21+
#include "Io.h"
2222

23-
#include <openssl/evp.h>
2423
#include <libxml/xmlwriter.h>
2524

2625
using namespace libcdoc;
@@ -81,72 +80,70 @@ XMLWriter::~XMLWriter()
8180
delete d;
8281
}
8382

84-
void XMLWriter::writeStartElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr)
83+
int64_t XMLWriter::writeStartElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr)
8584
{
85+
if(!d->w)
86+
return WRONG_ARGUMENTS;
8687
std::map<std::string, int>::iterator pos = d->nsmap.find(ns.prefix);
8788
if (pos != d->nsmap.cend())
8889
pos->second++;
8990
else
9091
pos = d->nsmap.insert({ns.prefix, 1}).first;
91-
if(!d->w)
92-
return;
93-
if(xmlTextWriterStartElementNS(d->w, ns.prefix.empty() ? nullptr : pcxmlChar(ns.prefix.c_str()),
94-
pcxmlChar(name.c_str()), pos->second > 1 ? nullptr : pcxmlChar(ns.ns.c_str())) < 0)
95-
return;
92+
if(xmlTextWriterStartElementNS(d->w, ns.prefix.empty() ? nullptr : pcxmlChar(ns.prefix.c_str()),
93+
pcxmlChar(name.c_str()), pos->second > 1 ? nullptr : pcxmlChar(ns.ns.c_str())) == -1)
94+
return IO_ERROR;
9695
for(auto i = attr.cbegin(), end = attr.cend(); i != end; ++i)
9796
{
98-
if(xmlTextWriterWriteAttribute(d->w, pcxmlChar(i->first.c_str()), pcxmlChar(i->second.c_str())) < 0)
99-
break;
97+
if(xmlTextWriterWriteAttribute(d->w, pcxmlChar(i->first.c_str()), pcxmlChar(i->second.c_str())) == -1)
98+
return IO_ERROR;
10099
}
100+
return OK;
101101
}
102102

103-
void XMLWriter::writeEndElement(const NS &ns)
103+
int64_t XMLWriter::writeEndElement(const NS &ns)
104104
{
105-
if(d->w)
106-
xmlTextWriterEndElement(d->w);
107-
std::map<std::string, int>::iterator pos = d->nsmap.find(ns.prefix);
108-
if (pos != d->nsmap.cend())
105+
if(!d->w)
106+
return WRONG_ARGUMENTS;
107+
if(xmlTextWriterEndElement(d->w) == -1)
108+
return IO_ERROR;
109+
if(std::map<std::string, int>::iterator pos = d->nsmap.find(ns.prefix);
110+
pos != d->nsmap.cend())
109111
pos->second--;
112+
return OK;
110113
}
111114

112-
void XMLWriter::writeElement(const NS &ns, const std::string &name, const std::function<void()> &f)
115+
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::function<void()> &f)
113116
{
114-
writeStartElement(ns, name, {});
117+
if(auto rv = writeStartElement(ns, name, {}); rv != OK)
118+
return rv;
115119
if(f)
116120
f();
117-
writeEndElement(ns);
121+
return writeEndElement(ns);
118122
}
119123

120-
void XMLWriter::writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<void()> &f)
124+
int64_t XMLWriter::writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<void()> &f)
121125
{
122-
writeStartElement(ns, name, attr);
126+
if(auto rv = writeStartElement(ns, name, attr); rv != OK)
127+
return rv;
123128
if(f)
124129
f();
125-
writeEndElement(ns);
130+
return writeEndElement(ns);
126131
}
127132

128-
void XMLWriter::writeBase64Element(const NS &ns, const std::string &name, const std::vector<xmlChar> &data, const std::map<std::string, std::string> &attr)
133+
int64_t XMLWriter::writeBase64Element(const NS &ns, const std::string &name, const std::vector<xmlChar> &data, const std::map<std::string, std::string> &attr)
129134
{
130-
if (!d->w)
131-
return;
132-
static const size_t bufLen = 48 * 10240;
133-
std::vector<xmlChar> result(((bufLen + 2) / 3) * 4, 0);
134-
writeStartElement(ns, name, attr);
135-
for (size_t i = 0; i < data.size(); i += bufLen)
136-
{
137-
int size = EVP_EncodeBlock(result.data(), &data[i], std::min(data.size() - i, bufLen));
138-
if(size == 0)
139-
break;
140-
if(xmlTextWriterWriteRawLen(d->w, result.data(), size) < 0)
141-
break;
142-
}
143-
writeEndElement(ns);
135+
if(auto rv = writeStartElement(ns, name, attr); rv != OK)
136+
return rv;
137+
if(xmlTextWriterWriteBase64(d->w, reinterpret_cast<const char*>(data.data()), 0, data.size()) == -1)
138+
return IO_ERROR;
139+
return writeEndElement(ns);
144140
}
145141

146-
void XMLWriter::writeTextElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::string &data)
142+
int64_t XMLWriter::writeTextElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::string &data)
147143
{
148-
writeStartElement(ns, name, attr);
149-
if(d->w)
150-
(void)xmlTextWriterWriteString(d->w, pcxmlChar(data.c_str()));
151-
writeEndElement(ns);
144+
if(auto rv = writeStartElement(ns, name, attr); rv != OK)
145+
return rv;
146+
if(xmlTextWriterWriteString(d->w, pcxmlChar(data.c_str())) == -1)
147+
return IO_ERROR;
148+
return writeEndElement(ns);
152149
}

cdoc/XmlWriter.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ class XMLWriter
3939
XMLWriter(DataConsumer *dst);
4040
virtual ~XMLWriter();
4141

42-
void writeStartElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr);
43-
void writeEndElement(const NS &ns);
44-
void writeElement(const NS &ns, const std::string &name, const std::function<void()> &f = nullptr);
45-
void writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<void()> &f = nullptr);
46-
void writeBase64Element(const NS &ns, const std::string &name, const std::vector<unsigned char> &data, const std::map<std::string, std::string> &attr = {});
47-
void writeTextElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::string &data);
42+
int64_t writeStartElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr);
43+
int64_t writeEndElement(const NS &ns);
44+
int64_t writeElement(const NS &ns, const std::string &name, const std::function<void()> &f = nullptr);
45+
int64_t writeElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::function<void()> &f = nullptr);
46+
int64_t writeBase64Element(const NS &ns, const std::string &name, const std::vector<unsigned char> &data, const std::map<std::string, std::string> &attr = {});
47+
int64_t writeTextElement(const NS &ns, const std::string &name, const std::map<std::string, std::string> &attr, const std::string &data);
4848

4949
private:
5050
struct Private;

vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"features": {
2222
"tests": { "description": "Build tests", "dependencies": ["boost-test"] }
2323
},
24-
"builtin-baseline": "4008642a50a01a7115c2406b04d5273898e7fe1c",
24+
"builtin-baseline": "031ad89ce6c575df35a8e58707ad2c898446c63e",
2525
"vcpkg-configuration": {
2626
"overlay-triplets": ["./vcpkg-triplets"]
2727
}

0 commit comments

Comments
 (0)