-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
zipfile.h
171 lines (154 loc) · 6.27 KB
/
zipfile.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright 2010-2024 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Interface for mapping the contents of a zipfile.
// You open a zip file archive by using the OpenZipArchive() method, which
// returns a shared_ptr to a ZipArchive object that maps its contents into the
// "/zip/" namespace. During the duration of the existence of the ZipArchive
// object, paths under it are available for File operations.
//
// Only a single ZipArchive will be opened for any unique path; all of the
// returned shared_ptrs will point to the same underlying ZipArchive object.
// The contents of the ZipArchive will remain mapped into the /zip/ namespace
// until the last shared_ptr is destroyed and its underlying object is
// released.
//
// To map the contents of zip file "/foo/bar.zip", use the following:
// {
// std::shared_ptr<zipfile::ZipArchive> zip_archive(
// zipfile::OpenZipArchive("/foo/bar.zip"));
// if (zip_archive == nullptr) {
// // Handle error
// }
//
// // Do interesting things with paths under "/zip/foo/bar.zip/..."
// }
//
// Paths in the zip file are available until the last shared_ptr to the
// ZipArchive object is released.
//
// You can use this pattern to read files from a Zip archive:
// {
// std::shared_ptr<zipfile::ZipArchive> zip_archive(
// zipfile::OpenZipArchive(filename));
// if (zip_archive == nullptr) {
// // Do not continue execution of the example code.
// }
// vector<string> files;
// absl::Status status = file::Match(file::JoinPath("/zip", filename, "*"),
// &files, file::Defaults());
// if (!status.ok()) {
// // Do not continue execution.
// }
// for (const string& fn : files) {
// File* f;
// absl::Status status = file::Open(fn, "r", &f, file::Defaults());
// if (!status.ok()) {
// // Handle error: abort, return, or continue.
// }
// DoStuffWithFile(f);
// status = f->Close();
// if (!status.ok()) {
// // Handle error: abort, return, or continue.
// }
// }
// }
#ifndef OR_TOOLS_BASE_ZIPFILE_H_
#define OR_TOOLS_BASE_ZIPFILE_H_
#include <memory>
#include <optional>
#include <string>
#include "absl/strings/string_view.h"
namespace zipfile {
// Performance hint: Specify what order you expect to visit the data
// in the file.
enum class AccessPattern {
// Keep whatever is default for your system (typically same as NORMAL).
ACCESS_NONE = 0,
// Moderate prefetching as the file gets accessed.
ACCESS_NORMAL = 1,
// No prefetching to be done, use this for random access.
ACCESS_RANDOM = 2,
// Aggressive prefetching on reads.
ACCESS_SEQUENTIAL = 3,
};
class ZipArchive;
// An options struct to be provided when opening a zip archive:
//
// `access_pattern`, possible values:
// NORMAL: Will use a small InputBuffer to cache small files, raw access to
// big files.
// RANDOM: Do not do any caching at all.
// SEQUENTIAL: Always use a (big) InputBuffer to cache read access.
// SEQUENTIAL mode
//
// `zip_bomb_max_ratio`, if greater than zero, indicates the maximum
// compression ratio to allow on any file in the zip archive. This can be used
// to reject files containing decompression bombs. A value of 0 disables zip
// bomb checking.
//
// `zip_bomb_max_size`, if greater than zero, indicates the maximum
// decompressed file size that is allowed on any file in the zip archive. This
// is an additional layer of protection against zip bombs in addition to the
// zip_bomb_max_ratio
struct ZipFileOptions {
AccessPattern access_pattern = AccessPattern::ACCESS_NONE;
std::optional<size_t> zip_bomb_max_ratio = std::nullopt;
std::optional<size_t> zip_bomb_max_size = std::nullopt;
};
// Open and return a ZipArchive. This maps the files in PATH into the /zip/
// namespace, and they will exist there until the ZipArchive is destroyed.
// If the archive is already opened, or opening it fails for some reason,
// nullptr will be returned.
//
// The path given to OpenZipArchive must be absolute.
// The ZipArchive can only be used for reading zipfile contents. To modify
// zip file contents, use ZipFileWriter from file/zipfile/zipfilewriter.h.
//
// The value of the returned shared_ptr may be nullptr if there is an
// error opening the archive. This may be caused by corruption, errors
// finding or opening the file, or any other problem which prevents the archive
// from being read.
//
// Note: Writing to an open ZipArchive will fail in strange and mysterious
// ways. You have been warned.
// The input options argument provides controls over zip bombs as well as
// access pattern controls
std::shared_ptr<ZipArchive> OpenZipArchive(absl::string_view path,
const ZipFileOptions& options);
inline std::shared_ptr<ZipArchive> OpenZipArchive(absl::string_view path) {
ZipFileOptions options;
return OpenZipArchive(path, options);
}
// A zip archive, which may contain files that can be read through the /zip
// filename prefix.
//
// Do not instantiate this class directly. Use the OpenZipArchive factory
// methods instead.
class ZipArchive {
public:
ZipArchive(absl::string_view path, const ZipFileOptions& options);
ZipArchive(const ZipArchive&) = delete;
ZipArchive& operator=(const ZipArchive&) = delete;
// Returns the filename at which this archive was first opened. Since all
// equivalent zip archive paths share the same archive, this name will not
// necessarily match the name at which the archive was opened. For example,
// we provide no guarantees about whether the filename will begin with "/zip",
// since the "/zip" prefix is optional for opening zip archives.
const std::string& filename() const { return filename_; }
~ZipArchive();
private:
std::string filename_;
ZipFileOptions options_;
};
}; // namespace zipfile
#endif // OR_TOOLS_BASE_ZIPFILE_H_