nss: upgrade to release 3.73
[LibreOffice.git] / hwpfilter / source / hwpfile.cxx
blob8be445919ed40482011333211a52b0ca4bf293f4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include "precompile.h"
23 #include <algorithm>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
29 #include <o3tl/safeint.hxx>
31 #include "hwplib.h"
32 #include "hwpfile.h"
33 #include "hiodev.h"
34 #include "hfont.h"
35 #include "hstyle.h"
36 #include "hbox.h"
37 #include "hpara.h"
38 #include "htags.h"
39 #include "hcode.h"
40 #include "hstream.hxx"
43 HWPFile *HWPFile::cur_doc = nullptr;
44 static int ccount = 0;
45 static int pcount = 0;
46 static int datecodecount = 0;
48 HWPFile::HWPFile()
49 : version(HWP_V30)
50 , compressed(false)
51 , encrypted(false)
52 , linenumber(0)
53 , info_block_len(0)
54 , error_code(HWP_NoError)
55 , readdepth(0)
56 , m_nCurrentPage(1)
57 , m_nMaxSettedPage(0)
58 , currenthyper(0)
60 SetCurrentDoc(this);
63 HWPFile::~HWPFile()
65 oledata.reset();
66 hiodev.reset();
69 int HWPFile::ReadHwpFile(std::unique_ptr<HStream> stream)
71 if (Open(std::move(stream)) != HWP_NoError)
72 return State();
73 InfoRead();
74 FontRead();
75 StyleRead();
76 AddColumnInfo();
77 ParaListRead();
78 TagsRead();
80 return State();
83 int detect_hwp_version(const char *str)
85 if (memcmp(V20SIGNATURE, str, HWPIDLen) == 0)
86 return HWP_V20;
87 else if (memcmp(V21SIGNATURE, str, HWPIDLen) == 0)
88 return HWP_V21;
89 else if (memcmp(V30SIGNATURE, str, HWPIDLen) == 0)
90 return HWP_V30;
91 return 0;
94 // HIODev wrapper
96 int HWPFile::Open(std::unique_ptr<HStream> stream)
98 std::unique_ptr<HStreamIODev> hstreamio(new HStreamIODev(std::move(stream)));
100 if (!hstreamio->open())
102 return SetState(HWP_EMPTY_FILE);
105 SetIODevice(std::move(hstreamio));
107 char idstr[HWPIDLen];
109 if (ReadBlock(idstr, HWPIDLen) < HWPIDLen)
110 return SetState(HWP_UNSUPPORTED_VERSION);
111 version = detect_hwp_version(idstr);
112 if (HWP_V30 != version)
113 return SetState(HWP_UNSUPPORTED_VERSION);
114 return HWP_NoError;
117 int HWPFile::SetState(int errcode)
119 error_code = errcode;
120 return error_code;
123 bool HWPFile::Read1b(unsigned char &out)
125 return hiodev && hiodev->read1b(out);
128 bool HWPFile::Read1b(char &out)
130 unsigned char tmp8;
131 if (!hiodev || !hiodev->read1b(tmp8))
132 return false;
133 out = tmp8;
134 return true;
137 bool HWPFile::Read2b(unsigned short &out)
139 return hiodev && hiodev->read2b(out);
142 bool HWPFile::Read4b(unsigned int &out)
144 return hiodev && hiodev->read4b(out);
147 bool HWPFile::Read4b(int &out)
149 unsigned int tmp32;
150 if (!Read4b(tmp32))
151 return false;
152 out = tmp32;
153 return true;
156 size_t HWPFile::Read2b(void *ptr, size_t nmemb)
158 return hiodev ? hiodev->read2b(ptr, nmemb) : 0;
161 void HWPFile::Read4b(void *ptr, size_t nmemb)
163 if (hiodev)
164 hiodev->read4b(ptr, nmemb);
167 size_t HWPFile::ReadBlock(void *ptr, size_t size)
169 return hiodev ? hiodev->readBlock(ptr, size) : 0;
172 size_t HWPFile::SkipBlock(size_t size)
174 return hiodev ? hiodev->skipBlock(size) : 0;
177 void HWPFile::SetCompressed(bool flag)
179 if (hiodev)
180 hiodev->setCompressed(flag);
184 std::unique_ptr<HIODev> HWPFile::SetIODevice(std::unique_ptr<HIODev> new_hiodev)
186 std::swap(hiodev, new_hiodev);
187 return new_hiodev;
191 // end of HIODev wrapper
193 void HWPFile::InfoRead()
195 _hwpInfo.Read(*this);
199 void HWPFile::FontRead()
201 _hwpFont.Read(*this);
205 void HWPFile::StyleRead()
207 _hwpStyle.Read(*this);
211 void HWPFile::ParaListRead()
213 ReadParaList(plist);
216 void HWPFile::ReadParaList(std::vector < HWPPara* > &aplist)
218 std::unique_ptr<HWPPara> spNode( new HWPPara );
219 unsigned char tmp_etcflag;
220 unsigned char prev_etcflag = 0;
221 while (spNode->Read(*this, 0))
223 if( !(spNode->etcflag & 0x04) ){
224 tmp_etcflag = spNode->etcflag;
225 spNode->etcflag = prev_etcflag;
226 prev_etcflag = tmp_etcflag;
228 if (spNode->nch && spNode->reuse_shape)
230 if (!aplist.empty()){
231 spNode->pshape = aplist.back()->pshape;
233 else{
234 spNode->nch = 0;
235 spNode->reuse_shape = 0;
238 spNode->pshape->pagebreak = spNode->etcflag;
239 if (spNode->nch)
240 AddParaShape(spNode->pshape);
242 if (!aplist.empty())
243 aplist.back()->SetNext(spNode.get());
244 aplist.push_back(spNode.release());
245 spNode.reset( new HWPPara );
249 void HWPFile::ReadParaList(std::vector< std::unique_ptr<HWPPara> > &aplist, unsigned char flag)
251 std::unique_ptr<HWPPara> spNode( new HWPPara );
252 unsigned char tmp_etcflag;
253 unsigned char prev_etcflag = 0;
254 while (spNode->Read(*this, flag))
256 if( !(spNode->etcflag & 0x04) ){
257 tmp_etcflag = spNode->etcflag;
258 spNode->etcflag = prev_etcflag;
259 prev_etcflag = tmp_etcflag;
261 if (spNode->nch && spNode->reuse_shape)
263 if (!aplist.empty()){
264 spNode->pshape = aplist.back()->pshape;
266 else{
267 spNode->nch = 0;
268 spNode->reuse_shape = 0;
271 spNode->pshape->pagebreak = spNode->etcflag;
272 if (spNode->nch)
273 AddParaShape(spNode->pshape);
275 if (!aplist.empty())
276 aplist.back()->SetNext(spNode.get());
277 aplist.push_back(std::move(spNode));
278 spNode.reset( new HWPPara );
282 void HWPFile::TagsRead()
284 while (true)
286 uint tag;
287 if (!Read4b(tag))
288 return;
289 int size;
290 if (!Read4b(size))
291 return;
292 if (size <= 0 && tag > 0){
293 continue;
296 if (tag == FILETAG_END_OF_COMPRESSED ||
297 tag == FILETAG_END_OF_UNCOMPRESSED)
298 return;
299 switch (tag)
301 case FILETAG_EMBEDDED_PICTURE:
303 std::unique_ptr<EmPicture> emb(new EmPicture(size));
305 if (emb->Read(*this))
306 emblist.push_back(std::move(emb));
308 break;
309 case FILETAG_OLE_OBJECT:
310 oledata.reset( new OlePicture(size) );
311 oledata->Read(*this);
312 break;
313 case FILETAG_HYPERTEXT:
315 const int nRecordLen = 617;
316 if( (size % nRecordLen) != 0 )
317 SkipBlock( size );
318 else
320 const int nRecords = size / nRecordLen;
321 for (int i = 0 ; i < nRecords; ++i)
323 std::unique_ptr<HyperText> hypert(new HyperText);
324 if (hypert->Read(*this))
325 hyperlist.push_back(std::move(hypert));
326 else
327 break;
330 break;
332 case 6:
334 ReadBlock(_hwpInfo.back_info.reserved1, 8);
335 if (!Read4b(_hwpInfo.back_info.luminance))
336 return;
337 if (!Read4b(_hwpInfo.back_info.contrast))
338 return;
339 if (!Read1b(_hwpInfo.back_info.effect))
340 return;
341 ReadBlock(_hwpInfo.back_info.reserved2, 7);
342 ReadBlock(_hwpInfo.back_info.filename, 260);
343 ReadBlock(_hwpInfo.back_info.color, 3);
344 unsigned short nFlag;
345 if (!Read2b(nFlag))
346 return;
347 _hwpInfo.back_info.flag = nFlag >> 8 ;
348 int nRange;
349 if (!Read4b(nRange))
350 return;
351 _hwpInfo.back_info.range = nRange >> 24;
352 ReadBlock(_hwpInfo.back_info.reserved3, 27);
353 if (!Read4b(_hwpInfo.back_info.size))
354 return;
356 if (_hwpInfo.back_info.size < 0)
358 _hwpInfo.back_info.size = 0;
359 return;
362 _hwpInfo.back_info.data.clear();
364 //read potentially compressed data in blocks as its more
365 //likely large values are simply broken and we'll run out
366 //of data before we need to realloc
367 for (int i = 0; i < _hwpInfo.back_info.size; i+= SAL_MAX_UINT16)
369 int nOldSize = _hwpInfo.back_info.data.size();
370 size_t nBlock = std::min<int>(SAL_MAX_UINT16, _hwpInfo.back_info.size - nOldSize);
371 _hwpInfo.back_info.data.resize(nOldSize + nBlock);
372 size_t nReadBlock = ReadBlock(_hwpInfo.back_info.data.data() + nOldSize, nBlock);
373 if (nBlock != nReadBlock)
375 _hwpInfo.back_info.data.resize(nOldSize + nReadBlock);
376 break;
379 _hwpInfo.back_info.size = _hwpInfo.back_info.data.size();
381 if( _hwpInfo.back_info.size > 0 )
382 _hwpInfo.back_info.type = 2;
383 else if( _hwpInfo.back_info.filename[0] )
384 _hwpInfo.back_info.type = 1;
385 else
386 _hwpInfo.back_info.type = 0;
389 _hwpInfo.back_info.isset = true;
391 break;
393 case FILETAG_PRESENTATION:
394 case FILETAG_PREVIEW_IMAGE:
395 case FILETAG_PREVIEW_TEXT:
396 default:
397 SkipBlock(size);
403 ColumnDef *HWPFile::GetColumnDef(int num)
405 if (o3tl::make_unsigned(num) < columnlist.size())
406 return columnlist[num]->xColdef.get();
407 else
408 return nullptr;
411 /* Index of @return starts from 1 */
412 int HWPFile::GetPageMasterNum(int page)
414 int i = 0;
415 for (auto const& column : columnlist)
417 if( page < column->start_page )
418 return i;
419 ++i;
421 return i;
424 HyperText *HWPFile::GetHyperText()
426 ++currenthyper;
427 if (o3tl::make_unsigned(currenthyper) <= hyperlist.size())
428 return hyperlist[currenthyper-1].get();
429 else
430 return nullptr;
433 EmPicture *HWPFile::GetEmPicture(Picture * pic)
435 char *name = pic->picinfo.picembed.embname;
437 name[0] = 'H';
438 name[1] = 'W';
439 name[2] = 'P';
441 for (auto const& emb : emblist)
442 if (strcmp(name, emb->name) == 0)
443 return emb.get();
444 return nullptr;
447 EmPicture *HWPFile::GetEmPictureByName(char * name)
449 name[0] = 'H';
450 name[1] = 'W';
451 name[2] = 'P';
453 for (auto const& emb : emblist)
454 if (strcmp(name, emb->name) == 0)
455 return emb.get();
456 return nullptr;
459 void HWPFile::AddBox(FBox * box)
461 blist.push_back(box);
464 ParaShape *HWPFile::getParaShape(int index)
466 if (index < 0 || o3tl::make_unsigned(index) >= pslist.size())
467 return nullptr;
468 return pslist[index].get();
471 CharShape *HWPFile::getCharShape(int index)
473 if (index < 0 || o3tl::make_unsigned(index) >= cslist.size())
474 return nullptr;
475 return cslist[index].get();
478 FBoxStyle *HWPFile::getFBoxStyle(int index)
480 if (index < 0 || o3tl::make_unsigned(index) >= fbslist.size())
481 return nullptr;
482 return fbslist[index];
485 DateCode *HWPFile::getDateCode(int index)
487 if (index < 0 || o3tl::make_unsigned(index) >= datecodes.size())
488 return nullptr;
489 return datecodes[index];
492 HeaderFooter *HWPFile::getHeaderFooter(int index)
494 if (index < 0 || o3tl::make_unsigned(index) >= headerfooters.size())
495 return nullptr;
496 return headerfooters[index];
499 ShowPageNum *HWPFile::getPageNumber(int index)
501 if (index < 0 || o3tl::make_unsigned(index) >= pagenumbers.size())
502 return nullptr;
503 return pagenumbers[index];
506 Table *HWPFile::getTable(int index)
508 if (index < 0 || o3tl::make_unsigned(index) >= tables.size())
509 return nullptr;
510 return tables[index].get();
513 void HWPFile::AddParaShape(std::shared_ptr<ParaShape> const & pshape)
515 int nscount = 0;
516 for(int j = 0 ; j < MAXTABS-1 ; j++)
518 if( j > 0 && pshape->tabs[j].position == 0 )
519 break;
520 if( pshape->tabs[0].position == 0 ){
521 if( pshape->tabs[j].type || pshape->tabs[j].dot_continue ||
522 (pshape->tabs[j].position != 1000 *j) )
523 nscount = j;
525 else {
526 if( pshape->tabs[j].type || pshape->tabs[j].dot_continue ||
527 (pshape->tabs[j].position != 1000 * (j + 1)) )
528 nscount = j;
531 if( nscount )
533 pshape->tabs[MAXTABS-1].type = sal::static_int_cast<char>(nscount);
534 pshape->index = ++pcount;
535 pslist.push_back(pshape);
536 return;
539 int value = compareParaShape(pshape.get());
540 if (value == 0)
542 pshape->index = ++pcount;
543 pslist.push_back(pshape);
544 return;
546 pshape->index = value;
549 void HWPFile::AddCharShape(std::shared_ptr<CharShape> const & cshape)
551 int value = compareCharShape(cshape.get());
552 if (value == 0)
554 cshape->index = ++ccount;
555 cslist.push_back(cshape);
557 else
558 cshape->index = value;
561 void HWPFile::AddColumnInfo()
563 columnlist.emplace_back(new ColumnInfo(m_nCurrentPage));
564 setMaxSettedPage();
567 void HWPFile::SetColumnDef(const std::shared_ptr<ColumnDef>& rColdef)
569 ColumnInfo *cinfo = columnlist.back().get();
570 if( cinfo->bIsSet )
571 return;
572 cinfo->xColdef = rColdef;
573 cinfo->bIsSet = true;
576 void HWPFile::AddDateFormat(DateCode * hbox)
578 hbox->key = sal::static_int_cast<char>(++datecodecount);
579 datecodes.push_back(hbox);
582 void HWPFile::AddPageNumber(ShowPageNum * hbox)
584 pagenumbers.push_back(hbox);
587 void HWPFile::AddHeaderFooter(HeaderFooter * hbox)
589 headerfooters.push_back(hbox);
592 void HWPFile::AddTable(std::unique_ptr<Table> hbox)
594 tables.push_back(std::move(hbox));
597 void HWPFile::AddFBoxStyle(FBoxStyle * fbstyle)
599 fbslist.push_back(fbstyle);
602 int HWPFile::compareCharShape(CharShape const *shape)
604 int count = cslist.size();
605 if( count > 0 )
607 for(int i = 0; i< count; i++)
609 CharShape *cshape = getCharShape(i);
611 if( shape->size == cshape->size &&
612 shape->font[0] == cshape->font[0] &&
613 shape->ratio[0] == cshape->ratio[0] &&
614 shape->space[0] == cshape->space[0] &&
615 shape->color[1] == cshape->color[1] &&
616 shape->color[0] == cshape->color[0] &&
617 shape->shade == cshape->shade &&
618 shape->attr == cshape->attr )
620 return cshape->index;
624 return 0;
628 int HWPFile::compareParaShape(ParaShape const *shape)
630 int count = pslist.size();
631 if( count > 0 )
633 for(int i = 0; i< count; i++)
635 ParaShape *pshape = getParaShape(i);
636 if( shape->left_margin == pshape->left_margin &&
637 shape->right_margin == pshape->right_margin &&
638 shape->pspacing_prev == pshape->pspacing_prev &&
639 shape->pspacing_next == pshape->pspacing_next &&
640 shape->indent == pshape->indent &&
641 shape->lspacing == pshape->lspacing &&
642 shape->arrange_type == pshape->arrange_type &&
643 shape->outline == pshape->outline &&
644 shape->pagebreak == pshape->pagebreak)
646 if( shape->cshape && pshape->cshape &&
647 shape->cshape->size == pshape->cshape->size &&
648 shape->cshape->font[0] == pshape->cshape->font[0] &&
649 shape->cshape->ratio[0] == pshape->cshape->ratio[0] &&
650 shape->cshape->space[0] == pshape->cshape->space[0] &&
651 shape->cshape->color[1] == pshape->cshape->color[1] &&
652 shape->cshape->color[0] == pshape->cshape->color[0] &&
653 shape->cshape->shade == pshape->cshape->shade &&
654 shape->cshape->attr == pshape->cshape->attr )
656 return pshape->index;
661 return 0;
665 HWPFile *GetCurrentDoc()
667 return HWPFile::cur_doc;
671 HWPFile *SetCurrentDoc(HWPFile * hwpfp)
673 HWPFile *org = HWPFile::cur_doc;
675 HWPFile::cur_doc = hwpfp;
676 return org;
679 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */