LibreOffice Module filter (master) 1
typedetectionimport.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 file is part of the LibreOffice 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 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <com/sun/star/xml/sax/InputSource.hpp>
21#include <com/sun/star/xml/sax/Parser.hpp>
22#include <com/sun/star/xml/sax/XAttributeList.hpp>
24#include <rtl/ref.hxx>
25#include <o3tl/string_view.hxx>
26
28#include "xmlfiltercommon.hxx"
29
30using namespace com::sun::star::lang;
31using namespace com::sun::star::uno;
32using namespace com::sun::star::io;
33using namespace com::sun::star::beans;
34using namespace com::sun::star::xml::sax;
35using namespace com::sun::star;
36
38{
39}
40
42{
43}
44
46 std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
47{
48 try
49 {
50 Reference< XParser > xParser = xml::sax::Parser::create( rxContext );
51
53 xParser->setDocumentHandler( pImporter );
54
55 InputSource source;
56 source.aInputStream = xIS;
57
58 // start parsing
59 xParser->parseStream( source );
60
61 pImporter->fillFilterVector( rFilters );
62 }
63 catch( const Exception& /* e */ )
64 {
65 TOOLS_WARN_EXCEPTION("filter.xslt", "");
66 }
67}
68
69void TypeDetectionImporter::fillFilterVector( std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
70{
71 // create filter infos from imported filter nodes
72 for (auto const& filterNode : maFilterNodes)
73 {
74 std::unique_ptr<filter_info_impl> pFilter = createFilterForNode(filterNode.get());
75 if( pFilter )
76 rFilters.push_back( std::move(pFilter) );
77 }
78 maFilterNodes.clear();
79
80 // now delete type nodes
81 maTypeNodes.clear();
82}
83
84static std::u16string_view getSubdata( int index, sal_Unicode delimiter, std::u16string_view rData )
85{
86 sal_Int32 nLastIndex = 0;
87
88 size_t nNextIndex = rData.find( delimiter );
89
90 std::u16string_view aSubdata;
91
92 while( index )
93 {
94 nLastIndex = nNextIndex == std::u16string_view::npos ? 0 : nNextIndex + 1;
95 nNextIndex = rData.find( delimiter, nLastIndex );
96
97 index--;
98
99 if( (index > 0) && (nLastIndex == 0) )
100 return aSubdata;
101 }
102
103 if( nNextIndex == std::u16string_view::npos )
104 {
105 aSubdata = rData.substr( nLastIndex );
106 }
107 else
108 {
109 aSubdata = rData.substr( nLastIndex, nNextIndex - nLastIndex );
110 }
111
112 return aSubdata;
113}
114
116{
117 auto aIter = std::find_if(maTypeNodes.begin(), maTypeNodes.end(),
118 [&rType](const std::unique_ptr<Node>& rxNode) { return rxNode->maName == rType; });
119 if (aIter != maTypeNodes.end())
120 return aIter->get();
121
122 return nullptr;
123}
124
125std::unique_ptr<filter_info_impl> TypeDetectionImporter::createFilterForNode( Node * pNode )
126{
127 std::unique_ptr<filter_info_impl> pFilter(new filter_info_impl);
128
129 pFilter->maFilterName = pNode->maName;
130 pFilter->maInterfaceName = pNode->maPropertyMap["UIName"];
131
132 OUString aData = pNode->maPropertyMap["Data"];
133
134 sal_Unicode aComma(',');
135
136 pFilter->maType = getSubdata( 1, aComma, aData );
137 pFilter->maDocumentService = getSubdata( 2, aComma, aData );
138
139 std::u16string_view aFilterService( getSubdata( 3, aComma, aData ) );
140 pFilter->maFlags = o3tl::toInt32(getSubdata( 4, aComma, aData ));
141
142 // parse filter user data
143 sal_Unicode aDelim(';');
144 std::u16string_view aFilterUserData( getSubdata( 5, aComma, aData ) );
145
146 std::u16string_view aAdapterService( getSubdata( 0, aDelim, aFilterUserData ) );
147 //Import/ExportService
148 pFilter->mbNeedsXSLT2 = OUString(getSubdata( 1, aDelim, aFilterUserData )).toBoolean();
149 pFilter->maImportService = getSubdata( 2, aDelim, aFilterUserData );
150 pFilter->maExportService = getSubdata( 3, aDelim, aFilterUserData );
151 pFilter->maImportXSLT = getSubdata( 4, aDelim, aFilterUserData );
152 pFilter->maExportXSLT = getSubdata( 5, aDelim, aFilterUserData );
153 pFilter->maComment = getSubdata( 7, aDelim, aFilterUserData );
154
155
156 pFilter->maImportTemplate = getSubdata( 7, aComma, aData );
157
158 Node* pTypeNode = findTypeNode( pFilter->maType );
159 if( pTypeNode )
160 {
161 OUString aTypeUserData( pTypeNode->maPropertyMap["Data"] );
162
163 pFilter->maDocType = getSubdata( 2, aComma, aTypeUserData );
164 pFilter->maExtension = getSubdata( 4, aComma, aTypeUserData );
165 pFilter->mnDocumentIconID = o3tl::toInt32(getSubdata( 5, aComma, aTypeUserData ));
166 }
167
168 bool bOk = true;
169
170 if( pTypeNode == nullptr )
171 bOk = false;
172
173 if( pFilter->maFilterName.isEmpty() )
174 bOk = false;
175
176 if( pFilter->maInterfaceName.isEmpty() )
177 bOk = false;
178
179 if( pFilter->maType.isEmpty() )
180 bOk = false;
181
182 if( pFilter->maFlags == 0 )
183 bOk = false;
184
185 if( aFilterService != u"com.sun.star.comp.Writer.XmlFilterAdaptor" )
186 bOk = false;
187
188 if( aAdapterService != u"com.sun.star.documentconversion.XSLTFilter" )
189 bOk = false;
190
191 if( pFilter->maExtension.isEmpty() )
192 bOk = false;
193
194 if( !bOk )
195 return nullptr;
196
197 return pFilter;
198}
199
201{
202}
203
205{
206}
207
208void SAL_CALL TypeDetectionImporter::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
209{
210 ImportState eNewState = e_Unknown;
211
212 if( maStack.empty() )
213 {
214 // #109668# support legacy name as well on import
215 if( aName == "oor:component-data" || aName == "oor:node" )
216 {
217 eNewState = e_Root;
218 }
219 }
220 else if( maStack.top() == e_Root )
221 {
222 if( aName == "node" )
223 {
224 OUString aNodeName( xAttribs->getValueByName( "oor:name" ) );
225
226 if( aNodeName == "Filters" )
227 {
228 eNewState = e_Filters;
229 }
230 else if( aNodeName == "Types" )
231 {
232 eNewState = e_Types;
233 }
234 }
235 }
236 else if( (maStack.top() == e_Filters) || (maStack.top() == e_Types) )
237 {
238 if( aName == "node" )
239 {
240 maNodeName = xAttribs->getValueByName( "oor:name" );
241
242 eNewState = (maStack.top() == e_Filters) ? e_Filter : e_Type;
243 }
244 }
245 else if( (maStack.top() == e_Filter) || (maStack.top() == e_Type))
246 {
247 if( aName == "prop" )
248 {
249 maPropertyName = xAttribs->getValueByName( "oor:name" );
250 eNewState = e_Property;
251 }
252 }
253 else if( maStack.top() == e_Property )
254 {
255 if( aName == "value" )
256 {
257 eNewState = e_Value;
258 maValue.clear();
259 }
260 }
261
262 maStack.push( eNewState );
263}
264void SAL_CALL TypeDetectionImporter::endElement( const OUString& /* aName */ )
265{
266 if( maStack.empty() )
267 return;
268
269 ImportState eCurrentState = maStack.top();
270 switch( eCurrentState )
271 {
272 case e_Filter:
273 case e_Type:
274 {
275 std::unique_ptr<Node> pNode(new Node);
276 pNode->maName = maNodeName;
277 pNode->maPropertyMap = maPropertyMap;
278 maPropertyMap.clear();
279
280 if( eCurrentState == e_Filter )
281 {
282 maFilterNodes.push_back( std::move(pNode) );
283 }
284 else
285 {
286 maTypeNodes.push_back( std::move(pNode) );
287 }
288 }
289 break;
290
291 case e_Property:
293 break;
294 default: break;
295 }
296
297 maStack.pop();
298}
299void SAL_CALL TypeDetectionImporter::characters( const OUString& aChars )
300{
301 if( !maStack.empty() && maStack.top() == e_Value )
302 {
303 maValue += aChars;
304 }
305}
306void SAL_CALL TypeDetectionImporter::ignorableWhitespace( const OUString& /* aWhitespaces */ )
307{
308}
309void SAL_CALL TypeDetectionImporter::processingInstruction( const OUString& /* aTarget */, const OUString& /* aData */ )
310{
311}
312void SAL_CALL TypeDetectionImporter::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /* xLocator */ )
313{
314}
315
316/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< std::unique_ptr< Node > > maFilterNodes
virtual void SAL_CALL startElement(const OUString &aName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttribs) override
virtual void SAL_CALL setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator > &xLocator) override
void fillFilterVector(std::vector< std::unique_ptr< filter_info_impl > > &rFilters)
virtual void SAL_CALL endDocument() override
virtual void SAL_CALL endElement(const OUString &aName) override
std::unique_ptr< filter_info_impl > createFilterForNode(Node *pNode)
virtual void SAL_CALL ignorableWhitespace(const OUString &aWhitespaces) override
std::vector< std::unique_ptr< Node > > maTypeNodes
virtual ~TypeDetectionImporter() override
Node * findTypeNode(const OUString &rType)
virtual void SAL_CALL startDocument() override
std::stack< ImportState > maStack
virtual void SAL_CALL characters(const OUString &aChars) override
static void doImport(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::io::XInputStream > &xOS, std::vector< std::unique_ptr< filter_info_impl > > &rFilters)
virtual void SAL_CALL processingInstruction(const OUString &aTarget, const OUString &aData) override
#define TOOLS_WARN_EXCEPTION(area, stream)
float u
OUString aName
constexpr OUStringLiteral aData
@ Exception
Shape IDs per cluster in DGG atom.
index
Definition: js2hxx.py:50
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
static std::u16string_view getSubdata(int index, sal_Unicode delimiter, std::u16string_view rData)
@ e_Property
sal_uInt16 sal_Unicode