Mercurial > hg > orthanc
annotate OrthancFramework/Sources/Compression/ZlibCompressor.cpp @ 4731:283d246fafdb
fix broken "Do lookup" button in Orthanc Explorer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sun, 27 Jun 2021 12:48:26 +0200 |
parents | 0b2484663233 |
children | 7053502fbf97 |
rev | line source |
---|---|
0 | 1 /** |
59 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
1900 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
1288
6e7e5ed91c2d
upgrade to year 2015
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
4 * Department, University Hospital of Liege, Belgium |
4437
d9473bd5ed43
upgrade to year 2021
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4297
diff
changeset
|
5 * Copyright (C) 2017-2021 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
8 * modify it under the terms of the GNU Lesser General Public License |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
9 * as published by the Free Software Foundation, either version 3 of |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
10 * the License, or (at your option) any later version. |
136 | 11 * |
0 | 12 * This program is distributed in the hope that it will be useful, but |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
15 * Lesser General Public License for more details. |
0 | 16 * |
4119
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
17 * You should have received a copy of the GNU Lesser General Public |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
18 * License along with this program. If not, see |
bf7b9edf6b81
re-licensing the OrthancFramework to LGPL, in order to license Stone of Orthanc under LGPL
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4044
diff
changeset
|
19 * <http://www.gnu.org/licenses/>. |
0 | 20 **/ |
21 | |
22 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
689
diff
changeset
|
23 #include "../PrecompiledHeaders.h" |
0 | 24 #include "ZlibCompressor.h" |
25 | |
4455
a8f554ca5ac6
Explicitly use little-endian to encode uncompressed file size with zlib compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
26 #include "../Endianness.h" |
1513 | 27 #include "../OrthancException.h" |
28 #include "../Logging.h" | |
29 | |
0 | 30 #include <stdio.h> |
31 #include <string.h> | |
32 #include <zlib.h> | |
33 | |
59 | 34 namespace Orthanc |
0 | 35 { |
4297 | 36 ZlibCompressor::ZlibCompressor() |
4296
3b70a2e6a06c
moving inline methods to source files for ABI compatibility
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4119
diff
changeset
|
37 { |
3b70a2e6a06c
moving inline methods to source files for ABI compatibility
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4119
diff
changeset
|
38 SetPrefixWithUncompressedSize(true); |
3b70a2e6a06c
moving inline methods to source files for ABI compatibility
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4119
diff
changeset
|
39 } |
3b70a2e6a06c
moving inline methods to source files for ABI compatibility
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4119
diff
changeset
|
40 |
0 | 41 void ZlibCompressor::Compress(std::string& compressed, |
42 const void* uncompressed, | |
43 size_t uncompressedSize) | |
44 { | |
45 if (uncompressedSize == 0) | |
46 { | |
47 compressed.clear(); | |
48 return; | |
49 } | |
50 | |
3378
596cfabd72c5
Fixed a couple of truncation warnings
Benjamin Golinvaux <bgo@osimis.io>
parents:
3060
diff
changeset
|
51 uLongf compressedSize = compressBound(static_cast<uLong>(uncompressedSize)) |
596cfabd72c5
Fixed a couple of truncation warnings
Benjamin Golinvaux <bgo@osimis.io>
parents:
3060
diff
changeset
|
52 + 1024 /* security margin */; |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
53 if (compressedSize == 0) |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
54 { |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
55 compressedSize = 1; |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
56 } |
0 | 57 |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
58 uint8_t* target; |
1512 | 59 if (HasPrefixWithUncompressedSize()) |
0 | 60 { |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
61 compressed.resize(compressedSize + sizeof(uint64_t)); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
62 target = reinterpret_cast<uint8_t*>(&compressed[0]) + sizeof(uint64_t); |
0 | 63 } |
64 else | |
65 { | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
66 compressed.resize(compressedSize); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
67 target = reinterpret_cast<uint8_t*>(&compressed[0]); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
68 } |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
69 |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
70 int error = compress2(target, |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
71 &compressedSize, |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
72 const_cast<Bytef *>(static_cast<const Bytef *>(uncompressed)), |
3378
596cfabd72c5
Fixed a couple of truncation warnings
Benjamin Golinvaux <bgo@osimis.io>
parents:
3060
diff
changeset
|
73 static_cast<uLong>(uncompressedSize), |
1512 | 74 GetCompressionLevel()); |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
75 |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
76 if (error != Z_OK) |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
77 { |
0 | 78 compressed.clear(); |
79 | |
80 switch (error) | |
81 { | |
82 case Z_MEM_ERROR: | |
59 | 83 throw OrthancException(ErrorCode_NotEnoughMemory); |
0 | 84 |
85 default: | |
59 | 86 throw OrthancException(ErrorCode_InternalError); |
0 | 87 } |
88 } | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
89 |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
90 // The compression was successful |
1512 | 91 if (HasPrefixWithUncompressedSize()) |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
92 { |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
93 uint64_t s = static_cast<uint64_t>(uncompressedSize); |
4455
a8f554ca5ac6
Explicitly use little-endian to encode uncompressed file size with zlib compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
94 |
a8f554ca5ac6
Explicitly use little-endian to encode uncompressed file size with zlib compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
95 // New in Orthanc 1.9.0: Explicitly use litte-endian encoding in size prefix |
a8f554ca5ac6
Explicitly use little-endian to encode uncompressed file size with zlib compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
96 s = htole64(s); |
a8f554ca5ac6
Explicitly use little-endian to encode uncompressed file size with zlib compression
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4437
diff
changeset
|
97 |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
98 memcpy(&compressed[0], &s, sizeof(uint64_t)); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
99 compressed.resize(compressedSize + sizeof(uint64_t)); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
100 } |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
101 else |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
102 { |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
103 compressed.resize(compressedSize); |
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
104 } |
0 | 105 } |
106 | |
107 | |
108 void ZlibCompressor::Uncompress(std::string& uncompressed, | |
109 const void* compressed, | |
110 size_t compressedSize) | |
111 { | |
112 if (compressedSize == 0) | |
113 { | |
114 uncompressed.clear(); | |
115 return; | |
116 } | |
117 | |
1513 | 118 if (!HasPrefixWithUncompressedSize()) |
0 | 119 { |
2954
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2447
diff
changeset
|
120 throw OrthancException(ErrorCode_InternalError, |
d924f9bb61cc
taking advantage of details in OrthancException
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2447
diff
changeset
|
121 "Cannot guess the uncompressed size of a zlib-encoded buffer"); |
0 | 122 } |
123 | |
1513 | 124 uint64_t uncompressedSize = ReadUncompressedSizePrefix(compressed, compressedSize); |
221
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
125 |
4492
0b2484663233
Fix build on big-endian architectures
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4455
diff
changeset
|
126 // New in Orthanc 1.9.0: Explicitly use litte-endian encoding in size prefix |
0b2484663233
Fix build on big-endian architectures
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4455
diff
changeset
|
127 uncompressedSize = le64toh(uncompressedSize); |
0b2484663233
Fix build on big-endian architectures
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
4455
diff
changeset
|
128 |
221
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
129 try |
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
130 { |
1545 | 131 uncompressed.resize(static_cast<size_t>(uncompressedSize)); |
221
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
132 } |
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
133 catch (...) |
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
134 { |
1513 | 135 throw OrthancException(ErrorCode_NotEnoughMemory); |
221
e7432706b354
accessors to storage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
136
diff
changeset
|
136 } |
0 | 137 |
1545 | 138 uLongf tmp = static_cast<uLongf>(uncompressedSize); |
0 | 139 int error = uncompress |
140 (reinterpret_cast<uint8_t*>(&uncompressed[0]), | |
141 &tmp, | |
1511
7962563129c9
starting support of deflate/gzip content types
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1288
diff
changeset
|
142 reinterpret_cast<const uint8_t*>(compressed) + sizeof(uint64_t), |
3378
596cfabd72c5
Fixed a couple of truncation warnings
Benjamin Golinvaux <bgo@osimis.io>
parents:
3060
diff
changeset
|
143 static_cast<uLong>(compressedSize - sizeof(uint64_t))); |
0 | 144 |
145 if (error != Z_OK) | |
146 { | |
147 uncompressed.clear(); | |
148 | |
149 switch (error) | |
150 { | |
151 case Z_DATA_ERROR: | |
1582
bd1889029cbb
encoding of exceptions
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
1545
diff
changeset
|
152 throw OrthancException(ErrorCode_CorruptedFile); |
0 | 153 |
154 case Z_MEM_ERROR: | |
59 | 155 throw OrthancException(ErrorCode_NotEnoughMemory); |
0 | 156 |
157 default: | |
59 | 158 throw OrthancException(ErrorCode_InternalError); |
0 | 159 } |
160 } | |
161 } | |
162 } |