Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / hwpfilter / source / hwpfile.cxx
bloba97c39cc8eb65b57aa8f6b68b0a398f6684a1e25
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>
28 #include "hwplib.h"
29 #include "hwpfile.h"
30 #include "hiodev.h"
31 #include "hfont.h"
32 #include "hstyle.h"
33 #include "hbox.h"
34 #include "hpara.h"
35 #include "htags.h"
36 #include "hcode.h"
37 #include "hstream.hxx"
40 HWPFile *HWPFile::cur_doc = nullptr;
41 static int ccount = 0;
42 static int pcount = 0;
43 static int datecodecount = 0;
45 HWPFile::HWPFile()
46 : version(HWP_V30)
47 , compressed(false)
48 , encrypted(false)
49 , linenumber(0)
50 , info_block_len(0)
51 , error_code(HWP_NoError)
52 , readdepth(0)
53 , m_nCurrentPage(1)
54 , m_nMaxSettedPage(0)
55 , currenthyper(0)
57 SetCurrentDoc(this);
60 HWPFile::~HWPFile()
62 oledata.reset();
63 hiodev.reset();
66 int HWPFile::ReadHwpFile(std::unique_ptr<HStream> stream)
68 if (Open(std::move(stream)) != HWP_NoError)
69 return State();
70 InfoRead();
71 FontRead();
72 StyleRead();
73 AddColumnInfo();
74 ParaListRead();
75 TagsRead();
77 return State();
80 int detect_hwp_version(const char *str)
82 if (memcmp(V20SIGNATURE, str, HWPIDLen) == 0)
83 return HWP_V20;
84 else if (memcmp(V21SIGNATURE, str, HWPIDLen) == 0)
85 return HWP_V21;
86 else if (memcmp(V30SIGNATURE, str, HWPIDLen) == 0)
87 return HWP_V30;
88 return 0;
91 // HIODev wrapper
93 int HWPFile::Open(std::unique_ptr<HStream> stream)
95 std::unique_ptr<HStreamIODev> hstreamio(new HStreamIODev(std::move(stream)));
97 if (!hstreamio->open())
99 return SetState(HWP_EMPTY_FILE);
102 SetIODevice(std::move(hstreamio));
104 char idstr[HWPIDLen];
106 if (ReadBlock(idstr, HWPIDLen) < HWPIDLen
107 || HWP_V30 != (version = detect_hwp_version(idstr)))
109 return SetState(HWP_UNSUPPORTED_VERSION);
111 return HWP_NoError;
114 int HWPFile::SetState(int errcode)
116 error_code = errcode;
117 return error_code;
120 bool HWPFile::Read1b(unsigned char &out)
122 return hiodev && hiodev->read1b(out);
125 bool HWPFile::Read1b(char &out)
127 unsigned char tmp8;
128 if (!hiodev || !hiodev->read1b(tmp8))
129 return false;
130 out = tmp8;
131 return true;
134 bool HWPFile::Read2b(unsigned short &out)
136 return hiodev && hiodev->read2b(out);
139 bool HWPFile::Read4b(unsigned int &out)
141 return hiodev && hiodev->read4b(out);
144 bool HWPFile::Read4b(int &out)
146 unsigned int tmp32;
147 if (!Read4b(tmp32))
148 return false;
149 out = tmp32;
150 return true;
153 size_t HWPFile::Read2b(void *ptr, size_t nmemb)
155 return hiodev ? hiodev->read2b(ptr, nmemb) : 0;
158 void HWPFile::Read4b(void *ptr, size_t nmemb)
160 if (hiodev)
161 hiodev->read4b(ptr, nmemb);
164 size_t HWPFile::ReadBlock(void *ptr, size_t size)
166 return hiodev ? hiodev->readBlock(ptr, size) : 0;
169 size_t HWPFile::SkipBlock(size_t size)
171 return hiodev ? hiodev->skipBlock(size) : 0;
174 void HWPFile::SetCompressed(bool flag)
176 if (hiodev)
177 hiodev->setCompressed(flag);
181 std::unique_ptr<HIODev> HWPFile::SetIODevice(std::unique_ptr<HIODev> new_hiodev)
183 std::swap(hiodev, new_hiodev);
184 return new_hiodev;
188 // end of HIODev wrapper
190 void HWPFile::InfoRead()
192 _hwpInfo.Read(*this);
196 void HWPFile::FontRead()
198 _hwpFont.Read(*this);
202 void HWPFile::StyleRead()
204 _hwpStyle.Read(*this);
208 void HWPFile::ParaListRead()
210 ReadParaList(plist);
213 void HWPFile::ReadParaList(std::vector < HWPPara* > &aplist)
215 std::unique_ptr<HWPPara> spNode( new HWPPara );
216 unsigned char tmp_etcflag;
217 unsigned char prev_etcflag = 0;
218 while (spNode->Read(*this, 0))
220 if( !(spNode->etcflag & 0x04) ){
221 tmp_etcflag = spNode->etcflag;
222 spNode->etcflag = prev_etcflag;
223 prev_etcflag = tmp_etcflag;
225 if (spNode->nch && spNode->reuse_shape)
227 if (!aplist.empty()){
228 spNode->pshape = aplist.back()->pshape;
230 else{
231 spNode->nch = 0;
232 spNode->reuse_shape = 0;
235 spNode->pshape->pagebreak = spNode->etcflag;
236 if (spNode->nch)
237 AddParaShape(spNode->pshape);
239 if (!aplist.empty())
240 aplist.back()->SetNext(spNode.get());
241 aplist.push_back(spNode.release());
242 spNode.reset( new HWPPara );
246 void HWPFile::ReadParaList(std::vector< std::unique_ptr<HWPPara> > &aplist, unsigned char flag)
248 std::unique_ptr<HWPPara> spNode( new HWPPara );
249 unsigned char tmp_etcflag;
250 unsigned char prev_etcflag = 0;
251 while (spNode->Read(*this, flag))
253 if( !(spNode->etcflag & 0x04) ){
254 tmp_etcflag = spNode->etcflag;
255 spNode->etcflag = prev_etcflag;
256 prev_etcflag = tmp_etcflag;
258 if (spNode->nch && spNode->reuse_shape)
260 if (!aplist.empty()){
261 spNode->pshape = aplist.back()->pshape;
263 else{
264 spNode->nch = 0;
265 spNode->reuse_shape = 0;
268 spNode->pshape->pagebreak = spNode->etcflag;
269 if (spNode->nch)
270 AddParaShape(spNode->pshape);
272 if (!aplist.empty())
273 aplist.back()->SetNext(spNode.get());
274 aplist.push_back(std::move(spNode));
275 spNode.reset( new HWPPara );
279 void HWPFile::TagsRead()
281 while (true)
283 uint tag;
284 if (!Read4b(tag))
285 return;
286 int size;
287 if (!Read4b(size))
288 return;
289 if (size <= 0 && tag > 0){
290 continue;
293 if (tag == FILETAG_END_OF_COMPRESSED ||
294 tag == FILETAG_END_OF_UNCOMPRESSED)
295 return;
296 switch (tag)
298 case FILETAG_EMBEDDED_PICTURE:
300 std::unique_ptr<EmPicture> emb(new EmPicture(size));
302 if (emb->Read(*this))
303 emblist.push_back(std::move(emb));
305 break;
306 case FILETAG_OLE_OBJECT:
307 oledata.reset( new OlePicture(size) );
308 oledata->Read(*this);
309 break;
310 case FILETAG_HYPERTEXT:
312 const int nRecordLen = 617;
313 if( (size % nRecordLen) != 0 )
314 SkipBlock( size );
315 else
317 const int nRecords = size / nRecordLen;
318 for (int i = 0 ; i < nRecords; ++i)
320 std::unique_ptr<HyperText> hypert(new HyperText);
321 if (hypert->Read(*this))
322 hyperlist.push_back(std::move(hypert));
323 else
324 break;
327 break;
329 case 6:
331 ReadBlock(_hwpInfo.back_info.reserved1, 8);
332 if (!Read4b(_hwpInfo.back_info.luminance))
333 return;
334 if (!Read4b(_hwpInfo.back_info.contrast))
335 return;
336 if (!Read1b(_hwpInfo.back_info.effect))
337 return;
338 ReadBlock(_hwpInfo.back_info.reserved2, 7);
339 ReadBlock(_hwpInfo.back_info.filename, 260);
340 ReadBlock(_hwpInfo.back_info.color, 3);
341 unsigned short nFlag;
342 if (!Read2b(nFlag))
343 return;
344 _hwpInfo.back_info.flag = nFlag >> 8 ;
345 int nRange;
346 if (!Read4b(nRange))
347 return;
348 _hwpInfo.back_info.range = nRange >> 24;
349 ReadBlock(_hwpInfo.back_info.reserved3, 27);
350 if (!Read4b(_hwpInfo.back_info.size))
351 return;
353 if (_hwpInfo.back_info.size < 0)
355 _hwpInfo.back_info.size = 0;
356 return;
359 _hwpInfo.back_info.data.clear();
361 //read potentially compressed data in blocks as its more
362 //likely large values are simply broken and we'll run out
363 //of data before we need to realloc
364 for (int i = 0; i < _hwpInfo.back_info.size; i+= SAL_MAX_UINT16)
366 int nOldSize = _hwpInfo.back_info.data.size();
367 size_t nBlock = std::min<int>(SAL_MAX_UINT16, _hwpInfo.back_info.size - nOldSize);
368 _hwpInfo.back_info.data.resize(nOldSize + nBlock);
369 size_t nReadBlock = ReadBlock(_hwpInfo.back_info.data.data() + nOldSize, nBlock);
370 if (nBlock != nReadBlock)
372 _hwpInfo.back_info.data.resize(nOldSize + nReadBlock);
373 break;
376 _hwpInfo.back_info.size = _hwpInfo.back_info.data.size();
378 if( _hwpInfo.back_info.size > 0 )
379 _hwpInfo.back_info.type = 2;
380 else if( _hwpInfo.back_info.filename[0] )
381 _hwpInfo.back_info.type = 1;
382 else
383 _hwpInfo.back_info.type = 0;
386 _hwpInfo.back_info.isset = true;
388 break;
390 case FILETAG_PRESENTATION:
391 case FILETAG_PREVIEW_IMAGE:
392 case FILETAG_PREVIEW_TEXT:
393 default:
394 SkipBlock(size);
400 ColumnDef *HWPFile::GetColumnDef(int num)
402 if (static_cast<size_t>(num) < columnlist.size())
403 return columnlist[num]->xColdef.get();
404 else
405 return nullptr;
408 /* Index of @return starts from 1 */
409 int HWPFile::GetPageMasterNum(int page)
411 int i = 0;
412 for (auto const& column : columnlist)
414 if( page < column->start_page )
415 return i;
416 ++i;
418 return i;
421 HyperText *HWPFile::GetHyperText()
423 ++currenthyper;
424 if (static_cast<size_t>(currenthyper) <= hyperlist.size())
425 return hyperlist[currenthyper-1].get();
426 else
427 return nullptr;
430 EmPicture *HWPFile::GetEmPicture(Picture * pic)
432 char *name = pic->picinfo.picembed.embname;
434 name[0] = 'H';
435 name[1] = 'W';
436 name[2] = 'P';
438 for (auto const& emb : emblist)
439 if (strcmp(name, emb->name) == 0)
440 return emb.get();
441 return nullptr;
444 EmPicture *HWPFile::GetEmPictureByName(char * name)
446 name[0] = 'H';
447 name[1] = 'W';
448 name[2] = 'P';
450 for (auto const& emb : emblist)
451 if (strcmp(name, emb->name) == 0)
452 return emb.get();
453 return nullptr;
456 void HWPFile::AddBox(FBox * box)
458 blist.push_back(box);
461 ParaShape *HWPFile::getParaShape(int index)
463 if (index < 0 || static_cast<unsigned int>(index) >= pslist.size())
464 return nullptr;
465 return pslist[index].get();
468 CharShape *HWPFile::getCharShape(int index)
470 if (index < 0 || static_cast<unsigned int>(index) >= cslist.size())
471 return nullptr;
472 return cslist[index].get();
475 FBoxStyle *HWPFile::getFBoxStyle(int index)
477 if (index < 0 || static_cast<unsigned int>(index) >= fbslist.size())
478 return nullptr;
479 return fbslist[index];
482 DateCode *HWPFile::getDateCode(int index)
484 if (index < 0 || static_cast<unsigned int>(index) >= datecodes.size())
485 return nullptr;
486 return datecodes[index];
489 HeaderFooter *HWPFile::getHeaderFooter(int index)
491 if (index < 0 || static_cast<unsigned int>(index) >= headerfooters.size())
492 return nullptr;
493 return headerfooters[index];
496 ShowPageNum *HWPFile::getPageNumber(int index)
498 if (index < 0 || static_cast<unsigned int>(index) >= pagenumbers.size())
499 return nullptr;
500 return pagenumbers[index];
503 Table *HWPFile::getTable(int index)
505 if (index < 0 || static_cast<unsigned int>(index) >= tables.size())
506 return nullptr;
507 return tables[index].get();
510 void HWPFile::AddParaShape(std::shared_ptr<ParaShape> const & pshape)
512 int nscount = 0;
513 for(int j = 0 ; j < MAXTABS-1 ; j++)
515 if( j > 0 && pshape->tabs[j].position == 0 )
516 break;
517 if( pshape->tabs[0].position == 0 ){
518 if( pshape->tabs[j].type || pshape->tabs[j].dot_continue ||
519 (pshape->tabs[j].position != 1000 *j) )
520 nscount = j;
522 else {
523 if( pshape->tabs[j].type || pshape->tabs[j].dot_continue ||
524 (pshape->tabs[j].position != 1000 * (j + 1)) )
525 nscount = j;
528 if( nscount )
530 pshape->tabs[MAXTABS-1].type = sal::static_int_cast<char>(nscount);
531 pshape->index = ++pcount;
532 pslist.push_back(pshape);
533 return;
536 int value = compareParaShape(pshape.get());
537 if (value == 0)
539 pshape->index = ++pcount;
540 pslist.push_back(pshape);
541 return;
543 pshape->index = value;
546 void HWPFile::AddCharShape(std::shared_ptr<CharShape> const & cshape)
548 int value = compareCharShape(cshape.get());
549 if (value == 0)
551 cshape->index = ++ccount;
552 cslist.push_back(cshape);
554 else
555 cshape->index = value;
558 void HWPFile::AddColumnInfo()
560 columnlist.emplace_back(new ColumnInfo(m_nCurrentPage));
561 setMaxSettedPage();
564 void HWPFile::SetColumnDef(const std::shared_ptr<ColumnDef>& rColdef)
566 ColumnInfo *cinfo = columnlist.back().get();
567 if( cinfo->bIsSet )
568 return;
569 cinfo->xColdef = rColdef;
570 cinfo->bIsSet = true;
573 void HWPFile::AddDateFormat(DateCode * hbox)
575 hbox->key = sal::static_int_cast<char>(++datecodecount);
576 datecodes.push_back(hbox);
579 void HWPFile::AddPageNumber(ShowPageNum * hbox)
581 pagenumbers.push_back(hbox);
584 void HWPFile::AddHeaderFooter(HeaderFooter * hbox)
586 headerfooters.push_back(hbox);
589 void HWPFile::AddTable(std::unique_ptr<Table> hbox)
591 tables.push_back(std::move(hbox));
594 void HWPFile::AddFBoxStyle(FBoxStyle * fbstyle)
596 fbslist.push_back(fbstyle);
599 int HWPFile::compareCharShape(CharShape const *shape)
601 int count = cslist.size();
602 if( count > 0 )
604 for(int i = 0; i< count; i++)
606 CharShape *cshape = getCharShape(i);
608 if( shape->size == cshape->size &&
609 shape->font[0] == cshape->font[0] &&
610 shape->ratio[0] == cshape->ratio[0] &&
611 shape->space[0] == cshape->space[0] &&
612 shape->color[1] == cshape->color[1] &&
613 shape->color[0] == cshape->color[0] &&
614 shape->shade == cshape->shade &&
615 shape->attr == cshape->attr )
617 return cshape->index;
621 return 0;
625 int HWPFile::compareParaShape(ParaShape const *shape)
627 int count = pslist.size();
628 if( count > 0 )
630 for(int i = 0; i< count; i++)
632 ParaShape *pshape = getParaShape(i);
633 if( shape->left_margin == pshape->left_margin &&
634 shape->right_margin == pshape->right_margin &&
635 shape->pspacing_prev == pshape->pspacing_prev &&
636 shape->pspacing_next == pshape->pspacing_next &&
637 shape->indent == pshape->indent &&
638 shape->lspacing == pshape->lspacing &&
639 shape->arrange_type == pshape->arrange_type &&
640 shape->outline == pshape->outline &&
641 shape->pagebreak == pshape->pagebreak)
643 if( shape->cshape && pshape->cshape &&
644 shape->cshape->size == pshape->cshape->size &&
645 shape->cshape->font[0] == pshape->cshape->font[0] &&
646 shape->cshape->ratio[0] == pshape->cshape->ratio[0] &&
647 shape->cshape->space[0] == pshape->cshape->space[0] &&
648 shape->cshape->color[1] == pshape->cshape->color[1] &&
649 shape->cshape->color[0] == pshape->cshape->color[0] &&
650 shape->cshape->shade == pshape->cshape->shade &&
651 shape->cshape->attr == pshape->cshape->attr )
653 return pshape->index;
658 return 0;
662 HWPFile *GetCurrentDoc()
664 return HWPFile::cur_doc;
668 HWPFile *SetCurrentDoc(HWPFile * hwpfp)
670 HWPFile *org = HWPFile::cur_doc;
672 HWPFile::cur_doc = hwpfp;
673 return org;
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */