1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3 /* libstaroffice
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 <cstring>
35 #include <iomanip>
36 #include <iostream>
37 #include <limits>
38 #include <sstream>
39
40 #include <librevenge/librevenge.h>
41
42 #include "StarAttribute.hxx"
43 #include "StarFileManager.hxx"
44 #include "StarItemPool.hxx"
45 #include "StarZone.hxx"
46 #include "StarFormatManager.hxx"
47
48 #include "StarObject.hxx"
49
50 /** Internal: the structures of a StarObject */
51 namespace StarObjectInternal
52 {
53 //! the state of a StarObject
54 struct State {
55 //! constructor
StateStarObjectInternal::State56 State()
57 : m_poolList()
58 , m_attributeManager(new StarAttributeManager)
59 , m_formatManager(new StarFormatManager)
60 {
61 }
62 //! copy constructor
63 State(State const &) = default;
64 //! the list of pool
65 std::vector<std::shared_ptr<StarItemPool> > m_poolList;
66 //! the attribute manager
67 std::shared_ptr<StarAttributeManager> m_attributeManager;
68 //! the format manager
69 std::shared_ptr<StarFormatManager> m_formatManager;
70 //! the list of user name
71 librevenge::RVNGString m_userMetaNames[4];
72 private:
73 State operator=(State const &) = delete;
74 };
75 }
76
77 ////////////////////////////////////////////////////////////
78 // constructor/destructor, ...
79 ////////////////////////////////////////////////////////////
StarObject(char const * passwd,std::shared_ptr<STOFFOLEParser> & oleParser,std::shared_ptr<STOFFOLEParser::OleDirectory> & directory)80 StarObject::StarObject(char const *passwd, std::shared_ptr<STOFFOLEParser> &oleParser, std::shared_ptr<STOFFOLEParser::OleDirectory> &directory)
81 : m_password(passwd)
82 , m_oleParser(oleParser)
83 , m_directory(directory)
84 , m_state(new StarObjectInternal::State())
85 , m_metaData()
86 {
87 }
88
StarObject(StarObject const & orig,bool duplicateState)89 StarObject::StarObject(StarObject const &orig, bool duplicateState)
90 : m_password(orig.m_password)
91 , m_oleParser(orig.m_oleParser)
92 , m_directory(orig.m_directory)
93 , m_state()
94 , m_metaData(orig.m_metaData)
95 {
96 if (duplicateState)
97 m_state.reset(new StarObjectInternal::State(*orig.m_state));
98 else
99 m_state.reset(new StarObjectInternal::State);
100 }
101
~StarObject()102 StarObject::~StarObject()
103 {
104 }
105
cleanPools()106 void StarObject::cleanPools()
107 {
108 for (auto &p : m_state->m_poolList) {
109 if (p)
110 p->clean();
111 }
112 m_state->m_poolList.clear();
113 }
114
getDocumentKind() const115 STOFFDocument::Kind StarObject::getDocumentKind() const
116 {
117 return m_directory ? m_directory->m_kind : STOFFDocument::STOFF_K_UNKNOWN;
118 }
119
getAttributeManager()120 std::shared_ptr<StarAttributeManager> StarObject::getAttributeManager()
121 {
122 return m_state->m_attributeManager;
123 }
124
getFormatManager()125 std::shared_ptr<StarFormatManager> StarObject::getFormatManager()
126 {
127 return m_state->m_formatManager;
128 }
129
getUserNameMetaData(int i) const130 librevenge::RVNGString StarObject::getUserNameMetaData(int i) const
131 {
132 if (i>=0 && i<=3) {
133 if (!m_state->m_userMetaNames[i].empty())
134 return m_state->m_userMetaNames[i];
135 }
136 STOFF_DEBUG_MSG(("StarObject::parse: can not find user meta data %d\n", i));
137 librevenge::RVNGString res;
138 res.sprintf("Info%d", i);
139 return res;
140 }
141
getNewItemPool(StarItemPool::Type type)142 std::shared_ptr<StarItemPool> StarObject::getNewItemPool(StarItemPool::Type type)
143 {
144 std::shared_ptr<StarItemPool> pool(new StarItemPool(*this, type));
145 m_state->m_poolList.push_back(pool);
146 return pool;
147 }
148
getCurrentPool(bool onlyInside)149 std::shared_ptr<StarItemPool> StarObject::getCurrentPool(bool onlyInside)
150 {
151 for (size_t i=m_state->m_poolList.size(); i>0;) {
152 auto pool=m_state->m_poolList[--i];
153 if (pool && !pool->isSecondaryPool() && (!onlyInside || pool->isInside()))
154 return pool;
155 }
156 return std::shared_ptr<StarItemPool>();
157 }
158
findItemPool(StarItemPool::Type type,bool isInside)159 std::shared_ptr<StarItemPool> StarObject::findItemPool(StarItemPool::Type type, bool isInside)
160 {
161 for (size_t i=m_state->m_poolList.size(); i>0;) {
162 auto pool=m_state->m_poolList[--i];
163 if (!pool || pool->getType()!=type) continue;
164 if (isInside && !pool->isInside()) continue;
165 return pool;
166 }
167 return std::shared_ptr<StarItemPool>();
168 }
169
parse()170 bool StarObject::parse()
171 {
172 if (!m_directory) {
173 STOFF_DEBUG_MSG(("StarObject::parse: can not find directory\n"));
174 return false;
175 }
176 if (!m_directory->m_hasCompObj) {
177 STOFF_DEBUG_MSG(("StarObject::parse: called with unknown document\n"));
178 }
179 for (auto &content : m_directory->m_contentList) {
180 if (content.isParsed()) continue;
181 auto name = content.getOleName();
182 auto const &base = content.getBaseName();
183 STOFFInputStreamPtr ole;
184 if (m_directory->m_input)
185 ole = m_directory->m_input->getSubStreamByName(name.c_str());
186 if (!ole.get()) {
187 STOFF_DEBUG_MSG(("StarObject::createZones: error: can not find OLE part: \"%s\"\n", name.c_str()));
188 continue;
189 }
190
191 ole->setReadInverted(true);
192 if (base=="VCPool") {
193 content.setParsed(true);
194 StarZone zone(ole, name, "VCPool", m_password);
195 zone.ascii().open(name);
196 ole->seek(0, librevenge::RVNG_SEEK_SET);
197 getNewItemPool(StarItemPool::T_VCControlPool)->read(zone);
198 continue;
199 }
200 if (base=="persist elements") {
201 content.setParsed(true);
202 readPersistElements(ole, name);
203 continue;
204 }
205 if (base=="SfxPreview") {
206 content.setParsed(true);
207 readSfxPreview(ole, name);
208 continue;
209 }
210 if (base=="SfxDocumentInfo") {
211 content.setParsed(true);
212 readSfxDocumentInformation(ole, name);
213 continue;
214 }
215 libstoff::DebugFile asciiFile(ole);
216 asciiFile.open(name);
217
218 bool ok=false;
219 if (base=="SfxWindows")
220 ok=readSfxWindows(ole, asciiFile);
221 else if (base=="Star Framework Config File")
222 ok=readStarFrameworkConfigFile(ole, asciiFile);
223 content.setParsed(ok);
224 }
225
226 return true;
227 }
228
readItemSet(StarZone & zone,std::vector<STOFFVec2i> const &,long lastPos,StarItemSet & itemSet,StarItemPool * pool,bool isDirect)229 bool StarObject::readItemSet(StarZone &zone, std::vector<STOFFVec2i> const &/*limits*/, long lastPos,
230 StarItemSet &itemSet, StarItemPool *pool, bool isDirect)
231 {
232 STOFFInputStreamPtr input=zone.input();
233 long pos=input->tell();
234 libstoff::DebugFile &ascFile=zone.ascii();
235 libstoff::DebugStream f;
236
237 itemSet.m_whichToItemMap.clear();
238 f << "Entries(StarItem):pool,";
239 // itemset.cxx: SfxItemSet::Load (ncount)
240 uint16_t n;
241 *input >> n;
242 f << "N=" << n << ",";
243 if (!pool) {
244 if (input->tell()+6*n > lastPos) {
245 STOFF_DEBUG_MSG(("StarObject::readItemSet: can not read a SfxItemSet\n"));
246 f << "###,";
247 ascFile.addPos(pos);
248 ascFile.addNote(f.str().c_str());
249
250 return false;
251 }
252 if (n) {
253 if (lastPos!=pos+2+6*n) {
254 // TODO poolio.cxx SfxItemPool::LoadItem
255 static bool first=true;
256 if (first) {
257 STOFF_DEBUG_MSG(("StarObject::readItemSet: reading a SfxItem is not implemented without pool\n"));
258 first=false;
259 }
260 f << "##noPool,";
261 }
262 else
263 f << "#";
264 input->seek(pos+2+6*n, librevenge::RVNG_SEEK_SET);
265 }
266 ascFile.addPos(pos);
267 ascFile.addNote(f.str().c_str());
268 return true;
269 }
270 ascFile.addPos(pos);
271 ascFile.addNote(f.str().c_str());
272 for (int i=0; i<int(n); ++i) {
273 pos=input->tell();
274 auto item=pool->readItem(zone, isDirect, lastPos);
275 if (item && input->tell()<=lastPos) {
276 itemSet.add(item);
277 continue;
278 }
279 input->seek(pos, librevenge::RVNG_SEEK_SET);
280 ascFile.addPos(pos);
281 ascFile.addNote("StarItem:pool,###extra");
282 break;
283 }
284 return true;
285 }
286
readPersistElements(STOFFInputStreamPtr input,std::string const & name)287 bool StarObject::readPersistElements(STOFFInputStreamPtr input, std::string const &name)
288 {
289 StarZone zone(input, name, "PersistsElement", m_password);
290 libstoff::DebugFile &ascii=zone.ascii();
291 ascii.open(name);
292 input->seek(0, librevenge::RVNG_SEEK_SET);
293 libstoff::DebugStream f;
294 f << "Entries(Persists):";
295 // persist.cxx: SvPersist::LoadContent
296 if (input->size()<21 || input->readLong(1)!=2) {
297 STOFF_DEBUG_MSG(("StarObject::readPersistElements: data seems bad\n"));
298 f << "###";
299 ascii.addPos(0);
300 ascii.addNote(f.str().c_str());
301 return true;
302 }
303 auto hasElt=int(input->readLong(1));
304 if (hasElt==1) {
305 if (input->size()<29) {
306 STOFF_DEBUG_MSG(("StarObject::readPersistElements: flag hasData, but zone seems too short\n"));
307 f << "###";
308 hasElt=0;
309 }
310 f << "hasData,";
311 }
312 else if (hasElt) {
313 STOFF_DEBUG_MSG(("StarObject::readPersistElements: flag hasData seems bad\n"));
314 f << "#hasData=" << hasElt << ",";
315 hasElt=0;
316 }
317 int val;
318 int N=0;
319 long endDataPos=0;
320 if (hasElt) {
321 val=int(input->readULong(1)); // always 80?
322 if (val!=0x80) f << "#f0=" << std::hex << val << std::dec << ",";
323 auto dSz=long(input->readULong(4));
324 N=int(input->readULong(4));
325 f << "dSz=" << dSz << ",N=" << N << ",";
326 if (!dSz || 7+dSz+18>input->size()) {
327 STOFF_DEBUG_MSG(("StarObject::readPersistElements: data size seems bad\n"));
328 f << "###dSz";
329 dSz=0;
330 N=0;
331 }
332 endDataPos=7+dSz;
333 }
334 ascii.addPos(0);
335 ascii.addNote(f.str().c_str());
336 for (int i=0; i<N; ++i) {
337 long pos=input->tell();
338 if (readPersistData(zone, endDataPos))
339 continue;
340 input->seek(pos, librevenge::RVNG_SEEK_SET);
341 f.str("");
342 f << "Persists-A" << i << ":";
343 STOFF_DEBUG_MSG(("StarObject::readPersistElements: data %d seems bad\n", i));
344 f << "###";
345 ascii.addPos(pos);
346 ascii.addNote(f.str().c_str());
347 break;
348 }
349 input->seek(-18, librevenge::RVNG_SEEK_END);
350 long pos=input->tell();
351 f.str("");
352 f << "Persists-B:";
353 int dim[4];
354 for (int &i : dim) i=int(input->readLong(4));
355 f << "dim=" << STOFFBox2i(STOFFVec2i(dim[0],dim[1]), STOFFVec2i(dim[2],dim[3])) << ",";
356 val=int(input->readLong(2)); // 0|9
357 if (val) f << "f0=" << val << ",";
358 ascii.addPos(pos);
359 ascii.addNote(f.str().c_str());
360 return true;
361 }
362
readPersistData(StarZone & zone,long lastPos)363 bool StarObject::readPersistData(StarZone &zone, long lastPos)
364 {
365 // pstm.cxx SvPersistStream::ReadObj
366 STOFFInputStreamPtr input=zone.input();
367 long pos=input->tell();
368 libstoff::DebugFile &ascii=zone.ascii();
369 libstoff::DebugStream f;
370 f << "Entries(PersistData)["<< zone.getRecordLevel() << "]:";
371 // SvPersistStream::ReadId
372 uint8_t hdr;
373 *input >> hdr;
374 long id=0, classId=0;
375 bool ok=true;
376 if (hdr&0x80) // nId=0
377 ;
378 else {
379 if ((hdr&0xf)==0) {
380 if ((hdr&0x20) || !(hdr&0x40))
381 ok=input->readCompressedLong(id);
382 }
383 else if (hdr&0x10)
384 ok=input->readCompressedLong(id);
385 if (hdr&0x60)
386 ok=input->readCompressedLong(classId);
387 }
388 if (id) f << "id=" << id << ",";
389 if (classId) f << "id[class]=" << classId << ",";
390 if (!ok || !hdr || input->tell()>lastPos) {
391 STOFF_DEBUG_MSG(("StarObject::readPersistData: find unexpected header\n"));
392 f << "###header";
393 ascii.addPos(pos);
394 ascii.addNote(f.str().c_str());
395 return false;
396 }
397 if (hdr&0x80 || (hdr&0x40)==0) {
398 ascii.addPos(pos);
399 ascii.addNote(f.str().c_str());
400 return true;
401 }
402 if (hdr&0x20) {
403 ok=zone.openSCRecord();
404 if (!ok || zone.getRecordLastPosition()>lastPos) {
405 STOFF_DEBUG_MSG(("StarObject::readPersistData: can not open main zone\n"));
406 if (ok) zone.closeSCRecord("PersistData");
407 f << "###,";
408 ascii.addPos(pos);
409 ascii.addNote(f.str().c_str());
410 return false;
411 }
412 lastPos=zone.getRecordLastPosition();
413 }
414 if (hdr&0x40) {
415 // app.cxx OfficeApplication::Init, or SV_DECL_PERSIST1
416 switch (classId) {
417 // case 1 SvxFieldData:: or SvInfoObject:: or SvClassElement::
418 case 2: { // embobj.cxx SvEmbeddedInfoObject::Load
419 long actPos=input->tell();
420 // SvInfoObject::Load
421 uint8_t vers;
422 *input>>vers;
423 f << "objData,";
424 if (vers) f << "vers=" << int(vers) << ","; // 0 or 1
425 bool objOk=true;
426 for (int i=0; i<2; ++i) {
427 std::vector<uint32_t> text;
428 if (!zone.readString(text)||input->tell()+16>=lastPos) {
429 input->seek(actPos, librevenge::RVNG_SEEK_SET);
430 f << "##stringId" << i << ",";
431 objOk=false;
432 break;
433 }
434 f << libstoff::getString(text).cstr() << ",";
435 }
436 if (!objOk) break;
437 // SvGlobalName::operator<<
438 int val;
439 for (int i=0; i<3; ++i) {
440 val=int(input->readULong(i==0 ? 4 : 2));
441 if (val)
442 f << "data" << i << "=" << std::hex << val << std::dec << ",";
443 }
444 f << "data3=[";
445 for (int i=0; i<8; ++i) {
446 val=int (input->readULong(1));
447 if (val)
448 f<< std::hex << val << std::dec << ",";
449 else
450 f << "_,";
451 }
452 f << "],";
453 if (vers>0) {
454 val=int (input->readULong(1));
455 if (val) f << "deleted,";
456 }
457 if (input->readULong(1)!=2 || input->tell()+17>lastPos) {
458 STOFF_DEBUG_MSG(("StarObject::readPersistData: can not find the object info\n"));
459 input->seek(actPos, librevenge::RVNG_SEEK_SET);
460 f << "##badInfo" << ",";
461 break;
462 }
463 val=int (input->readULong(1));
464 if (val)
465 f << "isLink,";
466 f << "rect=[";
467 for (int i=0; i<4; ++i) f << input->readLong(4) << ",";
468 f << "],";
469 break;
470 }
471 default:
472 STOFF_DEBUG_MSG(("StarObject::readPersistData: unknown class id\n"));
473 f << "##classId";
474 break;
475 }
476 }
477 if (input->tell()!=lastPos)
478 ascii.addDelimiter(input->tell(),'|');
479 input->seek(lastPos, librevenge::RVNG_SEEK_SET);
480 if (hdr&0x20)
481 zone.closeSCRecord("PersistData");
482
483 ascii.addPos(pos);
484 ascii.addNote(f.str().c_str());
485 return true;
486 }
487
readSfxDocumentInformation(STOFFInputStreamPtr input,std::string const & name)488 bool StarObject::readSfxDocumentInformation(STOFFInputStreamPtr input, std::string const &name)
489 {
490 StarZone zone(input, name, "SfxDocInfo", nullptr); // no password
491 libstoff::DebugFile &ascii=zone.ascii();
492 ascii.open(name);
493 input->seek(0, librevenge::RVNG_SEEK_SET);
494
495 libstoff::DebugStream f;
496 f << "Entries(SfxDocInfo):";
497
498 // see sfx2_docinf.cxx
499 auto sSz=int(input->readULong(2));
500 if (2+sSz>input->size()) {
501 STOFF_DEBUG_MSG(("StarObject::readSfxDocumentInformation: header seems bad\n"));
502 f << "###sSz=" << sSz << ",";
503 ascii.addPos(0);
504 ascii.addNote(f.str().c_str());
505 return true;
506 }
507 std::string text("");
508 for (int i=0; i<sSz; ++i) text+=char(input->readULong(1));
509 if (text!="SfxDocumentInfo") {
510 STOFF_DEBUG_MSG(("StarObject::readSfxDocumentInformation: header seems bad\n"));
511 f << "###text=" << text << ",";
512 ascii.addPos(0);
513 ascii.addNote(f.str().c_str());
514 return true;
515 }
516 // FileHeader::FileHeader, SfxDocumentInfo::Load
517 uint16_t nVersion, nUS;
518 bool bPasswd, bPGraphic, bQTemplate;
519 *input >> nVersion >> bPasswd >> nUS >> bPGraphic >> bQTemplate;
520 if (nVersion) f << "vers=" << std::hex << nVersion << std::dec << ",";
521 if (nUS) f << "encoding=" << nUS << ","; // need to load encoding here
522 if (bPasswd) f << "passwd,"; // the password does not seems to be kept/used in this block
523 if (bPGraphic) f << "portableGraphic,";
524 if (bQTemplate) f << "queryTemplate,";
525 auto encoding=StarEncoding::getEncodingForId(nUS);
526 ascii.addPos(0);
527 ascii.addNote(f.str().c_str());
528
529 librevenge::RVNGString prevAttrib;
530 for (int i=0; i<17; ++i) {
531 long pos=input->tell();
532 f.str("");
533 f << "SfxDocInfo-A" << i << ":";
534 auto dSz=int(input->readULong(2));
535 int expectedSz= i < 3 ? 33 : i < 5 ? 65 : i==5 ? 257 : i==6 ? 129 : i<15 ? 21 : 2;
536 static char const *wh[]= {
537 "time[creation]","time[mod]","time[print]","title","subject","comment","keyword",
538 "user0[name]", "user0[data]","user1[name]", "user1[data]","user2[name]", "user2[data]","user3[name]", "user3[data]",
539 "template[name]", "template[filename]"
540 };
541 f << wh[i] << ",";
542 if (dSz+2>expectedSz) {
543 if (i<15)
544 expectedSz+=0x10000; // rare but can happen, probably due to a bug when calling SkipRep with a negative value
545 else
546 expectedSz=2+dSz;
547 }
548 if (pos+expectedSz+(i<3 ? 8 : 0)>input->size()) {
549 STOFF_DEBUG_MSG(("StarObject::readSfxDocumentInformation: can not read string %d\n", i));
550 f << "###";
551 ascii.addPos(pos);
552 ascii.addNote(f.str().c_str());
553 return true;
554 }
555 std::vector<uint8_t> string;
556 for (int c=0; c<dSz; ++c) string.push_back(static_cast<uint8_t>(input->readULong(1)));
557 std::vector<uint32_t> finalString;
558 std::vector<size_t> srcPositions;
559 if (StarEncoding::convert(string, encoding, finalString, srcPositions)) {
560 auto attrib=libstoff::getString(finalString);
561 f << attrib.cstr() << ",";
562 static char const *attribNames[] = {
563 "meta:initial-creator", "dc:creator", "", "dc:title", "dc:subject", "dc:description"/*comment*/, "meta:keywords",
564 "", "user", "", "user", "", "user", "", "user",
565 "librevenge:template-name", "librevenge:template-filename"
566 };
567 if ((i%2)==1 && i>=7 && i<=13)
568 m_state->m_userMetaNames[(i-7)/2]=attrib;
569 if (attrib.empty() || std::string(attribNames[i]).empty())
570 prevAttrib=attrib;
571 else if (std::string(attribNames[i])=="user") {
572 if (!prevAttrib.empty()) {
573 librevenge::RVNGString userMeta("librevenge:");
574 userMeta.append(prevAttrib);
575 m_metaData.insert(userMeta.cstr(), attrib);
576 }
577 }
578 else
579 m_metaData.insert(attribNames[i], attrib);
580 }
581 else {
582 STOFF_DEBUG_MSG(("StarObject::readSfxDocumentInformation: can not convert a string\n"));
583 f << "###string,";
584 prevAttrib.clear();
585 }
586 input->seek(pos+expectedSz, librevenge::RVNG_SEEK_SET);
587 if (i<3) {
588 uint32_t date, time;
589 *input >> date >> time;
590 f << "date=" << date << ", time=" << time << ",";
591 std::string dateTime;
592 if (date && libstoff::convertToDateTime(date,time, dateTime)) {
593 static char const *attribNames[]= { "meta:creation-date", "dc:date", "meta:print-date" };
594 m_metaData.insert(attribNames[i], dateTime.c_str());
595 }
596 }
597 ascii.addPos(pos);
598 ascii.addNote(f.str().c_str());
599 }
600
601 long pos=input->tell();
602 f.str("");
603 f << "SfxDocInfo-B:";
604 if (pos+8>input->size()) {
605 STOFF_DEBUG_MSG(("StarObject::readSfxDocumentInformation: last zone seems too short\n"));
606 f << "###";
607 ascii.addPos(pos);
608 ascii.addNote(f.str().c_str());
609 return true;
610 }
611 uint32_t date, time;
612 *input >> date >> time;
613 f << "date=" << date << ", time=" << time << ",";
614 // the following depend on the file version, so let try to get the mail address and stop
615 if (input->tell()+6 <= input->size()) { // [MailAddr], lTime, ...
616 uint16_t nMailAdr;
617 *input >> nMailAdr;
618 if (nMailAdr && nMailAdr<20 && input->tell()+4*nMailAdr<input->tell()) {
619 f << "mailAdr=[";
620 for (int i=0; i<int(nMailAdr); ++i) {
621 sSz=int(input->readULong(2));
622 if (input->tell()+sSz+2>input->size())
623 break;
624 for (int c=0; c<sSz; ++c) text+=char(input->readULong(1));
625 f << text.c_str() << ",";
626 input->seek(2, librevenge::RVNG_SEEK_CUR); // flag dummy
627 }
628 f << "],";
629 }
630 }
631 if (!input->isEnd()) ascii.addDelimiter(input->tell(),'|');
632 ascii.addPos(pos);
633 ascii.addNote(f.str().c_str());
634
635 return true;
636 }
637
readSfxStyleSheets(STOFFInputStreamPtr input,std::string const & name)638 bool StarObject::readSfxStyleSheets(STOFFInputStreamPtr input, std::string const &name)
639 {
640 StarZone zone(input, name, "SfxStyleSheets", getPassword());
641 input->seek(0, librevenge::RVNG_SEEK_SET);
642 libstoff::DebugFile &ascFile=zone.ascii();
643 ascFile.open(name);
644
645 // sd_sdbinfilter.cxx SdBINFilter::Import: one pool followed by a pool style
646 // chart sch_docshell.cxx SchChartDocShell::Load
647 std::shared_ptr<StarItemPool> pool;
648 if (getDocumentKind()==STOFFDocument::STOFF_K_DRAW || getDocumentKind()==STOFFDocument::STOFF_K_PRESENTATION) {
649 pool=getNewItemPool(StarItemPool::T_XOutdevPool);
650 pool->addSecondaryPool(getNewItemPool(StarItemPool::T_EditEnginePool));
651 }
652 auto mainPool=pool;
653 while (!input->isEnd()) {
654 // REMOVEME: remove this loop, when creation of secondary pool is checked
655 long pos=input->tell();
656 bool extraPool=false;
657 if (!pool) {
658 extraPool=true;
659 pool=getNewItemPool(StarItemPool::T_Unknown);
660 }
661 if (pool && pool->read(zone)) {
662 if (extraPool) {
663 STOFF_DEBUG_MSG(("StarObject::readSfxStyleSheets: create extra pool for %d of type %d\n",
664 int(getDocumentKind()), int(pool->getType())));
665 }
666 if (!mainPool) mainPool=pool;
667 pool.reset();
668 continue;
669 }
670 input->seek(pos, librevenge::RVNG_SEEK_SET);
671 break;
672 }
673 if (input->isEnd()) return true;
674 long pos=input->tell();
675 if (!mainPool || !mainPool->readStyles(zone, *this)) {
676 STOFF_DEBUG_MSG(("StarObject::readSfxStyleSheets: can not read a style pool\n"));
677 input->seek(pos, librevenge::RVNG_SEEK_SET);
678 }
679 if (!input->isEnd()) {
680 STOFF_DEBUG_MSG(("StarObject::readSfxStyleSheets: find extra data\n"));
681 ascFile.addPos(input->tell());
682 ascFile.addNote("Entries(SfxStyleSheets):###extra");
683 }
684 return true;
685 }
686
readStarFrameworkConfigFile(STOFFInputStreamPtr input,libstoff::DebugFile & asciiFile)687 bool StarObject::readStarFrameworkConfigFile(STOFFInputStreamPtr input, libstoff::DebugFile &asciiFile)
688 {
689 input->seek(0, librevenge::RVNG_SEEK_SET);
690 libstoff::DebugStream f;
691 f << "Entries(StarFrameworkConfig):";
692 // see sfx2_cfgimex SfxConfigManagerImExport_Impl::Import
693 std::string header("");
694 for (int i=0; i<26; ++i) header+=char(input->readULong(1));
695 if (!input->checkPosition(33)||header!="Star Framework Config File") {
696 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: the header seems bad\n"));
697 f << "###" << header;
698 asciiFile.addPos(0);
699 asciiFile.addNote(f.str().c_str());
700 return true;
701 }
702 uint8_t cC;
703 uint16_t fileVersion;
704 int32_t lDirPos;
705 *input >> cC >> fileVersion >> lDirPos;
706 if (cC!=26) f << "c=" << cC << ",";
707 if (fileVersion!=26) f << "vers=" << fileVersion << ",";
708 auto pos=long(lDirPos);
709 if (!input->checkPosition(pos+2)) {
710 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: dir pos is bad\n"));
711 f << "###dirPos" << pos << ",";
712 asciiFile.addPos(0);
713 asciiFile.addNote(f.str().c_str());
714 return true;
715 }
716 if (input->tell()!=pos) asciiFile.addDelimiter(input->tell(),'|');
717 asciiFile.addPos(0);
718 asciiFile.addNote(f.str().c_str());
719
720 input->seek(pos, librevenge::RVNG_SEEK_SET);
721 f.str("");
722 f << "StarFrameworkConfig:";
723 uint16_t N;
724 *input >> N;
725 f << "N=" << N << ",";
726 for (uint16_t i=0; i<N; ++i) {
727 if (input->isEnd()) {
728 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: oops, end of file\n"));
729 f << "###";
730 break;
731 }
732 f << "item" << i << "=[";
733 uint16_t nType;
734 int32_t lPos, lLength;
735 *input >> nType >> lPos >> lLength;
736 if (nType) f << "nType=" << nType << ",";
737 if (lPos!=-1) {
738 long actPos=input->tell();
739 STOFFEntry entry;
740 entry.setId(int(nType));
741 entry.setBegin(lPos);
742 entry.setLength(lLength);
743 readStarFrameworkConfigItem(entry, input, asciiFile);
744 input->seek(actPos, librevenge::RVNG_SEEK_SET);
745 if (lLength) f << "len=" << lLength << ",";
746 }
747 auto strSz=int(input->readULong(2));
748 if (!input->checkPosition(input->tell()+strSz)) {
749 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: a item seems bad\n"));
750 f << "###item,";
751 break;
752 }
753 std::string name("");
754 for (int c=0; c<strSz; ++c) name+=char(input->readULong(1));
755 f << name << ",";
756 f << "],";
757 }
758 asciiFile.addPos(pos);
759 asciiFile.addNote(f.str().c_str());
760
761 return true;
762 }
763
readStarFrameworkConfigItem(STOFFEntry & entry,STOFFInputStreamPtr input,libstoff::DebugFile & asciiFile)764 bool StarObject::readStarFrameworkConfigItem(STOFFEntry &entry, STOFFInputStreamPtr input, libstoff::DebugFile &asciiFile)
765 {
766 libstoff::DebugStream f;
767 f << "StarFrameworkConfig[Item]:";
768 // see sfx2_cfgimex SfxConfigManagerImExport_Impl::ImportItem
769 if (!entry.valid() || !input->checkPosition(long(entry.end()))) {
770 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: a item position seems bad\n"));
771 f << "###";
772 asciiFile.addPos(entry.begin());
773 asciiFile.addNote(f.str().c_str());
774
775 return true;
776 }
777 input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
778 uint16_t nType;
779 *input >> nType;
780 f << "type=" << nType << ",";
781 if (nType!=uint16_t(entry.id()) &&
782 !(1294 <= nType && nType <= 1301 && 1294 <= entry.id() && entry.id() <= 1301)) {
783 STOFF_DEBUG_MSG(("StarObject::readStarFrameworkConfigFile: find unexpected type\n"));
784 f << "###";
785 asciiFile.addPos(entry.begin());
786 asciiFile.addNote(f.str().c_str());
787
788 return true;
789 }
790 f << "#";
791 // readme, some toolbar, ...
792 if (input->tell()!=entry.length())
793 asciiFile.addDelimiter(input->tell(),'|');
794
795 asciiFile.addPos(entry.begin());
796 asciiFile.addNote(f.str().c_str());
797 return true;
798 }
799
readSfxPreview(STOFFInputStreamPtr input,std::string const & name)800 bool StarObject::readSfxPreview(STOFFInputStreamPtr input, std::string const &name)
801 {
802 StarZone zone(input, name, "SfxPreview", m_password);
803 libstoff::DebugFile &ascii=zone.ascii();
804 ascii.open(name);
805 input->seek(0, librevenge::RVNG_SEEK_SET);
806 StarFileManager fileManager;
807 if (!fileManager.readSVGDI(zone)) {
808 STOFF_DEBUG_MSG(("StarObject::readSfxPreview: can not find the first image\n"));
809 input->seek(0, librevenge::RVNG_SEEK_SET);
810 }
811 if (input->isEnd()) return true;
812
813 long pos=input->tell();
814 libstoff::DebugStream f;
815 STOFF_DEBUG_MSG(("StarObject::readSfxPreview: find extra data\n"));
816 f << "Entries(SfxPreview):###extra";
817
818 ascii.addPos(pos);
819 ascii.addNote(f.str().c_str());
820
821 return true;
822 }
823
readSfxWindows(STOFFInputStreamPtr input,libstoff::DebugFile & ascii)824 bool StarObject::readSfxWindows(STOFFInputStreamPtr input, libstoff::DebugFile &ascii)
825 {
826 input->seek(0, librevenge::RVNG_SEEK_SET);
827 libstoff::DebugStream f;
828 f << "Entries(SfWindows):";
829 // see sc_docsh.cxx
830 ascii.addPos(0);
831 ascii.addNote(f.str().c_str());
832 while (!input->isEnd()) {
833 long pos=input->tell();
834 if (!input->checkPosition(pos+2))
835 break;
836 auto dSz=int(input->readULong(2));
837 if (!input->checkPosition(pos+2+dSz)) {
838 input->seek(pos, librevenge::RVNG_SEEK_SET);
839 break;
840 }
841 f.str("");
842 f << "SfWindows:";
843 std::string text("");
844 for (int i=0; i<dSz; ++i) text+=char(input->readULong(1));
845 f << text;
846 ascii.addPos(pos);
847 ascii.addNote(f.str().c_str());
848 }
849 if (!input->isEnd()) {
850 STOFF_DEBUG_MSG(("StarObject::readSfxWindows: find extra data\n"));
851 ascii.addPos(input->tell());
852 ascii.addNote("SfWindows:extra###");
853 }
854 return true;
855 }
856
857 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
858