Branch data TLA Line data Source code
1 : : /* POLE - Portable C++ library to access OLE Storage
2 : : Copyright (C) 2002-2007 Ariya Hidayat (ariya@kde.org).
3 : : Copyright (C) 2016-2022 Thomas Fussell
4 : : Copyright (c) 2024-2025 xlnt-community
5 : :
6 : : Redistribution and use in source and binary forms, with or without
7 : : modification, are permitted provided that the following conditions
8 : : are met:
9 : :
10 : : 1. Redistributions of source code must retain the above copyright
11 : : notice, this list of conditions and the following disclaimer.
12 : : 2. Redistributions in binary form must reproduce the above copyright
13 : : notice, this list of conditions and the following disclaimer in the
14 : : documentation and/or other materials provided with the distribution.
15 : :
16 : : THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : : IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : : OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : : IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : : INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : : NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : : THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : : */
27 : :
28 : : #pragma once
29 : :
30 : : #include <array>
31 : : #include <memory>
32 : : #include <string>
33 : : #include <unordered_map>
34 : :
35 : : #include <detail/binary.hpp>
36 : : #include <detail/unicode.hpp>
37 : :
38 : : namespace xlnt {
39 : : namespace detail {
40 : :
41 : : using directory_id = std::int32_t;
42 : : using sector_id = std::int32_t;
43 : : using sector_chain = std::vector<sector_id>;
44 : :
45 : : struct compound_document_header
46 : : {
47 : : enum class byte_order_type : uint16_t
48 : : {
49 : : big_endian = 0xFFFE,
50 : : little_endian = 0xFEFF
51 : : };
52 : :
53 : : std::uint64_t file_id = 0xE11AB1A1E011CFD0;
54 : : std::array<std::uint8_t, 16> ignore1 = { { 0 } };
55 : : std::uint16_t revision = 0x003E;
56 : : std::uint16_t version = 0x0003;
57 : : byte_order_type byte_order = byte_order_type::little_endian;
58 : : std::uint16_t sector_size_power = 9;
59 : : std::uint16_t short_sector_size_power = 6;
60 : : std::array<std::uint8_t, 10> ignore2 = { { 0 } };
61 : : std::uint32_t num_msat_sectors = 0;
62 : : sector_id directory_start = -1;
63 : : std::array<std::uint8_t, 4> ignore3 = { { 0 } };
64 : : std::uint32_t threshold = 4096;
65 : : sector_id ssat_start = -2;
66 : : std::uint32_t num_short_sectors = 0;
67 : : sector_id extra_msat_start = -2;
68 : : std::uint32_t num_extra_msat_sectors = 0;
69 : : std::array<sector_id, 109> msat = {{0}};
70 : : };
71 : :
72 : : struct compound_document_entry
73 : : {
74 :CBC 12 : void name(const std::string &new_name)
75 : : {
76 [ + ]: 12 : auto u16_name = utf8_to_utf16(new_name);
77 : 12 : name_length = std::min(static_cast<std::uint16_t>(u16_name.size()), std::uint16_t(31));
78 [ + ]: 12 : std::copy(u16_name.begin(), u16_name.begin() + name_length, name_array.begin());
79 : 12 : name_array[name_length] = 0;
80 : 12 : name_length = (name_length + 1) * 2;
81 : 12 : }
82 : :
83 : 278 : std::string name() const
84 : : {
85 : 278 : return utf16_to_utf8(std::u16string(name_array.begin(),
86 [ + + ]: 556 : name_array.begin() + (name_length - 1) / 2));
87 : : }
88 : :
89 : : enum class entry_type : std::uint8_t
90 : : {
91 : : Empty = 0,
92 : : UserStorage = 1,
93 : : UserStream = 2,
94 : : LockBytes = 3,
95 : : Property = 4,
96 : : RootStorage = 5
97 : : };
98 : :
99 : : enum class entry_color : std::uint8_t
100 : : {
101 : : Red = 0,
102 : : Black = 1
103 : : };
104 : :
105 : : std::array<char16_t, 32> name_array = { { 0 } };
106 : : std::uint16_t name_length = 2;
107 : : entry_type type = entry_type::Empty;
108 : : entry_color color = entry_color::Black;
109 : : directory_id prev = -1;
110 : : directory_id next = -1;
111 : : directory_id child = -1;
112 : : std::array<std::uint8_t, 36> ignore;
113 : : sector_id start = -2;
114 : : std::uint32_t size = 0;
115 : : std::uint32_t ignore2;
116 : : };
117 : :
118 : : class compound_document_istreambuf;
119 : : class compound_document_ostreambuf;
120 : :
121 : : class compound_document
122 : : {
123 : : public:
124 : : compound_document(std::istream &in);
125 : : compound_document(std::ostream &out);
126 : : ~compound_document();
127 : :
128 : : void close();
129 : :
130 : : std::istream &open_read_stream(const std::string &filename);
131 : : std::ostream &open_write_stream(const std::string &filename);
132 : :
133 : : private:
134 : : friend class compound_document_istreambuf;
135 : : friend class compound_document_ostreambuf;
136 : :
137 : : template<typename T>
138 : : void read_sector(sector_id id, binary_writer<T> &writer);
139 : : template<typename T>
140 : : void read_sector_chain(sector_id id, binary_writer<T> &writer);
141 : : template<typename T>
142 : : void read_sector_chain(sector_id start, binary_writer<T> &writer, sector_id offset, std::size_t count);
143 : : template<typename T>
144 : : void read_short_sector(sector_id id, binary_writer<T> &writer);
145 : : template<typename T>
146 : : void read_short_sector_chain(sector_id start, binary_writer<T> &writer);
147 : : template<typename T>
148 : : void read_short_sector_chain(sector_id start, binary_writer<T> &writer, sector_id offset, std::size_t count);
149 : :
150 : : sector_chain follow_chain(sector_id start, const sector_chain &table);
151 : :
152 : : template<typename T>
153 : : void write_sector(binary_reader<T> &reader, sector_id id);
154 : : template<typename T>
155 : : void write_short_sector(binary_reader<T> &reader, sector_id id);
156 : :
157 : : void read_header();
158 : : void read_msat();
159 : : void read_sat();
160 : : void read_ssat();
161 : : void read_entry(directory_id id);
162 : : void read_directory();
163 : :
164 : : void write_header();
165 : : void write_msat();
166 : : void write_sat();
167 : : void write_ssat();
168 : : void write_entry(directory_id id);
169 : : void write_directory();
170 : :
171 : : std::size_t sector_size();
172 : : std::size_t short_sector_size();
173 : : std::size_t sector_data_start();
174 : :
175 : : void print_directory();
176 : :
177 : : sector_id allocate_msat_sector();
178 : : sector_id allocate_sat_sector();
179 : : sector_id allocate_ssat_sector();
180 : :
181 : : sector_id allocate_sector();
182 : : sector_chain allocate_sectors(std::size_t sectors);
183 : : sector_id allocate_short_sector();
184 : : sector_chain allocate_short_sectors(std::size_t sectors);
185 : :
186 : : bool contains_entry(const std::string &path,
187 : : compound_document_entry::entry_type type);
188 : : directory_id find_entry(const std::string &path,
189 : : compound_document_entry::entry_type type);
190 : : directory_id next_empty_entry();
191 : : directory_id insert_entry(const std::string &path,
192 : : compound_document_entry::entry_type type);
193 : :
194 : : // Red black tree helper functions
195 : : void tree_insert(directory_id new_id, directory_id storage_id);
196 : : void tree_insert_fixup(directory_id x);
197 : : std::string tree_path(directory_id id);
198 : : void tree_rotate_left(directory_id x);
199 : : void tree_rotate_right(directory_id y);
200 : : directory_id &tree_left(directory_id id);
201 : : directory_id &tree_right(directory_id id);
202 : : directory_id &tree_parent(directory_id id);
203 : : directory_id &tree_root(directory_id id);
204 : : directory_id &tree_child(directory_id id);
205 : : std::string tree_key(directory_id id);
206 : : compound_document_entry::entry_color &tree_color(directory_id id);
207 : :
208 : : compound_document_header header_;
209 : : sector_chain msat_;
210 : : sector_chain sat_;
211 : : sector_chain ssat_;
212 : : std::vector<compound_document_entry> entries_;
213 : :
214 : : std::unordered_map<directory_id, directory_id> parent_storage_;
215 : : std::unordered_map<directory_id, directory_id> parent_;
216 : :
217 : : std::istream *in_;
218 : : std::ostream *out_;
219 : :
220 : : std::unique_ptr<compound_document_istreambuf> stream_in_buffer_;
221 : : std::istream stream_in_;
222 : : std::unique_ptr<compound_document_ostreambuf> stream_out_buffer_;
223 : : std::ostream stream_out_;
224 : : };
225 : :
226 : : } // namespace detail
227 : : } // namespace xlnt
|