/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * This file is part of the libmspub project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include "MSPUBCollector.h" #include "MSPUBParser.h" #include "MSPUBParser2k.h" #include "MSPUBParser97.h" #include "libmspub_utils.h" namespace libmspub { namespace { enum MSPUBVersion { MSPUB_UNKNOWN_VERSION = 0, MSPUB_2K, MSPUB_2K2 }; MSPUBVersion getVersion(librevenge::RVNGInputStream *input) { try { if (!input->isStructured()) return MSPUB_UNKNOWN_VERSION; std::unique_ptr contentsStream(input->getSubStreamByName("Contents")); if (!contentsStream) return MSPUB_UNKNOWN_VERSION; if (0xe8 != readU8(contentsStream.get()) || 0xac != readU8(contentsStream.get())) return MSPUB_UNKNOWN_VERSION; unsigned char magicVersionByte = readU8(contentsStream.get()); if (0x00 != readU8(contentsStream.get())) return MSPUB_UNKNOWN_VERSION; MSPUBVersion version = MSPUB_UNKNOWN_VERSION; switch (magicVersionByte) { case 0x2C: version = MSPUB_2K2; break; case 0x22: version = MSPUB_2K; break; default: break; } return version; } catch (...) { return MSPUB_UNKNOWN_VERSION; } } } // anonymous namespace /** Analyzes the content of an input stream to see if it can be parsed \param input The input stream \return A value that indicates whether the content from the input stream is a Microsoft Publisher Document that libmspub is able to parse */ PUBAPI bool MSPUBDocument::isSupported(librevenge::RVNGInputStream *input) { if (!input) return false; try { MSPUBVersion version = getVersion(input); if (version == MSPUB_UNKNOWN_VERSION) return false; if (version == MSPUB_2K2) { std::unique_ptr escherStream(input->getSubStreamByName("Escher/EscherStm")); if (!escherStream) return false; std::unique_ptr quillStream(input->getSubStreamByName("Quill/QuillSub/CONTENTS")); if (!quillStream) return false; } return true; } catch (...) { return false; } } /** Parses the input stream content. It will make callbacks to the functions provided by a RVNGDrawingInterface class implementation when needed. This is often commonly called the 'main parsing routine'. \param input The input stream \param painter A MSPUBPainterInterface implementation \return A value that indicates whether the parsing was successful */ PUBAPI bool MSPUBDocument::parse(librevenge::RVNGInputStream *input, librevenge::RVNGDrawingInterface *painter) { if (!input || !painter) return false; try { MSPUBCollector collector(painter); input->seek(0, librevenge::RVNG_SEEK_SET); std::unique_ptr parser; switch (getVersion(input)) { case MSPUB_2K: { std::unique_ptr quillStream(input->getSubStreamByName("Quill/QuillSub/CONTENTS")); if (!quillStream) parser.reset(new MSPUBParser97(input, &collector)); else parser.reset(new MSPUBParser2k(input, &collector)); break; } case MSPUB_2K2: { parser.reset(new MSPUBParser(input, &collector)); break; } default: return false; } if (parser) { return parser->parse(); } return false; } catch (...) { return false; } } } /* vim:set shiftwidth=2 softtabstop=2 expandtab: */