summaryrefslogtreecommitdiff
path: root/zen
diff options
context:
space:
mode:
authorB Stack <bgstack15@gmail.com>2019-09-17 08:06:14 -0400
committerB Stack <bgstack15@gmail.com>2019-09-17 08:06:14 -0400
commitca250bf14979d359a82d5baf11ae9587d5605594 (patch)
treefc3041d022fee1abfc6df2ffd903fd7662b0b0d9 /zen
parentadd upstream 10.15 (diff)
downloadFreeFileSync-ca250bf14979d359a82d5baf11ae9587d5605594.tar.gz
FreeFileSync-ca250bf14979d359a82d5baf11ae9587d5605594.tar.bz2
FreeFileSync-ca250bf14979d359a82d5baf11ae9587d5605594.zip
add upstream 10.16
Diffstat (limited to 'zen')
-rw-r--r--zen/http.cpp97
-rw-r--r--zen/http.h1
-rw-r--r--zen/json.h101
-rw-r--r--zen/shell_execute.h2
-rw-r--r--zen/zlib_wrap.cpp44
-rw-r--r--zen/zlib_wrap.h33
6 files changed, 197 insertions, 81 deletions
diff --git a/zen/http.cpp b/zen/http.cpp
index d4c30741..93651d0b 100644
--- a/zen/http.cpp
+++ b/zen/http.cpp
@@ -46,7 +46,7 @@ public:
else //HTTP default port: 80, see %WINDIR%\system32\drivers\etc\services
socket_ = std::make_unique<Socket>(server, Zstr("http")); //throw SysError
- //we don't support "chunked and gzip transfer encoding" => HTTP 1.0
+ //we don't support "chunked and gzip transfer encoding" => HTTP 1.0
std::map<std::string, std::string, LessAsciiNoCase> headers;
headers["Host" ] = utfTo<std::string>(server); //only required for HTTP/1.1 but a few servers expect it even for HTTP/1.0
headers["User-Agent"] = utfTo<std::string>(userAgent);
@@ -235,8 +235,8 @@ std::unique_ptr<HttpInputStream::Impl> sendHttpRequestImpl(const Zstring& url,
auto response = std::make_unique<HttpInputStream::Impl>(urlRed, postParams, false /*disableGetCache*/, userAgent, caCertFilePath, notifyUnbufferedIO); //throw SysError
//https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection
- const int statusCode = response->getStatusCode();
- if (statusCode / 100 == 3) //e.g. 301, 302, 303, 307... we're not too greedy since we check location, too!
+ const int httpStatusCode = response->getStatusCode();
+ if (httpStatusCode / 100 == 3) //e.g. 301, 302, 303, 307... we're not too greedy since we check location, too!
{
const std::string* value = response->getHeader("Location");
if (!value || value->empty())
@@ -246,9 +246,8 @@ std::unique_ptr<HttpInputStream::Impl> sendHttpRequestImpl(const Zstring& url,
}
else
{
- if (statusCode != 200) //HTTP_STATUS_OK
- throw SysError(replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(statusCode)));
- //e.g. 404 - HTTP_STATUS_NOT_FOUND
+ if (httpStatusCode != 200) //HTTP_STATUS_OK(200)
+ throw SysError(formatHttpStatusCode(httpStatusCode)); //e.g. HTTP_STATUS_NOT_FOUND(404)
return response;
}
@@ -271,7 +270,7 @@ std::string urlencode(const std::string& str)
out += c;
else
{
- const auto [high, low] = hexify(c);
+ const auto [high, low] = hexify(c);
out += '%';
out += high;
out += low;
@@ -327,7 +326,7 @@ std::vector<std::pair<std::string, std::string>> zen::xWwwFormUrlDecode(const st
HttpInputStream zen::sendHttpPost(const Zstring& url, const std::vector<std::pair<std::string, std::string>>& postParams,
- const Zstring& userAgent, const Zstring* caCertFilePath, const IOCallback& notifyUnbufferedIO) //throw SysError
+ const Zstring& userAgent, const Zstring* caCertFilePath, const IOCallback& notifyUnbufferedIO) //throw SysError
{
return sendHttpRequestImpl(url, &postParams, userAgent, caCertFilePath, notifyUnbufferedIO); //throw SysError
}
@@ -357,3 +356,85 @@ bool zen::internetIsAlive() //noexcept
}
catch (SysError&) { return false; }
}
+
+
+std::wstring zen::formatHttpStatusCode(int sc)
+{
+ const wchar_t* statusText = [&] //https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
+ {
+ switch (sc)
+ {
+ //*INDENT-OFF*
+ case 300: return L"Multiple choices.";
+ case 301: return L"Moved permanently.";
+ case 302: return L"Moved temporarily.";
+ case 303: return L"See other";
+ case 304: return L"Not modified.";
+ case 305: return L"Use proxy.";
+ case 306: return L"Switch proxy.";
+ case 307: return L"Temporary redirect.";
+ case 308: return L"Permanent redirect.";
+
+ case 400: return L"Bad request.";
+ case 401: return L"Unauthorized.";
+ case 402: return L"Payment required.";
+ case 403: return L"Forbidden.";
+ case 404: return L"Not found.";
+ case 405: return L"Method not allowed.";
+ case 406: return L"Not acceptable.";
+ case 407: return L"Proxy authentication required.";
+ case 408: return L"Request timeout.";
+ case 409: return L"Conflict.";
+ case 410: return L"Gone.";
+ case 411: return L"Length required.";
+ case 412: return L"Precondition failed.";
+ case 413: return L"Payload too large.";
+ case 414: return L"URI too long.";
+ case 415: return L"Unsupported media type.";
+ case 416: return L"Range not satisfiable.";
+ case 417: return L"Expectation failed.";
+ case 418: return L"I'm a teapot.";
+ case 421: return L"Misdirected request.";
+ case 422: return L"Unprocessable entity.";
+ case 423: return L"Locked.";
+ case 424: return L"Failed dependency.";
+ case 425: return L"Too early.";
+ case 426: return L"Upgrade required.";
+ case 428: return L"Precondition required.";
+ case 429: return L"Too many requests.";
+ case 431: return L"Request header fields too large.";
+ case 451: return L"Unavailable for legal reasons.";
+
+ case 500: return L"Internal server error.";
+ case 501: return L"Not implemented.";
+ case 502: return L"Bad gateway.";
+ case 503: return L"Service unavailable.";
+ case 504: return L"Gateway timeout.";
+ case 505: return L"HTTP version not supported.";
+ case 506: return L"Variant also negotiates.";
+ case 507: return L"Insufficient storage.";
+ case 508: return L"Loop detected.";
+ case 510: return L"Not extended.";
+ case 511: return L"Network authentication required.";
+
+ //Cloudflare errors regarding origin server:
+ case 520: return L"Unknown error (Cloudflare)";
+ case 521: return L"Web server is down (Cloudflare)";
+ case 522: return L"Connection timed out (Cloudflare)";
+ case 523: return L"Origin is unreachable (Cloudflare)";
+ case 524: return L"A timeout occurred (Cloudflare)";
+ case 525: return L"SSL handshake failed (Cloudflare)";
+ case 526: return L"Invalid SSL certificate (Cloudflare)";
+ case 527: return L"Railgun error (Cloudflare)";
+ case 530: return L"Origin DNS error (Cloudflare)";
+
+ default: return L"";
+ //*INDENT-ON*
+ }
+ }();
+
+ if (strLength(statusText) == 0)
+ return trimCpy(replaceCpy<std::wstring>(L"HTTP status %x.", L"%x", numberTo<std::wstring>(sc)));
+ else
+ return trimCpy(replaceCpy<std::wstring>(L"HTTP status %x: ", L"%x", numberTo<std::wstring>(sc)) + statusText);
+} \ No newline at end of file
diff --git a/zen/http.h b/zen/http.h
index 2fafa574..42b0e279 100644
--- a/zen/http.h
+++ b/zen/http.h
@@ -47,6 +47,7 @@ HttpInputStream sendHttpPost(const Zstring& url,
const Zstring* caCertFilePath /*optional: enable certificate validation*/,
const IOCallback& notifyUnbufferedIO /*throw X*/);
bool internetIsAlive(); //noexcept
+std::wstring formatHttpStatusCode(int httpStatusCode);
std::string xWwwFormUrlEncode(const std::vector<std::pair<std::string, std::string>>& paramPairs);
std::vector<std::pair<std::string, std::string>> xWwwFormUrlDecode(const std::string& str);
diff --git a/zen/json.h b/zen/json.h
index 9b85ccb9..15157cf7 100644
--- a/zen/json.h
+++ b/zen/json.h
@@ -12,7 +12,8 @@
namespace zen
{
-//https://tools.ietf.org/html/rfc8259
+//Spec: https://tools.ietf.org/html/rfc8259
+//Test: http://seriot.ch/parsing_json.php
struct JsonValue
{
enum class Type
@@ -92,26 +93,31 @@ std::string jsonEscape(const std::string& str)
{
std::string output;
for (const char c : str)
- {
- if (c == '"') output += "\\\""; //escaping mandatory
- else if (c == '\\') output += "\\\\"; //
-
- else if (c == '\b') output += "\\b"; //
- else if (c == '\f') output += "\\f"; //
- else if (c == '\n') output += "\\n"; //prefer compact escaping
- else if (c == '\r') output += "\\r"; //
- else if (c == '\t') output += "\\t"; //
-
- else if (static_cast<unsigned char>(c) < 32)
+ switch (c)
{
- const auto [high, low] = hexify(c);
- output += "\\u00";
- output += high;
- output += low;
+ //*INDENT-OFF*
+ case '"': output += "\\\""; break; //escaping mandatory
+ case '\\': output += "\\\\"; break; //
+
+ case '\b': output += "\\b"; break; //
+ case '\f': output += "\\f"; break; //
+ case '\n': output += "\\n"; break; //prefer compact escaping
+ case '\r': output += "\\r"; break; //
+ case '\t': output += "\\t"; break; //
+
+ default:
+ if (static_cast<unsigned char>(c) < 32)
+ {
+ const auto [high, low] = hexify(c);
+ output += "\\u00";
+ output += high;
+ output += low;
+ }
+ else
+ output += c;
+ break;
+ //*INDENT-ON*
}
- else
- output += c;
- }
return output;
}
@@ -151,31 +157,36 @@ std::string jsonUnescape(const std::string& str)
}
const char c2 = *it;
- if (c2 == '"' ||
- c2 == '\\' ||
- c2 == '/')
- writeOut(c2);
- else if (c2 == 'b') writeOut('\b');
- else if (c2 == 'f') writeOut('\f');
- else if (c2 == 'n') writeOut('\n');
- else if (c2 == 'r') writeOut('\r');
- else if (c2 == 't') writeOut('\t');
-
- else if (c2 == 'u' &&
- str.end() - it >= 5 &&
- isHexDigit(it[1]) &&
- isHexDigit(it[2]) &&
- isHexDigit(it[3]) &&
- isHexDigit(it[4]))
- {
- utf16Buf += static_cast<impl::Char16>(static_cast<unsigned char>(unhexify(it[1], it[2])) * 256 +
- static_cast<unsigned char>(unhexify(it[3], it[4])));
- it += 4;
- }
- else //unknown escape sequence!
+ switch (c2)
{
- writeOut(c);
- writeOut(c2);
+ //*INDENT-OFF*
+ case '"':
+ case '\\':
+ case '/': writeOut(c2); break;
+ case 'b': writeOut('\b'); break;
+ case 'f': writeOut('\f'); break;
+ case 'n': writeOut('\n'); break;
+ case 'r': writeOut('\r'); break;
+ case 't': writeOut('\t'); break;
+ default:
+ if (c2 == 'u' &&
+ str.end() - it >= 5 &&
+ isHexDigit(it[1]) &&
+ isHexDigit(it[2]) &&
+ isHexDigit(it[3]) &&
+ isHexDigit(it[4]))
+ {
+ utf16Buf += static_cast<impl::Char16>(static_cast<unsigned char>(unhexify(it[1], it[2])) * 256 +
+ static_cast<unsigned char>(unhexify(it[3], it[4])));
+ it += 4;
+ }
+ else //unknown escape sequence!
+ {
+ writeOut(c);
+ writeOut(c2);
+ }
+ break;
+ //*INDENT-ON*
}
}
else
@@ -322,7 +333,7 @@ public:
Token getNextToken() //throw JsonParsingError
{
//skip whitespace
- pos_ = std::find_if(pos_, stream_.end(), std::not_fn(isJsonWhiteSpace));
+ pos_ = std::find_if_not(pos_, stream_.end(), isJsonWhiteSpace);
if (pos_ == stream_.end())
return Token::Type::eof;
@@ -368,7 +379,7 @@ public:
}
//expect a number:
- const auto itNumEnd = std::find_if(pos_, stream_.end(), std::not_fn(isJsonNumDigit));
+ const auto itNumEnd = std::find_if_not(pos_, stream_.end(), isJsonNumDigit);
if (itNumEnd == pos_)
throw JsonParsingError(posRow(), posCol());
diff --git a/zen/shell_execute.h b/zen/shell_execute.h
index 4875a039..56322236 100644
--- a/zen/shell_execute.h
+++ b/zen/shell_execute.h
@@ -72,7 +72,7 @@ void shellExecute(const Zstring& command, ExecutionType type, bool hideConsole)
inline
void openWithDefaultApplication(const Zstring& itemPath) //throw FileError
{
- shellExecute("xdg-open \"" + itemPath + '"', ExecutionType::ASYNC, false/*hideConsole*/); //
+ shellExecute("xdg-open \"" + itemPath + '"', ExecutionType::ASYNC, false /*hideConsole*/); //throw FileError
}
}
diff --git a/zen/zlib_wrap.cpp b/zen/zlib_wrap.cpp
index ff5799c3..8979efa6 100644
--- a/zen/zlib_wrap.cpp
+++ b/zen/zlib_wrap.cpp
@@ -9,17 +9,39 @@
//Linux/macOS: use zlib system header for both wxWidgets and libcurl (zlib is required for HTTP)
// => don't compile wxWidgets with: --with-zlib=builtin
#include <zlib.h> //https://www.zlib.net/manual.html
+#include <zen/scope_guard.h>
using namespace zen;
+namespace
+{
+std::wstring formatZlibStatusCode(int sc)
+{
+ switch (sc)
+ {
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_OK);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_STREAM_END);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_NEED_DICT);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_ERRNO);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_STREAM_ERROR);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_DATA_ERROR);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_MEM_ERROR);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_BUF_ERROR);
+ ZEN_CHECK_CASE_FOR_CONSTANT(Z_VERSION_ERROR);
+ }
+ return replaceCpy<std::wstring>(L"zlib status %x.", L"%x", numberTo<std::wstring>(sc));
+}
+}
+
+
size_t zen::impl::zlib_compressBound(size_t len)
{
return ::compressBound(static_cast<uLong>(len)); //upper limit for buffer size, larger than input size!!!
}
-size_t zen::impl::zlib_compress(const void* src, size_t srcLen, void* trg, size_t trgLen, int level) //throw ZlibInternalError
+size_t zen::impl::zlib_compress(const void* src, size_t srcLen, void* trg, size_t trgLen, int level) //throw SysError
{
uLongf bufferSize = static_cast<uLong>(trgLen);
const int rv = ::compress2(static_cast<Bytef*>(trg), //Bytef* dest,
@@ -31,12 +53,13 @@ size_t zen::impl::zlib_compress(const void* src, size_t srcLen, void* trg, size_
// Z_MEM_ERROR: not enough memory
// Z_BUF_ERROR: not enough room in the output buffer
if (rv != Z_OK || bufferSize > trgLen)
- throw ZlibInternalError();
+ throw SysError(formatSystemError(L"compress2", formatZlibStatusCode(rv), L"zlib error"));
+
return bufferSize;
}
-size_t zen::impl::zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen) //throw ZlibInternalError
+size_t zen::impl::zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen) //throw SysError
{
uLongf bufferSize = static_cast<uLong>(trgLen);
const int rv = ::uncompress(static_cast<Bytef*>(trg), //Bytef* dest,
@@ -48,7 +71,8 @@ size_t zen::impl::zlib_decompress(const void* src, size_t srcLen, void* trg, siz
// Z_BUF_ERROR: not enough room in the output buffer
// Z_DATA_ERROR: input data was corrupted or incomplete
if (rv != Z_OK || bufferSize > trgLen)
- throw ZlibInternalError();
+ throw SysError(formatSystemError(L"uncompress", formatZlibStatusCode(rv), L"zlib error"));
+
return bufferSize;
}
@@ -56,7 +80,7 @@ size_t zen::impl::zlib_decompress(const void* src, size_t srcLen, void* trg, siz
class InputStreamAsGzip::Impl
{
public:
- Impl(const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/) : //throw ZlibInternalError; returning 0 signals EOF: Posix read() semantics
+ Impl(const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/) : //throw SysError; returning 0 signals EOF: Posix read() semantics
readBlock_(readBlock)
{
const int windowBits = MAX_WBITS + 16; //"add 16 to windowBits to write a simple gzip header"
@@ -72,7 +96,7 @@ public:
memLevel, //int memLevel
Z_DEFAULT_STRATEGY); //int strategy
if (rv != Z_OK)
- throw ZlibInternalError();
+ throw SysError(formatSystemError(L"deflateInit2", formatZlibStatusCode(rv), L"zlib error"));
}
~Impl()
@@ -81,7 +105,7 @@ public:
assert(rv == Z_OK);
}
- size_t read(void* buffer, size_t bytesToRead) //throw ZlibInternalError, X; return "bytesToRead" bytes unless end of stream!
+ size_t read(void* buffer, size_t bytesToRead) //throw SysError, X; return "bytesToRead" bytes unless end of stream!
{
if (bytesToRead == 0) //"read() with a count of 0 returns zero" => indistinguishable from end of file! => check!
throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__));
@@ -107,7 +131,7 @@ public:
if (rv == Z_STREAM_END)
return bytesToRead - gzipStream_.avail_out;
if (rv != Z_OK)
- throw ZlibInternalError();
+ throw SysError(formatSystemError(L"deflate", formatZlibStatusCode(rv), L"zlib error"));
if (gzipStream_.avail_out == 0)
return bytesToRead;
@@ -122,6 +146,6 @@ private:
};
-zen::InputStreamAsGzip::InputStreamAsGzip(const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/) : pimpl_(std::make_unique<Impl>(readBlock)) {} //throw ZlibInternalError
+zen::InputStreamAsGzip::InputStreamAsGzip(const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/) : pimpl_(std::make_unique<Impl>(readBlock)) {} //throw SysError
zen::InputStreamAsGzip::~InputStreamAsGzip() {}
-size_t zen::InputStreamAsGzip::read(void* buffer, size_t bytesToRead) { return pimpl_->read(buffer, bytesToRead); } //throw ZlibInternalError, X
+size_t zen::InputStreamAsGzip::read(void* buffer, size_t bytesToRead) { return pimpl_->read(buffer, bytesToRead); } //throw SysError, X
diff --git a/zen/zlib_wrap.h b/zen/zlib_wrap.h
index c8647baf..fbe26193 100644
--- a/zen/zlib_wrap.h
+++ b/zen/zlib_wrap.h
@@ -8,31 +8,30 @@
#define ZLIB_WRAP_H_428597064566
#include "serialize.h"
+#include "sys_error.h"
namespace zen
{
-class ZlibInternalError {};
-
// compression level must be between 0 and 9:
// 0: no compression
// 9: best compression
template <class BinContainer> //as specified in serialize.h
-BinContainer compress(const BinContainer& stream, int level); //throw ZlibInternalError
+BinContainer compress(const BinContainer& stream, int level); //throw SysError
//caveat: output stream is physically larger than input! => strip additional reserved space if needed: "BinContainer(output.begin(), output.end())"
template <class BinContainer>
-BinContainer decompress(const BinContainer& stream); //throw ZlibInternalError
+BinContainer decompress(const BinContainer& stream); //throw SysError
class InputStreamAsGzip //convert input stream into gzip on the fly
{
public:
- InputStreamAsGzip( //throw ZlibInternalError
+ InputStreamAsGzip( //throw SysError
const std::function<size_t(void* buffer, size_t bytesToRead)>& readBlock /*throw X*/); //returning 0 signals EOF: Posix read() semantics
~InputStreamAsGzip();
- size_t read(void* buffer, size_t bytesToRead); //throw ZlibInternalError, X; return "bytesToRead" bytes unless end of stream!
+ size_t read(void* buffer, size_t bytesToRead); //throw SysError, X; return "bytesToRead" bytes unless end of stream!
private:
class Impl;
@@ -49,13 +48,13 @@ private:
namespace impl
{
size_t zlib_compressBound(size_t len);
-size_t zlib_compress (const void* src, size_t srcLen, void* trg, size_t trgLen, int level); //throw ZlibInternalError
-size_t zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen); //throw ZlibInternalError
+size_t zlib_compress (const void* src, size_t srcLen, void* trg, size_t trgLen, int level); //throw SysError
+size_t zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen); //throw SysError
}
template <class BinContainer>
-BinContainer compress(const BinContainer& stream, int level) //throw ZlibInternalError
+BinContainer compress(const BinContainer& stream, int level) //throw SysError
{
BinContainer contOut;
if (!stream.empty()) //don't dereference iterator into empty container!
@@ -73,7 +72,7 @@ BinContainer compress(const BinContainer& stream, int level) //throw ZlibInterna
stream.size(),
&*contOut.begin() + contOut.size() - bufferEstimate,
bufferEstimate,
- level); //throw ZlibInternalError
+ level); //throw SysError
if (bytesWritten < bufferEstimate)
contOut.resize(contOut.size() - (bufferEstimate - bytesWritten)); //caveat: unsigned arithmetics
//caveat: physical memory consumption still *unchanged*!
@@ -83,7 +82,7 @@ BinContainer compress(const BinContainer& stream, int level) //throw ZlibInterna
template <class BinContainer>
-BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError
+BinContainer decompress(const BinContainer& stream) //throw SysError
{
BinContainer contOut;
if (!stream.empty()) //don't dereference iterator into empty container!
@@ -91,30 +90,30 @@ BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError
//retrieve size of uncompressed data
uint64_t uncompressedSize = 0; //use portable number type!
if (stream.size() < sizeof(uncompressedSize))
- throw ZlibInternalError();
+ throw SysError(L"zlib error: stream size < 8");
std::memcpy(&uncompressedSize, &*stream.begin(), sizeof(uncompressedSize));
//attention: contOut MUST NOT be empty! Else it will pass a nullptr to zlib_decompress() => Z_STREAM_ERROR although "uncompressedSize == 0"!!!
//secondary bug: don't dereference iterator into empty container!
if (uncompressedSize == 0) //cannot be 0: compress() directly maps empty -> empty container skipping zlib!
- throw ZlibInternalError();
+ throw SysError(L"zlib error: uncompressed size == 0");
try
{
contOut.resize(static_cast<size_t>(uncompressedSize)); //throw std::bad_alloc
}
- catch (std::bad_alloc&) //most likely due to data corruption!
+ catch (const std::bad_alloc& e) //most likely due to data corruption!
{
- throw ZlibInternalError();
+ throw SysError(L"zlib error: " + _("Out of memory.") + L" " + utfTo<std::wstring>(e.what()));
}
const size_t bytesWritten = impl::zlib_decompress(&*stream.begin() + sizeof(uncompressedSize),
stream.size() - sizeof(uncompressedSize),
&*contOut.begin(),
- static_cast<size_t>(uncompressedSize)); //throw ZlibInternalError
+ static_cast<size_t>(uncompressedSize)); //throw SysError
if (bytesWritten != static_cast<size_t>(uncompressedSize))
- throw ZlibInternalError();
+ throw SysError(L"zlib error: bytes written != uncompressed size");
}
return contOut;
}
bgstack15