Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libe-book/src/lib/EBOOKDocument.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/*
3
 * This file is part of the libe-book project.
4
 *
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/.
8
 */
9
10
#include "config.h"
11
12
#include <algorithm>
13
#include <cstring>
14
15
#include <libe-book/libe-book.h>
16
17
#include <librevenge-stream/librevenge-stream.h>
18
19
#include <libxml/HTMLparser.h>
20
#include <libxml/xmlreader.h>
21
22
#include "libebook_utils.h"
23
#include "libebook_xml.h"
24
#include "EBOOKHTMLToken.h"
25
#include "EBOOKOPFToken.h"
26
#include "EPubToken.h"
27
#include "FictionBook2Parser.h"
28
#include "FictionBook2Token.h"
29
#include "SoftBookParser.h"
30
#include "BBeBParser.h"
31
#include "PalmDocParser.h"
32
#include "PluckerParser.h"
33
#include "PeanutPressParser.h"
34
#include "QiOOParser.h"
35
#include "TCRParser.h"
36
#include "TealDocParser.h"
37
#include "ZTXTParser.h"
38
#include "ZVRParser.h"
39
40
#if defined LIBE_BOOK_EXPERIMENTAL
41
#include "HTMLHelpParser.h"
42
#include "HTMLHelpStream.h"
43
#include "EBOOKOPFParser.h"
44
#include "EPubParser.h"
45
#include "HTMLParser.h"
46
#include "OpenEBookParser.h"
47
#include "RocketEBookParser.h"
48
#endif
49
50
using std::unique_ptr;
51
using std::shared_ptr;
52
53
using librevenge::RVNGInputStream;
54
55
using std::equal;
56
57
namespace libebook
58
{
59
60
namespace
61
{
62
63
enum BOMEncoding
64
{
65
  BOM_ENCODING_UTF8,
66
  BOM_ENCODING_UTF16BE,
67
  BOM_ENCODING_UTF16LE,
68
  BOM_ENCODING_OTHER
69
};
70
71
static const unsigned char BOM_UTF8[] = "\xef\xbb\xbf";
72
static const unsigned char BOM_UTF16BE[] = "\xfe\xff";
73
static const unsigned char BOM_UTF16LE[] = "\xff\xfe";
74
75
static const unsigned char XML_DECL_UTF8[] = "<?xml ";
76
static const unsigned char XML_DECL_UTF16BE[] = "\0<\0?\0x\0m\0l\0 ";
77
static const unsigned char XML_DECL_UTF16LE[] = "<\0?\0x\0m\0l\0 \0";
78
79
BOMEncoding detectBOMEncoding(RVNGInputStream *const input)
80
0
{
81
0
  BOMEncoding encoding = BOM_ENCODING_OTHER;
82
83
0
  const unsigned char *const bom = readNBytes(input, 3);
84
0
  if (equal(BOM_UTF8, BOM_UTF8 + EBOOK_NUM_ELEMENTS(BOM_UTF8) - 1, bom))
85
0
    encoding = BOM_ENCODING_UTF8;
86
0
  else if (equal(BOM_UTF16BE, BOM_UTF16BE + EBOOK_NUM_ELEMENTS(BOM_UTF16BE) - 1, bom))
87
0
    encoding = BOM_ENCODING_UTF16BE;
88
0
  else if (equal(BOM_UTF16LE, BOM_UTF16LE + EBOOK_NUM_ELEMENTS(BOM_UTF16LE) - 1, bom))
89
0
    encoding = BOM_ENCODING_UTF16LE;
90
0
  else
91
0
    seek(input, 0); // no BOM, return the swallowed chars back
92
93
0
  return encoding;
94
0
}
95
96
bool isXML(RVNGInputStream *const input)
97
0
{
98
0
  bool xml = false;
99
100
0
  const unsigned char *decl = nullptr;
101
0
  unsigned len = 0;
102
103
0
  const BOMEncoding bom = detectBOMEncoding(input);
104
0
  switch (bom)
105
0
  {
106
0
  case BOM_ENCODING_UTF16BE :
107
0
    decl = XML_DECL_UTF16BE;
108
0
    len = EBOOK_NUM_ELEMENTS(XML_DECL_UTF16BE) - 1;
109
0
    break;
110
0
  case BOM_ENCODING_UTF16LE :
111
0
    decl = XML_DECL_UTF16LE;
112
0
    len = EBOOK_NUM_ELEMENTS(XML_DECL_UTF16LE) - 1;
113
0
    break;
114
0
  case BOM_ENCODING_UTF8 :
115
0
  case BOM_ENCODING_OTHER:
116
0
  default :
117
0
    len = EBOOK_NUM_ELEMENTS(XML_DECL_UTF8) - 1;
118
0
    decl = XML_DECL_UTF8;
119
0
  }
120
121
0
  const unsigned char *const data = readNBytes(input, len);
122
0
  xml = equal(decl, decl + len, data);
123
124
0
  seek(input, 0);
125
126
0
  return xml;
127
0
}
128
129
0
EBOOKDocument::Type detectXML(RVNGInputStream *const input) try
130
0
{
131
0
  EBOOKDocument::Type type = EBOOKDocument::TYPE_UNKNOWN;
132
133
0
  seek(input, 0);
134
135
0
  if (isXML(input))
136
0
  {
137
0
    const auto reader = makeXmlReader(input);
138
139
0
    if (bool(reader))
140
0
    {
141
0
      int ret = xmlTextReaderRead(reader.get());
142
143
      // seek to the first element and check its name
144
0
      while (1 == ret)
145
0
      {
146
0
        if (XML_READER_TYPE_ELEMENT == xmlTextReaderNodeType(reader.get()))
147
0
        {
148
0
          const char *const name = char_cast(xmlTextReaderConstLocalName(reader.get()));
149
0
          const char *const uri = char_cast(xmlTextReaderConstNamespaceUri(reader.get()));
150
0
          if ((+EBOOKHTMLToken::html | EBOOKHTMLToken::NS_html) == getHTMLTokenId(name, uri))
151
0
            type = EBOOKDocument::TYPE_XHTML;
152
0
          else if ((+EPubToken::container | EPubToken::NS_container) == getEPubTokenId(name, uri))
153
0
            type = EBOOKDocument::TYPE_EPUB;
154
0
          else if ((+EBOOKOPFToken::package | EBOOKOPFToken::NS_opf) == getOPFTokenId(name, uri))
155
0
            type = EBOOKDocument::TYPE_EPUB;
156
0
          else if (EBOOKOPFToken::package == getOPFTokenId(name, uri))
157
0
            type = EBOOKDocument::TYPE_OPENEBOOK;
158
0
          else if ((FictionBook2Token::FictionBook == getFictionBook2TokenID(name)) && (FictionBook2Token::NS_FICTIONBOOK == getFictionBook2TokenID(uri)))
159
0
            type = EBOOKDocument::TYPE_FICTIONBOOK2;
160
0
          break;
161
0
        }
162
0
        ret = xmlTextReaderRead(reader.get());
163
0
      }
164
0
    }
165
0
  }
166
167
0
  return type;
168
0
}
169
0
catch (...)
170
0
{
171
0
  return EBOOKDocument::TYPE_UNKNOWN;
172
0
}
173
174
#if defined LIBE_BOOK_EXPERIMENTAL
175
176
extern "C"
177
{
178
179
  void detectInternalSubset(void *const ctx, const xmlChar *const name, const xmlChar *, const xmlChar *);
180
  void detectExternalSubset(void *const ctx, const xmlChar *const name, const xmlChar *, const xmlChar *);
181
  void detectStartElement(void *const ctx, const xmlChar *const name, const xmlChar **);
182
183
}
184
185
struct HTMLContext
186
{
187
  xmlSAXHandler handler;
188
  bool detected;
189
  bool html;
190
191
  HTMLContext();
192
};
193
194
void detectHTMLContent(void *const ctx, const xmlChar *const name)
195
{
196
  HTMLContext *const context = reinterpret_cast<HTMLContext *>(ctx);
197
198
  assert(context);
199
  assert(name);
200
201
  if (context->detected)
202
    return;
203
204
  context->detected = true;
205
  context->html = EBOOKHTMLToken::html == getHTMLTokenId(char_cast(name));
206
}
207
208
HTMLContext::HTMLContext()
209
  : handler()
210
  , detected(false)
211
  , html(false)
212
{
213
  std::memset(&handler, 0, sizeof(handler));
214
215
  handler.internalSubset = &detectInternalSubset;
216
  handler.externalSubset = &detectExternalSubset;
217
  handler.startElement = &detectStartElement;
218
}
219
220
bool detectHTML(RVNGInputStream *const input) try
221
{
222
  assert(input);
223
224
  seek(input, 0);
225
226
  const unsigned len = 40;
227
  const char *data = char_cast(readNBytes(input, len));
228
229
  HTMLContext context;
230
  const shared_ptr<htmlParserCtxt> ctxt(htmlCreatePushParserCtxt(&context.handler, &context, data, len, "", XML_CHAR_ENCODING_NONE), htmlFreeParserCtxt);
231
232
  while ((XML_ERR_OK == htmlParseChunk(ctxt.get(), data, len, 0)) && !context.detected)
233
    data = char_cast(readNBytes(input, len));
234
235
  return context.html;
236
}
237
catch (...)
238
{
239
  return false;
240
}
241
242
extern "C"
243
{
244
245
  void detectInternalSubset(void *const ctx, const xmlChar *const name, const xmlChar *, const xmlChar *)
246
  {
247
    detectHTMLContent(ctx, name);
248
  }
249
250
  void detectExternalSubset(void *const ctx, const xmlChar *const name, const xmlChar *, const xmlChar *)
251
  {
252
    detectHTMLContent(ctx, name);
253
  }
254
255
  void detectStartElement(void *const ctx, const xmlChar *const name, const xmlChar **)
256
  {
257
    detectHTMLContent(ctx, name);
258
  }
259
260
}
261
262
#endif
263
264
bool findFB2Stream(const RVNGInputStreamPtr_t &package, unsigned &id)
265
1.44k
{
266
1.44k
  return findSubStreamByExt(package, ".fb2", id);
267
1.44k
}
268
269
270
template<class Parser>
271
bool probe(const RVNGInputStreamPtr_t &input, const EBOOKDocument::Type type, EBOOKDocument::Type *const typeOut, EBOOKDocument::Confidence &confidence) try
272
{
273
  seek(input, 0);
274
275
  Parser parser(input);
276
277
  if (typeOut)
278
    *typeOut = type;
279
  confidence = EBOOKDocument::CONFIDENCE_EXCELLENT;
280
281
  return true;
282
}
283
catch (const UnsupportedEncryption &)
284
{
285
  confidence = EBOOKDocument::CONFIDENCE_UNSUPPORTED_ENCRYPTION;
286
  return false;
287
}
288
catch (...)
289
{
290
  confidence = EBOOKDocument::CONFIDENCE_NONE;
291
  return false;
292
}
293
294
template<class Parser>
295
0
bool probePtr(RVNGInputStream *input, const EBOOKDocument::Type type, EBOOKDocument::Type *const typeOut, EBOOKDocument::Confidence &confidence) try
296
0
{
297
0
  seek(input, 0);
298
299
0
  Parser parser(input);
300
301
0
  if (typeOut)
302
0
    *typeOut = type;
303
0
  confidence = EBOOKDocument::CONFIDENCE_EXCELLENT;
304
305
0
  return true;
306
0
}
307
0
catch (const UnsupportedEncryption &)
308
0
{
309
0
  confidence = EBOOKDocument::CONFIDENCE_UNSUPPORTED_ENCRYPTION;
310
0
  return false;
311
0
}
312
0
catch (...)
313
0
{
314
0
  confidence = EBOOKDocument::CONFIDENCE_NONE;
315
0
  return false;
316
0
}
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::PalmDocParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::PluckerParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::PeanutPressParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::TealDocParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::ZTXTParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::TCRParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
Unexecuted instantiation: EBOOKDocument.cpp:bool libebook::(anonymous namespace)::probePtr<libebook::ZVRParser>(librevenge::RVNGInputStream*, libebook::EBOOKDocument::Type, libebook::EBOOKDocument::Type*, libebook::EBOOKDocument::Confidence&)
317
318
typedef bool (*CheckTypeFun_t)(unsigned, unsigned);
319
typedef bool (*ProbeFun_t)(RVNGInputStream *, EBOOKDocument::Type, EBOOKDocument::Type *, EBOOKDocument::Confidence &);
320
321
struct PalmDetector
322
{
323
  CheckTypeFun_t checkFun;
324
  ProbeFun_t probeFun;
325
  EBOOKDocument::Type type;
326
};
327
328
static PalmDetector PALM_DETECTORS[] =
329
{
330
  {PalmDocParser::checkType, probePtr<PalmDocParser>, EBOOKDocument::TYPE_PALMDOC},
331
  {PluckerParser::checkType, probePtr<PluckerParser>, EBOOKDocument::TYPE_PLUCKER},
332
  {PeanutPressParser::checkType, probePtr<PeanutPressParser>, EBOOKDocument::TYPE_PEANUTPRESS},
333
  {TealDocParser::checkType, probePtr<TealDocParser>, EBOOKDocument::TYPE_TEALDOC},
334
  {ZTXTParser::checkType, probePtr<ZTXTParser>, EBOOKDocument::TYPE_ZTXT}
335
};
336
337
bool detectPalm(RVNGInputStream *const input, EBOOKDocument::Type *const type, EBOOKDocument::Confidence &confidence)
338
0
{
339
0
  unsigned typ = 0;
340
0
  unsigned creator = 0;
341
342
0
  try
343
0
  {
344
0
    seek(input, 60);
345
0
    typ = readU32(input, true);
346
0
    creator = readU32(input, true);
347
0
  }
348
0
  catch (...)
349
0
  {
350
0
    return false;
351
0
  }
352
353
0
  for (int i = 0; EBOOK_NUM_ELEMENTS(PALM_DETECTORS) != i; ++i)
354
0
  {
355
0
    const PalmDetector &detector = PALM_DETECTORS[i];
356
0
    if ((detector.checkFun)(typ, creator))
357
0
      return detector.probeFun(input, detector.type, type, confidence);
358
0
  }
359
360
0
  return false;
361
0
}
362
363
template<class Parser>
364
EBOOKDocument::Result doParse(RVNGInputStream *const input, librevenge::RVNGTextInterface *const document)
365
5.98k
{
366
5.98k
  Parser parser(input, document);
367
5.98k
  parser.parse();
368
5.98k
  return EBOOKDocument::RESULT_OK;
369
5.98k
}
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::SoftBookParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::BBeBParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Line
Count
Source
365
5.98k
{
366
5.98k
  Parser parser(input, document);
367
5.98k
  parser.parse();
368
5.98k
  return EBOOKDocument::RESULT_OK;
369
5.98k
}
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::PalmDocParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::PluckerParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::PeanutPressParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::TCRParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::TealDocParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::ZTXTParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
Unexecuted instantiation: EBOOKDocument.cpp:libebook::EBOOKDocument::Result libebook::(anonymous namespace)::doParse<libebook::ZVRParser>(librevenge::RVNGInputStream*, librevenge::RVNGTextInterface*)
370
371
template<class Parser>
372
EBOOKDocument::Result doParse(const RVNGInputStreamPtr_t &input, librevenge::RVNGTextInterface *const document)
373
0
{
374
0
  Parser parser(input, document);
375
0
  parser.parse();
376
0
  return EBOOKDocument::RESULT_OK;
377
0
}
378
379
}
380
381
0
EBOOKAPI EBOOKDocument::Confidence EBOOKDocument::isSupported(librevenge::RVNGInputStream *const input, Type *const type) try
382
0
{
383
0
  if (!input)
384
0
    return CONFIDENCE_NONE;
385
386
0
  if (type)
387
0
    *type = TYPE_UNKNOWN;
388
389
0
  if (input->isStructured())
390
0
  {
391
0
    if (input->existsSubStream("mimetype"))
392
0
    {
393
0
      const unique_ptr<RVNGInputStream> mimetype(input->getSubStreamByName("mimetype"));
394
0
      static const char mime[] = "application/epub+zip";
395
0
      const unsigned char *const data = readNBytes(mimetype.get(), sizeof(mime));
396
0
      if (EPubToken::MIME_epub == getEPubTokenId(char_cast(data), sizeof(mime)))
397
0
      {
398
0
        if (type)
399
0
          *type = TYPE_EPUB;
400
0
        return CONFIDENCE_EXCELLENT;
401
0
      }
402
0
    }
403
404
0
    if (input->existsSubStream("META-INF/container.xml"))
405
0
    {
406
0
      const unique_ptr<RVNGInputStream> container(input->getSubStreamByName("META-INF/container.xml"));
407
0
      const Type xmlType = detectXML(container.get());
408
0
      if (TYPE_EPUB == xmlType)
409
0
      {
410
0
        if (type)
411
0
          *type = TYPE_EPUB;
412
0
        return CONFIDENCE_EXCELLENT;
413
0
      }
414
0
    }
415
416
0
    if ((input->existsSubStream("reader/MobileLibrary.class")) && (input->existsSubStream("data")))
417
0
    {
418
0
      if (type)
419
0
        *type = TYPE_QIOO;
420
0
      return CONFIDENCE_WEAK;
421
0
    }
422
423
0
    const RVNGInputStreamPtr_t package(input, EBOOKDummyDeleter());
424
425
#if defined LIBE_BOOK_EXPERIMENTAL
426
    {
427
      unsigned opfId = 0;
428
      if (EBOOKOPFParser::findOPFStream(package, opfId))
429
      {
430
        const unique_ptr<RVNGInputStream> opf(input->getSubStreamById(opfId));
431
        const Type xmlType = detectXML(opf.get());
432
        if ((TYPE_EPUB == xmlType) || (TYPE_OPENEBOOK == xmlType))
433
        {
434
          if (type)
435
            *type = xmlType;
436
          return CONFIDENCE_EXCELLENT;
437
        }
438
      }
439
    }
440
#endif
441
442
0
    unsigned fb2Stream = 0;
443
0
    if (findFB2Stream(package, fb2Stream))
444
0
    {
445
0
      const unique_ptr<RVNGInputStream> fb2(package->getSubStreamById(fb2Stream));
446
0
      const Type xmlType = detectXML(fb2.get());
447
0
      if (TYPE_FICTIONBOOK2 == xmlType)
448
0
      {
449
0
        if (type)
450
0
          *type = xmlType;
451
0
        return CONFIDENCE_EXCELLENT;
452
0
      }
453
0
    }
454
0
  }
455
456
0
  Confidence confidence = CONFIDENCE_NONE;
457
458
0
  if (detectPalm(input, type, confidence))
459
0
    return confidence;
460
461
0
  Type xmlType = detectXML(input);
462
0
  if (TYPE_UNKNOWN != xmlType)
463
0
  {
464
0
    if (type)
465
0
      *type = xmlType;
466
467
0
    if ((TYPE_EPUB == xmlType) || (TYPE_OPENEBOOK == xmlType))
468
0
      return CONFIDENCE_SUPPORTED_PART;
469
0
    else
470
0
      return CONFIDENCE_EXCELLENT;
471
0
  }
472
473
#if defined LIBE_BOOK_EXPERIMENTAL
474
  if (detectHTML(input))
475
  {
476
    if (type)
477
      *type = TYPE_HTML;
478
    return CONFIDENCE_EXCELLENT;
479
  }
480
#endif
481
482
0
  seek(input, 0);
483
484
0
  {
485
0
    const std::shared_ptr<SoftBookHeader> header(SoftBookHeader::create(input));
486
0
    if (bool(header))
487
0
    {
488
0
      if (type)
489
0
        *type = TYPE_SOFTBOOK;
490
0
      return CONFIDENCE_EXCELLENT;
491
0
    }
492
0
  }
493
494
0
  seek(input, 0);
495
496
0
  if (BBeBParser::isSupported(input))
497
0
  {
498
0
    if (type)
499
0
      *type = TYPE_BBEB;
500
0
    return CONFIDENCE_EXCELLENT;
501
0
  }
502
503
0
  const RVNGInputStreamPtr_t input2(input, EBOOKDummyDeleter());
504
505
#if defined LIBE_BOOK_EXPERIMENTAL
506
  if (probe<RocketEBookParser>(input2, TYPE_ROCKETEBOOK, type, confidence))
507
    return confidence;
508
509
  if (probe<HTMLHelpStream>(input2, TYPE_HTMLHELP, type, confidence))
510
    return confidence;
511
#endif
512
513
0
  if (probePtr<TCRParser>(input, TYPE_TCR, type, confidence))
514
0
    return CONFIDENCE_WEAK;
515
516
0
  if (probePtr<ZVRParser>(input, TYPE_ZVR, type, confidence))
517
0
    return CONFIDENCE_WEAK;
518
519
0
  return CONFIDENCE_NONE;
520
0
}
521
0
catch (...)
522
0
{
523
0
  return CONFIDENCE_NONE;
524
0
}
525
526
EBOOKAPI EBOOKDocument::Result EBOOKDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGTextInterface *const document, const char *const)
527
0
{
528
0
  if (!input || !document)
529
0
    return RESULT_UNSUPPORTED_FORMAT;
530
531
0
  Type type;
532
0
  Confidence confidence = isSupported(input, &type);
533
0
  if (CONFIDENCE_NONE == confidence)
534
0
    return RESULT_UNSUPPORTED_FORMAT;
535
0
  else if (CONFIDENCE_SUPPORTED_PART == confidence)
536
0
    return RESULT_UNSUPPORTED_FORMAT;
537
0
  else if (CONFIDENCE_UNSUPPORTED_ENCRYPTION == confidence)
538
0
    return RESULT_UNSUPPORTED_ENCRYPTION;
539
540
0
  return parse(input, document, type);
541
0
}
542
543
33.2k
EBOOKAPI EBOOKDocument::Result EBOOKDocument::parse(librevenge::RVNGInputStream *const input, librevenge::RVNGTextInterface *const document, const EBOOKDocument::Type type, const char *const) try
544
33.2k
{
545
33.2k
  if (!input || !document)
546
0
    return RESULT_UNSUPPORTED_FORMAT;
547
548
  // sanity check
549
33.2k
  if (EBOOKDocument::TYPE_UNKNOWN == type)
550
0
    return EBOOKDocument::RESULT_UNSUPPORTED_FORMAT;
551
33.2k
  if (EBOOKDocument::TYPE_RESERVED1 <= type)
552
0
    return EBOOKDocument::RESULT_UNSUPPORTED_FORMAT;
553
554
33.2k
  const RVNGInputStreamPtr_t input_(input, EBOOKDummyDeleter());
555
556
33.2k
  input_->seek(0, librevenge::RVNG_SEEK_SET);
557
558
33.2k
  switch (type)
559
33.2k
  {
560
#if defined LIBE_BOOK_EXPERIMENTAL
561
  case TYPE_EPUB :
562
    return doParse<EPubParser>(input_.get(), document);
563
#endif
564
27.3k
  case TYPE_FICTIONBOOK2 :
565
27.3k
  {
566
27.3k
    RVNGInputStreamPtr_t fb2Input(input_);
567
27.3k
    if (input_->isStructured())
568
1.44k
    {
569
1.44k
      unsigned id = 0;
570
1.44k
      if (!findFB2Stream(input_, id))
571
751
        return RESULT_PACKAGE_ERROR;
572
692
      fb2Input.reset(input_->getSubStreamById(id));
573
692
      if (!fb2Input)
574
663
        return RESULT_PACKAGE_ERROR;
575
692
    }
576
25.9k
    FictionBook2Parser parser(fb2Input.get());
577
25.9k
    return parser.parse(document) ? RESULT_OK : RESULT_UNKNOWN_ERROR;
578
27.3k
  }
579
#if defined LIBE_BOOK_EXPERIMENTAL
580
  case TYPE_HTML :
581
  case TYPE_XHTML :
582
  {
583
    HTMLParser parser(input_.get(), document, TYPE_XHTML == type);
584
    parser.parse();
585
    return RESULT_OK;
586
  }
587
  case TYPE_HTMLHELP :
588
  {
589
    HTMLHelpStream package(input_);
590
    return doParse<HTMLHelpParser>(RVNGInputStreamPtr_t(&package, EBOOKDummyDeleter()), document);
591
  }
592
#endif
593
0
  case TYPE_SOFTBOOK :
594
0
    return doParse<SoftBookParser>(input_.get(), document);
595
5.98k
  case TYPE_BBEB :
596
5.98k
    return doParse<BBeBParser>(input_.get(), document);
597
#if defined LIBE_BOOK_EXPERIMENTAL
598
  case TYPE_OPENEBOOK :
599
    return doParse<OpenEBookParser>(input_.get(), document);
600
#endif
601
0
  case TYPE_PALMDOC :
602
0
    return doParse<PalmDocParser>(input_.get(), document);
603
0
  case TYPE_PLUCKER :
604
0
    return doParse<PluckerParser>(input_.get(), document);
605
0
  case TYPE_PEANUTPRESS :
606
0
    return doParse<PeanutPressParser>(input_.get(), document);
607
0
  case TYPE_QIOO :
608
0
    return doParse<QiOOParser>(input_, document);
609
#if defined LIBE_BOOK_EXPERIMENTAL
610
  case TYPE_ROCKETEBOOK :
611
    return doParse<RocketEBookParser>(input_, document);
612
#endif
613
0
  case TYPE_TCR :
614
0
    return doParse<TCRParser>(input_.get(), document);
615
0
  case TYPE_TEALDOC :
616
0
    return doParse<TealDocParser>(input_.get(), document);
617
0
  case TYPE_ZTXT :
618
0
    return doParse<ZTXTParser>(input_.get(), document);
619
0
  case TYPE_ZVR :
620
0
    return doParse<ZVRParser>(input_.get(), document);
621
0
  case TYPE_UNKNOWN:
622
0
#if !defined LIBE_BOOK_EXPERIMENTAL
623
0
  case TYPE_EPUB:
624
0
  case TYPE_HTML:
625
0
  case TYPE_HTMLHELP:
626
0
  case TYPE_OPENEBOOK:
627
0
  case TYPE_ROCKETEBOOK:
628
0
  case TYPE_XHTML:
629
0
#endif
630
0
  case TYPE_HIEBOOK:
631
0
  case TYPE_KINDLE8:
632
0
  case TYPE_LIT:
633
0
  case TYPE_MOBIPOCKET:
634
0
  case TYPE_TEBR:
635
0
  case TYPE_TOMERAIDER:
636
0
  case TYPE_TOMERAIDER3:
637
0
  case TYPE_RESERVED1:
638
0
  case TYPE_RESERVED2:
639
0
  case TYPE_RESERVED3:
640
0
  case TYPE_RESERVED4:
641
0
  case TYPE_RESERVED5:
642
0
  case TYPE_RESERVED6:
643
0
  case TYPE_RESERVED7:
644
0
  case TYPE_RESERVED8:
645
0
  case TYPE_RESERVED9:
646
0
  default :
647
0
    EBOOK_DEBUG_MSG(("unhandled document type %d\n", type));
648
0
    return RESULT_UNSUPPORTED_FORMAT;
649
33.2k
  }
650
651
0
  return RESULT_UNKNOWN_ERROR;
652
33.2k
}
653
33.2k
catch (const FileAccessError &)
654
33.2k
{
655
0
  return RESULT_FILE_ACCESS_ERROR;
656
0
}
657
33.2k
catch (const PackageError &)
658
33.2k
{
659
0
  return RESULT_PACKAGE_ERROR;
660
0
}
661
33.2k
catch (const PasswordMismatch &)
662
33.2k
{
663
0
  return RESULT_PASSWORD_MISMATCH;
664
0
}
665
33.2k
catch (const UnsupportedEncryption &)
666
33.2k
{
667
0
  return RESULT_UNSUPPORTED_ENCRYPTION;
668
0
}
669
33.2k
catch (const UnsupportedFormat &)
670
33.2k
{
671
0
  return RESULT_UNSUPPORTED_FORMAT;
672
0
}
673
33.2k
catch (...)
674
33.2k
{
675
5.03k
  return RESULT_UNKNOWN_ERROR;
676
5.03k
}
677
678
} // namespace libebook
679
680
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */