1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 27 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 28 #include <com/sun/star/xml/dom/XSAXDocumentBuilder.hpp> 29 #include <com/sun/star/xml/xpath/XXPathAPI.hpp> 30 #include <com/sun/star/beans/XPropertySet.hpp> 31 #include <com/sun/star/beans/XPropertySetInfo.hpp> 32 33 #include <tools/debug.hxx> 34 35 #include <xmloff/xmlmetai.hxx> 36 #include <xmloff/xmlimp.hxx> 37 #include <xmloff/nmspmap.hxx> 38 #include <xmloff/xmltoken.hxx> 39 #include "xmloff/xmlnmspe.hxx" 40 41 42 using ::rtl::OUString; 43 using ::rtl::OUStringBuffer; 44 using namespace com::sun::star; 45 using namespace ::xmloff::token; 46 47 48 //=========================================================================== 49 50 /// builds a DOM tree from SAX events, by forwarding to SAXDocumentBuilder 51 class XMLDocumentBuilderContext : public SvXMLImportContext 52 { 53 private: 54 ::com::sun::star::uno::Reference< 55 ::com::sun::star::xml::sax::XDocumentHandler> mxDocBuilder; 56 57 public: 58 XMLDocumentBuilderContext(SvXMLImport& rImport, sal_uInt16 nPrfx, 59 const ::rtl::OUString& rLName, 60 const ::com::sun::star::uno::Reference< 61 ::com::sun::star::xml::sax::XAttributeList>& xAttrList, 62 const ::com::sun::star::uno::Reference< 63 ::com::sun::star::xml::sax::XDocumentHandler>& rDocBuilder); 64 65 virtual ~XMLDocumentBuilderContext(); 66 67 virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, 68 const rtl::OUString& rLocalName, 69 const ::com::sun::star::uno::Reference< 70 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 71 72 virtual void StartElement( const ::com::sun::star::uno::Reference< 73 ::com::sun::star::xml::sax::XAttributeList >& xAttrList ); 74 75 virtual void Characters( const ::rtl::OUString& rChars ); 76 77 virtual void EndElement(); 78 }; 79 80 XMLDocumentBuilderContext::XMLDocumentBuilderContext(SvXMLImport& rImport, 81 sal_uInt16 nPrfx, const ::rtl::OUString& rLName, 82 const uno::Reference<xml::sax::XAttributeList>&, 83 const uno::Reference<xml::sax::XDocumentHandler>& rDocBuilder) : 84 SvXMLImportContext( rImport, nPrfx, rLName ), 85 mxDocBuilder(rDocBuilder) 86 { 87 } 88 89 XMLDocumentBuilderContext::~XMLDocumentBuilderContext() 90 { 91 } 92 93 SvXMLImportContext * 94 XMLDocumentBuilderContext::CreateChildContext( sal_uInt16 nPrefix, 95 const rtl::OUString& rLocalName, 96 const uno::Reference< xml::sax::XAttributeList>& rAttrs) 97 { 98 return new XMLDocumentBuilderContext( 99 GetImport(), nPrefix, rLocalName, rAttrs, mxDocBuilder); 100 } 101 102 void XMLDocumentBuilderContext::StartElement( 103 const uno::Reference< xml::sax::XAttributeList >& xAttrList ) 104 { 105 mxDocBuilder->startElement( 106 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName()), 107 xAttrList); 108 } 109 110 void XMLDocumentBuilderContext::Characters( const ::rtl::OUString& rChars ) 111 { 112 mxDocBuilder->characters(rChars); 113 } 114 115 void XMLDocumentBuilderContext::EndElement() 116 { 117 mxDocBuilder->endElement( 118 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), GetLocalName())); 119 } 120 121 122 //=========================================================================== 123 124 static void 125 lcl_initDocumentProperties(SvXMLImport & rImport, 126 uno::Reference<xml::sax::XDocumentHandler> const& xDocBuilder, 127 uno::Reference<document::XDocumentProperties> const& xDocProps) 128 { 129 uno::Sequence< uno::Any > aSeq(1); 130 uno::Reference< xml::dom::XSAXDocumentBuilder > const xDB(xDocBuilder, 131 uno::UNO_QUERY_THROW); 132 aSeq[0] <<= xDB->getDocument(); 133 uno::Reference< lang::XInitialization > const xInit(xDocProps, 134 uno::UNO_QUERY_THROW); 135 try { 136 xInit->initialize(aSeq); 137 rImport.SetStatistics(xDocProps->getDocumentStatistics()); 138 // convert all URLs from relative to absolute 139 xDocProps->setTemplateURL(rImport.GetAbsoluteReference( 140 xDocProps->getTemplateURL())); 141 xDocProps->setAutoloadURL(rImport.GetAbsoluteReference( 142 xDocProps->getAutoloadURL())); 143 SvXMLMetaDocumentContext::setBuildId( 144 xDocProps->getGenerator(), rImport.getImportInfo()); 145 } catch (uno::RuntimeException) { 146 throw; 147 } catch (uno::Exception & e) { 148 throw lang::WrappedTargetRuntimeException( 149 ::rtl::OUString::createFromAscii( 150 "SvXMLMetaDocumentContext::initDocumentProperties: " 151 "properties init exception"), 152 rImport, makeAny(e)); 153 } 154 } 155 156 static void 157 lcl_initGenerator(SvXMLImport & rImport, 158 uno::Reference<xml::sax::XDocumentHandler> const& xDocBuilder) 159 { 160 uno::Reference< xml::dom::XSAXDocumentBuilder > const xDB(xDocBuilder, 161 uno::UNO_QUERY_THROW); 162 uno::Reference< xml::dom::XDocument > const xDoc(xDB->getDocument(), 163 uno::UNO_SET_THROW); 164 try { 165 uno::Reference< xml::xpath::XXPathAPI > const xPath( 166 rImport.getServiceFactory()->createInstance( 167 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 168 "com.sun.star.xml.xpath.XPathAPI"))), 169 uno::UNO_QUERY_THROW ); 170 xPath->registerNS(GetXMLToken(XML_NP_OFFICE),GetXMLToken(XML_N_OFFICE)); 171 xPath->registerNS(GetXMLToken(XML_NP_META), GetXMLToken(XML_N_META)); 172 173 ::rtl::OUString const expr(RTL_CONSTASCII_USTRINGPARAM( 174 "string(/office:document-meta/office:meta/meta:generator)")); 175 uno::Reference< xml::xpath::XXPathObject > const xObj( 176 xPath->eval(xDoc.get(), expr), uno::UNO_SET_THROW); 177 OUString const value(xObj->getString()); 178 SvXMLMetaDocumentContext::setBuildId(value, rImport.getImportInfo()); 179 } catch (uno::RuntimeException) { 180 throw; 181 } catch (uno::Exception & e) { 182 throw lang::WrappedTargetRuntimeException( 183 ::rtl::OUString::createFromAscii( 184 "SvXMLMetaDocumentContext::initGenerator: exception"), 185 rImport, makeAny(e)); 186 } 187 } 188 189 SvXMLMetaDocumentContext::SvXMLMetaDocumentContext(SvXMLImport& rImport, 190 sal_uInt16 nPrfx, const rtl::OUString& rLName, 191 const uno::Reference<document::XDocumentProperties>& xDocProps, 192 const uno::Reference<xml::sax::XDocumentHandler>& xDocBuilder) : 193 SvXMLImportContext( rImport, nPrfx, rLName ), 194 mxDocProps(xDocProps), 195 mxDocBuilder(xDocBuilder) 196 { 197 // #i103539#: must always read meta.xml for generator, xDocProps unwanted then 198 // OSL_ENSURE(xDocProps.is(), "SvXMLMetaDocumentContext: no document props"); 199 OSL_ENSURE(xDocBuilder.is(), "SvXMLMetaDocumentContext: no document hdlr"); 200 // here are no attributes 201 } 202 203 SvXMLMetaDocumentContext::~SvXMLMetaDocumentContext() 204 { 205 } 206 207 SvXMLImportContext *SvXMLMetaDocumentContext::CreateChildContext( 208 sal_uInt16 nPrefix, const rtl::OUString& rLocalName, 209 const uno::Reference<xml::sax::XAttributeList>& rAttrs) 210 { 211 if ( (XML_NAMESPACE_OFFICE == nPrefix) && 212 IsXMLToken(rLocalName, XML_META) ) 213 { 214 return new XMLDocumentBuilderContext( 215 GetImport(), nPrefix, rLocalName, rAttrs, mxDocBuilder); 216 } 217 else 218 { 219 return new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); 220 } 221 } 222 223 224 void SvXMLMetaDocumentContext::StartElement( 225 const uno::Reference< xml::sax::XAttributeList >& xAttrList ) 226 { 227 mxDocBuilder->startDocument(); 228 // hardcode office:document-meta (necessary in case of flat file ODF) 229 mxDocBuilder->startElement( 230 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), 231 GetXMLToken(XML_DOCUMENT_META)), xAttrList); 232 233 } 234 235 void SvXMLMetaDocumentContext::EndElement() 236 { 237 // hardcode office:document-meta (necessary in case of flat file ODF) 238 mxDocBuilder->endElement( 239 GetImport().GetNamespaceMap().GetQNameByKey(GetPrefix(), 240 GetXMLToken(XML_DOCUMENT_META))); 241 mxDocBuilder->endDocument(); 242 if (mxDocProps.is()) 243 { 244 lcl_initDocumentProperties(GetImport(), mxDocBuilder, mxDocProps); 245 } 246 else 247 { 248 lcl_initGenerator(GetImport(), mxDocBuilder); 249 } 250 } 251 252 void SvXMLMetaDocumentContext::setBuildId(::rtl::OUString const& i_rBuildId, const uno::Reference<beans::XPropertySet>& xImportInfo ) 253 { 254 OUString sBuildId; 255 // skip to second product 256 sal_Int32 nBegin = i_rBuildId.indexOf( ' ' ); 257 if ( nBegin != -1 ) 258 { 259 // skip to build information 260 nBegin = i_rBuildId.indexOf( '/', nBegin ); 261 if ( nBegin != -1 ) 262 { 263 sal_Int32 nEnd = i_rBuildId.indexOf( 'm', nBegin ); 264 if ( nEnd != -1 ) 265 { 266 OUStringBuffer sBuffer( 267 i_rBuildId.copy( nBegin+1, nEnd-nBegin-1 ) ); 268 const OUString sBuildCompare( 269 RTL_CONSTASCII_USTRINGPARAM( "$Build-" ) ); 270 nBegin = i_rBuildId.indexOf( sBuildCompare, nEnd ); 271 if ( nBegin != -1 ) 272 { 273 sBuffer.append( (sal_Unicode)'$' ); 274 sBuffer.append( i_rBuildId.copy( 275 nBegin + sBuildCompare.getLength() ) ); 276 sBuildId = sBuffer.makeStringAndClear(); 277 } 278 } 279 } 280 } 281 282 if ( sBuildId.getLength() == 0 ) 283 { 284 if ((i_rBuildId.compareToAscii( 285 RTL_CONSTASCII_STRINGPARAM("StarOffice 7") ) == 0) || 286 (i_rBuildId.compareToAscii( 287 RTL_CONSTASCII_STRINGPARAM("StarSuite 7") ) == 0) || 288 (i_rBuildId.compareToAscii( 289 RTL_CONSTASCII_STRINGPARAM("OpenOffice.org 1") ) == 0)) 290 { 291 sBuildId = OUString::createFromAscii( "645$8687" ); 292 } 293 if ((i_rBuildId.compareToAscii( RTL_CONSTASCII_STRINGPARAM("NeoOffice/2") ) == 0) ) 294 { 295 sBuildId = OUString::createFromAscii( "680$9134" ); // fake NeoOffice as OpenOffice.org 2.2 release 296 } 297 } 298 else 299 { 300 if ((i_rBuildId.compareToAscii( RTL_CONSTASCII_STRINGPARAM("LibreOffice/3") ) == 0) ) 301 { 302 // #118558# fake LibreOffice3 as OpenOffice.org 3.3 release 303 sBuildId = OUString::createFromAscii( "330$9567" ); 304 } 305 } 306 307 if ( sBuildId.getLength() ) try 308 { 309 if( xImportInfo.is() ) 310 { 311 const OUString aPropName(RTL_CONSTASCII_USTRINGPARAM("BuildId")); 312 uno::Reference< beans::XPropertySetInfo > xSetInfo( 313 xImportInfo->getPropertySetInfo()); 314 if( xSetInfo.is() && xSetInfo->hasPropertyByName( aPropName ) ) 315 xImportInfo->setPropertyValue( aPropName, uno::makeAny( sBuildId ) ); 316 } 317 } 318 catch( uno::Exception& ) 319 { 320 } 321 } 322 323