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 <oox/ole/axcontrolfragment.hxx>
21 
22 #include <oox/core/xmlfilterbase.hxx>
23 #include <oox/helper/attributelist.hxx>
24 #include <oox/helper/binaryinputstream.hxx>
25 #include <oox/helper/binaryoutputstream.hxx>
26 #include <oox/ole/axcontrol.hxx>
27 #include <oox/ole/olehelper.hxx>
28 #include <oox/ole/olestorage.hxx>
29 #include <oox/token/namespaces.hxx>
30 #include <oox/token/tokens.hxx>
31 
32 #include <osl/diagnose.h>
33 
34 namespace oox {
35 namespace ole {
36 
37 using namespace ::com::sun::star::io;
38 using namespace ::com::sun::star::uno;
39 
40 using ::oox::core::ContextHandler2;
41 using ::oox::core::ContextHandlerRef;
42 using ::oox::core::FragmentHandler2;
43 using ::oox::core::XmlFilterBase;
44 
AxControlPropertyContext(FragmentHandler2 const & rFragment,ControlModelBase & rModel)45 AxControlPropertyContext::AxControlPropertyContext( FragmentHandler2 const & rFragment, ControlModelBase& rModel ) :
46     ContextHandler2( rFragment ),
47     mrModel( rModel ),
48     mnPropId( XML_TOKEN_INVALID )
49 {
50 }
51 
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)52 ContextHandlerRef AxControlPropertyContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
53 {
54     switch( getCurrentElement() )
55     {
56         case AX_TOKEN( ocx ):
57             if( nElement == AX_TOKEN( ocxPr ) )
58             {
59                 mnPropId = rAttribs.getToken( AX_TOKEN( name ), XML_TOKEN_INVALID );
60                 switch( mnPropId )
61                 {
62                     case XML_TOKEN_INVALID:
63                         return nullptr;
64                     case XML_Picture:
65                     case XML_MouseIcon:
66                         return this;        // import picture path from ax:picture child element
67                     default:
68                         mrModel.importProperty( mnPropId, rAttribs.getString( AX_TOKEN( value ), OUString() ) );
69                 }
70             }
71         break;
72 
73         case AX_TOKEN( ocxPr ):
74             if( nElement == AX_TOKEN( picture ) )
75             {
76                 OUString aPicturePath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
77                 if( !aPicturePath.isEmpty() )
78                 {
79                     BinaryXInputStream aInStrm( getFilter().openInputStream( aPicturePath ), true );
80                     mrModel.importPictureData( mnPropId, aInStrm );
81                 }
82             }
83         break;
84     }
85     return nullptr;
86 }
87 
AxControlFragment(XmlFilterBase & rFilter,const OUString & rFragmentPath,EmbeddedControl & rControl)88 AxControlFragment::AxControlFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, EmbeddedControl& rControl ) :
89     FragmentHandler2( rFilter, rFragmentPath, true ),
90     mrControl( rControl )
91 {
92 }
93 
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)94 ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
95 {
96     if( isRootElement() && (nElement == AX_TOKEN( ocx )) )
97     {
98         OUString aClassId = rAttribs.getString( AX_TOKEN( classid ), OUString() );
99         switch( rAttribs.getToken( AX_TOKEN( persistence ), XML_TOKEN_INVALID ) )
100         {
101             case XML_persistPropertyBag:
102                 if( ControlModelBase* pModel = mrControl.createModelFromGuid( aClassId ) )
103                     return new AxControlPropertyContext( *this, *pModel );
104             break;
105 
106             case XML_persistStreamInit:
107             {
108                 OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
109                 if( !aFragmentPath.isEmpty() )
110                 {
111                     BinaryXInputStream aInStrm( getFilter().openInputStream( aFragmentPath ), true );
112                     if( !aInStrm.isEof() )
113                     {
114                         // binary stream contains a copy of the class ID, must be equal to attribute value
115                         OUString aStrmClassId = OleHelper::importGuid( aInStrm );
116                         OSL_ENSURE( aClassId.equalsIgnoreAsciiCase( aStrmClassId ),
117                             "AxControlFragment::importBinaryControl - form control class ID mismatch" );
118                         if( ControlModelBase* pModel = mrControl.createModelFromGuid( aStrmClassId ) )
119                             pModel->importBinaryModel( aInStrm );
120                     }
121                 }
122             }
123             break;
124 
125             case XML_persistStorage:
126             {
127                 OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
128                 if( !aFragmentPath.isEmpty() )
129                 {
130                     Reference< XInputStream > xStrgStrm = getFilter().openInputStream( aFragmentPath );
131                     if( xStrgStrm.is() )
132                     {
133                         // Try to import as a parent control
134                         bool bImportedAsParent = false;
135                         OleStorage aStorage( getFilter().getComponentContext(), xStrgStrm, false );
136                         BinaryXInputStream aInStrm( aStorage.openInputStream( "f" ), true );
137                         if( !aInStrm.isEof() )
138                         {
139                             if( AxContainerModelBase* pModel = dynamic_cast< AxContainerModelBase* >( mrControl.createModelFromGuid( aClassId ) ) )
140                             {
141                                 pModel->importBinaryModel( aInStrm );
142                                 bImportedAsParent = true;
143                             }
144                         }
145                         // Import it as a non-parent control
146                         if(!bImportedAsParent)
147                         {
148                             BinaryXInputStream aInStrm2(aStorage.openInputStream("contents"), true);
149                             if (!aInStrm2.isEof())
150                             {
151                                 if (ControlModelBase* pModel = mrControl.createModelFromGuid(aClassId))
152                                 {
153                                     pModel->importBinaryModel(aInStrm2);
154                                 }
155                             }
156                         }
157                     }
158                 }
159             }
160             break;
161         }
162     }
163     return nullptr;
164 }
165 
166 } // namespace ole
167 } // namespace oox
168 
169 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
170