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