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 #include "EventOASISTContext.hxx" 31 #include "EventMap.hxx" 32 #include "MutableAttrList.hxx" 33 #include "xmloff/xmlnmspe.hxx" 34 #include "ActionMapTypesOASIS.hxx" 35 #include "AttrTransformerAction.hxx" 36 #include "TransformerActions.hxx" 37 #ifndef _XMLOFF_TRANSFORMERBASE_HXX 38 #include "TransformerBase.hxx" 39 #endif 40 41 #ifndef OASIS_FILTER_OOO_1X 42 // Used to parse Scripting Framework URLs 43 #include <com/sun/star/uri/XUriReferenceFactory.hpp> 44 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> 45 #include <comphelper/processfactory.hxx> 46 #endif 47 48 #include <hash_map> 49 50 using ::rtl::OUString; 51 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::xml::sax; 54 using namespace ::xmloff::token; 55 56 class XMLTransformerOASISEventMap_Impl: 57 public ::std::hash_map< NameKey_Impl, ::rtl::OUString, 58 NameHash_Impl, NameHash_Impl > 59 { 60 public: 61 XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit ); 62 ~XMLTransformerOASISEventMap_Impl(); 63 }; 64 65 XMLTransformerOASISEventMap_Impl::XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit ) 66 { 67 if( pInit ) 68 { 69 XMLTransformerOASISEventMap_Impl::key_type aKey; 70 XMLTransformerOASISEventMap_Impl::data_type aData; 71 while( pInit->m_pOASISName ) 72 { 73 aKey.m_nPrefix = pInit->m_nOASISPrefix; 74 aKey.m_aLocalName = OUString::createFromAscii(pInit->m_pOASISName); 75 76 OSL_ENSURE( find( aKey ) == end(), "duplicate event map entry" ); 77 78 aData = OUString::createFromAscii(pInit->m_pOOoName); 79 80 XMLTransformerOASISEventMap_Impl::value_type aVal( aKey, aData ); 81 82 insert( aVal ); 83 ++pInit; 84 } 85 } 86 } 87 88 XMLTransformerOASISEventMap_Impl::~XMLTransformerOASISEventMap_Impl() 89 { 90 } 91 92 // ----------------------------------------------------------------------------- 93 94 TYPEINIT1( XMLEventOASISTransformerContext, XMLRenameElemTransformerContext); 95 96 XMLEventOASISTransformerContext::XMLEventOASISTransformerContext( 97 XMLTransformerBase& rImp, 98 const OUString& rQName ) : 99 XMLRenameElemTransformerContext( rImp, rQName, 100 rImp.GetNamespaceMap().GetKeyByAttrName( rQName ), XML_EVENT ) 101 { 102 } 103 104 XMLEventOASISTransformerContext::~XMLEventOASISTransformerContext() 105 { 106 } 107 108 XMLTransformerOASISEventMap_Impl 109 *XMLEventOASISTransformerContext::CreateEventMap() 110 { 111 return new XMLTransformerOASISEventMap_Impl( aTransformerEventMap ); 112 } 113 114 XMLTransformerOASISEventMap_Impl 115 *XMLEventOASISTransformerContext::CreateFormEventMap() 116 { 117 return new XMLTransformerOASISEventMap_Impl( aFormTransformerEventMap ); 118 } 119 120 void XMLEventOASISTransformerContext::FlushEventMap( 121 XMLTransformerOASISEventMap_Impl *p ) 122 { 123 delete p; 124 } 125 126 OUString XMLEventOASISTransformerContext::GetEventName( 127 sal_uInt16 nPrefix, 128 const OUString& rName, 129 XMLTransformerOASISEventMap_Impl& rMap, 130 XMLTransformerOASISEventMap_Impl *pMap2) 131 { 132 XMLTransformerOASISEventMap_Impl::key_type aKey( nPrefix, rName ); 133 if( pMap2 ) 134 { 135 XMLTransformerOASISEventMap_Impl::const_iterator aIter = 136 pMap2->find( aKey ); 137 if( !(aIter == pMap2->end()) ) 138 return (*aIter).second; 139 } 140 141 XMLTransformerOASISEventMap_Impl::const_iterator aIter = rMap.find( aKey ); 142 if( aIter == rMap.end() ) 143 return rName; 144 else 145 return (*aIter).second; 146 } 147 148 bool ParseURLAsString( 149 const OUString& rAttrValue, 150 OUString* pName, OUString* pLocation ) 151 { 152 OUString SCHEME( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:" ) ); 153 154 sal_Int32 params = rAttrValue.indexOf( '?' ); 155 if ( rAttrValue.indexOf( SCHEME ) != 0 || params < 0 ) 156 { 157 return sal_False; 158 } 159 160 sal_Int32 start = SCHEME.getLength(); 161 *pName = rAttrValue.copy( start, params - start ); 162 163 OUString aToken; 164 OUString aLanguage; 165 params++; 166 do 167 { 168 aToken = rAttrValue.getToken( 0, '&', params ); 169 sal_Int32 dummy = 0; 170 171 if ( aToken.match( GetXMLToken( XML_LANGUAGE ) ) ) 172 { 173 aLanguage = aToken.getToken( 1, '=', dummy ); 174 } 175 else if ( aToken.match( GetXMLToken( XML_LOCATION ) ) ) 176 { 177 OUString tmp = aToken.getToken( 1, '=', dummy ); 178 if ( tmp.equalsIgnoreAsciiCase( GetXMLToken( XML_DOCUMENT ) ) ) 179 { 180 *pLocation = GetXMLToken( XML_DOCUMENT ); 181 } 182 else 183 { 184 *pLocation = GetXMLToken( XML_APPLICATION ); 185 } 186 } 187 } while ( params >= 0 ); 188 189 if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) ) 190 { 191 return sal_True; 192 } 193 return sal_False; 194 } 195 196 bool ParseURL( 197 const OUString& rAttrValue, 198 OUString* pName, OUString* pLocation ) 199 { 200 #ifdef OASIS_FILTER_OOO_1X 201 return ParseURLAsString( rAttrValue, pName, pLocation ); 202 #else 203 Reference< com::sun::star::lang::XMultiServiceFactory > 204 xSMgr = ::comphelper::getProcessServiceFactory(); 205 206 Reference< com::sun::star::uri::XUriReferenceFactory > 207 xFactory( xSMgr->createInstance( OUString::createFromAscii( 208 "com.sun.star.uri.UriReferenceFactory" ) ), UNO_QUERY ); 209 210 if ( xFactory.is() ) 211 { 212 Reference< com::sun::star::uri::XVndSunStarScriptUrl > xUrl ( 213 xFactory->parse( rAttrValue ), UNO_QUERY ); 214 215 if ( xUrl.is() ) 216 { 217 OUString aLanguageKey = GetXMLToken( XML_LANGUAGE ); 218 if ( xUrl.is() && xUrl->hasParameter( aLanguageKey ) ) 219 { 220 OUString aLanguage = xUrl->getParameter( aLanguageKey ); 221 222 if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) ) 223 { 224 *pName = xUrl->getName(); 225 226 OUString tmp = 227 xUrl->getParameter( GetXMLToken( XML_LOCATION ) ); 228 229 OUString doc = GetXMLToken( XML_DOCUMENT ); 230 231 if ( tmp.equalsIgnoreAsciiCase( doc ) ) 232 { 233 *pLocation = doc; 234 } 235 else 236 { 237 *pLocation = GetXMLToken( XML_APPLICATION ); 238 } 239 return sal_True; 240 } 241 } 242 } 243 return sal_False; 244 } 245 else 246 { 247 return ParseURLAsString( rAttrValue, pName, pLocation ); 248 } 249 #endif 250 } 251 252 void XMLEventOASISTransformerContext::StartElement( 253 const Reference< XAttributeList >& rAttrList ) 254 { 255 OSL_TRACE("XMLEventOASISTransformerContext::StartElement"); 256 257 XMLTransformerActions *pActions = 258 GetTransformer().GetUserDefinedActions( OASIS_EVENT_ACTIONS ); 259 OSL_ENSURE( pActions, "go no actions" ); 260 261 Reference< XAttributeList > xAttrList( rAttrList ); 262 XMLMutableAttributeList *pMutableAttrList = 0; 263 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 264 for( sal_Int16 i=0; i < nAttrCount; i++ ) 265 { 266 const OUString& rAttrName = xAttrList->getNameByIndex( i ); 267 OUString aLocalName; 268 sal_uInt16 nPrefix = 269 GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName, 270 &aLocalName ); 271 XMLTransformerActions::key_type aKey( nPrefix, aLocalName ); 272 XMLTransformerActions::const_iterator aIter = 273 pActions->find( aKey ); 274 if( !(aIter == pActions->end() ) ) 275 { 276 if( !pMutableAttrList ) 277 { 278 pMutableAttrList = 279 new XMLMutableAttributeList( xAttrList ); 280 xAttrList = pMutableAttrList; 281 } 282 const OUString& rAttrValue = xAttrList->getValueByIndex( i ); 283 switch( (*aIter).second.m_nActionType ) 284 { 285 case XML_ATACTION_HREF: 286 { 287 OUString aAttrValue( rAttrValue ); 288 OUString aName, aLocation; 289 290 bool bNeedsTransform = 291 ParseURL( rAttrValue, &aName, &aLocation ); 292 293 if ( bNeedsTransform ) 294 { 295 pMutableAttrList->RemoveAttributeByIndex( i ); 296 297 OUString aAttrQName( 298 GetTransformer().GetNamespaceMap().GetQNameByKey( 299 XML_NAMESPACE_SCRIPT, 300 ::xmloff::token::GetXMLToken( XML_MACRO_NAME ) ) ); 301 302 pMutableAttrList->AddAttribute( aAttrQName, aName ); 303 304 sal_Int16 idx = pMutableAttrList->GetIndexByName( 305 GetTransformer().GetNamespaceMap().GetQNameByKey( 306 XML_NAMESPACE_SCRIPT, 307 GetXMLToken( XML_LANGUAGE ) ) ); 308 309 pMutableAttrList->SetValueByIndex( idx, 310 OUString::createFromAscii("StarBasic") ); 311 312 OUString aLocQName( 313 GetTransformer().GetNamespaceMap().GetQNameByKey( 314 XML_NAMESPACE_SCRIPT, 315 GetXMLToken( XML_LOCATION ) ) ); 316 317 pMutableAttrList->AddAttribute( aLocQName, aLocation ); 318 } 319 } 320 break; 321 case XML_ATACTION_EVENT_NAME: 322 { 323 // Check if the event belongs to a form or control by 324 // cehcking the 2nd ancestor element, f.i.: 325 // <form:button><form:event-listeners><form:event-listener> 326 const XMLTransformerContext *pObjContext = 327 GetTransformer().GetAncestorContext( 1 ); 328 sal_Bool bForm = pObjContext && 329 330 pObjContext->HasNamespace(XML_NAMESPACE_FORM ); 331 pMutableAttrList->SetValueByIndex( i, 332 GetTransformer().GetEventName( rAttrValue, 333 bForm ) ); 334 } 335 break; 336 case XML_ATACTION_REMOVE_NAMESPACE_PREFIX: 337 { 338 OUString aAttrValue( rAttrValue ); 339 sal_uInt16 nValPrefix = 340 static_cast<sal_uInt16>((*aIter).second.m_nParam1); 341 if( GetTransformer().RemoveNamespacePrefix( 342 aAttrValue, nValPrefix ) ) 343 pMutableAttrList->SetValueByIndex( i, aAttrValue ); 344 } 345 break; 346 case XML_ATACTION_MACRO_NAME: 347 { 348 OUString aName, aLocation; 349 bool bNeedsTransform = 350 ParseURL( rAttrValue, &aName, &aLocation ); 351 352 if ( bNeedsTransform ) 353 { 354 pMutableAttrList->SetValueByIndex( i, aName ); 355 356 sal_Int16 idx = pMutableAttrList->GetIndexByName( 357 GetTransformer().GetNamespaceMap().GetQNameByKey( 358 XML_NAMESPACE_SCRIPT, 359 GetXMLToken( XML_LANGUAGE ) ) ); 360 361 pMutableAttrList->SetValueByIndex( idx, 362 OUString::createFromAscii("StarBasic") ); 363 364 OUString aLocQName( 365 GetTransformer().GetNamespaceMap().GetQNameByKey( 366 XML_NAMESPACE_SCRIPT, 367 GetXMLToken( XML_LOCATION ) ) ); 368 369 pMutableAttrList->AddAttribute( aLocQName, aLocation ); 370 } 371 else 372 { 373 const OUString& rApp = GetXMLToken( XML_APPLICATION ); 374 const OUString& rDoc = GetXMLToken( XML_DOCUMENT ); 375 OUString aAttrValue; 376 if( rAttrValue.getLength() > rApp.getLength()+1 && 377 rAttrValue.copy(0,rApp.getLength()). 378 equalsIgnoreAsciiCase( rApp ) && 379 ':' == rAttrValue[rApp.getLength()] ) 380 { 381 aLocation = rApp; 382 aAttrValue = rAttrValue.copy( rApp.getLength()+1 ); 383 } 384 else if( rAttrValue.getLength() > rDoc.getLength()+1 && 385 rAttrValue.copy(0,rDoc.getLength()). 386 equalsIgnoreAsciiCase( rDoc ) && 387 ':' == rAttrValue[rDoc.getLength()] ) 388 { 389 aLocation= rDoc; 390 aAttrValue = rAttrValue.copy( rDoc.getLength()+1 ); 391 } 392 if( aAttrValue.getLength() ) 393 pMutableAttrList->SetValueByIndex( i, 394 aAttrValue ); 395 if( aLocation.getLength() ) 396 { 397 OUString aAttrQName( GetTransformer().GetNamespaceMap(). 398 GetQNameByKey( XML_NAMESPACE_SCRIPT, 399 ::xmloff::token::GetXMLToken( XML_LOCATION ) ) ); 400 pMutableAttrList->AddAttribute( aAttrQName, aLocation ); 401 // draw bug 402 aAttrQName = GetTransformer().GetNamespaceMap(). 403 GetQNameByKey( XML_NAMESPACE_SCRIPT, 404 ::xmloff::token::GetXMLToken( XML_LIBRARY ) ); 405 pMutableAttrList->AddAttribute( aAttrQName, aLocation ); 406 } 407 } 408 } 409 break; 410 case XML_ATACTION_COPY: 411 break; 412 default: 413 OSL_ENSURE( !this, "unknown action" ); 414 break; 415 } 416 } 417 } 418 419 XMLRenameElemTransformerContext::StartElement( xAttrList ); 420 } 421