LCOV - code coverage report
Current view: top level - oox/source/ole - vbaproject.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 157 206 76.2 %
Date: 2012-08-25 Functions: 21 30 70.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 206 483 42.7 %

           Branch data     Line data    Source code
       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/vbaproject.hxx"
      21                 :            : 
      22                 :            : #include <com/sun/star/document/XStorageBasedDocument.hpp>
      23                 :            : #include <com/sun/star/embed/ElementModes.hpp>
      24                 :            : #include <com/sun/star/embed/XTransactedObject.hpp>
      25                 :            : #include <com/sun/star/frame/XModel.hpp>
      26                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      27                 :            : #include <com/sun/star/script/ModuleType.hpp>
      28                 :            : #include <com/sun/star/script/XLibraryContainer.hpp>
      29                 :            : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
      30                 :            : #include <com/sun/star/script/vba/XVBAMacroResolver.hpp>
      31                 :            : #include <com/sun/star/uno/XComponentContext.hpp>
      32                 :            : #include <comphelper/configurationhelper.hxx>
      33                 :            : #include <comphelper/string.hxx>
      34                 :            : #include <rtl/tencinfo.h>
      35                 :            : #include <rtl/ustrbuf.h>
      36                 :            : #include "oox/helper/binaryinputstream.hxx"
      37                 :            : #include "oox/helper/containerhelper.hxx"
      38                 :            : #include "oox/helper/propertyset.hxx"
      39                 :            : #include "oox/helper/textinputstream.hxx"
      40                 :            : #include "oox/ole/olestorage.hxx"
      41                 :            : #include "oox/ole/vbacontrol.hxx"
      42                 :            : #include "oox/ole/vbahelper.hxx"
      43                 :            : #include "oox/ole/vbainputstream.hxx"
      44                 :            : #include "oox/ole/vbamodule.hxx"
      45                 :            : #include "oox/token/properties.hxx"
      46                 :            : 
      47                 :            : namespace oox {
      48                 :            : namespace ole {
      49                 :            : 
      50                 :            : // ============================================================================
      51                 :            : 
      52                 :            : using namespace ::com::sun::star::container;
      53                 :            : using namespace ::com::sun::star::document;
      54                 :            : using namespace ::com::sun::star::embed;
      55                 :            : using namespace ::com::sun::star::frame;
      56                 :            : using namespace ::com::sun::star::io;
      57                 :            : using namespace ::com::sun::star::lang;
      58                 :            : using namespace ::com::sun::star::script;
      59                 :            : using namespace ::com::sun::star::script::vba;
      60                 :            : using namespace ::com::sun::star::uno;
      61                 :            : 
      62                 :            : using ::comphelper::ConfigurationHelper;
      63                 :            : using ::rtl::OUString;
      64                 :            : using ::rtl::OUStringBuffer;
      65                 :            : 
      66                 :            : // ============================================================================
      67                 :            : 
      68                 :            : namespace {
      69                 :            : 
      70                 :         39 : bool lclReadConfigItem( const Reference< XInterface >& rxConfigAccess, const OUString& rItemName )
      71                 :            : {
      72                 :            :     // some applications do not support all configuration items, assume 'false' in this case
      73                 :            :     try
      74                 :            :     {
      75 [ +  - ][ +  - ]:         39 :         Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess, CREATE_OUSTRING( "Filter/Import/VBA" ), rItemName );
      76 [ +  - ][ +  - ]:         39 :         return aItem.has< bool >() && aItem.get< bool >();
         [ +  - ][ #  # ]
                 [ +  - ]
      77                 :            :     }
      78                 :          0 :     catch(const Exception& )
      79                 :            :     {
      80                 :            :     }
      81                 :          0 :     return false;
      82                 :            : }
      83                 :            : 
      84                 :            : } // namespace
      85                 :            : 
      86                 :            : // ----------------------------------------------------------------------------
      87                 :            : 
      88                 :         16 : VbaFilterConfig::VbaFilterConfig( const Reference< XComponentContext >& rxContext, const OUString& rConfigCompName )
      89                 :            : {
      90                 :            :     OSL_ENSURE( rxContext.is(), "VbaFilterConfig::VbaFilterConfig - missing component context" );
      91         [ +  - ]:         16 :     if( rxContext.is() ) try
      92                 :            :     {
      93                 :            :         OSL_ENSURE( !rConfigCompName.isEmpty(), "VbaFilterConfig::VbaFilterConfig - invalid configuration component name" );
      94         [ +  - ]:         16 :         OUString aConfigPackage = CREATE_OUSTRING( "org.openoffice.Office." ) + rConfigCompName;
      95 [ +  - ][ +  - ]:         16 :         Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW );
                 [ +  - ]
      96 [ +  - ][ #  # ]:         16 :         mxConfigAccess = ConfigurationHelper::openConfig( xFactory, aConfigPackage, ConfigurationHelper::E_READONLY );
                 [ +  - ]
      97                 :            :     }
      98         [ #  # ]:          0 :     catch(const Exception& )
      99                 :            :     {
     100                 :            :     }
     101                 :            :     OSL_ENSURE( mxConfigAccess.is(), "VbaFilterConfig::VbaFilterConfig - cannot open configuration" );
     102                 :         16 : }
     103                 :            : 
     104                 :         16 : VbaFilterConfig::~VbaFilterConfig()
     105                 :            : {
     106                 :         16 : }
     107                 :            : 
     108                 :         13 : bool VbaFilterConfig::isImportVba() const
     109                 :            : {
     110         [ +  - ]:         13 :     return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Load" ) );
     111                 :            : }
     112                 :            : 
     113                 :         13 : bool VbaFilterConfig::isImportVbaExecutable() const
     114                 :            : {
     115         [ +  - ]:         13 :     return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Executable" ) );
     116                 :            : }
     117                 :            : 
     118                 :         13 : bool VbaFilterConfig::isExportVba() const
     119                 :            : {
     120         [ +  - ]:         13 :     return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Save" ) );
     121                 :            : }
     122                 :            : 
     123                 :            : // ============================================================================
     124                 :            : 
     125                 :          0 : VbaMacroAttacherBase::VbaMacroAttacherBase( const OUString& rMacroName ) :
     126                 :          0 :     maMacroName( rMacroName )
     127                 :            : {
     128                 :            :     OSL_ENSURE( !maMacroName.isEmpty(), "VbaMacroAttacherBase::VbaMacroAttacherBase - empty macro name" );
     129                 :          0 : }
     130                 :            : 
     131                 :          0 : VbaMacroAttacherBase::~VbaMacroAttacherBase()
     132                 :            : {
     133         [ #  # ]:          0 : }
     134                 :            : 
     135                 :          0 : void VbaMacroAttacherBase::resolveAndAttachMacro( const Reference< XVBAMacroResolver >& rxResolver )
     136                 :            : {
     137                 :            :     try
     138                 :            :     {
     139 [ #  # ][ #  # ]:          0 :         attachMacro( rxResolver->resolveVBAMacroToScriptURL( maMacroName ) );
         [ #  # ][ #  # ]
     140                 :            :     }
     141                 :          0 :     catch(const Exception& )
     142                 :            :     {
     143                 :            :     }
     144                 :          0 : }
     145                 :            : 
     146                 :            : // ============================================================================
     147                 :            : 
     148                 :         16 : VbaProject::VbaProject( const Reference< XComponentContext >& rxContext,
     149                 :            :         const Reference< XModel >& rxDocModel, const OUString& rConfigCompName ) :
     150                 :            :     VbaFilterConfig( rxContext, rConfigCompName ),
     151                 :            :     mxContext( rxContext ),
     152                 :            :     mxDocModel( rxDocModel ),
     153 [ +  - ][ +  - ]:         16 :     maPrjName( CREATE_OUSTRING( "Standard" ) )
                 [ +  - ]
     154                 :            : {
     155                 :            :     OSL_ENSURE( mxContext.is(), "VbaProject::VbaProject - missing component context" );
     156                 :            :     OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" );
     157                 :         16 : }
     158                 :            : 
     159                 :         16 : VbaProject::~VbaProject()
     160                 :            : {
     161         [ -  + ]:         16 : }
     162                 :            : 
     163                 :            : 
     164                 :         16 : bool VbaProject::importVbaProject( StorageBase& rVbaPrjStrg )
     165                 :            : {
     166                 :            :    // create GraphicHelper
     167                 :         16 :    Reference< ::com::sun::star::frame::XFrame > xFrame;
     168         [ +  - ]:         16 :    if ( mxDocModel.is() )
     169                 :            :    {
     170 [ +  - ][ +  - ]:         16 :        Reference< ::com::sun::star::frame::XController > xController =  mxDocModel->getCurrentController();
     171 [ -  + ][ #  # ]:         16 :        xFrame =  xController.is() ? xController->getFrame() : NULL;
         [ #  # ][ +  - ]
                 [ +  - ]
     172                 :            :    }
     173         [ +  - ]:         16 :    StorageRef noStorage;
     174                 :            :    // if the GraphicHelper tries to use noStorage it will of course crash
     175                 :            :    // but.. this shouldn't happen as there is no reason for GraphicHelper
     176                 :            :    // to do that when importing VBA projects
     177         [ +  + ]:         16 :    GraphicHelper grfHlp( mxContext, xFrame, noStorage );
     178         [ +  - ]:         13 :    importVbaProject( rVbaPrjStrg, grfHlp );
     179                 :            :    // return true if something has been imported
     180 [ +  - ][ -  + ]:         16 :    return hasModules() || hasDialogs();
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
     181                 :            : }
     182                 :            : 
     183                 :         13 : void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
     184                 :            : {
     185         [ +  - ]:         13 :     if( rVbaPrjStrg.isStorage() )
     186                 :            :     {
     187                 :            :         // load the code modules and forms
     188         [ +  - ]:         13 :         if( isImportVba() )
     189                 :         13 :             importVba( rVbaPrjStrg, rGraphicHelper, bDefaultColorBgr );
     190                 :            :         // copy entire storage into model
     191         [ +  - ]:         13 :         if( isExportVba() )
     192                 :         13 :             copyStorage( rVbaPrjStrg );
     193                 :            :     }
     194                 :         13 : }
     195                 :            : 
     196                 :          0 : void VbaProject::registerMacroAttacher( const VbaMacroAttacherRef& rxAttacher )
     197                 :            : {
     198                 :            :     OSL_ENSURE( rxAttacher.get(), "VbaProject::registerMacroAttacher - unexpected empty reference" );
     199                 :          0 :     maMacroAttachers.push_back( rxAttacher );
     200                 :          0 : }
     201                 :            : 
     202                 :         13 : bool VbaProject::hasModules() const
     203                 :            : {
     204 [ +  - ][ +  - ]:         13 :     return mxBasicLib.is() && mxBasicLib->hasElements();
     205                 :            : }
     206                 :            : 
     207                 :          0 : bool VbaProject::hasDialogs() const
     208                 :            : {
     209 [ #  # ][ #  # ]:          0 :     return mxDialogLib.is() && mxDialogLib->hasElements();
     210                 :            : }
     211                 :            : 
     212                 :            : // protected ------------------------------------------------------------------
     213                 :            : 
     214                 :          0 : void VbaProject::addDummyModule( const OUString& rName, sal_Int32 nType )
     215                 :            : {
     216                 :            :     OSL_ENSURE( !rName.isEmpty(), "VbaProject::addDummyModule - missing module name" );
     217                 :          0 :     maDummyModules[ rName ] = nType;
     218                 :          0 : }
     219                 :            : 
     220                 :         13 : void VbaProject::prepareImport()
     221                 :            : {
     222                 :         13 : }
     223                 :            : 
     224                 :         13 : void VbaProject::finalizeImport()
     225                 :            : {
     226                 :         13 : }
     227                 :            : 
     228                 :            : // private --------------------------------------------------------------------
     229                 :            : 
     230                 :         26 : Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId )
     231                 :            : {
     232         [ +  - ]:         26 :     PropertySet aDocProp( mxDocModel );
     233 [ +  - ][ +  - ]:         26 :     Reference< XLibraryContainer > xLibContainer( aDocProp.getAnyProperty( nPropId ), UNO_QUERY );
     234         [ +  - ]:         26 :     return xLibContainer;
     235                 :            : }
     236                 :            : 
     237                 :         13 : Reference< XNameContainer > VbaProject::openLibrary( sal_Int32 nPropId, bool bCreateMissing )
     238                 :            : {
     239                 :         13 :     Reference< XNameContainer > xLibrary;
     240                 :            :     try
     241                 :            :     {
     242 [ +  - ][ +  - ]:         13 :         Reference< XLibraryContainer > xLibContainer( getLibraryContainer( nPropId ), UNO_SET_THROW );
     243 [ +  - ][ +  - ]:         13 :         if( bCreateMissing && !xLibContainer->hasByName( maPrjName ) )
         [ +  - ][ +  - ]
                 [ +  - ]
     244 [ +  - ][ +  - ]:         13 :             xLibContainer->createLibrary( maPrjName );
     245 [ +  - ][ +  - ]:         13 :         xLibrary.set( xLibContainer->getByName( maPrjName ), UNO_QUERY_THROW );
         [ +  - ][ #  # ]
     246                 :            :     }
     247         [ #  # ]:          0 :     catch(const Exception& )
     248                 :            :     {
     249                 :            :     }
     250                 :            :     OSL_ENSURE( !bCreateMissing || xLibrary.is(), "VbaProject::openLibrary - cannot create library" );
     251                 :         13 :     return xLibrary;
     252                 :            : }
     253                 :            : 
     254                 :         13 : Reference< XNameContainer > VbaProject::createBasicLibrary()
     255                 :            : {
     256         [ +  - ]:         13 :     if( !mxBasicLib.is() )
     257         [ +  - ]:         13 :         mxBasicLib = openLibrary( PROP_BasicLibraries, true );
     258                 :         13 :     return mxBasicLib;
     259                 :            : }
     260                 :            : 
     261                 :          0 : Reference< XNameContainer > VbaProject::createDialogLibrary()
     262                 :            : {
     263         [ #  # ]:          0 :     if( !mxDialogLib.is() )
     264         [ #  # ]:          0 :         mxDialogLib = openLibrary( PROP_DialogLibraries, true );
     265                 :          0 :     return mxDialogLib;
     266                 :            : }
     267                 :            : 
     268                 :         13 : void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
     269                 :            : {
     270 [ +  - ][ +  - ]:         13 :     StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( CREATE_OUSTRING( "VBA" ), false );
     271                 :            :     OSL_ENSURE( xVbaStrg.get(), "VbaProject::importVba - cannot open 'VBA' substorage" );
     272         [ -  + ]:         13 :     if( !xVbaStrg )
     273                 :            :         return;
     274                 :            : 
     275                 :            :     /*  Read the 'VBA/dir' stream which contains general settings of the VBA
     276                 :            :         project such as the text encoding used throughout several streams, and
     277                 :            :         a list of all code modules.
     278                 :            :      */
     279 [ +  - ][ +  - ]:         13 :     BinaryXInputStream aInStrm( xVbaStrg->openInputStream( CREATE_OUSTRING( "dir" ) ), true );
                 [ +  - ]
     280                 :            :     // VbaInputStream implements decompression
     281         [ +  - ]:         13 :     VbaInputStream aDirStrm( aInStrm );
     282                 :            :     OSL_ENSURE( !aDirStrm.isEof(), "VbaProject::importVba - cannot open 'dir' stream" );
     283         [ -  + ]:         13 :     if( aDirStrm.isEof() )
     284                 :            :         return;
     285                 :            : 
     286                 :            :     // virtual call, derived classes may do some preparations
     287         [ +  - ]:         13 :     prepareImport();
     288                 :            : 
     289                 :            :     // read all records of the directory
     290                 :         13 :     rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
     291                 :         13 :     sal_uInt16 nModuleCount = 0;
     292         [ +  - ]:         13 :     bool bExecutable = isImportVbaExecutable();
     293                 :            : 
     294                 :            :     typedef RefMap< OUString, VbaModule > VbaModuleMap;
     295 [ +  - ][ +  - ]:         13 :     VbaModuleMap aModules, aModulesByStrm;
     296                 :            : 
     297                 :         13 :     sal_uInt16 nRecId = 0;
     298         [ +  - ]:         13 :     StreamDataSequence aRecData;
     299 [ +  - ][ +  - ]:        417 :     while( VbaHelper::readDirRecord( nRecId, aRecData, aDirStrm ) && (nRecId != VBA_ID_PROJECTEND) )
         [ +  + ][ +  + ]
     300                 :            :     {
     301                 :            :         // create record stream object from imported record data
     302         [ +  - ]:        404 :         SequenceInputStream aRecStrm( aRecData );
     303                 :        404 :         sal_Int32 nRecSize = aRecData.getLength();
     304   [ +  +  +  +  :        404 :         switch( nRecId )
                      + ]
     305                 :            :         {
     306                 :            : #define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaProject::importVba - invalid record size" )
     307                 :            :             case VBA_ID_PROJECTCODEPAGE:
     308                 :            :             {
     309                 :            :                 OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
     310                 :            :                 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" );
     311 [ +  - ][ +  - ]:         13 :                 rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() );
     312                 :            :                 OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" );
     313         [ +  - ]:         13 :                 if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
     314                 :         13 :                     eTextEnc = eNewTextEnc;
     315                 :            :             }
     316                 :         13 :             break;
     317                 :            :             case VBA_ID_PROJECTNAME:
     318                 :            :             {
     319         [ +  - ]:         13 :                 OUString aPrjName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
     320                 :            :                 OSL_ENSURE( !aPrjName.isEmpty(), "VbaProject::importVba - invalid project name" );
     321         [ +  - ]:         13 :                 if( !aPrjName.isEmpty() )
     322                 :         13 :                     maPrjName = aPrjName;
     323                 :            :             }
     324                 :         13 :             break;
     325                 :            :             case VBA_ID_PROJECTMODULES:
     326                 :            :                 OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
     327                 :            :                 OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" );
     328         [ +  - ]:         13 :                 aRecStrm >> nModuleCount;
     329                 :         13 :             break;
     330                 :            :             case VBA_ID_MODULENAME:
     331                 :            :             {
     332         [ +  - ]:         65 :                 OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
     333                 :            :                 OSL_ENSURE( !aName.isEmpty(), "VbaProject::importVba - invalid module name" );
     334                 :            :                 OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" );
     335         [ +  - ]:         65 :                 VbaModuleMap::mapped_type& rxModule = aModules[ aName ];
     336 [ +  - ][ +  - ]:         65 :                 rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) );
                 [ +  - ]
     337                 :            :                 // read all remaining records until the MODULEEND record
     338         [ +  - ]:         65 :                 rxModule->importDirRecords( aDirStrm );
     339                 :            :                 OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" );
     340 [ +  - ][ +  - ]:         65 :                 aModulesByStrm[ rxModule->getStreamName() ] = rxModule;
     341                 :            :             }
     342                 :         65 :             break;
     343                 :            : #undef OOX_ENSURE_RECORDSIZE
     344                 :            :         }
     345         [ +  - ]:        404 :     }
     346                 :            :     OSL_ENSURE( nModuleCount == aModules.size(), "VbaProject::importVba - invalid module count" );
     347                 :            : 
     348                 :            :     /*  The directory does not contain the real type of the modules, it
     349                 :            :         distinguishes only between 'procedural' and 'document' (the latter
     350                 :            :         includes class and form modules). Now, the exact type of all modules
     351                 :            :         will be read from the 'PROJECT' stream. It consists of text lines in
     352                 :            :         'key=value' format which list the code modules by type.
     353                 :            : 
     354                 :            :         -   The line 'document=<modulename>/&HXXXXXXXX' declares document
     355                 :            :             modules. These are attached to the Word document (usually called
     356                 :            :             'ThisDocument'), the Excel workbook (usually called
     357                 :            :             'ThisWorkbook'), or single Excel worksheets or chartsheets (usually
     358                 :            :             called 'SheetX' or 'ChartX', X being a decimal number). Of course,
     359                 :            :             users may rename all these modules. The slash character separates
     360                 :            :             an automation server version number (hexadecimal 'XXXXXXXX') from
     361                 :            :             the module name.
     362                 :            :         -   The line 'Module=<modulename>' declares common procedural code
     363                 :            :             modules.
     364                 :            :         -   The line 'Class=<modulename>' declares a class module.
     365                 :            :         -   The line 'BaseClass=<modulename>' declares a code module attached
     366                 :            :             to a user form with the same name.
     367                 :            :      */
     368 [ +  - ][ +  - ]:         13 :     BinaryXInputStream aPrjStrm( rVbaPrjStrg.openInputStream( CREATE_OUSTRING( "PROJECT" ) ), true );
                 [ +  - ]
     369                 :            :     OSL_ENSURE( !aPrjStrm.isEof(), "VbaProject::importVba - cannot open 'PROJECT' stream" );
     370                 :            :     // do not exit if this stream does not exist, but proceed to load the modules below
     371         [ +  - ]:         13 :     if( !aPrjStrm.isEof() )
     372                 :            :     {
     373         [ +  - ]:         13 :         TextInputStream aPrjTextStrm( mxContext, aPrjStrm, eTextEnc );
     374                 :         13 :         OUString aKey, aValue;
     375                 :         13 :         bool bExitLoop = false;
     376 [ +  + ][ +  - ]:        198 :         while( !bExitLoop && !aPrjTextStrm.isEof() )
         [ +  - ][ +  + ]
     377                 :            :         {
     378                 :            :             // read a text line from the stream
     379         [ +  - ]:        185 :             OUString aLine = aPrjTextStrm.readLine().trim();
     380                 :        185 :             sal_Int32 nLineLen = aLine.getLength();
     381                 :            :             // exit if a subsection starts (section name is given in brackets)
     382 [ +  + ][ +  - ]:        185 :             bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] == '[') && (aLine[ nLineLen - 1 ] == ']');
                 [ +  + ]
     383 [ +  + ][ +  - ]:        185 :             if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
         [ +  + ][ +  + ]
     384                 :            :             {
     385                 :        159 :                 sal_Int32 nType = ModuleType::UNKNOWN;
     386         [ +  + ]:        159 :                 if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Document" ) ) )
     387                 :            :                 {
     388                 :         55 :                     nType = ModuleType::DOCUMENT;
     389                 :            :                     // strip automation server version from module names
     390                 :         55 :                     sal_Int32 nSlashPos = aValue.indexOf( '/' );
     391         [ +  - ]:         55 :                     if( nSlashPos >= 0 )
     392                 :         55 :                         aValue = aValue.copy( 0, nSlashPos );
     393                 :            :                 }
     394         [ +  + ]:        104 :                 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Module" ) ) )
     395                 :         10 :                     nType = ModuleType::NORMAL;
     396         [ -  + ]:         94 :                 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Class" ) ) )
     397                 :          0 :                     nType = ModuleType::CLASS;
     398         [ -  + ]:         94 :                 else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "BaseClass" ) ) )
     399                 :          0 :                     nType = ModuleType::FORM;
     400                 :            : 
     401 [ +  + ][ +  - ]:        159 :                 if( (nType != ModuleType::UNKNOWN) && !aValue.isEmpty() )
                 [ +  + ]
     402                 :            :                 {
     403                 :            :                     OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" );
     404 [ +  - ][ +  - ]:         65 :                     if( VbaModule* pModule = aModules.get( aValue ).get() )
                 [ +  - ]
     405                 :         65 :                         pModule->setType( nType );
     406                 :            :                 }
     407                 :            :             }
     408         [ +  - ]:        198 :         }
     409                 :            :     }
     410                 :            : 
     411                 :            :     // create empty dummy modules
     412         [ +  - ]:         13 :     VbaModuleMap aDummyModules;
     413         [ -  + ]:         13 :     for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt )
     414                 :            :     {
     415                 :            :         OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" );
     416         [ #  # ]:          0 :         VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ];
     417 [ #  # ][ #  # ]:          0 :         rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) );
                 [ #  # ]
     418                 :          0 :         rxModule->setType( aIt->second );
     419                 :            :     }
     420                 :            : 
     421                 :            :     /*  Now it is time to load the source code. All modules will be inserted
     422                 :            :         into the Basic library of the document specified by the 'maPrjName'
     423                 :            :         member. Do not create the Basic library, if there are no modules
     424                 :            :         specified. */
     425 [ -  + ][ #  # ]:         13 :     if( !aModules.empty() || !aDummyModules.empty() ) try
                 [ +  - ]
     426                 :            :     {
     427                 :            :         // get the model factory and the basic library
     428         [ +  - ]:         13 :         Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
     429 [ +  - ][ +  - ]:         13 :         Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW );
     430                 :            : 
     431                 :            :         /*  Set library container to VBA compatibility mode. This will create
     432                 :            :             the VBA Globals object and store it in the Basic manager of the
     433                 :            :             document. */
     434                 :            :         try
     435                 :            :         {
     436 [ +  - ][ +  - ]:         13 :             Reference< XVBACompatibility > xVBACompat( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW );
     437 [ +  - ][ +  - ]:         13 :             xVBACompat->setVBACompatibilityMode( sal_True );
     438 [ +  - ][ +  - ]:         13 :             xVBACompat->setProjectName( maPrjName );
                 [ #  # ]
     439                 :            : 
     440                 :            :         }
     441         [ #  # ]:          0 :         catch(const Exception& )
     442                 :            :         {
     443                 :            :         }
     444                 :            : 
     445                 :            :         // try to get access to document objects related to code modules
     446                 :         13 :         Reference< XNameAccess > xDocObjectNA;
     447                 :            :         try
     448                 :            :         {
     449 [ +  - ][ +  + ]:         13 :             xDocObjectNA.set( xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY );
         [ +  - ][ -  + ]
                 [ +  - ]
     450                 :            :         }
     451         [ +  - ]:          9 :         catch(const Exception& )
     452                 :            :         {
     453                 :            :             // not all documents support this
     454                 :            :         }
     455                 :            : 
     456         [ +  - ]:         13 :         if( xBasicLib.is() )
     457                 :            :         {
     458                 :            :             // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref
     459                 :            :             aModules.forEachMem( &VbaModule::createAndImportModule,
     460                 :         13 :                 ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ),
     461 [ +  - ][ +  - ]:         26 :                 ::boost::cref( xDocObjectNA ), ::boost::cref( mxOleOverridesSink ) );
           [ +  -  +  - ]
                 [ +  - ]
     462                 :            : 
     463                 :            :             // create empty dummy modules
     464                 :            :             aDummyModules.forEachMem( &VbaModule::createEmptyModule,
     465 [ +  - ][ +  - ]:         13 :                 ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
                 [ +  - ]
     466         [ #  # ]:         13 :         }
     467                 :            :     }
     468         [ #  # ]:          0 :     catch(const Exception& )
     469                 :            :     {
     470                 :            :     }
     471                 :            : 
     472                 :            :     /*  Load the forms. The file format specification requires that a module
     473                 :            :         must exist for every form. We are a bit more tolerant and scan the
     474                 :            :         project storage for all form substorages. This may 'repair' broken VBA
     475                 :            :         storages that misses to mention a module for an existing form. */
     476         [ +  - ]:         13 :     ::std::vector< OUString > aElements;
     477         [ +  - ]:         13 :     rVbaPrjStrg.getElementNames( aElements );
     478 [ +  - ][ +  + ]:         52 :     for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
     479                 :            :     {
     480                 :            :         // try to open the element as storage
     481         [ +  + ]:         39 :         if( *aIt != "VBA" )
     482                 :            :         {
     483         [ +  - ]:         26 :             StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( *aIt, false );
     484         [ -  + ]:         26 :             if( xSubStrg.get() ) try
     485                 :            :             {
     486                 :            :                 // resolve module name from storage name (which equals the module stream name)
     487 [ #  # ][ #  # ]:          0 :                 VbaModule* pModule = aModulesByStrm.get( *aIt ).get();
     488                 :            :                 OSL_ENSURE( pModule && (pModule->getType() == ModuleType::FORM),
     489                 :            :                     "VbaProject::importVba - form substorage without form module" );
     490                 :          0 :                 OUString aModuleName;
     491         [ #  # ]:          0 :                 if( pModule )
     492                 :          0 :                     aModuleName = pModule->getName();
     493                 :            : 
     494                 :            :                 // create and import the form
     495 [ #  # ][ #  # ]:          0 :                 Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW );
     496         [ #  # ]:          0 :                 VbaUserForm aForm( mxContext, mxDocModel, rGraphicHelper, bDefaultColorBgr );
     497 [ #  # ][ #  # ]:          0 :                 aForm.importForm( mxDocModel, xDialogLib, *xSubStrg, aModuleName, eTextEnc );
                 [ #  # ]
     498                 :            :             }
     499         [ #  # ]:          0 :             catch(const Exception& )
     500                 :            :             {
     501         [ +  - ]:         26 :             }
     502                 :            :         }
     503                 :            :     }
     504                 :            : 
     505                 :            :     // attach macros to registered objects
     506         [ +  - ]:         13 :     attachMacros();
     507                 :            :     // virtual call, derived classes may do some more processing
     508 [ +  - ][ +  - ]:         13 :     finalizeImport();
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
     509                 :            : }
     510                 :            : 
     511                 :         13 : void VbaProject::attachMacros()
     512                 :            : {
     513 [ -  + ][ #  # ]:         13 :     if( !maMacroAttachers.empty() && mxContext.is() ) try
                 [ -  + ]
     514                 :            :     {
     515 [ #  # ][ #  # ]:          0 :         Reference< XMultiComponentFactory > xFactory( mxContext->getServiceManager(), UNO_SET_THROW );
                 [ #  # ]
     516         [ #  # ]:          0 :         Sequence< Any > aArgs( 2 );
     517 [ #  # ][ #  # ]:          0 :         aArgs[ 0 ] <<= mxDocModel;
     518 [ #  # ][ #  # ]:          0 :         aArgs[ 1 ] <<= maPrjName;
     519         [ #  # ]:          0 :         Reference< XVBAMacroResolver > xResolver( xFactory->createInstanceWithArgumentsAndContext(
     520 [ #  # ][ #  # ]:          0 :             CREATE_OUSTRING( "com.sun.star.script.vba.VBAMacroResolver" ), aArgs, mxContext ), UNO_QUERY_THROW );
                 [ #  # ]
     521 [ #  # ][ #  # ]:          0 :         maMacroAttachers.forEachMem( &VbaMacroAttacherBase::resolveAndAttachMacro, ::boost::cref( xResolver ) );
         [ #  # ][ #  # ]
     522                 :            :     }
     523                 :          0 :     catch(const Exception& )
     524                 :            :     {
     525                 :            :     }
     526                 :         13 : }
     527                 :            : 
     528                 :         13 : void VbaProject::copyStorage( StorageBase& rVbaPrjStrg )
     529                 :            : {
     530         [ +  - ]:         13 :     if( mxContext.is() ) try
     531                 :            :     {
     532         [ +  - ]:         13 :         Reference< XStorageBasedDocument > xStorageBasedDoc( mxDocModel, UNO_QUERY_THROW );
     533 [ +  - ][ +  - ]:         13 :         Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_QUERY_THROW );
                 [ +  - ]
     534                 :            :         {
     535                 :         13 :             const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE;
     536 [ +  - ][ +  - ]:         13 :             Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), nOpenMode ), UNO_SET_THROW );
         [ +  - ][ +  - ]
     537         [ +  - ]:         13 :             OleStorage aDestStorage( mxContext, xDocStream, false );
     538         [ +  - ]:         13 :             rVbaPrjStrg.copyStorageToStorage( aDestStorage );
     539 [ +  - ][ +  - ]:         13 :             aDestStorage.commit();
     540                 :            :         }
     541 [ +  - ][ +  - ]:         13 :         Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit();
         [ #  # ][ +  - ]
     542                 :            :     }
     543                 :          0 :     catch(const Exception& )
     544                 :            :     {
     545                 :            :     }
     546                 :         13 : }
     547                 :            : 
     548                 :            : // ============================================================================
     549                 :            : 
     550                 :            : } // namespace ole
     551 [ +  - ][ +  - ]:        285 : } // namespace oox
     552                 :            : 
     553                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10