LibreOffice Module writerperfect (master) 1
WordPerfectImportFilter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 */
7/* "This product is not manufactured, approved, or supported by
8 * Corel Corporation or Corel Corporation Limited."
9 */
10
11#include <osl/diagnose.h>
12
13#include <com/sun/star/awt/XWindow.hpp>
14#include <com/sun/star/io/XInputStream.hpp>
15#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
16#include <com/sun/star/uno/Reference.h>
18
19#include <DocumentHandler.hxx>
20#include <WPXSvInputStream.hxx>
21
22#include <sfx2/passwd.hxx>
23#include <ucbhelper/content.hxx>
24#include <vcl/svapp.hxx>
25#include <xmloff/xmlimp.hxx>
26
27#include <libwpd/libwpd.h>
28#include <libwpg/libwpg.h>
29
31
33
34using com::sun::star::awt::XWindow;
35using com::sun::star::document::XImporter;
36using com::sun::star::io::XInputStream;
37using com::sun::star::xml::sax::XFastDocumentHandler;
38
41
42static bool handleEmbeddedWPGObject(const librevenge::RVNGBinaryData& data,
43 OdfDocumentHandler* pHandler, const OdfStreamType streamType)
44{
45 OdgGenerator exporter;
46 exporter.addDocumentHandler(pHandler, streamType);
47
48 libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
49
50 if (!libwpg::WPGraphics::isSupported(data.getDataStream()))
51 fileFormat = libwpg::WPG_WPG1;
52
53 return libwpg::WPGraphics::parse(data.getDataStream(), &exporter, fileFormat);
54}
55
56static bool handleEmbeddedWPGImage(const librevenge::RVNGBinaryData& input,
57 librevenge::RVNGBinaryData& output)
58{
59 libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT;
60
61 if (!libwpg::WPGraphics::isSupported(input.getDataStream()))
62 fileFormat = libwpg::WPG_WPG1;
63
64 librevenge::RVNGStringVector svgOutput;
65 librevenge::RVNGSVGDrawingGenerator aSVGGenerator(svgOutput, "");
66
67 if (!libwpg::WPGraphics::parse(input.getDataStream(), &aSVGGenerator, fileFormat))
68 return false;
69
70 if (svgOutput.empty())
71 return false;
72
73 assert(1 == svgOutput.size());
74
75 output.clear();
76 output.append(reinterpret_cast<const unsigned char*>(svgOutput[0].cstr()), svgOutput[0].size());
77 return true;
78}
79
81 const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor)
82{
83 Reference<XInputStream> xInputStream;
84 Reference<XWindow> xDialogParent;
85 for (const auto& rValue : aDescriptor)
86 {
87 if (rValue.Name == "InputStream")
88 rValue.Value >>= xInputStream;
89 else if (rValue.Name == "ParentWindow")
90 rValue.Value >>= xDialogParent;
91 }
92 if (!xInputStream.is())
93 {
94 OSL_ASSERT(false);
95 return false;
96 }
97
98 WPXSvInputStream input(xInputStream);
99
100 OString aUtf8Passwd;
101
102 libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input);
103
104 if (libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence)
105 {
106 int unsuccessfulAttempts = 0;
107 while (true)
108 {
109 SfxPasswordDialog aPasswdDlg(Application::GetFrameWeld(xDialogParent));
110 aPasswdDlg.SetMinLen(0);
111 if (!aPasswdDlg.run())
112 return false;
113 OUString aPasswd = aPasswdDlg.GetPassword();
114 aUtf8Passwd = OUStringToOString(aPasswd, RTL_TEXTENCODING_UTF8);
115 if (libwpd::WPD_PASSWORD_MATCH_OK
116 == libwpd::WPDocument::verifyPassword(&input, aUtf8Passwd.getStr()))
117 break;
118 else
119 unsuccessfulAttempts++;
120 if (unsuccessfulAttempts == 3) // timeout after 3 password attempts
121 return false;
122 }
123 }
124
125 // An XML import service: what we push sax messages to.
126 Reference<XInterface> xInternalFilter
127 = mxContext->getServiceManager()->createInstanceWithContext(
128 "com.sun.star.comp.Writer.XMLOasisImporter", mxContext);
129 assert(xInternalFilter);
130 css::uno::Reference<css::xml::sax::XFastDocumentHandler> xInternalHandler(xInternalFilter,
131 css::uno::UNO_QUERY);
132 assert(xInternalHandler);
133
134 // The XImporter sets up an empty target document for XDocumentHandler to write to.
135 Reference<XImporter> xImporter(xInternalHandler, css::uno::UNO_QUERY);
136 xImporter->setTargetDocument(mxDoc);
137
138 // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
139 // writes to in-memory target doc
140 DocumentHandler aHandler(
141 new SvXMLLegacyToFastDocHandler(static_cast<SvXMLImport*>(xInternalHandler.get())));
142
143 OdtGenerator collector;
144 collector.addDocumentHandler(&aHandler, ODF_FLAT_XML);
145 collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPGObject);
146 collector.registerEmbeddedImageHandler("image/x-wpg", &handleEmbeddedWPGImage);
147 return libwpd::WPD_OK
148 == libwpd::WPDocument::parse(&input, &collector,
149 aUtf8Passwd.isEmpty() ? nullptr : aUtf8Passwd.getStr());
150}
151
152sal_Bool SAL_CALL
153WordPerfectImportFilter::filter(const css::uno::Sequence<css::beans::PropertyValue>& aDescriptor)
154{
155 return importImpl(aDescriptor);
156}
158
159// XImporter
160void SAL_CALL
162{
163 mxDoc = xDoc;
164}
165
166// XExtendedFilterDetection
167OUString SAL_CALL
168WordPerfectImportFilter::detect(css::uno::Sequence<css::beans::PropertyValue>& Descriptor)
169{
170 sal_Int32 nLength = Descriptor.getLength();
171 sal_Int32 location = nLength;
172 Reference<XInputStream> xInputStream;
173 for (sal_Int32 i = 0; i < nLength; i++)
174 {
175 if (Descriptor[i].Name == "TypeName")
176 location = i;
177 else if (Descriptor[i].Name == "InputStream")
178 Descriptor[i].Value >>= xInputStream;
179 }
180
181 if (!xInputStream.is())
182 return OUString();
183
184 WPXSvInputStream input(xInputStream);
185
186 OUString sTypeName;
187 libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&input);
188 if (confidence == libwpd::WPD_CONFIDENCE_EXCELLENT
189 || confidence == libwpd::WPD_CONFIDENCE_SUPPORTED_ENCRYPTION)
190 {
191 if (location == nLength)
192 {
193 Descriptor.realloc(nLength + 1);
194 Descriptor.getArray()[location].Name = "TypeName";
195 }
196
197 sTypeName = "writer_WordPerfect_Document";
198 Descriptor.getArray()[location].Value <<= sTypeName;
199 }
200
201 return sTypeName;
202}
203
204// XInitialization
205void SAL_CALL
206WordPerfectImportFilter::initialize(const css::uno::Sequence<css::uno::Any>& /*aArguments*/)
207{
208}
209
210// XServiceInfo
212{
213 return "com.sun.star.comp.Writer.WordPerfectImportFilter";
214}
215
216sal_Bool SAL_CALL WordPerfectImportFilter::supportsService(const OUString& rServiceName)
217{
218 return cppu::supportsService(this, rServiceName);
219}
220
221css::uno::Sequence<OUString> SAL_CALL WordPerfectImportFilter::getSupportedServiceNames()
222{
223 return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
224}
225
226extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
228 css::uno::XComponentContext* const context, const css::uno::Sequence<css::uno::Any>&)
229{
230 return cppu::acquire(new WordPerfectImportFilter(context));
231}
232
233/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool handleEmbeddedWPGImage(const librevenge::RVNGBinaryData &input, librevenge::RVNGBinaryData &output)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_Writer_WordPerfectImportFilter_get_implementation(css::uno::XComponentContext *const context, const css::uno::Sequence< css::uno::Any > &)
static bool handleEmbeddedWPGObject(const librevenge::RVNGBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType streamType)
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
OUString GetPassword() const
virtual short run() override
void SetMinLen(sal_uInt16 Len)
virtual void SAL_CALL cancel() override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual sal_Bool SAL_CALL filter(const css::uno::Sequence< css::beans::PropertyValue > &aDescriptor) override
css::uno::Reference< css::uno::XComponentContext > mxContext
css::uno::Reference< css::lang::XComponent > mxDoc
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
bool importImpl(const css::uno::Sequence< css::beans::PropertyValue > &aDescriptor)
virtual void SAL_CALL setTargetDocument(const css::uno::Reference< css::lang::XComponent > &xDoc) override
virtual OUString SAL_CALL getImplementationName() override
virtual OUString SAL_CALL detect(css::uno::Sequence< css::beans::PropertyValue > &Descriptor) override
size
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OUString Name
unsigned char sal_Bool
sal_Int32 nLength