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