xref: /trunk/main/xmloff/source/transform/EventOASISTContext.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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