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 #include "vbahelper/vbadocumentbase.hxx"
25 #include "vbahelper/helperdecl.hxx"
26 
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
29 #include <com/sun/star/util/XModifiable.hpp>
30 #include <com/sun/star/util/XProtectable.hpp>
31 #include <com/sun/star/util/XCloseable.hpp>
32 #include <com/sun/star/util/XURLTransformer.hpp>
33 #include <com/sun/star/frame/XStorable.hpp>
34 #include <com/sun/star/frame/XFrame.hpp>
35 #include <com/sun/star/document/XEmbeddedScripts.hpp> //Michael E. Bohn
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <ooo/vba/XApplicationBase.hpp>
38 
39 #include <cppuhelper/exc_hlp.hxx>
40 #include <comphelper/unwrapargs.hxx>
41 #include <tools/urlobj.hxx>
42 #include <osl/file.hxx>
43 
44 using namespace ::com::sun::star;
45 using namespace ::ooo::vba;
46 
VbaDocumentBase(const uno::Reference<ov::XHelperInterface> & xParent,const uno::Reference<uno::XComponentContext> & xContext)47 VbaDocumentBase::VbaDocumentBase( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext) :VbaDocumentBase_BASE( xParent, xContext ), mxModel(NULL)
48 {
49 }
50 
VbaDocumentBase(const uno::Reference<ov::XHelperInterface> & xParent,const uno::Reference<uno::XComponentContext> & xContext,uno::Reference<frame::XModel> xModel)51 VbaDocumentBase::VbaDocumentBase( const uno::Reference< ov::XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, uno::Reference< frame::XModel > xModel ) : VbaDocumentBase_BASE( xParent, xContext ),  mxModel( xModel )
52 {
53 }
54 
VbaDocumentBase(uno::Sequence<uno::Any> const & args,uno::Reference<uno::XComponentContext> const & xContext)55 VbaDocumentBase::VbaDocumentBase( uno::Sequence< uno::Any> const & args,
56     uno::Reference< uno::XComponentContext> const & xContext ) : VbaDocumentBase_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext ),  mxModel( getXSomethingFromArgs< frame::XModel >( args, 1 ) )
57 {
58 }
59 
60 ::rtl::OUString
getName()61 VbaDocumentBase::getName() throw (uno::RuntimeException)
62 {
63 	rtl::OUString sName = getModel()->getURL();
64 	if ( sName.getLength() )
65 	{
66 
67 		INetURLObject aURL( getModel()->getURL() );
68 		::osl::File::getSystemPathFromFileURL( aURL.GetLastName(), sName );
69 	}
70 	else
71 	{
72 		const static rtl::OUString sTitle( RTL_CONSTASCII_USTRINGPARAM("Title" ) );
73 		// process "UntitledX - $(PRODUCTNAME)"
74 		uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW );
75 		uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW );
76 		xProps->getPropertyValue(sTitle ) >>= sName;
77 		sal_Int32 pos = 0;
78 		sName = sName.getToken(0,'-',pos);
79 		sName = sName.trim();
80 	}
81 	return sName;
82 }
83 ::rtl::OUString
getPath()84 VbaDocumentBase::getPath() throw (uno::RuntimeException)
85 {
86     INetURLObject aURL( getModel()->getURL() );
87 	rtl::OUString sURL = aURL.GetMainURL( INetURLObject::DECODE_TO_IURI );
88     rtl::OUString sPath;
89 	if( sURL.getLength() > 0 )
90 	{
91 	   sURL = sURL.copy( 0, sURL.getLength() - aURL.GetLastName().getLength() - 1 );
92 	   ::osl::File::getSystemPathFromFileURL( sURL, sPath );
93 	}
94 	return sPath;
95 }
96 
97 ::rtl::OUString
getFullName()98 VbaDocumentBase::getFullName() throw (uno::RuntimeException)
99 {
100 	rtl::OUString sPath = getName();
101 	//::osl::File::getSystemPathFromFileURL( getModel()->getURL(), sPath );
102 	return sPath;
103 }
104 
105 void
Close(const uno::Any & rSaveArg,const uno::Any & rFileArg,const uno::Any & rRouteArg)106 VbaDocumentBase::Close( const uno::Any &rSaveArg, const uno::Any &rFileArg,
107 					  const uno::Any &rRouteArg ) throw (uno::RuntimeException)
108 {
109 	sal_Bool bSaveChanges = sal_False;
110 	rtl::OUString aFileName;
111 	sal_Bool bRouteWorkbook = sal_True;
112 
113 	rSaveArg >>= bSaveChanges;
114 	sal_Bool bFileName =  ( rFileArg >>= aFileName );
115 	rRouteArg >>= bRouteWorkbook;
116 	uno::Reference< frame::XStorable > xStorable( getModel(), uno::UNO_QUERY_THROW );
117 	uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW );
118 
119 	if( bSaveChanges )
120 	{
121 		if( xStorable->isReadonly() )
122 		{
123 			throw uno::RuntimeException(::rtl::OUString(
124 				RTL_CONSTASCII_USTRINGPARAM( "Unable to save to a read only file ") ),
125                         	uno::Reference< XInterface >() );
126 		}
127 		if( bFileName )
128 			xStorable->storeAsURL( aFileName, uno::Sequence< beans::PropertyValue >(0) );
129 		else
130 			xStorable->store();
131 	}
132 	else
133 		xModifiable->setModified( false );
134 
135     // first try to close the document using UI dispatch functionality
136     sal_Bool bUIClose = sal_False;
137     try
138     {
139         uno::Reference< frame::XController > xController( getModel()->getCurrentController(), uno::UNO_SET_THROW );
140         uno::Reference< frame::XDispatchProvider > xDispatchProvider( xController->getFrame(), uno::UNO_QUERY_THROW );
141 
142         uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW );
143         uno::Reference< util::XURLTransformer > xURLTransformer(
144                         xServiceManager->createInstanceWithContext(
145                             rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ),
146                             mxContext ),
147                         uno::UNO_QUERY_THROW );
148 
149         util::URL aURL;
150         aURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CloseDoc" ) );
151         xURLTransformer->parseStrict( aURL );
152 
153         uno::Reference< css::frame::XDispatch > xDispatch(
154                 xDispatchProvider->queryDispatch( aURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), 0 ),
155                 uno::UNO_SET_THROW );
156         xDispatch->dispatch( aURL, uno::Sequence< beans::PropertyValue >() );
157         bUIClose = sal_True;
158     }
159     catch( uno::Exception& )
160     {
161     }
162 
163     if ( !bUIClose )
164     {
165         // if it is not possible to use UI dispatch, try to close the model directly
166         uno::Reference< util::XCloseable > xCloseable( getModel(), uno::UNO_QUERY );
167         if( xCloseable.is() )
168         {
169             // use close(boolean DeliverOwnership)
170 
171             // The boolean parameter DeliverOwnership tells objects vetoing the close process that they may
172             // assume ownership if they object the closure by throwing a CloseVetoException
173             // Here we give up ownership. To be on the safe side, catch possible veto exception anyway.
174             xCloseable->close(sal_True);
175         }
176         else
177         {
178             // If close is not supported by this model - try to dispose it.
179             // But if the model disagree with a reset request for the modify state
180             // we shouldn't do so. Otherwhise some strange things can happen.
181             uno::Reference< lang::XComponent > xDisposable ( getModel(), uno::UNO_QUERY );
182             if ( xDisposable.is() )
183                 xDisposable->dispose();
184         }
185     }
186 }
187 
188 void
Protect(const uno::Any & aPassword)189 VbaDocumentBase::Protect( const uno::Any &aPassword ) throw (uno::RuntimeException)
190 {
191 	rtl::OUString rPassword;
192 	uno::Reference< util::XProtectable > xProt( getModel(), uno::UNO_QUERY_THROW );
193 	SC_VBA_FIXME(("Workbook::Protect stub"));
194 	if(  aPassword >>= rPassword )
195 		xProt->protect( rPassword );
196 	else
197 		xProt->protect( rtl::OUString() );
198 }
199 
200 void
Unprotect(const uno::Any & aPassword)201 VbaDocumentBase::Unprotect( const uno::Any &aPassword ) throw (uno::RuntimeException)
202 {
203 	rtl::OUString rPassword;
204 	uno::Reference< util::XProtectable > xProt( getModel(), uno::UNO_QUERY_THROW );
205 	if( !xProt->isProtected() )
206 		throw uno::RuntimeException(::rtl::OUString(
207 			RTL_CONSTASCII_USTRINGPARAM( "File is already unprotected" ) ),
208 			uno::Reference< XInterface >() );
209 	else
210 	{
211 		if( aPassword >>= rPassword )
212 			xProt->unprotect( rPassword );
213 		else
214 			xProt->unprotect( rtl::OUString() );
215 	}
216 }
217 
218 void
setSaved(sal_Bool bSave)219 VbaDocumentBase::setSaved( sal_Bool bSave ) throw (uno::RuntimeException)
220 {
221     uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW );
222     try
223     {
224         xModifiable->setModified( !bSave );
225     }
226     catch ( lang::DisposedException& )
227     {
228         // impossibility to set the modified state on disposed document should not trigger an error
229     }
230     catch ( beans::PropertyVetoException& )
231     {
232         uno::Any aCaught( ::cppu::getCaughtException() );
233         throw lang::WrappedTargetRuntimeException(
234                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't change modified state of model!" ) ),
235                 uno::Reference< uno::XInterface >(),
236                 aCaught );
237     }
238 }
239 
240 sal_Bool
getSaved()241 VbaDocumentBase::getSaved() throw (uno::RuntimeException)
242 {
243 	uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY_THROW );
244 	return !xModifiable->isModified();
245 }
246 
247 void
Save()248 VbaDocumentBase::Save() throw (uno::RuntimeException)
249 {
250 	rtl::OUString url = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
251 	uno::Reference< frame::XModel > xModel = getModel();
252 	dispatchRequests(xModel,url);
253 }
254 
255 void
Activate()256 VbaDocumentBase::Activate() throw (uno::RuntimeException)
257 {
258 	uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW );
259 	xFrame->activate();
260 }
261 
262 uno::Any SAL_CALL
getVBProject()263 VbaDocumentBase::getVBProject() throw (uno::RuntimeException)
264 {
265     if( !mxVBProject.is() )	try
266 	{
267         uno::Reference< XApplicationBase > xApp( Application(), uno::UNO_QUERY_THROW );
268         uno::Reference< XInterface > xVBE( xApp->getVBE(), uno::UNO_QUERY_THROW );
269 		uno::Sequence< uno::Any > aArgs( 2 );
270 		aArgs[ 0 ] <<= xVBE;          // the VBE
271 		aArgs[ 1 ] <<= getModel();    // document model for script container access
272         uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW );
273 		mxVBProject = xServiceManager->createInstanceWithArgumentsAndContext(
274             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.vbide.VBProject" ) ), aArgs, mxContext );
275 	}
276     catch( uno::Exception& )
277 	{
278 	}
279     return uno::Any( mxVBProject );
280 }
281 
282 rtl::OUString&
getServiceImplName()283 VbaDocumentBase::getServiceImplName()
284 {
285 	static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("VbaDocumentBase") );
286 	return sImplName;
287 }
288 
289 uno::Sequence< rtl::OUString >
getServiceNames()290 VbaDocumentBase::getServiceNames()
291 {
292 	static uno::Sequence< rtl::OUString > aServiceNames;
293 	if ( aServiceNames.getLength() == 0 )
294 	{
295 		aServiceNames.realloc( 1 );
296 		aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.VbaDocumentBase" ) );
297 	}
298 	return aServiceNames;
299 }
300 
301