/src/libmwaw/src/lib/PowerPoint3OLE.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ |
2 | | |
3 | | /* libmwaw |
4 | | * Version: MPL 2.0 / LGPLv2+ |
5 | | * |
6 | | * The contents of this file are subject to the Mozilla Public License Version |
7 | | * 2.0 (the "License"); you may not use this file except in compliance with |
8 | | * the License or as specified alternatively below. You may obtain a copy of |
9 | | * the License at http://www.mozilla.org/MPL/ |
10 | | * |
11 | | * Software distributed under the License is distributed on an "AS IS" basis, |
12 | | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
13 | | * for the specific language governing rights and limitations under the |
14 | | * License. |
15 | | * |
16 | | * Major Contributor(s): |
17 | | * Copyright (C) 2002 William Lachance (wrlach@gmail.com) |
18 | | * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) |
19 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
20 | | * Copyright (C) 2006, 2007 Andrew Ziem |
21 | | * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) |
22 | | * |
23 | | * |
24 | | * All Rights Reserved. |
25 | | * |
26 | | * For minor contributions see the git repository. |
27 | | * |
28 | | * Alternatively, the contents of this file may be used under the terms of |
29 | | * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), |
30 | | * in which case the provisions of the LGPLv2+ are applicable |
31 | | * instead of those above. |
32 | | */ |
33 | | |
34 | | #include <algorithm> |
35 | | #include <iomanip> |
36 | | #include <iostream> |
37 | | #include <set> |
38 | | #include <sstream> |
39 | | #include <utility> |
40 | | |
41 | | #include <librevenge/librevenge.h> |
42 | | |
43 | | #include "MWAWDebug.hxx" |
44 | | #include "MWAWEntry.hxx" |
45 | | #include "MWAWOLEParser.hxx" |
46 | | |
47 | | #include "PowerPoint3OLE.hxx" |
48 | | |
49 | | /** Internal: the structures of a PowerPoint3OLE */ |
50 | | namespace PowerPoint3OLEInternal |
51 | | { |
52 | | //////////////////////////////////////// |
53 | | //! Internal: the state of a PowerPoint3OLE |
54 | | struct State { |
55 | | //! constructor |
56 | | explicit State(MWAWInputStreamPtr input, int vers) |
57 | 2.99k | : m_input(input) |
58 | 2.99k | , m_version(vers) |
59 | 2.99k | , m_oleParser() |
60 | 2.99k | , m_unparsedNameSet() |
61 | 2.99k | { |
62 | 2.99k | } |
63 | | /** the input */ |
64 | | MWAWInputStreamPtr m_input; |
65 | | /** the version */ |
66 | | int m_version; |
67 | | /** the ole parser */ |
68 | | std::shared_ptr<MWAWOLEParser> m_oleParser; |
69 | | /** the list of unparsed zone */ |
70 | | std::set<std::string> m_unparsedNameSet; |
71 | | }; |
72 | | |
73 | | } |
74 | | |
75 | | //////////////////////////////////////////////////////////// |
76 | | // constructor/destructor, ... |
77 | | //////////////////////////////////////////////////////////// |
78 | | PowerPoint3OLE::PowerPoint3OLE(MWAWInputStreamPtr const &input, int vers, MWAWFontConverterPtr const &fontConverter, int fId) |
79 | 2.99k | : m_state(new PowerPoint3OLEInternal::State(input, vers)) |
80 | 2.99k | { |
81 | 2.99k | char const *mainOle =(version()<=4 ? "PP40" : "PowerPoint Document"); |
82 | 2.99k | if (input && input->isStructured() && input->getSubStreamByName(mainOle)) |
83 | 2.99k | m_state->m_oleParser.reset(new MWAWOLEParser(mainOle, fontConverter, fId)); |
84 | 2.99k | } |
85 | | |
86 | | PowerPoint3OLE::~PowerPoint3OLE() |
87 | 2.99k | { |
88 | 2.99k | } |
89 | | |
90 | | int PowerPoint3OLE::version() const |
91 | 8.36k | { |
92 | 8.36k | return m_state->m_version; |
93 | 8.36k | } |
94 | | |
95 | | int PowerPoint3OLE::getFontEncoding() const |
96 | 2.99k | { |
97 | 2.99k | if (m_state->m_oleParser) |
98 | 2.99k | return m_state->m_oleParser->getFontEncoding(); |
99 | 0 | return -1; |
100 | 2.99k | } |
101 | | |
102 | | void PowerPoint3OLE::updateMetaData(librevenge::RVNGPropertyList &metaData) const |
103 | 1.20k | { |
104 | 1.20k | if (m_state->m_oleParser) |
105 | 1.20k | m_state->m_oleParser->updateMetaData(metaData); |
106 | 1.20k | } |
107 | | |
108 | | //////////////////////////////////////////////////////////// |
109 | | // the parser |
110 | | //////////////////////////////////////////////////////////// |
111 | | bool PowerPoint3OLE::parse() |
112 | 2.99k | { |
113 | 2.99k | int const vers=version(); |
114 | 2.99k | MWAWInputStreamPtr input=m_state->m_input; |
115 | 2.99k | if (!input || !m_state->m_oleParser || !m_state->m_oleParser->parse(input)) return false; |
116 | 2.99k | std::vector<std::string> unparsed = m_state->m_oleParser->getNotParse(); |
117 | | |
118 | 6.13k | for (auto const &name : unparsed) { |
119 | | // separated the directory and the name |
120 | | // MatOST/MatadorObject1/Ole10Native |
121 | | // -> dir="MatOST/MatadorObject1", base="Ole10Native" |
122 | 6.13k | std::string::size_type pos = name.find_last_of('/'); |
123 | 6.13k | std::string base; |
124 | 6.13k | if (pos == std::string::npos) base = name; |
125 | 1.15k | else if (pos == 0) base = name.substr(1); |
126 | 1.15k | else |
127 | 1.15k | base = name.substr(pos+1); |
128 | | |
129 | 6.13k | MWAWInputStreamPtr ole = input->getSubStreamByName(name.c_str()); |
130 | 6.13k | if (!ole.get()) { |
131 | 0 | MWAW_DEBUG_MSG(("PowerPoint3OLE::createZones: error: can not find OLE part: \"%s\"\n", name.c_str())); |
132 | 0 | continue; |
133 | 0 | } |
134 | 6.13k | ole->setReadInverted(true); |
135 | 6.13k | bool done=false; |
136 | 6.13k | switch (base[0]) { |
137 | 3.00k | case 'C': |
138 | 3.00k | if (base=="Current User") |
139 | 2.36k | done=parseCurrentUser(ole, name); |
140 | 632 | else if (base=="Current ID") |
141 | 56 | done=parseCurrentId(ole, name); |
142 | 3.00k | break; |
143 | 470 | case 'H': |
144 | 470 | if (vers>=7 && name=="Header") |
145 | 463 | done=parseHeader(ole, name); |
146 | 470 | break; |
147 | 1.33k | case 'P': |
148 | 1.33k | if (vers>=7 && name=="PersistentStorage Directory") |
149 | 1.31k | done=parsePersistentStorage(ole, name); |
150 | 1.33k | break; |
151 | 1.33k | default: |
152 | 1.33k | break; |
153 | 6.13k | } |
154 | 6.13k | if (done) continue; |
155 | 1.96k | m_state->m_unparsedNameSet.insert(name); |
156 | 1.96k | } |
157 | 2.99k | return true; |
158 | 2.99k | } |
159 | | |
160 | | void PowerPoint3OLE::checkForUnparsedStream() |
161 | 0 | { |
162 | 0 | int const vers=version(); |
163 | 0 | for (auto const &name : m_state->m_unparsedNameSet) { |
164 | 0 | if (vers>=7 && name=="Text_Content") continue; |
165 | 0 | auto pos = name.find_last_of('/'); |
166 | 0 | std::string base; |
167 | 0 | if (pos == std::string::npos) base = name; |
168 | 0 | else if (pos == 0) base = name.substr(1); |
169 | 0 | else |
170 | 0 | base = name.substr(pos+1); |
171 | 0 | MWAWInputStreamPtr ole = m_state->m_input->getSubStreamByName(name.c_str()); |
172 | 0 | if (!ole.get()) { |
173 | 0 | MWAW_DEBUG_MSG(("PowerPoint3OLE::checkForUnparsedStream: error: can not find OLE part: \"%s\"\n", name.c_str())); |
174 | 0 | continue; |
175 | 0 | } |
176 | 0 | libmwaw::DebugFile asciiFile(ole); |
177 | 0 | asciiFile.open(name); |
178 | 0 | libmwaw::DebugStream f; |
179 | 0 | f << "Entries(" << base << "):"; |
180 | 0 | asciiFile.addPos(0); |
181 | 0 | asciiFile.addNote(f.str().c_str()); |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | | //////////////////////////////////////////////////////////// |
186 | | // try to read the different stream |
187 | | //////////////////////////////////////////////////////////// |
188 | | bool PowerPoint3OLE::parseCurrentId(MWAWInputStreamPtr input, std::string const &name) |
189 | 56 | { |
190 | 56 | if (!input||input->size()!=4) { |
191 | 1 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentId: can not find the input\n")); |
192 | 1 | return false; |
193 | 1 | } |
194 | 55 | libmwaw::DebugFile ascFile(input); |
195 | 55 | ascFile.open(name); |
196 | 55 | input->seek(0, librevenge::RVNG_SEEK_SET); |
197 | 55 | libmwaw::DebugStream f; |
198 | 55 | f << "Entries(CurrentId):"; |
199 | 55 | auto val=int(input->readLong(4)); |
200 | 55 | if (val) f << "id=" << val << ","; |
201 | 55 | ascFile.addPos(0); |
202 | 55 | ascFile.addNote(f.str().c_str()); |
203 | 55 | return true; |
204 | 56 | } |
205 | | |
206 | | bool PowerPoint3OLE::parseCurrentUser(MWAWInputStreamPtr input, std::string const &name) |
207 | 2.36k | { |
208 | 2.36k | int const vers=version(); |
209 | 2.36k | int const szSize=vers<=4 ? 1 : 4; |
210 | 2.36k | if (!input||input->size() < szSize) { |
211 | 23 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentUser: can not find the input\n")); |
212 | 23 | return false; |
213 | 23 | } |
214 | 2.34k | libmwaw::DebugFile ascFile(input); |
215 | 2.34k | ascFile.open(name); |
216 | 2.34k | input->seek(0, librevenge::RVNG_SEEK_SET); |
217 | 2.34k | long endPos=input->size(); |
218 | 2.34k | libmwaw::DebugStream f; |
219 | 2.34k | f << "Entries(CurrentUser):"; |
220 | 2.34k | auto sSz=int(input->readULong(szSize)); |
221 | 2.34k | if (sSz<0 || sSz>input->size()-szSize) { |
222 | 96 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parseCurrentUser: the stream size seems bad\n")); |
223 | 96 | f << "###sSz,"; |
224 | 96 | ascFile.addPos(0); |
225 | 96 | ascFile.addNote(f.str().c_str()); |
226 | 96 | return true; |
227 | 96 | } |
228 | 2.25k | std::string user; |
229 | 7.43k | for (int c=0; c<sSz; ++c) { |
230 | 5.18k | auto ch=char(input->readULong(1)); |
231 | 5.18k | if (ch) |
232 | 4.29k | user+=ch; |
233 | 888 | else if (c+1!=sSz) |
234 | 865 | f << "###"; |
235 | 5.18k | } |
236 | 2.25k | f << user; |
237 | 2.25k | ascFile.addPos(0); |
238 | 2.25k | ascFile.addNote(f.str().c_str()); |
239 | 2.25k | if (input->tell()!=endPos) { |
240 | 1.73k | ascFile.addPos(input->tell()); |
241 | 1.73k | ascFile.addNote("CurrentUser:##extra"); |
242 | 1.73k | } |
243 | 2.25k | return true; |
244 | 2.34k | } |
245 | | |
246 | | bool PowerPoint3OLE::parseHeader(MWAWInputStreamPtr input, std::string const &name) |
247 | 463 | { |
248 | 463 | if (!input || input->size()<19) { |
249 | 3 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parseHeader: the input seems bad\n")); |
250 | 3 | return false; |
251 | 3 | } |
252 | 460 | input->seek(0, librevenge::RVNG_SEEK_SET); |
253 | 460 | long endPos=input->size(); |
254 | 460 | libmwaw::DebugFile ascFile(input); |
255 | 460 | ascFile.open(name); |
256 | 460 | libmwaw::DebugStream f; |
257 | 460 | f << "Entries(Headr):"; |
258 | 460 | std::string text; // Microsoft (R) PowerPoint (R) Windows |
259 | 15.2k | for (long i=0; i<endPos; ++i) { |
260 | 15.2k | auto c=char(input->readULong(1)); |
261 | 15.2k | if (!c) break; |
262 | 14.8k | text+=c; |
263 | 14.8k | } |
264 | 460 | f << text << ","; |
265 | 460 | if (input->tell()+18>endPos) { |
266 | 16 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parseHeader: the input seems short\n")); |
267 | 16 | f << "###"; |
268 | 16 | ascFile.addDelimiter(input->tell(),'|'); |
269 | 16 | ascFile.addPos(0); |
270 | 16 | ascFile.addNote(f.str().c_str()); |
271 | 16 | return true; |
272 | 16 | } |
273 | 4.44k | for (int i=0; i<9; ++i) { |
274 | 3.99k | auto val=int(input->readULong(2)); |
275 | 3.99k | int const expected[]= {7,0,0x3f0,0,0xc05f,0xe391,1,0,0}; |
276 | 3.99k | if (val!=expected[i]) f << "f" << i << "=" << std::hex << val << std::dec << ","; |
277 | 3.99k | } |
278 | 444 | ascFile.addPos(0); |
279 | 444 | ascFile.addNote(f.str().c_str()); |
280 | 444 | if (input->tell()!=endPos) { |
281 | 112 | ascFile.addPos(input->tell()); |
282 | 112 | ascFile.addNote("Headr:###"); |
283 | 112 | } |
284 | 444 | return true; |
285 | 460 | } |
286 | | |
287 | | bool PowerPoint3OLE::parsePersistentStorage(MWAWInputStreamPtr input, std::string const &name) |
288 | 1.31k | { |
289 | 1.31k | if (!input || input->size()<62) { |
290 | 11 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parsePersistentStorage: the input seems bad\n")); |
291 | 11 | return false; |
292 | 11 | } |
293 | 1.30k | input->seek(0, librevenge::RVNG_SEEK_SET); |
294 | 1.30k | long endPos=input->size(); |
295 | 1.30k | libmwaw::DebugFile ascFile(input); |
296 | 1.30k | ascFile.open(name); |
297 | 1.30k | libmwaw::DebugStream f; |
298 | 1.30k | f << "Entries(PersistentStorage):"; |
299 | 1.30k | int val; |
300 | 3.92k | for (int i=0; i<2; ++i) { // f1=3c6|3e0 |
301 | 2.61k | val=int(input->readULong(2)); |
302 | 2.61k | int const expected[]= {7,0x3e0}; |
303 | 2.61k | if (val!=expected[i]) |
304 | 2.36k | f << "f" << i << "=" << val << ","; |
305 | 2.61k | } |
306 | 18.2k | for (int i=0; i<13; ++i) { // f9=f11=f13=1 |
307 | 16.9k | val=int(input->readULong(2)); |
308 | 16.9k | if (val) f << "f" << i+2 << "=" << val << ","; |
309 | 16.9k | } |
310 | 1.30k | auto sSz=int(input->readULong(4)); |
311 | 1.30k | if (sSz<0 || endPos-30-8<sSz || 30+sSz+8>endPos) { |
312 | 287 | MWAW_DEBUG_MSG(("PowerPoint3OLE::parsePersistentStorage: the string size seems bad\n")); |
313 | 287 | f << "###sSz=" << sSz << ","; |
314 | 287 | ascFile.addPos(0); |
315 | 287 | ascFile.addNote(f.str().c_str()); |
316 | 287 | return true; |
317 | 287 | } |
318 | 1.02k | std::string text; // PowerPoint Document |
319 | 22.3k | for (int i=0; i<sSz; ++i) { |
320 | 21.2k | auto c=char(input->readULong(1)); |
321 | 21.2k | if (c) |
322 | 11.0k | text+=c; |
323 | 10.2k | else if (i+1!=sSz) { |
324 | 10.0k | MWAW_DEBUG_MSG(("PowerPoint3OLE::parsePersistentStorage: the name seems bad\n")); |
325 | 10.0k | f << "##name,"; |
326 | 10.0k | } |
327 | 21.2k | } |
328 | 1.02k | f << text << ","; |
329 | 5.10k | for (int i=0; i<4; ++i) { // g0=1 |
330 | 4.08k | val=int(input->readULong(2)); |
331 | 4.08k | if (val) f << "g" << i << "=" << val << ","; |
332 | 4.08k | } |
333 | 1.02k | ascFile.addPos(0); |
334 | 1.02k | ascFile.addNote(f.str().c_str()); |
335 | 1.02k | if (input->tell()!=endPos) { // seems junk, unsure |
336 | 1.01k | ascFile.addPos(input->tell()); |
337 | 1.01k | ascFile.addNote("_"); |
338 | 1.01k | } |
339 | 1.02k | return true; |
340 | 1.30k | } |
341 | | |
342 | | //////////////////////////////////////////////////////////// |
343 | | // try to send data |
344 | | //////////////////////////////////////////////////////////// |
345 | | |
346 | | |
347 | | // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: |