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