/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. */ /* "This product is not manufactured, approved, or supported by * Corel Corporation or Corel Corporation Limited." */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "WordPerfectImportFilter.hxx" using com::sun::star::uno::Reference; using com::sun::star::awt::XWindow; using com::sun::star::document::XImporter; using com::sun::star::io::XInputStream; using com::sun::star::xml::sax::XDocumentHandler; using writerperfect::DocumentHandler; using writerperfect::WPXSvInputStream; static bool handleEmbeddedWPGObject(const librevenge::RVNGBinaryData& data, OdfDocumentHandler* pHandler, const OdfStreamType streamType) { OdgGenerator exporter; exporter.addDocumentHandler(pHandler, streamType); libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT; if (!libwpg::WPGraphics::isSupported(data.getDataStream())) fileFormat = libwpg::WPG_WPG1; return libwpg::WPGraphics::parse(data.getDataStream(), &exporter, fileFormat); } static bool handleEmbeddedWPGImage(const librevenge::RVNGBinaryData& input, librevenge::RVNGBinaryData& output) { libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT; if (!libwpg::WPGraphics::isSupported(input.getDataStream())) fileFormat = libwpg::WPG_WPG1; librevenge::RVNGStringVector svgOutput; librevenge::RVNGSVGDrawingGenerator aSVGGenerator(svgOutput, ""); if (!libwpg::WPGraphics::parse(input.getDataStream(), &aSVGGenerator, fileFormat)) return false; if (svgOutput.empty()) return false; assert(1 == svgOutput.size()); output.clear(); output.append(reinterpret_cast(svgOutput[0].cstr()), svgOutput[0].size()); return true; } bool WordPerfectImportFilter::importImpl( const css::uno::Sequence& aDescriptor) { Reference xInputStream; Reference xDialogParent; for (const auto& rValue : aDescriptor) { if (rValue.Name == "InputStream") rValue.Value >>= xInputStream; else if (rValue.Name == "ParentWindow") rValue.Value >>= xDialogParent; } if (!xInputStream.is()) { OSL_ASSERT(false); return false; } WPXSvInputStream input(xInputStream); OString aUtf8Passwd; libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input); if (libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence) { int unsuccessfulAttempts = 0; while (true) { SfxPasswordDialog aPasswdDlg(Application::GetFrameWeld(xDialogParent)); aPasswdDlg.SetMinLen(0); if (!aPasswdDlg.run()) return false; OUString aPasswd = aPasswdDlg.GetPassword(); aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8); if (libwpd::WPD_PASSWORD_MATCH_OK == libwpd::WPDocument::verifyPassword(&input, aUtf8Passwd.getStr())) break; else unsuccessfulAttempts++; if (unsuccessfulAttempts == 3) // timeout after 3 password attempts return false; } } // An XML import service: what we push sax messages to. Reference xInternalHandler( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.Writer.XMLOasisImporter", mxContext), css::uno::UNO_QUERY_THROW); // The XImporter sets up an empty target document for XDocumentHandler to write to. Reference xImporter(xInternalHandler, css::uno::UNO_QUERY); xImporter->setTargetDocument(mxDoc); // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here // writes to in-memory target doc DocumentHandler aHandler(xInternalHandler); OdtGenerator collector; collector.addDocumentHandler(&aHandler, ODF_FLAT_XML); collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPGObject); collector.registerEmbeddedImageHandler("image/x-wpg", &handleEmbeddedWPGImage); return libwpd::WPD_OK == libwpd::WPDocument::parse(&input, &collector, aUtf8Passwd.isEmpty() ? nullptr : aUtf8Passwd.getStr()); } sal_Bool SAL_CALL WordPerfectImportFilter::filter(const css::uno::Sequence& aDescriptor) { return importImpl(aDescriptor); } void SAL_CALL WordPerfectImportFilter::cancel() {} // XImporter void SAL_CALL WordPerfectImportFilter::setTargetDocument(const Reference& xDoc) { mxDoc = xDoc; } // XExtendedFilterDetection OUString SAL_CALL WordPerfectImportFilter::detect(css::uno::Sequence& Descriptor) { libwpd::WPDConfidence confidence = libwpd::WPD_CONFIDENCE_NONE; OUString sTypeName; sal_Int32 nLength = Descriptor.getLength(); sal_Int32 location = nLength; const css::beans::PropertyValue* pValue = Descriptor.getConstArray(); Reference xInputStream; for (sal_Int32 i = 0; i < nLength; i++) { if (pValue[i].Name == "TypeName") location = i; else if (pValue[i].Name == "InputStream") pValue[i].Value >>= xInputStream; } if (!xInputStream.is()) return OUString(); WPXSvInputStream input(xInputStream); confidence = libwpd::WPDocument::isFileFormatSupported(&input); if (confidence == libwpd::WPD_CONFIDENCE_EXCELLENT || confidence == libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION) sTypeName = "writer_WordPerfect_Document"; if (!sTypeName.isEmpty()) { if (location == nLength) { Descriptor.realloc(nLength + 1); Descriptor[location].Name = "TypeName"; } Descriptor[location].Value <<= sTypeName; } return sTypeName; } // XInitialization void SAL_CALL WordPerfectImportFilter::initialize(const css::uno::Sequence& /*aArguments*/) { } // XServiceInfo OUString SAL_CALL WordPerfectImportFilter::getImplementationName() { return "com.sun.star.comp.Writer.WordPerfectImportFilter"; } sal_Bool SAL_CALL WordPerfectImportFilter::supportsService(const OUString& rServiceName) { return cppu::supportsService(this, rServiceName); } css::uno::Sequence SAL_CALL WordPerfectImportFilter::getSupportedServiceNames() { return css::uno::Sequence{ "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" }; } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* com_sun_star_comp_Writer_WordPerfectImportFilter_get_implementation( css::uno::XComponentContext* const context, const css::uno::Sequence&) { return cppu::acquire(new WordPerfectImportFilter(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */