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_package.hxx" 30 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 31 #include <com/sun/star/embed/ElementModes.hpp> 32 #include <com/sun/star/embed/StorageFormats.hpp> 33 #include <com/sun/star/beans/PropertyValue.hpp> 34 #include <com/sun/star/io/XSeekable.hpp> 35 36 #include <comphelper/storagehelper.hxx> 37 38 #include "xfactory.hxx" 39 #include "xstorage.hxx" 40 41 42 using namespace ::com::sun::star; 43 44 //------------------------------------------------------------------------- 45 sal_Bool CheckPackageSignature_Impl( const uno::Reference< io::XInputStream >& xInputStream, 46 const uno::Reference< io::XSeekable >& xSeekable ) 47 { 48 if ( !xInputStream.is() || !xSeekable.is() ) 49 throw uno::RuntimeException(); 50 51 if ( xSeekable->getLength() ) 52 { 53 uno::Sequence< sal_Int8 > aData( 4 ); 54 xSeekable->seek( 0 ); 55 sal_Int32 nRead = xInputStream->readBytes( aData, 4 ); 56 xSeekable->seek( 0 ); 57 58 // TODO/LATER: should the disk spanned files be supported? 59 // 0x50, 0x4b, 0x07, 0x08 60 return ( nRead == 4 && aData[0] == 0x50 && aData[1] == 0x4b && aData[2] == 0x03 && aData[3] == 0x04 ); 61 } 62 else 63 return sal_True; // allow to create a storage based on empty stream 64 } 65 66 //------------------------------------------------------------------------- 67 uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::impl_staticGetSupportedServiceNames() 68 { 69 uno::Sequence< ::rtl::OUString > aRet(2); 70 aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.StorageFactory"); 71 aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.StorageFactory"); 72 return aRet; 73 } 74 75 //------------------------------------------------------------------------- 76 ::rtl::OUString SAL_CALL OStorageFactory::impl_staticGetImplementationName() 77 { 78 return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.StorageFactory"); 79 } 80 81 //------------------------------------------------------------------------- 82 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::impl_staticCreateSelfInstance( 83 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) 84 { 85 return uno::Reference< uno::XInterface >( *new OStorageFactory( xServiceManager ) ); 86 } 87 88 //------------------------------------------------------------------------- 89 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstance() 90 throw ( uno::Exception, 91 uno::RuntimeException ) 92 { 93 // TODO: reimplement TempStream service to support XStream interface 94 uno::Reference < io::XStream > xTempStream( 95 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 96 uno::UNO_QUERY ); 97 98 if ( !xTempStream.is() ) 99 throw uno::RuntimeException(); // TODO: 100 101 return uno::Reference< uno::XInterface >( 102 static_cast< OWeakObject* >( new OStorage( xTempStream, 103 embed::ElementModes::READWRITE, 104 uno::Sequence< beans::PropertyValue >(), 105 m_xFactory, 106 embed::StorageFormats::PACKAGE ) ), 107 uno::UNO_QUERY ); 108 } 109 110 //------------------------------------------------------------------------- 111 uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithArguments( 112 const uno::Sequence< uno::Any >& aArguments ) 113 throw ( uno::Exception, 114 uno::RuntimeException ) 115 { 116 // The request for storage can be done with up to three arguments 117 118 // The first argument specifies a source for the storage 119 // it can be URL, XStream, XInputStream. 120 // The second value is a mode the storage should be open in. 121 // And the third value is a media descriptor. 122 123 sal_Int32 nArgNum = aArguments.getLength(); 124 OSL_ENSURE( nArgNum < 4, "Wrong parameter number" ); 125 126 if ( !nArgNum ) 127 return createInstance(); 128 129 // first try to retrieve storage open mode if any 130 // by default the storage will be open in readonly mode 131 sal_Int32 nStorageMode = embed::ElementModes::READ; 132 if ( nArgNum >= 2 ) 133 { 134 if( !( aArguments[1] >>= nStorageMode ) ) 135 { 136 OSL_ENSURE( sal_False, "Wrong second argument!\n" ); 137 throw lang::IllegalArgumentException(); // TODO: 138 } 139 // it's allways possible to read written storage in this implementation 140 nStorageMode |= embed::ElementModes::READ; 141 } 142 143 if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE 144 && ( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE ) 145 throw lang::IllegalArgumentException(); // TODO: 146 147 // retrieve storage source stream 148 ::rtl::OUString aURL; 149 uno::Reference< io::XStream > xStream; 150 uno::Reference< io::XInputStream > xInputStream; 151 152 if ( aArguments[0] >>= aURL ) 153 { 154 if ( !aURL.getLength() ) 155 { 156 OSL_ENSURE( sal_False, "Empty URL is provided!\n" ); 157 throw lang::IllegalArgumentException(); // TODO: 158 } 159 160 if ( aURL.equalsIgnoreAsciiCaseAsciiL( "vnd.sun.star.pkg", 16 ) ) 161 { 162 OSL_ENSURE( sal_False, "Packages URL's are not valid for storages!\n" ); // ??? 163 throw lang::IllegalArgumentException(); // TODO: 164 } 165 166 uno::Reference < ::com::sun::star::ucb::XSimpleFileAccess > xTempAccess( 167 m_xFactory->createInstance ( 168 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 169 uno::UNO_QUERY ); 170 171 if ( !xTempAccess.is() ) 172 throw uno::RuntimeException(); // TODO: 173 174 if ( nStorageMode & embed::ElementModes::WRITE ) 175 xStream = xTempAccess->openFileReadWrite( aURL ); 176 else 177 xInputStream = xTempAccess->openFileRead( aURL ); 178 } 179 else if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) ) 180 { 181 OSL_ENSURE( sal_False, "Wrong first argument!\n" ); 182 throw uno::Exception(); // TODO: Illegal argument 183 } 184 185 // retrieve mediadescriptor and set storage properties 186 uno::Sequence< beans::PropertyValue > aDescr; 187 uno::Sequence< beans::PropertyValue > aPropsToSet; 188 189 sal_Int32 nStorageType = embed::StorageFormats::PACKAGE; 190 191 if ( nArgNum >= 3 ) 192 { 193 if( aArguments[2] >>= aDescr ) 194 { 195 if ( aURL.getLength() ) 196 { 197 aPropsToSet.realloc(1); 198 aPropsToSet[0].Name = ::rtl::OUString::createFromAscii( "URL" ); 199 aPropsToSet[0].Value <<= aURL; 200 } 201 202 for ( sal_Int32 nInd = 0, nNumArgs = 1; nInd < aDescr.getLength(); nInd++ ) 203 { 204 if ( aDescr[nInd].Name.equalsAscii( "InteractionHandler" ) 205 || aDescr[nInd].Name.equalsAscii( "Password" ) 206 || aDescr[nInd].Name.equalsAscii( "RepairPackage" ) 207 || aDescr[nInd].Name.equalsAscii( "StatusIndicator" ) ) 208 // || aDescr[nInd].Name.equalsAscii( "Unpacked" ) // TODO: 209 { 210 aPropsToSet.realloc( ++nNumArgs ); 211 aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name; 212 aPropsToSet[nNumArgs-1].Value = aDescr[nInd].Value; 213 } 214 else if ( aDescr[nInd].Name.equalsAscii( "StorageFormat" ) ) 215 { 216 ::rtl::OUString aFormatName; 217 sal_Int32 nFormatID = 0; 218 if ( aDescr[nInd].Value >>= aFormatName ) 219 { 220 if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) ) 221 nStorageType = embed::StorageFormats::PACKAGE; 222 else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) ) 223 nStorageType = embed::StorageFormats::ZIP; 224 else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) ) 225 nStorageType = embed::StorageFormats::OFOPXML; 226 else 227 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 228 } 229 else if ( aDescr[nInd].Value >>= nFormatID ) 230 { 231 if ( nFormatID != embed::StorageFormats::PACKAGE 232 && nFormatID != embed::StorageFormats::ZIP 233 && nFormatID != embed::StorageFormats::OFOPXML ) 234 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 235 236 nStorageType = nFormatID; 237 } 238 else 239 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 240 } 241 else 242 OSL_ENSURE( sal_False, "Unacceptable property, will be ignored!\n" ); 243 } 244 } 245 else 246 { 247 OSL_ENSURE( sal_False, "Wrong third argument!\n" ); 248 throw uno::Exception(); // TODO: Illegal argument 249 } 250 251 } 252 253 // create storage based on source 254 if ( xInputStream.is() ) 255 { 256 // if xInputStream is set the storage should be open from it 257 if ( ( nStorageMode & embed::ElementModes::WRITE ) ) 258 throw uno::Exception(); // TODO: access denied 259 260 uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY ); 261 if ( !xSeekable.is() ) 262 { 263 // TODO: wrap stream to let it be seekable 264 OSL_ENSURE( sal_False, "Nonseekable streams are not supported for now!\n" ); 265 } 266 267 if ( !CheckPackageSignature_Impl( xInputStream, xSeekable ) ) 268 throw io::IOException(); // TODO: this is not a package file 269 270 return uno::Reference< uno::XInterface >( 271 static_cast< OWeakObject* >( new OStorage( xInputStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ), 272 uno::UNO_QUERY ); 273 } 274 else if ( xStream.is() ) 275 { 276 if ( ( ( nStorageMode & embed::ElementModes::WRITE ) && !xStream->getOutputStream().is() ) 277 || !xStream->getInputStream().is() ) 278 throw uno::Exception(); // TODO: access denied 279 280 uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY ); 281 if ( !xSeekable.is() ) 282 { 283 // TODO: wrap stream to let it be seekable 284 OSL_ENSURE( sal_False, "Nonseekable streams are not supported for now!\n" ); 285 } 286 287 if ( !CheckPackageSignature_Impl( xStream->getInputStream(), xSeekable ) ) 288 throw io::IOException(); // TODO: this is not a package file 289 290 return uno::Reference< uno::XInterface >( 291 static_cast< OWeakObject* >( new OStorage( xStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ), 292 uno::UNO_QUERY ); 293 } 294 295 throw uno::Exception(); // general error during creation 296 } 297 298 //------------------------------------------------------------------------- 299 ::rtl::OUString SAL_CALL OStorageFactory::getImplementationName() 300 throw ( uno::RuntimeException ) 301 { 302 return impl_staticGetImplementationName(); 303 } 304 305 //------------------------------------------------------------------------- 306 sal_Bool SAL_CALL OStorageFactory::supportsService( const ::rtl::OUString& ServiceName ) 307 throw ( uno::RuntimeException ) 308 { 309 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); 310 311 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 312 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) 313 return sal_True; 314 315 return sal_False; 316 } 317 318 //------------------------------------------------------------------------- 319 uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::getSupportedServiceNames() 320 throw ( uno::RuntimeException ) 321 { 322 return impl_staticGetSupportedServiceNames(); 323 } 324 325