Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/xmloff/source/transform/EventOASISTContext.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include "EventOASISTContext.hxx"
21
#include "EventMap.hxx"
22
#include "MutableAttrList.hxx"
23
#include <xmloff/xmlnamespace.hxx>
24
#include "ActionMapTypesOASIS.hxx"
25
#include "AttrTransformerAction.hxx"
26
#include "TransformerActions.hxx"
27
#include "TransformerBase.hxx"
28
#include <osl/diagnose.h>
29
#include <sal/log.hxx>
30
#include <o3tl/string_view.hxx>
31
32
// Used to parse Scripting Framework URLs
33
#include <com/sun/star/uri/UriReferenceFactory.hpp>
34
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
35
#include <comphelper/processfactory.hxx>
36
37
#include <unordered_map>
38
39
using namespace ::com::sun::star::uno;
40
using namespace ::com::sun::star::xml::sax;
41
using namespace ::xmloff::token;
42
43
class XMLTransformerOASISEventMap_Impl:
44
    public std::unordered_map< NameKey_Impl, OUString,
45
                            NameHash_Impl, NameHash_Impl >
46
{
47
public:
48
    explicit XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry const *pInit );
49
};
50
51
XMLTransformerOASISEventMap_Impl::XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry const *pInit )
52
0
{
53
0
    if( !pInit )
54
0
        return;
55
56
0
    XMLTransformerOASISEventMap_Impl::key_type aKey;
57
0
    XMLTransformerOASISEventMap_Impl::mapped_type aData;
58
0
    while( !pInit->m_pOASISName.isEmpty() )
59
0
    {
60
0
        aKey.m_nPrefix = pInit->m_nOASISPrefix;
61
0
        aKey.m_aLocalName = pInit->m_pOASISName;
62
63
0
        OSL_ENSURE( find( aKey ) == end(), "duplicate event map entry" );
64
65
0
        aData = pInit->m_pOOoName;
66
67
0
        XMLTransformerOASISEventMap_Impl::value_type aVal( aKey, aData );
68
69
0
        insert( aVal );
70
0
        ++pInit;
71
0
    }
72
0
}
73
74
XMLEventOASISTransformerContext::XMLEventOASISTransformerContext(
75
        XMLTransformerBase& rImp,
76
        const OUString& rQName ) :
77
0
    XMLRenameElemTransformerContext( rImp, rQName,
78
0
         rImp.GetNamespaceMap().GetKeyByAttrName( rQName ), XML_EVENT )
79
0
{
80
0
}
81
82
XMLEventOASISTransformerContext::~XMLEventOASISTransformerContext()
83
0
{
84
0
}
85
86
XMLTransformerOASISEventMap_Impl
87
    *XMLEventOASISTransformerContext::CreateEventMap()
88
0
{
89
0
    return new XMLTransformerOASISEventMap_Impl( aTransformerEventMap );
90
0
}
91
92
XMLTransformerOASISEventMap_Impl
93
    *XMLEventOASISTransformerContext::CreateFormEventMap()
94
0
{
95
0
    return new XMLTransformerOASISEventMap_Impl( aFormTransformerEventMap );
96
0
}
97
98
void XMLEventOASISTransformerContext::FlushEventMap(
99
        XMLTransformerOASISEventMap_Impl *p )
100
0
{
101
0
    delete p;
102
0
}
103
104
OUString XMLEventOASISTransformerContext::GetEventName(
105
        sal_uInt16 nPrefix,
106
        const OUString& rName,
107
           XMLTransformerOASISEventMap_Impl& rMap,
108
           XMLTransformerOASISEventMap_Impl *pMap2)
109
0
{
110
0
    XMLTransformerOASISEventMap_Impl::key_type aKey( nPrefix, rName );
111
0
    if( pMap2 )
112
0
    {
113
0
        XMLTransformerOASISEventMap_Impl::const_iterator aIter =
114
0
            pMap2->find( aKey );
115
0
        if( aIter != pMap2->end() )
116
0
            return (*aIter).second;
117
0
    }
118
119
0
    XMLTransformerOASISEventMap_Impl::const_iterator aIter = rMap.find( aKey );
120
0
    if( aIter == rMap.end() )
121
0
        return rName;
122
0
    else
123
0
        return (*aIter).second;
124
0
}
125
126
static bool ParseURL(
127
    const OUString& rAttrValue,
128
    OUString* pName, OUString* pLocation )
129
0
{
130
0
    const Reference< css::uno::XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
131
132
0
    Reference< css::uri::XUriReferenceFactory > xFactory = css::uri::UriReferenceFactory::create(xContext);
133
134
0
    Reference< css::uri::XVndSunStarScriptUrl > xUrl ( xFactory->parse( rAttrValue ), UNO_QUERY );
135
136
0
    if ( xUrl.is() )
137
0
    {
138
0
        const OUString& aLanguageKey = GetXMLToken( XML_LANGUAGE );
139
0
        if ( xUrl.is() && xUrl->hasParameter( aLanguageKey ) )
140
0
        {
141
0
            OUString aLanguage = xUrl->getParameter( aLanguageKey );
142
143
0
            if ( aLanguage.equalsIgnoreAsciiCase("basic") )
144
0
            {
145
0
                *pName = xUrl->getName();
146
147
0
                OUString tmp =
148
0
                    xUrl->getParameter( GetXMLToken( XML_LOCATION ) );
149
150
0
                const OUString& doc = GetXMLToken( XML_DOCUMENT );
151
152
0
                if ( tmp.equalsIgnoreAsciiCase( doc ) )
153
0
                {
154
0
                    *pLocation = doc;
155
0
                }
156
0
                else
157
0
                {
158
0
                    *pLocation = GetXMLToken( XML_APPLICATION );
159
0
                }
160
0
                return true;
161
0
            }
162
0
        }
163
0
    }
164
0
    return false;
165
0
}
166
167
void XMLEventOASISTransformerContext::StartElement(
168
    const Reference< XAttributeList >& rAttrList )
169
0
{
170
0
    SAL_INFO("xmloff.transform", "XMLEventOASISTransformerContext::StartElement");
171
172
0
    XMLTransformerActions *pActions =
173
0
        GetTransformer().GetUserDefinedActions( OASIS_EVENT_ACTIONS );
174
0
    SAL_WARN_IF( pActions == nullptr, "xmloff.transform", "got no actions" );
175
176
0
    Reference< XAttributeList > xAttrList( rAttrList );
177
0
    rtl::Reference<XMLMutableAttributeList> pMutableAttrList;
178
0
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
179
0
    for( sal_Int16 i=0; i < nAttrCount; i++ )
180
0
    {
181
0
        const OUString aAttrName = xAttrList->getNameByIndex( i );
182
0
        OUString aLocalName;
183
0
        sal_uInt16 nPrefix =
184
0
            GetTransformer().GetNamespaceMap().GetKeyByAttrName( aAttrName,
185
0
                                                                 &aLocalName );
186
0
        XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
187
0
        XMLTransformerActions::const_iterator aIter =
188
0
            pActions->find( aKey );
189
0
        if( aIter != pActions->end() )
190
0
        {
191
0
            if( !pMutableAttrList )
192
0
            {
193
0
                pMutableAttrList =
194
0
                        new XMLMutableAttributeList( xAttrList );
195
0
                xAttrList = pMutableAttrList;
196
0
            }
197
0
            const OUString aAttrValue = xAttrList->getValueByIndex( i );
198
0
            switch( (*aIter).second.m_nActionType )
199
0
            {
200
0
            case XML_ATACTION_HREF:
201
0
                {
202
0
                    OUString aName, aLocation;
203
204
0
                    bool bNeedsTransform =
205
0
                        ParseURL( aAttrValue, &aName, &aLocation );
206
207
0
                    if ( bNeedsTransform )
208
0
                    {
209
0
                        pMutableAttrList->RemoveAttributeByIndex( i );
210
211
0
                        OUString aAttrQName(
212
0
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
213
0
                                XML_NAMESPACE_SCRIPT,
214
0
                            ::xmloff::token::GetXMLToken( XML_MACRO_NAME ) ) );
215
216
0
                        pMutableAttrList->AddAttribute( aAttrQName, aName );
217
218
0
                        sal_Int16 idx = pMutableAttrList->GetIndexByName(
219
0
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
220
0
                                XML_NAMESPACE_SCRIPT,
221
0
                            GetXMLToken( XML_LANGUAGE ) ) );
222
223
0
                        if (idx != -1)
224
0
                            pMutableAttrList->SetValueByIndex(idx, u"StarBasic"_ustr);
225
226
0
                        OUString aLocQName(
227
0
                            GetTransformer().GetNamespaceMap().GetQNameByKey(
228
0
                                XML_NAMESPACE_SCRIPT,
229
0
                                GetXMLToken( XML_LOCATION ) ) );
230
231
0
                        pMutableAttrList->AddAttribute( aLocQName, aLocation );
232
0
                    }
233
0
                }
234
0
                break;
235
0
            case XML_ATACTION_EVENT_NAME:
236
0
                {
237
                    // Check if the event belongs to a form or control by
238
                    // checking the 2nd ancestor element, f.i.:
239
                    // <form:button><form:event-listeners><form:event-listener>
240
0
                    const XMLTransformerContext *pObjContext =
241
0
                        GetTransformer().GetAncestorContext( 1 );
242
0
                    bool bForm = pObjContext &&
243
244
0
                        pObjContext->HasNamespace(XML_NAMESPACE_FORM );
245
0
                    pMutableAttrList->SetValueByIndex( i,
246
0
                                   GetTransformer().GetEventName( aAttrValue,
247
0
                                                                    bForm ) );
248
0
                }
249
0
                break;
250
0
            case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
251
0
                {
252
0
                    OUString aAttrValue2( aAttrValue );
253
0
                    sal_uInt16 nValPrefix =
254
0
                        static_cast<sal_uInt16>((*aIter).second.m_nParam1);
255
0
                    if( GetTransformer().RemoveNamespacePrefix(
256
0
                                aAttrValue2, nValPrefix ) )
257
0
                        pMutableAttrList->SetValueByIndex( i, aAttrValue2 );
258
0
                }
259
0
                break;
260
0
            case XML_ATACTION_MACRO_NAME:
261
0
            {
262
0
                OUString aName, aLocation;
263
0
                bool bNeedsTransform =
264
0
                ParseURL( aAttrValue, &aName, &aLocation );
265
266
0
                if ( bNeedsTransform )
267
0
                {
268
0
                    pMutableAttrList->SetValueByIndex( i, aName );
269
270
0
                    sal_Int16 idx = pMutableAttrList->GetIndexByName(
271
0
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
272
0
                    XML_NAMESPACE_SCRIPT,
273
0
                    GetXMLToken( XML_LANGUAGE ) ) );
274
275
0
                    if (idx != -1)
276
0
                        pMutableAttrList->SetValueByIndex(idx, u"StarBasic"_ustr);
277
278
0
                    OUString aLocQName(
279
0
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
280
0
                    XML_NAMESPACE_SCRIPT,
281
0
                    GetXMLToken( XML_LOCATION ) ) );
282
283
0
                    pMutableAttrList->AddAttribute( aLocQName, aLocation );
284
0
                }
285
0
                else
286
0
                {
287
0
                    const OUString& rApp = GetXMLToken( XML_APPLICATION );
288
0
                    const OUString& rDoc = GetXMLToken( XML_DOCUMENT );
289
0
                    OUString aAttrValue2;
290
0
                    if( aAttrValue.getLength() > rApp.getLength()+1 &&
291
0
                        o3tl::equalsIgnoreAsciiCase(aAttrValue.subView(0,rApp.getLength()), rApp) &&
292
0
                        ':' == aAttrValue[rApp.getLength()] )
293
0
                    {
294
0
                        aLocation = rApp;
295
0
                        aAttrValue2 = aAttrValue.copy( rApp.getLength()+1 );
296
0
                    }
297
0
                    else if( aAttrValue.getLength() > rDoc.getLength()+1 &&
298
0
                             o3tl::equalsIgnoreAsciiCase(aAttrValue.subView(0,rDoc.getLength()), rDoc) &&
299
0
                             ':' == aAttrValue[rDoc.getLength()] )
300
0
                    {
301
0
                        aLocation= rDoc;
302
0
                        aAttrValue2 = aAttrValue.copy( rDoc.getLength()+1 );
303
0
                    }
304
0
                    if( !aAttrValue2.isEmpty() )
305
0
                        pMutableAttrList->SetValueByIndex( i, aAttrValue2 );
306
0
                    if( !aLocation.isEmpty() )
307
0
                    {
308
0
                        OUString aAttrQName( GetTransformer().GetNamespaceMap().
309
0
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
310
0
                        ::xmloff::token::GetXMLToken( XML_LOCATION ) ) );
311
0
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
312
                        // draw bug
313
0
                        aAttrQName = GetTransformer().GetNamespaceMap().
314
0
                        GetQNameByKey( XML_NAMESPACE_SCRIPT,
315
0
                        ::xmloff::token::GetXMLToken( XML_LIBRARY ) );
316
0
                        pMutableAttrList->AddAttribute( aAttrQName, aLocation );
317
0
                    }
318
0
                }
319
0
            }
320
0
            break;
321
0
            case XML_ATACTION_COPY:
322
0
                break;
323
0
            default:
324
0
                SAL_WARN( "xmloff.transform", "unknown action" );
325
0
                break;
326
0
            }
327
0
        }
328
0
    }
329
330
0
    XMLRenameElemTransformerContext::StartElement( xAttrList );
331
0
}
332
333
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */