Files
libreoffice/unotools/source/ucbhelper/tempfile.cxx
2000-10-30 12:16:36 +00:00

385 lines
11 KiB
C++

/*************************************************************************
*
* $RCSfile: tempfile.cxx,v $
*
* $Revision: 1.2 $
*
* last change: $Author: mba $ $Date: 2000-10-30 13:16:36 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#include <unotools/tempfile.hxx>
#include <ucbhelper/Fileidentifierconverter.hxx>
#include <ucbhelper/contentbroker.hxx>
#include <rtl/ustring.hxx>
#include <osl/file.hxx>
#include <osl/socket.h>
#include <tools/time.hxx>
#include <tools/debug.hxx>
#include <stdio.h>
using namespace osl;
namespace utl
{
static ::rtl::OUString aTempNameBase_Impl;
struct TempFile_Impl
{
String aName;
String aURL;
sal_Bool bIsDirectory;
};
#define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
String ConstructTempDir_Impl( const String* pParent )
{
String aName;
if ( pParent && pParent->Len() )
{
::ucb::ContentBroker* pBroker = ::ucb::ContentBroker::get();
if ( pBroker )
{
::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager =
pBroker->getContentProviderManagerInterface();
// if parent given try to use it
rtl::OUString aTmp( *pParent );
rtl::OUString aHost;
osl_getLocalHostname( &aHost.pData );
// test for valid filename
rtl::OUString aRet = ::ucb::getNormalizedPathFromFileURL( xManager, aTmp, aHost );
if ( aRet.getLength() )
{
::osl::DirectoryItem aItem;
sal_Int32 i = aRet.getLength();
if ( aRet[i-1] == '/' )
i--;
if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None )
aName = aRet;
}
}
else
{
DBG_WARNING( "::unotools::TempFile : UCB not present or not initialized!" );
}
}
if ( !aName.Len() )
{
// if no parent or invalid parent : use default directory
DBG_ASSERT( aTempNameBase_Impl.getLength(), "No TempDir!" );
aName = aTempNameBase_Impl;
}
// Make sure that directory ends with a separator
sal_Int32 i = aName.Len();
if( i>0 && aName.GetChar(i-1) != '/' )
aName += '/';
return aName;
}
void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
{
// add a suitable tempname
// Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
// ER 13.07.00 why not radix 36 [0-9A-Z] ?!?
const unsigned nRadix = 26;
String aName( rName );
aName += String::CreateFromAscii( "sv" );
sal_Int32 i = aName.Len();
rName.Erase();
static unsigned long u = Time::GetSystemTicks();
for ( unsigned long nOld = u; ++u != nOld; )
{
u %= (nRadix*nRadix*nRadix);
String aTmp( aName );
aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
aTmp += String::CreateFromAscii( ".tmp" );
if ( bDir )
{
FileBase::RC err = Directory::create( aTmp );
if ( err == FileBase::E_None )
{
// !bKeep: only for creating a name, not a file or directory
if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
rName = aTmp;
break;
}
else if ( err != FileBase::E_EXIST )
{
// if f.e. name contains invalid chars stop trying to create dirs
break;
}
}
else
{
DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
File aFile( aTmp );
FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
if ( err == FileBase::E_None )
{
rName = aTmp;
aFile.close();
break;
}
else if ( err != FileBase::E_EXIST )
{
// if f.e. name contains invalid chars stop trying to create files
break;
}
}
}
}
String TempFile::CreateTempName( const String* pParent )
{
// get correct directory
String aName = ConstructTempDir_Impl( pParent );
// get TempFile name with default naming scheme
CreateTempName_Impl( aName, sal_False );
// convert to file URL
rtl::OUString aTmp;
if ( aName.Len() )
FileBase::getSystemPathFromNormalizedPath( aName, aTmp );
return aTmp;
}
TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
: pImp( new TempFile_Impl )
, bKillingFileEnabled( sal_False )
{
pImp->bIsDirectory = bDirectory;
// get correct directory
pImp->aName = ConstructTempDir_Impl( pParent );
// get TempFile with default naming scheme
CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
}
TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
: pImp( new TempFile_Impl )
, bKillingFileEnabled( sal_False )
{
pImp->bIsDirectory = bDirectory;
// get correct directory
String aName = ConstructTempDir_Impl( pParent );
// now use special naming scheme ( name takes leading chars and an index counting up from zero
aName += rLeadingChars;
for ( sal_Int32 i=0;; i++ )
{
String aTmp( aName );
aTmp += String::CreateFromInt32( i );
if ( pExtension )
aTmp += *pExtension;
else
aTmp += String::CreateFromAscii( ".tmp" );
if ( bDirectory )
{
FileBase::RC err = Directory::create( aTmp );
if ( err == FileBase::E_None )
{
pImp->aName = aTmp;
break;
}
else if ( err != FileBase::E_EXIST )
// if f.e. name contains invalid chars stop trying to create dirs
break;
}
else
{
File aFile( aTmp );
FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
if ( err == FileBase::E_None )
{
pImp->aName = aTmp;
aFile.close();
break;
}
else if ( err != FileBase::E_EXIST )
// if f.e. name contains invalid chars stop trying to create dirs
break;
}
}
}
TempFile::~TempFile()
{
if ( bKillingFileEnabled )
{
if ( pImp->bIsDirectory )
{
// at the moment no recursiv algorithm present
Directory::remove( pImp->aName );
}
else
{
File::remove( pImp->aName );
}
}
delete pImp;
}
sal_Bool TempFile::IsValid() const
{
return pImp->aName.Len() != 0;
}
String TempFile::GetFileName() const
{
rtl::OUString aTmp;
FileBase::getSystemPathFromNormalizedPath( pImp->aName, aTmp );
return aTmp;
}
String TempFile::GetURL() const
{
if ( !pImp->aURL.Len() )
{
String aTmp;
LocalFileHelper::ConvertPhysicalNameToURL( GetFileName(), aTmp );
pImp->aURL = aTmp;
}
return pImp->aURL;
}
String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
{
String aName( rBaseName );
FileBase::RC err= Directory::create( aName );
if ( err == FileBase::E_None || err == FileBase::E_EXIST )
{
aTempNameBase_Impl = aName;
aTempNameBase_Impl += ::rtl::OUString( '/' );
TempFile aBase( NULL, sal_True );
if ( aBase.IsValid() )
aTempNameBase_Impl = aBase.pImp->aName;
}
rtl::OUString aTmp;
FileBase::getSystemPathFromNormalizedPath( aTempNameBase_Impl, aTmp );
return aTmp;
}
String TempFile::GetTempNameBaseDirectory()
{
if ( !aTempNameBase_Impl.getLength() )
return String();
rtl::OUString aTmp;
FileBase::getSystemPathFromNormalizedPath( aTempNameBase_Impl, aTmp );
return aTmp;
}
sal_Bool LocalFileHelper::ConvertPhysicalNameToURL( const String& rName, String& rReturn )
{
::ucb::ContentBroker* pBroker = ::ucb::ContentBroker::get();
if ( !pBroker )
{
DBG_WARNING( "::unotools::TempFile : UCB not present or not initialized!" );
return sal_False;
}
::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager =
pBroker->getContentProviderManagerInterface();
rtl::OUString aHost;
osl_getLocalHostname( &aHost.pData );
::rtl::OUString aTmp;
FileBase::normalizePath( rName, aTmp );
rtl::OUString aRet = ::ucb::getFileURLFromNormalizedPath( xManager, aHost, aTmp );
rReturn = aRet;
return sal_True;
}
sal_Bool LocalFileHelper::ConvertURLToPhysicalName( const String& rName, String& rReturn )
{
::ucb::ContentBroker* pBroker = ::ucb::ContentBroker::get();
if ( !pBroker )
{
DBG_WARNING( "::unotools::TempFile : UCB not present or not initialized!" );
return sal_False;
}
::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContentProviderManager > xManager =
pBroker->getContentProviderManagerInterface();
rtl::OUString aHost;
osl_getLocalHostname( &aHost.pData );
rtl::OUString aRet = ::ucb::getNormalizedPathFromFileURL( xManager, aHost, rName );
::rtl::OUString aTmp;
FileBase::getSystemPathFromNormalizedPath( aRet, aTmp );
rReturn = aTmp;
return sal_True;
}
};