Line data Source code
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 :
21 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
22 : #include <com/sun/star/xml/dom/SAXDocumentBuilder.hpp>
23 : #include <com/sun/star/xml/dom/XSAXDocumentBuilder2.hpp>
24 : #include <com/sun/star/xml/xpath/XPathAPI.hpp>
25 : #include <com/sun/star/beans/XPropertySet.hpp>
26 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
27 : #include <comphelper/processfactory.hxx>
28 : #include <xmloff/xmlmetai.hxx>
29 : #include <xmloff/xmlimp.hxx>
30 : #include <xmloff/nmspmap.hxx>
31 : #include <xmloff/xmltoken.hxx>
32 : #include "xmloff/xmlnmspe.hxx"
33 :
34 :
35 : using namespace com::sun::star;
36 : using namespace ::xmloff::token;
37 :
38 :
39 : //===========================================================================
40 :
41 : /// builds a DOM tree from SAX events, by forwarding to SAXDocumentBuilder
42 : class XMLDocumentBuilderContext : public SvXMLImportContext
43 : {
44 : private:
45 : ::com::sun::star::uno::Reference<
46 : ::com::sun::star::xml::dom::XSAXDocumentBuilder2> mxDocBuilder;
47 :
48 : public:
49 : XMLDocumentBuilderContext(SvXMLImport& rImport, sal_uInt16 nPrfx,
50 : const OUString& rLName,
51 : const ::com::sun::star::uno::Reference<
52 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
53 : const ::com::sun::star::uno::Reference<
54 : ::com::sun::star::xml::dom::XSAXDocumentBuilder2>& rDocBuilder);
55 :
56 : virtual ~XMLDocumentBuilderContext();
57 :
58 : virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
59 : const OUString& rLocalName,
60 : const ::com::sun::star::uno::Reference<
61 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
62 :
63 : virtual void StartElement( const ::com::sun::star::uno::Reference<
64 : ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
65 :
66 : virtual void Characters( const OUString& rChars );
67 :
68 : virtual void EndElement();
69 : };
70 :
71 1421 : XMLDocumentBuilderContext::XMLDocumentBuilderContext(SvXMLImport& rImport,
72 : sal_uInt16 nPrfx, const OUString& rLName,
73 : const uno::Reference<xml::sax::XAttributeList>&,
74 : const uno::Reference<xml::dom::XSAXDocumentBuilder2>& rDocBuilder) :
75 : SvXMLImportContext( rImport, nPrfx, rLName ),
76 1421 : mxDocBuilder(rDocBuilder)
77 : {
78 1421 : }
79 :
80 2842 : XMLDocumentBuilderContext::~XMLDocumentBuilderContext()
81 : {
82 2842 : }
83 :
84 : SvXMLImportContext *
85 1248 : XMLDocumentBuilderContext::CreateChildContext( sal_uInt16 nPrefix,
86 : const OUString& rLocalName,
87 : const uno::Reference< xml::sax::XAttributeList>& rAttrs)
88 : {
89 : return new XMLDocumentBuilderContext(
90 1248 : GetImport(), nPrefix, rLocalName, rAttrs, mxDocBuilder);
91 : }
92 :
93 1421 : void XMLDocumentBuilderContext::StartElement(
94 : const uno::Reference< xml::sax::XAttributeList >& xAttrList )
95 : {
96 1421 : mxDocBuilder->startElement(
97 2842 : GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()),
98 4263 : xAttrList);
99 1421 : }
100 :
101 1013 : void XMLDocumentBuilderContext::Characters( const OUString& rChars )
102 : {
103 1013 : mxDocBuilder->characters(rChars);
104 1013 : }
105 :
106 1421 : void XMLDocumentBuilderContext::EndElement()
107 : {
108 1421 : mxDocBuilder->endElement(
109 1421 : GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()));
110 1421 : }
111 :
112 :
113 : //===========================================================================
114 :
115 : static void
116 172 : lcl_initDocumentProperties(SvXMLImport & rImport,
117 : uno::Reference<xml::dom::XSAXDocumentBuilder2> const& xDocBuilder,
118 : uno::Reference<document::XDocumentProperties> const& xDocProps)
119 : {
120 172 : uno::Sequence< uno::Any > aSeq(1);
121 172 : aSeq[0] <<= xDocBuilder->getDocument();
122 : uno::Reference< lang::XInitialization > const xInit(xDocProps,
123 344 : uno::UNO_QUERY_THROW);
124 : try {
125 172 : xInit->initialize(aSeq);
126 172 : rImport.SetStatistics(xDocProps->getDocumentStatistics());
127 : // convert all URLs from relative to absolute
128 172 : xDocProps->setTemplateURL(rImport.GetAbsoluteReference(
129 172 : xDocProps->getTemplateURL()));
130 172 : xDocProps->setAutoloadURL(rImport.GetAbsoluteReference(
131 172 : xDocProps->getAutoloadURL()));
132 : SvXMLMetaDocumentContext::setBuildId(
133 172 : xDocProps->getGenerator(), rImport.getImportInfo());
134 0 : } catch (const uno::RuntimeException&) {
135 0 : throw;
136 0 : } catch (const uno::Exception& e) {
137 : throw lang::WrappedTargetRuntimeException(
138 : OUString(
139 : "SvXMLMetaDocumentContext::initDocumentProperties: "
140 : "properties init exception"),
141 0 : rImport, makeAny(e));
142 172 : }
143 172 : }
144 :
145 : static void
146 2 : lcl_initGenerator(SvXMLImport & rImport,
147 : uno::Reference<xml::dom::XSAXDocumentBuilder2> const& xDocBuilder)
148 : {
149 4 : uno::Reference< xml::dom::XDocument > const xDoc(xDocBuilder->getDocument(),
150 4 : uno::UNO_SET_THROW);
151 : try {
152 : uno::Reference< xml::xpath::XXPathAPI > const xPath = xml::xpath::XPathAPI::create(
153 2 : rImport.GetComponentContext() );
154 2 : xPath->registerNS(GetXMLToken(XML_NP_OFFICE),GetXMLToken(XML_N_OFFICE));
155 2 : xPath->registerNS(GetXMLToken(XML_NP_META), GetXMLToken(XML_N_META));
156 :
157 4 : OUString const expr( "string(/office:document-meta/office:meta/meta:generator)");
158 : uno::Reference< xml::xpath::XXPathObject > const xObj(
159 4 : xPath->eval(xDoc.get(), expr), uno::UNO_SET_THROW);
160 4 : OUString const value(xObj->getString());
161 4 : SvXMLMetaDocumentContext::setBuildId(value, rImport.getImportInfo());
162 0 : } catch (const uno::RuntimeException&) {
163 0 : throw;
164 0 : } catch (const uno::Exception& e) {
165 : throw lang::WrappedTargetRuntimeException(
166 : OUString(
167 : "SvXMLMetaDocumentContext::initGenerator: exception"),
168 0 : rImport, makeAny(e));
169 2 : }
170 2 : }
171 :
172 174 : SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport& rImport,
173 : sal_uInt16 nPrfx, const OUString& rLName,
174 : const uno::Reference<document::XDocumentProperties>& xDocProps) :
175 : SvXMLImportContext( rImport, nPrfx, rLName ),
176 : mxDocProps(xDocProps),
177 : mxDocBuilder(
178 : xml::dom::SAXDocumentBuilder::create(
179 174 : comphelper::getProcessComponentContext()))
180 : {
181 : // #i103539#: must always read meta.xml for generator, xDocProps unwanted then
182 : // OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props");
183 174 : }
184 :
185 520 : SvXMLMetaDocumentContext::~SvXMLMetaDocumentContext()
186 : {
187 520 : }
188 :
189 173 : SvXMLImportContext *SvXMLMetaDocumentContext::CreateChildContext(
190 : sal_uInt16 nPrefix, const OUString& rLocalName,
191 : const uno::Reference<xml::sax::XAttributeList>& rAttrs)
192 : {
193 346 : if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
194 173 : IsXMLToken(rLocalName, XML_META) )
195 : {
196 : return new XMLDocumentBuilderContext(
197 173 : GetImport(), nPrefix, rLocalName, rAttrs, mxDocBuilder);
198 : }
199 : else
200 : {
201 0 : return new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
202 : }
203 : }
204 :
205 :
206 174 : void SvXMLMetaDocumentContext::StartElement(
207 : const uno::Reference< xml::sax::XAttributeList >& xAttrList )
208 : {
209 174 : mxDocBuilder->startDocument();
210 : // hardcode office:document-meta (necessary in case of flat file ODF)
211 174 : mxDocBuilder->startElement(
212 348 : GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
213 522 : GetXMLToken(XML_DOCUMENT_META)), xAttrList);
214 :
215 174 : }
216 :
217 174 : void SvXMLMetaDocumentContext::EndElement()
218 : {
219 : // hardcode office:document-meta (necessary in case of flat file ODF)
220 174 : mxDocBuilder->endElement(
221 348 : GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(),
222 522 : GetXMLToken(XML_DOCUMENT_META)));
223 174 : mxDocBuilder->endDocument();
224 174 : if (mxDocProps.is())
225 : {
226 172 : lcl_initDocumentProperties(GetImport(), mxDocBuilder, mxDocProps);
227 : }
228 : else
229 : {
230 2 : lcl_initGenerator(GetImport(), mxDocBuilder);
231 : }
232 174 : }
233 :
234 193 : void SvXMLMetaDocumentContext::setBuildId(OUString const& i_rBuildId, const uno::Reference<beans::XPropertySet>& xImportInfo )
235 : {
236 193 : OUString sBuildId;
237 : // skip to second product
238 193 : sal_Int32 nBegin = i_rBuildId.indexOf( ' ' );
239 193 : if ( nBegin != -1 )
240 : {
241 : // skip to build information
242 191 : nBegin = i_rBuildId.indexOf( '/', nBegin );
243 191 : if ( nBegin != -1 )
244 : {
245 185 : sal_Int32 nEnd = i_rBuildId.indexOf( 'm', nBegin );
246 185 : if ( nEnd != -1 )
247 : {
248 : OUStringBuffer sBuffer(
249 40 : i_rBuildId.copy( nBegin+1, nEnd-nBegin-1 ) );
250 : const OUString sBuildCompare(
251 80 : "$Build-" );
252 40 : nBegin = i_rBuildId.indexOf( sBuildCompare, nEnd );
253 40 : if ( nBegin != -1 )
254 : {
255 40 : sBuffer.append( (sal_Unicode)'$' );
256 : sBuffer.append( i_rBuildId.copy(
257 40 : nBegin + sBuildCompare.getLength() ) );
258 40 : sBuildId = sBuffer.makeStringAndClear();
259 40 : }
260 : }
261 : }
262 : }
263 :
264 193 : if ( sBuildId.isEmpty() )
265 : {
266 306 : if ( i_rBuildId.startsWith("StarOffice 7")
267 153 : || i_rBuildId.startsWith("StarSuite 7")
268 306 : || i_rBuildId.startsWith("OpenOffice.org 1"))
269 : {
270 0 : sBuildId = OUString("645$8687");
271 : }
272 153 : else if (i_rBuildId.startsWith("NeoOffice/2"))
273 : {
274 0 : sBuildId = OUString("680$9134"); // fake NeoOffice as OpenOffice.org 2.2 release
275 : }
276 : }
277 :
278 193 : if (i_rBuildId.startsWith("LibreOffice/"))
279 : {
280 160 : OUStringBuffer sNumber;
281 2278 : for (sal_Int32 i = sizeof("LibreOffice/") - 1;
282 1139 : i < i_rBuildId.getLength(); ++i)
283 : {
284 1139 : if (isdigit(i_rBuildId[i]))
285 : {
286 530 : sNumber.append(i_rBuildId[i]);
287 : }
288 609 : else if ('.' != i_rBuildId[i])
289 : {
290 160 : break;
291 : }
292 : }
293 160 : if (!sNumber.isEmpty())
294 : {
295 160 : sBuildId += (";" + sNumber.makeStringAndClear());
296 160 : }
297 : }
298 :
299 193 : if ( !sBuildId.isEmpty() ) try
300 : {
301 177 : if( xImportInfo.is() )
302 : {
303 177 : const OUString aPropName("BuildId");
304 : uno::Reference< beans::XPropertySetInfo > xSetInfo(
305 354 : xImportInfo->getPropertySetInfo());
306 177 : if( xSetInfo.is() && xSetInfo->hasPropertyByName( aPropName ) )
307 331 : xImportInfo->setPropertyValue( aPropName, uno::makeAny( sBuildId ) );
308 : }
309 : }
310 0 : catch(const uno::Exception&)
311 : {
312 193 : }
313 193 : }
314 :
315 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|