2005-04-23 05:41:42 +04:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2004-04-18 18:21:17 +04:00
/* ***** BEGIN LICENSE BLOCK *****
* Version : MPL 1.1 / GPL 2.0 / LGPL 2.1
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
1999-12-04 04:13:44 +03:00
*
2004-04-18 18:21:17 +04:00
* The Original Code is Mozilla Communicator client code , released
* March 31 , 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation .
* Portions created by the Initial Developer are Copyright ( C ) 1998 - 1999
* the Initial Developer . All Rights Reserved .
1999-12-04 04:13:44 +03:00
*
2003-09-29 22:15:52 +04:00
* Contributor ( s ) :
2004-04-18 18:21:17 +04:00
* Doug Turner < dougt @ netscape . com >
2004-06-02 12:19:42 +04:00
* Dean Tessman < dean_tessman @ hotmail . com >
2004-06-17 20:37:25 +04:00
* Brodie Thiesfield < brofield @ jellycan . com >
2004-04-18 18:21:17 +04:00
*
* Alternatively , the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later ( the " GPL " ) ,
* or the GNU Lesser General Public License Version 2.1 or later ( the " LGPL " ) ,
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above . If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL , and not to allow others to
* use your version of this file under the terms of the MPL , indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL . If you do not delete
* the provisions above , a recipient may use your version of this file under
* the terms of any one of the MPL , the GPL or the LGPL .
*
* * * * * * END LICENSE BLOCK * * * * * */
1999-12-04 04:13:44 +03:00
# include "nsCOMPtr.h"
2000-06-03 13:46:12 +04:00
# include "nsMemory.h"
1999-12-04 04:13:44 +03:00
2003-06-19 03:19:11 +04:00
# include "nsLocalFile.h"
2005-04-23 05:39:51 +04:00
# include "nsIDirectoryEnumerator.h"
2002-10-06 04:29:46 +04:00
# include "nsNativeCharsetUtils.h"
1999-12-04 04:13:44 +03:00
# include "nsISimpleEnumerator.h"
# include "nsIComponentManager.h"
# include "prtypes.h"
# include "prio.h"
2005-02-25 12:00:45 +03:00
# include "prprf.h"
1999-12-04 04:13:44 +03:00
2001-06-22 02:02:47 +04:00
# include "nsXPIDLString.h"
2001-11-01 12:09:57 +03:00
# include "nsReadableUtils.h"
2001-06-22 02:02:47 +04:00
1999-12-04 04:13:44 +03:00
# include <direct.h>
# include <windows.h>
# include "shellapi.h"
# include "shlguid.h"
2000-02-22 00:51:47 +03:00
# include <io.h>
# include <stdio.h>
# include <stdlib.h>
2000-04-26 07:57:34 +04:00
# include <mbstring.h>
1999-12-04 04:13:44 +03:00
2001-01-30 08:02:48 +03:00
# include "nsXPIDLString.h"
2000-02-17 19:08:53 +03:00
# include "prproces.h"
2001-08-17 06:03:34 +04:00
# include "nsITimelineService.h"
2000-02-17 19:08:53 +03:00
2002-01-08 05:20:13 +03:00
# include "nsAutoLock.h"
2004-06-02 12:19:42 +04:00
# include "SpecialSystemDirectory.h"
2002-01-08 05:20:13 +03:00
2003-03-12 11:35:57 +03:00
// _mbsstr isn't declared in w32api headers but it's there in the libs
# ifdef __MINGW32__
extern " C " {
unsigned char * _mbsstr ( const unsigned char * str ,
const unsigned char * substr ) ;
2004-05-13 08:08:34 +04:00
}
2003-03-12 11:35:57 +03:00
# endif
2002-01-08 05:20:13 +03:00
2004-04-29 12:16:50 +04:00
class nsDriveEnumerator : public nsISimpleEnumerator
{
public :
nsDriveEnumerator ( ) ;
virtual ~ nsDriveEnumerator ( ) ;
NS_DECL_ISUPPORTS
NS_DECL_NSISIMPLEENUMERATOR
nsresult Init ( ) ;
private :
/* mDrives and mLetter share data
* Init sets them .
* HasMoreElements reads mLetter .
* GetNext advances mLetter .
*/
nsCString mDrives ;
const char * mLetter ;
} ;
2002-04-27 09:33:09 +04:00
//----------------------------------------------------------------------------
// short cut resolver
//----------------------------------------------------------------------------
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-01-08 05:20:13 +03:00
class ShortcutResolver
{
public :
ShortcutResolver ( ) ;
2004-02-11 09:19:03 +03:00
// nonvirtual since we're not subclassed
~ ShortcutResolver ( ) ;
2002-01-08 05:20:13 +03:00
nsresult Init ( ) ;
2003-03-07 09:07:56 +03:00
nsresult Resolve ( const WCHAR * in , char * out ) ;
2002-01-08 05:20:13 +03:00
private :
PRLock * mLock ;
2003-09-29 22:15:52 +04:00
IPersistFile * mPersistFile ;
2002-01-08 05:20:13 +03:00
IShellLink * mShellLink ;
} ;
ShortcutResolver : : ShortcutResolver ( )
{
mLock = nsnull ;
mPersistFile = nsnull ;
mShellLink = nsnull ;
}
ShortcutResolver : : ~ ShortcutResolver ( )
{
if ( mLock )
PR_DestroyLock ( mLock ) ;
2003-09-29 22:15:52 +04:00
// Release the pointer to the IPersistFile interface.
2002-01-08 05:20:13 +03:00
if ( mPersistFile )
2003-09-29 22:15:52 +04:00
mPersistFile - > Release ( ) ;
// Release the pointer to the IShellLink interface.
2002-01-08 05:20:13 +03:00
if ( mShellLink )
mShellLink - > Release ( ) ;
CoUninitialize ( ) ;
}
nsresult
ShortcutResolver : : Init ( )
{
CoInitialize ( NULL ) ; // FIX: we should probably move somewhere higher up during startup
mLock = PR_NewLock ( ) ;
if ( ! mLock )
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
HRESULT hres = CoCreateInstance ( CLSID_ShellLink ,
NULL ,
CLSCTX_INPROC_SERVER ,
IID_IShellLink ,
( void * * ) & mShellLink ) ;
if ( SUCCEEDED ( hres ) )
2002-01-08 05:20:13 +03:00
{
2003-09-29 22:15:52 +04:00
// Get a pointer to the IPersistFile interface.
hres = mShellLink - > QueryInterface ( IID_IPersistFile , ( void * * ) & mPersistFile ) ;
2002-01-08 05:20:13 +03:00
}
2003-09-29 22:15:52 +04:00
2002-01-08 05:20:13 +03:00
if ( mPersistFile = = nsnull | | mShellLink = = nsnull )
return NS_ERROR_FAILURE ;
return NS_OK ;
}
// |out| must be an allocated buffer of size MAX_PATH
2003-09-29 22:15:52 +04:00
nsresult
2003-03-07 09:07:56 +03:00
ShortcutResolver : : Resolve ( const WCHAR * in , char * out )
2002-01-08 05:20:13 +03:00
{
nsAutoLock lock ( mLock ) ;
2003-09-29 22:15:52 +04:00
2002-01-08 05:20:13 +03:00
// see if we can Load the path.
2003-09-29 22:15:52 +04:00
HRESULT hres = mPersistFile - > Load ( in , STGM_READ ) ;
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
// Resolve the link.
hres = mShellLink - > Resolve ( nsnull , SLR_NO_UI ) ;
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
WIN32_FIND_DATA wfd ;
// Get the path to the link target.
hres = mShellLink - > GetPath ( out , MAX_PATH , & wfd , SLGP_UNCPRIORITY ) ;
if ( FAILED ( hres ) )
2002-01-08 05:20:13 +03:00
return NS_ERROR_FAILURE ;
return NS_OK ;
}
static ShortcutResolver * gResolver = nsnull ;
2002-04-27 09:33:09 +04:00
static nsresult NS_CreateShortcutResolver ( )
2002-01-08 05:20:13 +03:00
{
gResolver = new ShortcutResolver ( ) ;
if ( ! gResolver )
return NS_ERROR_OUT_OF_MEMORY ;
return gResolver - > Init ( ) ;
}
2002-04-27 09:33:09 +04:00
static void NS_DestroyShortcutResolver ( )
2002-01-08 05:20:13 +03:00
{
delete gResolver ;
gResolver = nsnull ;
}
2005-01-31 00:33:47 +03:00
# endif
2002-01-08 05:20:13 +03:00
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// static helper functions
//-----------------------------------------------------------------------------
2003-09-29 22:15:52 +04:00
// certainly not all the error that can be
1999-12-04 04:13:44 +03:00
// encountered, but many of them common ones
static nsresult ConvertWinError ( DWORD winErr )
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
switch ( winErr )
{
case ERROR_FILE_NOT_FOUND :
case ERROR_PATH_NOT_FOUND :
case ERROR_INVALID_DRIVE :
rv = NS_ERROR_FILE_NOT_FOUND ;
break ;
case ERROR_ACCESS_DENIED :
case ERROR_NOT_SAME_DEVICE :
rv = NS_ERROR_FILE_ACCESS_DENIED ;
break ;
case ERROR_NOT_ENOUGH_MEMORY :
case ERROR_INVALID_BLOCK :
case ERROR_INVALID_HANDLE :
case ERROR_ARENA_TRASHED :
rv = NS_ERROR_OUT_OF_MEMORY ;
break ;
case ERROR_CURRENT_DIRECTORY :
rv = NS_ERROR_FILE_DIR_NOT_EMPTY ;
break ;
case ERROR_WRITE_PROTECT :
rv = NS_ERROR_FILE_READ_ONLY ;
break ;
case ERROR_HANDLE_DISK_FULL :
rv = NS_ERROR_FILE_TOO_BIG ;
break ;
2000-06-24 05:50:53 +04:00
case ERROR_FILE_EXISTS :
case ERROR_ALREADY_EXISTS :
case ERROR_CANNOT_MAKE :
rv = NS_ERROR_FILE_ALREADY_EXISTS ;
break ;
2005-03-02 21:16:37 +03:00
case ERROR_FILENAME_EXCED_RANGE :
rv = NS_ERROR_FILE_NAME_TOO_LONG ;
break ;
1999-12-04 04:13:44 +03:00
case 0 :
rv = NS_OK ;
2005-03-02 21:16:37 +03:00
break ;
2003-09-29 22:15:52 +04:00
default :
1999-12-04 04:13:44 +03:00
rv = NS_ERROR_FAILURE ;
2005-03-02 21:16:37 +03:00
break ;
1999-12-04 04:13:44 +03:00
}
return rv ;
}
2004-06-17 20:37:25 +04:00
// definition of INVALID_SET_FILE_POINTER from VC.NET header files
// it doesn't appear to be defined by VC6
# ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
# endif
// same goes for INVALID_FILE_ATTRIBUTES
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
// as suggested in the MSDN documentation on SetFilePointer
static __int64
MyFileSeek64 ( HANDLE aHandle , __int64 aDistance , DWORD aMoveMethod )
1999-12-08 02:31:25 +03:00
{
2004-06-17 20:37:25 +04:00
LARGE_INTEGER li ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
li . QuadPart = aDistance ;
li . LowPart = SetFilePointer ( aHandle , li . LowPart , & li . HighPart , aMoveMethod ) ;
if ( li . LowPart = = INVALID_SET_FILE_POINTER & & GetLastError ( ) ! = NO_ERROR )
{
li . QuadPart = - 1 ;
}
1999-12-08 02:31:25 +03:00
2004-06-17 20:37:25 +04:00
return li . QuadPart ;
1999-12-08 02:31:25 +03:00
}
2003-08-25 22:28:10 +04:00
static PRBool
2004-06-17 20:37:25 +04:00
IsShortcutPath ( const char * path )
{
// Under Windows, the shortcuts are just files with a ".lnk" extension.
// Note also that we don't resolve links in the middle of paths.
// i.e. "c:\foo.lnk\bar.txt" is invalid.
NS_ABORT_IF_FALSE ( path , " don't pass nulls " ) ;
const char * ext = ( const char * ) _mbsrchr ( ( const unsigned char * ) path , ' . ' ) ;
if ( ! ext | | 0 ! = stricmp ( ext + 1 , " lnk " ) )
2002-11-27 00:37:58 +03:00
return PR_FALSE ;
return PR_TRUE ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsDirEnumerator
//-----------------------------------------------------------------------------
2005-04-23 05:39:51 +04:00
class nsDirEnumerator : public nsISimpleEnumerator ,
public nsIDirectoryEnumerator
1999-12-04 04:13:44 +03:00
{
public :
NS_DECL_ISUPPORTS
2003-09-29 22:15:52 +04:00
nsDirEnumerator ( ) : mDir ( nsnull )
1999-12-04 04:13:44 +03:00
{
}
2003-09-29 22:15:52 +04:00
nsresult Init ( nsILocalFile * parent )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
nsCAutoString filepath ;
parent - > GetNativeTarget ( filepath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( filepath . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
parent - > GetNativePath ( filepath ) ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( filepath . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
return NS_ERROR_UNEXPECTED ;
1999-12-04 04:13:44 +03:00
}
2002-04-27 09:33:09 +04:00
mDir = PR_OpenDir ( filepath . get ( ) ) ;
1999-12-04 04:13:44 +03:00
if ( mDir = = nsnull ) // not a directory?
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
mParent = parent ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHOD HasMoreElements ( PRBool * result )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
if ( mNext = = nsnull & & mDir )
1999-12-04 04:13:44 +03:00
{
PRDirEntry * entry = PR_ReadDir ( mDir , PR_SKIP_BOTH ) ;
2003-09-29 22:15:52 +04:00
if ( entry = = nsnull )
1999-12-04 04:13:44 +03:00
{
// end of dir entries
PRStatus status = PR_CloseDir ( mDir ) ;
if ( status ! = PR_SUCCESS )
return NS_ERROR_FAILURE ;
mDir = nsnull ;
* result = PR_FALSE ;
return NS_OK ;
}
1999-12-22 04:56:45 +03:00
nsCOMPtr < nsIFile > file ;
2000-02-11 07:50:23 +03:00
rv = mParent - > Clone ( getter_AddRefs ( file ) ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
2000-02-11 07:50:23 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
rv = file - > AppendNative ( nsDependentCString ( entry - > name ) ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
// make sure the thing exists. If it does, try the next one.
PRBool exists ;
2002-04-27 09:33:09 +04:00
rv = file - > Exists ( & exists ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) | | ! exists )
2000-01-25 00:28:28 +03:00
{
2003-09-29 22:15:52 +04:00
return HasMoreElements ( result ) ;
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-22 04:56:45 +03:00
mNext = do_QueryInterface ( file ) ;
1999-12-04 04:13:44 +03:00
}
* result = mNext ! = nsnull ;
2005-04-23 05:39:51 +04:00
if ( ! * result )
Close ( ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHOD GetNext ( nsISupports * * result )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
PRBool hasMore ;
rv = HasMoreElements ( & hasMore ) ;
if ( NS_FAILED ( rv ) ) return rv ;
* result = mNext ; // might return nsnull
NS_IF_ADDREF ( * result ) ;
2002-07-18 09:09:10 +04:00
2001-10-07 14:58:39 +04:00
mNext = nsnull ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2005-04-23 05:39:51 +04:00
NS_IMETHOD GetNextFile ( nsIFile * * result )
{
* result = nsnull ;
PRBool hasMore = PR_FALSE ;
nsresult rv = HasMoreElements ( & hasMore ) ;
if ( NS_FAILED ( rv ) | | ! hasMore )
return rv ;
* result = mNext ;
NS_IF_ADDREF ( * result ) ;
mNext = nsnull ;
return NS_OK ;
}
NS_IMETHOD Close ( )
1999-12-04 04:13:44 +03:00
{
2003-09-29 22:15:52 +04:00
if ( mDir )
1999-12-04 04:13:44 +03:00
{
PRStatus status = PR_CloseDir ( mDir ) ;
NS_ASSERTION ( status = = PR_SUCCESS , " close failed " ) ;
2005-04-23 05:39:51 +04:00
if ( status ! = PR_SUCCESS )
return NS_ERROR_FAILURE ;
mDir = nsnull ;
1999-12-04 04:13:44 +03:00
}
2005-04-23 05:39:51 +04:00
return NS_OK ;
}
// dtor can be non-virtual since there are no subclasses, but must be
// public to use the class on the stack.
~ nsDirEnumerator ( )
{
Close ( ) ;
1999-12-04 04:13:44 +03:00
}
protected :
PRDir * mDir ;
nsCOMPtr < nsILocalFile > mParent ;
nsCOMPtr < nsILocalFile > mNext ;
} ;
2005-04-23 05:39:51 +04:00
NS_IMPL_ISUPPORTS2 ( nsDirEnumerator , nsISimpleEnumerator , nsIDirectoryEnumerator )
1999-12-04 04:13:44 +03:00
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <public>
//-----------------------------------------------------------------------------
1999-12-04 04:13:44 +03:00
nsLocalFile : : nsLocalFile ( )
2004-07-25 09:39:26 +04:00
: mFollowSymlinks ( PR_FALSE )
1999-12-04 04:13:44 +03:00
{
MakeDirty ( ) ;
2004-08-02 10:10:37 +04:00
memset ( & mFileInfo64 , 0 , sizeof ( mFileInfo64 ) ) ;
1999-12-04 04:13:44 +03:00
}
NS_METHOD
2000-01-25 00:28:28 +03:00
nsLocalFile : : nsLocalFileConstructor ( nsISupports * outer , const nsIID & aIID , void * * aInstancePtr )
1999-12-04 04:13:44 +03:00
{
NS_ENSURE_ARG_POINTER ( aInstancePtr ) ;
2000-01-25 00:28:28 +03:00
NS_ENSURE_NO_AGGREGATION ( outer ) ;
1999-12-04 04:13:44 +03:00
nsLocalFile * inst = new nsLocalFile ( ) ;
if ( inst = = NULL )
return NS_ERROR_OUT_OF_MEMORY ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
nsresult rv = inst - > QueryInterface ( aIID , aInstancePtr ) ;
if ( NS_FAILED ( rv ) )
{
delete inst ;
return rv ;
}
return NS_OK ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile::nsISupports
//-----------------------------------------------------------------------------
2005-02-25 12:00:45 +03:00
NS_IMPL_THREADSAFE_ISUPPORTS3 ( nsLocalFile , nsILocalFile , nsIFile , nsILocalFileWin )
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <private>
//-----------------------------------------------------------------------------
2003-07-19 02:14:16 +04:00
nsLocalFile : : nsLocalFile ( const nsLocalFile & other )
: mDirty ( other . mDirty )
, mFollowSymlinks ( other . mFollowSymlinks )
, mWorkingPath ( other . mWorkingPath )
, mResolvedPath ( other . mResolvedPath )
, mFileInfo64 ( other . mFileInfo64 )
{
}
2004-06-17 20:37:25 +04:00
// Resolve the shortcut file from mWorkingPath and write the path
// it points to into mResolvedPath.
2003-09-29 22:15:52 +04:00
nsresult
2004-06-17 20:37:25 +04:00
nsLocalFile : : ResolveShortcut ( )
1999-12-04 04:13:44 +03:00
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2004-06-17 20:37:25 +04:00
// we can't do anything without the resolver
if ( ! gResolver )
return NS_ERROR_FAILURE ;
2001-04-13 03:56:28 +04:00
2004-06-17 20:37:25 +04:00
// allocate the memory for the result of the resolution
nsAutoString ucsBuf ;
NS_CopyNativeToUnicode ( mWorkingPath , ucsBuf ) ;
1999-12-08 05:07:38 +03:00
2004-06-17 20:37:25 +04:00
mResolvedPath . SetLength ( MAX_PATH ) ;
char * resolvedPath = mResolvedPath . BeginWriting ( ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// resolve this shortcut
nsresult rv = gResolver - > Resolve ( ucsBuf . get ( ) , resolvedPath ) ;
1999-12-08 02:31:25 +03:00
2004-06-17 20:37:25 +04:00
size_t len = NS_FAILED ( rv ) ? 0 : strlen ( resolvedPath ) ;
mResolvedPath . SetLength ( len ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return rv ;
2005-01-31 00:33:47 +03:00
# else
return NS_OK ;
# endif
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// Resolve any shortcuts and stat the resolved path. After a successful return
// the path is guaranteed valid and the members of mFileInfo64 can be used.
1999-12-04 04:13:44 +03:00
nsresult
2004-06-17 20:37:25 +04:00
nsLocalFile : : ResolveAndStat ( )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// if we aren't dirty then we are already done
if ( ! mDirty )
2000-01-25 00:28:28 +03:00
return NS_OK ;
2000-03-08 05:53:04 +03:00
2004-06-17 20:37:25 +04:00
// we can't resolve/stat anything that isn't a valid NSPR addressable path
if ( mWorkingPath . IsEmpty ( ) )
return NS_ERROR_FILE_INVALID_PATH ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// this is usually correct
mResolvedPath . Assign ( mWorkingPath ) ;
2003-09-29 22:15:52 +04:00
2004-06-25 21:27:24 +04:00
// slutty hack designed to work around bug 134796 until it is fixed
char temp [ 4 ] ;
const char * nsprPath = mWorkingPath . get ( ) ;
if ( mWorkingPath . Length ( ) = = 2 & & mWorkingPath . CharAt ( 1 ) = = ' : ' )
{
temp [ 0 ] = mWorkingPath [ 0 ] ;
temp [ 1 ] = mWorkingPath [ 1 ] ;
temp [ 2 ] = ' \\ ' ;
temp [ 3 ] = ' \0 ' ;
nsprPath = temp ;
}
2004-06-17 20:37:25 +04:00
// first we will see if the working path exists. If it doesn't then
// there is nothing more that can be done
2004-06-25 21:27:24 +04:00
PRStatus status = PR_GetFileInfo64 ( nsprPath , & mFileInfo64 ) ;
2004-06-17 20:37:25 +04:00
if ( status ! = PR_SUCCESS )
return NS_ERROR_FILE_NOT_FOUND ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// if this isn't a shortcut file or we aren't following symlinks then we're done
if ( ! mFollowSymlinks
| | mFileInfo64 . type ! = PR_FILE_FILE
| | ! IsShortcutPath ( mWorkingPath . get ( ) ) )
{
mDirty = PR_FALSE ;
return NS_OK ;
2000-01-25 00:28:28 +03:00
}
2004-06-17 20:37:25 +04:00
// we need to resolve this shortcut to what it points to, this will
// set mResolvedPath. Even if it fails we need to have the resolved
// path equal to working path for those functions that always use
// the resolved path.
nsresult rv = ResolveShortcut ( ) ;
if ( NS_FAILED ( rv ) )
{
mResolvedPath . Assign ( mWorkingPath ) ;
return rv ;
}
2000-01-25 00:28:28 +03:00
2004-06-17 20:37:25 +04:00
// get the details of the resolved path
2001-11-01 12:09:57 +03:00
status = PR_GetFileInfo64 ( mResolvedPath . get ( ) , & mFileInfo64 ) ;
2004-06-17 20:37:25 +04:00
if ( status ! = PR_SUCCESS )
return NS_ERROR_FILE_NOT_FOUND ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
mDirty = PR_FALSE ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile::nsIFile,nsILocalFile
//-----------------------------------------------------------------------------
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-22 04:56:45 +03:00
nsLocalFile : : Clone ( nsIFile * * file )
1999-12-04 04:13:44 +03:00
{
2002-02-06 23:40:40 +03:00
// Just copy-construct ourselves
2003-07-19 02:14:16 +04:00
* file = new nsLocalFile ( * this ) ;
if ( ! * file )
return NS_ERROR_OUT_OF_MEMORY ;
1999-12-04 04:13:44 +03:00
2002-02-06 23:40:40 +03:00
NS_ADDREF ( * file ) ;
2003-07-19 02:14:16 +04:00
2002-02-06 23:40:40 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : InitWithNativePath ( const nsACString & filePath )
1999-12-04 04:13:44 +03:00
{
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
nsACString : : const_iterator begin , end ;
filePath . BeginReading ( begin ) ;
filePath . EndReading ( end ) ;
// input string must not be empty
if ( begin = = end )
return NS_ERROR_FAILURE ;
char firstChar = * begin ;
char secondChar = * ( + + begin ) ;
1999-12-04 04:13:44 +03:00
// just do a sanity check. if it has any forward slashes, it is not a Native path
// on windows. Also, it must have a colon at after the first char.
2002-04-27 09:33:09 +04:00
char * path = nsnull ;
PRInt32 pathLen = 0 ;
if ( ( ( secondChar = = ' : ' ) & & ! FindCharInReadable ( ' / ' , begin , end ) ) | | // normal path
2005-01-31 00:33:47 +03:00
# ifdef WINCE
( ( firstChar = = ' \\ ' ) ) // wince absolute path or network path
# else
( ( firstChar = = ' \\ ' ) & & ( secondChar = = ' \\ ' ) ) // network path
# endif
)
1999-12-04 04:13:44 +03:00
{
// This is a native path
2002-04-27 09:33:09 +04:00
path = ToNewCString ( filePath ) ;
pathLen = filePath . Length ( ) ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2005-01-31 00:33:47 +03:00
if ( path = = nsnull ) {
1999-12-04 04:13:44 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2005-01-31 00:33:47 +03:00
}
1999-12-04 04:13:44 +03:00
2002-04-27 09:33:09 +04:00
// kill any trailing '\' provided it isn't the second char of DBCS
PRInt32 len = pathLen - 1 ;
2004-04-29 12:16:50 +04:00
if ( path [ len ] = = ' \\ ' & &
( ! : : IsDBCSLeadByte ( path [ len - 1 ] ) | |
_mbsrchr ( ( const unsigned char * ) path , ' \\ ' ) = = ( const unsigned char * ) path + len ) )
2002-04-27 09:33:09 +04:00
{
path [ len ] = ' \0 ' ;
pathLen = len ;
}
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
mWorkingPath . Adopt ( path , pathLen ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-01-25 00:28:28 +03:00
nsLocalFile : : OpenNSPRFileDesc ( PRInt32 flags , PRInt32 mode , PRFileDesc * * _retval )
1999-12-22 04:56:45 +03:00
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-22 04:56:45 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2001-11-01 12:09:57 +03:00
* _retval = PR_Open ( mResolvedPath . get ( ) , flags , mode ) ;
2000-01-25 00:28:28 +03:00
if ( * _retval )
return NS_OK ;
return NS_ErrorAccordingToNSPR ( ) ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-01-25 00:28:28 +03:00
nsLocalFile : : OpenANSIFileDesc ( const char * mode , FILE * * _retval )
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2000-01-25 00:28:28 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2001-11-01 12:09:57 +03:00
* _retval = fopen ( mResolvedPath . get ( ) , mode ) ;
1999-12-22 04:56:45 +03:00
if ( * _retval )
return NS_OK ;
return NS_ERROR_FAILURE ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : Create ( PRUint32 type , PRUint32 attributes )
2003-09-29 22:15:52 +04:00
{
1999-12-04 04:13:44 +03:00
if ( type ! = NORMAL_FILE_TYPE & & type ! = DIRECTORY_TYPE )
return NS_ERROR_FILE_UNKNOWN_TYPE ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
2003-09-29 22:15:52 +04:00
return rv ;
2003-05-15 01:56:49 +04:00
// create directories to target
//
// A given local file can be either one of these forms:
//
// - normal: X:\some\path\on\this\drive
// ^--- start here
//
// - UNC path: \\machine\volume\some\path\on\this\drive
// ^--- start here
//
// Skip the first 'X:\' for the first form, and skip the first full
// '\\machine\volume\' segment for the second form.
2005-04-24 20:53:25 +04:00
unsigned char * path = ( unsigned char * ) mResolvedPath . BeginWriting ( ) ;
2005-01-31 00:33:47 +03:00
2003-05-15 01:56:49 +04:00
if ( path [ 0 ] = = ' \\ ' & & path [ 1 ] = = ' \\ ' )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
+ + path ;
# else
2003-05-15 01:56:49 +04:00
// dealing with a UNC path here; skip past '\\machine\'
path = _mbschr ( path + 2 , ' \\ ' ) ;
if ( ! path )
return NS_ERROR_FILE_INVALID_PATH ;
+ + path ;
2005-01-31 00:33:47 +03:00
# endif
2003-05-15 01:56:49 +04:00
}
// search for first slash after the drive (or volume) name
unsigned char * slash = _mbschr ( path , ' \\ ' ) ;
1999-12-04 04:13:44 +03:00
2002-01-08 05:20:13 +03:00
if ( slash )
1999-12-04 04:13:44 +03:00
{
2002-01-08 05:20:13 +03:00
// skip the first '\\'
1999-12-04 04:13:44 +03:00
+ + slash ;
2000-04-26 07:57:34 +04:00
slash = _mbschr ( slash , ' \\ ' ) ;
2003-09-29 22:15:52 +04:00
2002-01-08 05:20:13 +03:00
while ( slash )
{
* slash = ' \0 ' ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( ! CreateDirectoryA ( mResolvedPath . get ( ) , NULL ) ) {
rv = ConvertWinError ( GetLastError ( ) ) ;
2003-05-15 01:56:49 +04:00
// perhaps the base path already exists, or perhaps we don't have
// permissions to create the directory. NOTE: access denied could
// occur on a parent directory even though it exists.
if ( rv ! = NS_ERROR_FILE_ALREADY_EXISTS & &
rv ! = NS_ERROR_FILE_ACCESS_DENIED )
return rv ;
2002-04-27 09:33:09 +04:00
}
* slash = ' \\ ' ;
+ + slash ;
slash = _mbschr ( slash , ' \\ ' ) ;
2002-01-08 05:20:13 +03:00
}
1999-12-04 04:13:44 +03:00
}
if ( type = = NORMAL_FILE_TYPE )
{
2001-11-01 12:09:57 +03:00
PRFileDesc * file = PR_Open ( mResolvedPath . get ( ) , PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL , attributes ) ;
2000-06-24 05:50:53 +04:00
if ( ! file ) return NS_ERROR_FILE_ALREADY_EXISTS ;
PR_Close ( file ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
if ( type = = DIRECTORY_TYPE )
{
2001-11-01 12:09:57 +03:00
if ( ! CreateDirectoryA ( mResolvedPath . get ( ) , NULL ) )
2000-06-24 05:50:53 +04:00
return ConvertWinError ( GetLastError ( ) ) ;
2003-09-29 22:15:52 +04:00
else
2000-06-24 05:50:53 +04:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
return NS_ERROR_FILE_UNKNOWN_TYPE ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : AppendNative ( const nsACString & node )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// append this path, multiple components are not permitted
return AppendNativeInternal ( PromiseFlatCString ( node ) , PR_FALSE ) ;
2000-05-05 09:47:32 +04:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : AppendRelativeNativePath ( const nsACString & node )
2000-05-05 09:47:32 +04:00
{
2004-06-17 20:37:25 +04:00
// append this path, multiple components are permitted
return AppendNativeInternal ( PromiseFlatCString ( node ) , PR_TRUE ) ;
}
nsresult
nsLocalFile : : AppendNativeInternal ( const nsAFlatCString & node , PRBool multipleComponents )
{
if ( node . IsEmpty ( ) )
return NS_OK ;
// check the relative path for validity
const unsigned char * nodePath = ( const unsigned char * ) node . get ( ) ;
2004-06-25 21:27:24 +04:00
if ( * nodePath = = ' \\ ' // can't start with an '\'
2004-06-17 20:37:25 +04:00
| | _mbschr ( nodePath , ' / ' ) // can't contain /
| | node . Equals ( " .. " ) ) // can't be ..
2000-01-25 00:28:28 +03:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2004-06-17 20:37:25 +04:00
2005-01-31 00:33:47 +03:00
# ifndef WINCE // who cares?
2004-06-17 20:37:25 +04:00
if ( multipleComponents )
{
// can't contain .. as a path component. Ensure that the valid components
// "foo..foo", "..foo", and "foo.." are not falsely detected, but the invalid
// paths "..\", "foo\..", "foo\..\foo", "..\foo", etc are.
2005-04-24 20:53:25 +04:00
const unsigned char * doubleDot = _mbsstr ( nodePath , ( const unsigned char * ) " \\ .. " ) ;
2004-06-17 20:37:25 +04:00
while ( doubleDot )
{
doubleDot + = 3 ;
if ( * doubleDot = = ' \0 ' | | * doubleDot = = ' \\ ' )
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
doubleDot = _mbsstr ( doubleDot , ( unsigned char * ) " \\ .. " ) ;
}
if ( 0 = = _mbsncmp ( nodePath , ( unsigned char * ) " .. \\ " , 3 ) ) // catches the remaining cases of prefixes
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
1999-12-04 04:13:44 +03:00
}
2004-06-25 21:27:24 +04:00
else if ( _mbschr ( nodePath , ' \\ ' ) ) // single components can't contain '\'
2004-06-17 20:37:25 +04:00
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2005-01-31 00:33:47 +03:00
# endif
2004-06-17 20:37:25 +04:00
2000-01-25 00:28:28 +03:00
MakeDirty ( ) ;
2004-06-17 20:37:25 +04:00
2002-04-27 09:33:09 +04:00
mWorkingPath . Append ( NS_LITERAL_CSTRING ( " \\ " ) + node ) ;
2004-06-17 20:37:25 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
NS_IMETHODIMP
nsLocalFile : : Normalize ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2004-07-29 19:08:25 +04:00
// XXX See bug 187957 comment 18 for possible problems with this implementation.
if ( mWorkingPath . IsEmpty ( ) )
return NS_OK ;
// work in unicode for ease
nsAutoString path ;
NS_CopyNativeToUnicode ( mWorkingPath , path ) ;
// find the index of the root backslash for the path. Everything before
// this is considered fully normalized and cannot be ascended beyond
// using ".." For a local drive this is the first slash (e.g. "c:\").
// For a UNC path it is the slash following the share name
// (e.g. "\\server\share\").
PRInt32 rootIdx = 2 ; // default to local drive
if ( path . First ( ) = = ' \\ ' ) // if a share then calculate the rootIdx
{
rootIdx = path . FindChar ( ' \\ ' , 2 ) ; // skip \\ in front of the server
if ( rootIdx = = kNotFound )
return NS_OK ; // already normalized
rootIdx = path . FindChar ( ' \\ ' , rootIdx + 1 ) ;
if ( rootIdx = = kNotFound )
return NS_OK ; // already normalized
}
else if ( path . CharAt ( rootIdx ) ! = ' \\ ' )
{
// The path has been specified relative to the current working directory
// for that drive. To normalize it, the current working directory for
// that drive needs to be inserted before the supplied relative path
// which will provide an absolute path (and the rootIdx will still be 2).
char cwd [ MAX_PATH ] ;
char * pcwd = cwd ;
int drive = toupper ( path . First ( ) ) - ' A ' + 1 ;
if ( ! _getdcwd ( drive , pcwd , MAX_PATH ) )
pcwd = _getdcwd ( drive , 0 , 0 ) ;
if ( ! pcwd )
return NS_ERROR_OUT_OF_MEMORY ;
nsAutoString currentDir ;
NS_CopyNativeToUnicode ( nsDependentCString ( pcwd ) , currentDir ) ;
if ( pcwd ! = cwd )
free ( pcwd ) ;
if ( currentDir . Last ( ) = = ' \\ ' )
path . Replace ( 0 , 2 , currentDir ) ;
else
path . Replace ( 0 , 2 , currentDir + NS_LITERAL_STRING ( " \\ " ) ) ;
}
NS_POSTCONDITION ( 0 < rootIdx & & rootIdx < ( PRInt32 ) path . Length ( ) , " rootIdx is invalid " ) ;
NS_POSTCONDITION ( path . CharAt ( rootIdx ) = = ' \\ ' , " rootIdx is invalid " ) ;
// if there is nothing following the root path then it is already normalized
if ( rootIdx + 1 = = ( PRInt32 ) path . Length ( ) )
return NS_OK ;
// assign the root
nsAutoString normal ;
const PRUnichar * pathBuffer = path . get ( ) ; // simplify access to the buffer
normal . SetCapacity ( path . Length ( ) ) ; // it won't ever grow longer
normal . Assign ( pathBuffer , rootIdx ) ;
// Normalize the path components. The actions taken are:
//
// "\\" condense to single backslash
// "." remove from path
// ".." up a directory
// "..." remove from path (any number of dots > 2)
//
// The last form is something that Windows 95 and 98 supported and
// is a shortcut for changing up multiple directories. Windows XP
// and ilk ignore it in a path, as is done here.
PRInt32 len , begin , end = rootIdx ;
while ( end < ( PRInt32 ) path . Length ( ) )
{
// find the current segment (text between the backslashes) to
// be examined, this will set the following variables:
// begin == index of first char in segment
// end == index 1 char after last char in segment
// len == length of segment
begin = end + 1 ;
end = path . FindChar ( ' \\ ' , begin ) ;
if ( end = = kNotFound )
end = path . Length ( ) ;
len = end - begin ;
// ignore double backslashes
if ( len = = 0 )
continue ;
// len != 0, and interesting paths always begin with a dot
if ( pathBuffer [ begin ] = = ' . ' )
{
// ignore single dots
if ( len = = 1 )
continue ;
// handle multiple dots
if ( len > = 2 & & pathBuffer [ begin + 1 ] = = ' . ' )
{
// back up a path component on double dot
if ( len = = 2 )
{
PRInt32 prev = normal . RFindChar ( ' \\ ' ) ;
if ( prev > = rootIdx )
normal . Truncate ( prev ) ;
continue ;
}
// length is > 2 and the first two characters are dots.
// if the rest of the string is dots, then ignore it.
int idx = len - 1 ;
for ( ; idx > = 2 ; - - idx )
{
if ( pathBuffer [ begin + idx ] ! = ' . ' )
break ;
}
// this is true if the loop above didn't break
// and all characters in this segment are dots.
if ( idx < 2 )
continue ;
}
}
// add the current component to the path, including the preceding backslash
normal . Append ( pathBuffer + begin - 1 , len + 1 ) ;
}
2005-02-12 01:11:45 +03:00
// kill trailing dots and spaces.
PRInt32 filePathLen = normal . Length ( ) - 1 ;
while ( filePathLen > 0 & & ( normal [ filePathLen ] = = ' ' | | normal [ filePathLen ] = = ' . ' ) )
{
normal . Truncate ( filePathLen - - ) ;
}
2004-07-29 19:08:25 +04:00
NS_CopyUnicodeToNative ( normal , mWorkingPath ) ;
MakeDirty ( ) ;
2005-01-31 00:33:47 +03:00
# else // WINCE
// WINCE FIX
# endif
1999-12-08 02:31:25 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : GetNativeLeafName ( nsACString & aLeafName )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
aLeafName . Truncate ( ) ;
1999-12-04 04:13:44 +03:00
2001-03-02 12:26:57 +03:00
const char * temp = mWorkingPath . get ( ) ;
1999-12-04 04:13:44 +03:00
if ( temp = = nsnull )
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2000-04-26 07:57:34 +04:00
const char * leaf = ( const char * ) _mbsrchr ( ( const unsigned char * ) temp , ' \\ ' ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// if the working path is just a node without any lashes.
if ( leaf = = nsnull )
leaf = temp ;
else
leaf + + ;
2002-04-27 09:33:09 +04:00
aLeafName . Assign ( leaf ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : SetNativeLeafName ( const nsACString & aLeafName )
2000-01-25 00:28:28 +03:00
{
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2001-03-02 12:26:57 +03:00
const unsigned char * temp = ( const unsigned char * ) mWorkingPath . get ( ) ;
2000-01-25 00:28:28 +03:00
if ( temp = = nsnull )
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2000-04-26 07:57:34 +04:00
// cannot use nsCString::RFindChar() due to 0x5c problem
PRInt32 offset = ( PRInt32 ) ( _mbsrchr ( temp , ' \\ ' ) - temp ) ;
2000-01-25 00:28:28 +03:00
if ( offset )
{
mWorkingPath . Truncate ( offset + 1 ) ;
}
mWorkingPath . Append ( aLeafName ) ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : GetNativePath ( nsACString & _retval )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
_retval = mWorkingPath ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2005-02-25 12:00:45 +03:00
typedef struct {
WORD wLanguage ;
WORD wCodePage ;
} LANGANDCODEPAGE ;
NS_IMETHODIMP
nsLocalFile : : GetVersionInfoField ( const char * aField , nsAString & _retval )
{
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
rv = NS_ERROR_FAILURE ;
// Cast away const-ness here because WinAPI functions don't understand it,
// the path is used for [in] parameters only however so it's safe.
char * path = NS_CONST_CAST ( char * , mFollowSymlinks ? mResolvedPath . get ( )
: mWorkingPath . get ( ) ) ;
// Per http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/versioninformation/versioninformationreference/versioninformationfunctions/getfileversioninfosize.asp
// if the "short" version of this file name is > 125 characters,
// GetFileVersionInfoSize will not work (for Win9x compatibility)
char shortPath [ 126 ] ;
: : GetShortPathName ( path , shortPath , sizeof ( shortPath ) ) ;
DWORD dummy ;
DWORD size = : : GetFileVersionInfoSize ( shortPath , & dummy ) ;
if ( ! size )
return rv ;
void * ver = calloc ( size , 1 ) ;
if ( ! ver )
return NS_ERROR_OUT_OF_MEMORY ;
if ( : : GetFileVersionInfo ( path , 0 , size , ver ) )
{
LANGANDCODEPAGE * translate = nsnull ;
UINT pageCount ;
BOOL queryResult = : : VerQueryValue ( ver , " \\ VarFileInfo \\ Translation " ,
( void * * ) & translate , & pageCount ) ;
if ( queryResult & & translate )
{
for ( PRInt32 i = 0 ; i < 2 ; + + i )
{
char subBlock [ MAX_PATH ] ;
PR_snprintf ( subBlock , sizeof ( subBlock ) ,
" \\ StringFileInfo \\ %04x%04x \\ %s " ,
( i = = 0 ? translate [ 0 ] . wLanguage
: : : GetUserDefaultLangID ( ) ) ,
translate [ 0 ] . wCodePage , aField ) ;
LPVOID value = nsnull ;
UINT size ;
queryResult = : : VerQueryValue ( ver , subBlock , & value , & size ) ;
if ( queryResult & & value )
{
NS_CopyNativeToUnicode ( nsDependentCString ( ( const char * ) value ) , _retval ) ;
if ( ! _retval . IsEmpty ( ) )
{
rv = NS_OK ;
break ;
}
}
}
}
}
free ( ver ) ;
return rv ;
}
1999-12-04 04:13:44 +03:00
nsresult
2004-06-17 20:37:25 +04:00
nsLocalFile : : CopySingleFile ( nsIFile * sourceFile , nsIFile * destParent , const nsACString & newName ,
PRBool followSymlinks , PRBool move )
1999-12-04 04:13:44 +03:00
{
nsresult rv ;
2002-04-27 09:33:09 +04:00
nsCAutoString filePath ;
1999-12-04 04:13:44 +03:00
// get the path that we are going to copy to.
// Since windows does not know how to auto
2004-06-17 20:37:25 +04:00
// resolve shortcuts, we must work with the
1999-12-04 04:13:44 +03:00
// target.
2002-04-27 09:33:09 +04:00
nsCAutoString destPath ;
2003-09-29 22:15:52 +04:00
destParent - > GetNativeTarget ( destPath ) ;
1999-12-04 04:13:44 +03:00
destPath . Append ( " \\ " ) ;
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
nsCAutoString aFileName ;
sourceFile - > GetNativeLeafName ( aFileName ) ;
1999-12-04 04:13:44 +03:00
destPath . Append ( aFileName ) ;
}
else
{
destPath . Append ( newName ) ;
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
if ( followSymlinks )
{
2002-04-27 09:33:09 +04:00
rv = sourceFile - > GetNativeTarget ( filePath ) ;
if ( filePath . IsEmpty ( ) )
rv = sourceFile - > GetNativePath ( filePath ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2002-04-27 09:33:09 +04:00
rv = sourceFile - > GetNativePath ( filePath ) ;
1999-12-04 04:13:44 +03:00
}
if ( NS_FAILED ( rv ) )
return rv ;
int copyOK ;
if ( ! move )
2002-04-27 09:33:09 +04:00
copyOK = CopyFile ( filePath . get ( ) , destPath . get ( ) , PR_TRUE ) ;
2003-09-29 22:15:52 +04:00
else
2002-11-13 17:04:51 +03:00
{
2003-09-29 22:15:52 +04:00
// What we have to do is check to see if the destPath exists. If it
// does, we have to move it out of the say so that MoveFile will
// succeed. However, we don't want to just remove it since MoveFile
2002-11-13 17:04:51 +03:00
// can fail leaving us without a file.
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
nsCAutoString backup ;
PRFileInfo64 fileInfo64 ;
PRStatus status = PR_GetFileInfo64 ( destPath . get ( ) , & fileInfo64 ) ;
if ( status = = PR_SUCCESS )
{
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// the file exists. Check to make sure it is not a directory,
// then move it out of the way.
if ( fileInfo64 . type = = PR_FILE_FILE )
{
backup . Append ( destPath ) ;
backup . Append ( " .moztmp " ) ;
// remove any existing backup file that we may already have.
2003-09-29 22:15:52 +04:00
// maybe we should be doing some kind of unique naming here,
2002-11-13 17:04:51 +03:00
// but why bother.
remove ( backup . get ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// move destination file to backup file
copyOK = MoveFile ( destPath . get ( ) , backup . get ( ) ) ;
if ( ! copyOK )
{
// I guess we can't do the backup copy, so return.
rv = ConvertWinError ( GetLastError ( ) ) ;
return rv ;
}
}
}
// move source file to destination file
2002-04-27 09:33:09 +04:00
copyOK = MoveFile ( filePath . get ( ) , destPath . get ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
if ( ! backup . IsEmpty ( ) )
{
2003-09-29 22:15:52 +04:00
if ( copyOK )
2002-11-13 17:04:51 +03:00
{
// remove the backup copy.
2003-06-19 03:19:11 +04:00
remove ( backup . get ( ) ) ;
2002-11-13 17:04:51 +03:00
}
else
{
// restore backup
int backupOk = MoveFile ( backup . get ( ) , destPath . get ( ) ) ;
NS_ASSERTION ( backupOk , " move backup failed " ) ;
}
}
2003-09-29 22:15:52 +04:00
}
1999-12-04 04:13:44 +03:00
if ( ! copyOK ) // CopyFile and MoveFile returns non-zero if succeeds (backward if you ask me).
rv = ConvertWinError ( GetLastError ( ) ) ;
return rv ;
}
nsresult
2002-04-27 09:33:09 +04:00
nsLocalFile : : CopyMove ( nsIFile * aParentDir , const nsACString & newName , PRBool followSymlinks , PRBool move )
1999-12-04 04:13:44 +03:00
{
2000-03-24 08:47:39 +03:00
nsCOMPtr < nsIFile > newParentDir = aParentDir ;
1999-12-04 04:13:44 +03:00
// check to see if this exists, otherwise return an error.
// we will check this by resolving. If the user wants us
// to follow links, then we are talking about the target,
// hence we can use the |followSymlinks| parameter.
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2000-03-24 08:47:39 +03:00
if ( ! newParentDir )
{
// no parent was specified. We must rename.
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
2000-03-24 08:47:39 +03:00
return NS_ERROR_INVALID_ARG ;
rv = GetParent ( getter_AddRefs ( newParentDir ) ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
if ( ! newParentDir )
return NS_ERROR_FILE_DESTINATION_NOT_DIR ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// make sure it exists and is a directory. Create it if not there.
PRBool exists ;
newParentDir - > Exists ( & exists ) ;
2002-11-13 17:04:51 +03:00
if ( ! exists )
1999-12-04 04:13:44 +03:00
{
rv = newParentDir - > Create ( DIRECTORY_TYPE , 0644 ) ; // TODO, what permissions should we use
if ( NS_FAILED ( rv ) )
return rv ;
}
else
{
PRBool isDir ;
newParentDir - > IsDirectory ( & isDir ) ;
if ( isDir = = PR_FALSE )
{
if ( followSymlinks )
{
PRBool isLink ;
newParentDir - > IsSymlink ( & isLink ) ;
if ( isLink )
{
2002-04-27 09:33:09 +04:00
nsCAutoString target ;
newParentDir - > GetNativeTarget ( target ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
nsCOMPtr < nsILocalFile > realDest = new nsLocalFile ( ) ;
if ( realDest = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
1999-12-04 04:13:44 +03:00
2002-04-27 09:33:09 +04:00
rv = realDest - > InitWithNativePath ( target ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return CopyMove ( realDest , newName , followSymlinks , move ) ;
}
}
else
2003-09-29 22:15:52 +04:00
{
1999-12-04 04:13:44 +03:00
return NS_ERROR_FILE_DESTINATION_NOT_DIR ;
}
2000-03-24 08:47:39 +03:00
}
1999-12-04 04:13:44 +03:00
}
2005-04-27 08:38:21 +04:00
// Try different ways to move/copy files/directories
PRBool done = PR_FALSE ;
1999-12-04 04:13:44 +03:00
PRBool isDir ;
IsDirectory ( & isDir ) ;
1999-12-08 05:07:38 +03:00
PRBool isSymlink ;
IsSymlink ( & isSymlink ) ;
2005-04-27 08:38:21 +04:00
// Try to move the file or directory, or try to copy a single file (or non-followed symlink)
if ( move | | ! isDir | | ( isSymlink & & ! followSymlinks ) )
1999-12-04 04:13:44 +03:00
{
2005-04-27 08:38:21 +04:00
// Copy/Move single file, or move a directory
1999-12-04 04:13:44 +03:00
rv = CopySingleFile ( this , newParentDir , newName , followSymlinks , move ) ;
2005-04-27 08:38:21 +04:00
done = NS_SUCCEEDED ( rv ) ;
// If we are moving a directory and that fails, fallback on directory
// enumeration. See bug 231300 for details.
if ( ! done & & ! ( move & & isDir ) )
return rv ;
1999-12-04 04:13:44 +03:00
}
2005-04-27 08:38:21 +04:00
// Not able to copy or move directly, so enumerate it
if ( ! done )
1999-12-04 04:13:44 +03:00
{
// create a new target destination in the new parentDir;
1999-12-22 04:56:45 +03:00
nsCOMPtr < nsIFile > target ;
rv = newParentDir - > Clone ( getter_AddRefs ( target ) ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
nsCAutoString allocatedNewName ;
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
1999-12-08 02:31:25 +03:00
PRBool isLink ;
IsSymlink ( & isLink ) ;
if ( isLink )
{
2002-04-27 09:33:09 +04:00
nsCAutoString temp ;
GetNativeTarget ( temp ) ;
const char * leaf = ( const char * ) _mbsrchr ( ( const unsigned char * ) temp . get ( ) , ' \\ ' ) ;
1999-12-08 02:31:25 +03:00
if ( leaf [ 0 ] = = ' \\ ' )
leaf + + ;
2002-04-27 09:33:09 +04:00
allocatedNewName = leaf ;
1999-12-08 02:31:25 +03:00
}
else
{
2003-09-29 22:15:52 +04:00
GetNativeLeafName ( allocatedNewName ) ; // this should be the leaf name of the
1999-12-08 02:31:25 +03:00
}
1999-12-04 04:13:44 +03:00
}
else
{
2002-04-27 09:33:09 +04:00
allocatedNewName = newName ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
rv = target - > AppendNative ( allocatedNewName ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2002-04-27 09:33:09 +04:00
allocatedNewName . Truncate ( ) ;
2003-09-29 22:15:52 +04:00
2002-11-13 17:04:51 +03:00
// check if the destination directory already exists
target - > Exists ( & exists ) ;
if ( ! exists )
{
// if the destination directory cannot be created, return an error
rv = target - > Create ( DIRECTORY_TYPE , 0644 ) ; // TODO, what permissions should we use
if ( NS_FAILED ( rv ) )
return rv ;
}
else
{
// check if the destination directory is writable and empty
PRBool isWritable ;
target - > IsWritable ( & isWritable ) ;
if ( ! isWritable )
return NS_ERROR_FILE_ACCESS_DENIED ;
nsCOMPtr < nsISimpleEnumerator > targetIterator ;
rv = target - > GetDirectoryEntries ( getter_AddRefs ( targetIterator ) ) ;
PRBool more ;
targetIterator - > HasMoreElements ( & more ) ;
// return error if target directory is not empty
if ( more )
return NS_ERROR_FILE_DIR_NOT_EMPTY ;
}
1999-12-04 04:13:44 +03:00
2003-08-25 22:28:10 +04:00
nsDirEnumerator dirEnum ;
rv = dirEnum . Init ( this ) ;
2002-06-04 22:47:37 +04:00
if ( NS_FAILED ( rv ) ) {
NS_WARNING ( " dirEnum initalization failed " ) ;
return rv ;
}
1999-12-04 04:13:44 +03:00
PRBool more ;
2003-08-25 22:28:10 +04:00
while ( NS_SUCCEEDED ( dirEnum . HasMoreElements ( & more ) ) & & more )
1999-12-04 04:13:44 +03:00
{
nsCOMPtr < nsISupports > item ;
nsCOMPtr < nsIFile > file ;
2003-08-25 22:28:10 +04:00
dirEnum . GetNext ( getter_AddRefs ( item ) ) ;
1999-12-04 04:13:44 +03:00
file = do_QueryInterface ( item ) ;
2002-07-18 09:09:10 +04:00
if ( file )
2003-09-29 22:15:52 +04:00
{
2002-07-18 09:09:10 +04:00
PRBool isDir , isLink ;
2003-09-29 22:15:52 +04:00
2002-07-18 09:09:10 +04:00
file - > IsDirectory ( & isDir ) ;
file - > IsSymlink ( & isLink ) ;
2003-09-29 22:15:52 +04:00
2002-07-18 09:09:10 +04:00
if ( move )
{
if ( followSymlinks )
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2005-01-04 22:31:31 +03:00
rv = file - > MoveToNative ( target , EmptyCString ( ) ) ;
2002-07-18 09:09:10 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
else
2003-09-29 22:15:52 +04:00
{
2002-07-18 09:09:10 +04:00
if ( followSymlinks )
2005-01-04 22:31:31 +03:00
rv = file - > CopyToFollowingLinksNative ( target , EmptyCString ( ) ) ;
2002-07-18 09:09:10 +04:00
else
2005-01-04 22:31:31 +03:00
rv = file - > CopyToNative ( target , EmptyCString ( ) ) ;
2002-07-18 09:09:10 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
}
}
2002-04-25 22:56:04 +04:00
// we've finished moving all the children of this directory
// in the new directory. so now delete the directory
// note, we don't need to do a recursive delete.
// MoveTo() is recursive. At this point,
2003-09-29 22:15:52 +04:00
// we've already moved the children of the current folder
2002-04-25 22:56:04 +04:00
// to the new location. nothing should be left in the folder.
if ( move )
2002-06-04 22:47:37 +04:00
{
2002-04-25 22:56:04 +04:00
rv = Remove ( PR_FALSE /* recursive */ ) ;
2002-06-04 22:47:37 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
}
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
// If we moved, we want to adjust this.
if ( move )
{
1999-12-22 04:56:45 +03:00
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
nsCAutoString newParentPath ;
newParentDir - > GetNativePath ( newParentPath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( newParentPath . IsEmpty ( ) )
1999-12-22 04:56:45 +03:00
return NS_ERROR_FAILURE ;
2002-04-27 09:33:09 +04:00
if ( newName . IsEmpty ( ) )
1999-12-04 04:13:44 +03:00
{
2002-04-27 09:33:09 +04:00
nsCAutoString aFileName ;
GetNativeLeafName ( aFileName ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
InitWithNativePath ( newParentPath ) ;
2003-09-29 22:15:52 +04:00
AppendNative ( aFileName ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2002-04-27 09:33:09 +04:00
InitWithNativePath ( newParentPath ) ;
AppendNative ( newName ) ;
1999-12-04 04:13:44 +03:00
}
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : CopyToNative ( nsIFile * newParentDir , const nsACString & newName )
1999-12-04 04:13:44 +03:00
{
return CopyMove ( newParentDir , newName , PR_FALSE , PR_FALSE ) ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : CopyToFollowingLinksNative ( nsIFile * newParentDir , const nsACString & newName )
1999-12-04 04:13:44 +03:00
{
return CopyMove ( newParentDir , newName , PR_TRUE , PR_FALSE ) ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : MoveToNative ( nsIFile * newParentDir , const nsACString & newName )
1999-12-04 04:13:44 +03:00
{
return CopyMove ( newParentDir , newName , PR_FALSE , PR_TRUE ) ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-22 07:11:13 +03:00
nsLocalFile : : Load ( PRLibrary * * _retval )
1999-12-22 06:01:08 +03:00
{
PRBool isFile ;
nsresult rv = IsFile ( & isFile ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
1999-12-22 06:01:08 +03:00
if ( ! isFile )
return NS_ERROR_FILE_IS_DIRECTORY ;
2001-08-17 06:03:34 +04:00
NS_TIMELINE_START_TIMER ( " PR_LoadLibrary " ) ;
2001-11-01 12:09:57 +03:00
* _retval = PR_LoadLibrary ( mResolvedPath . get ( ) ) ;
2001-08-17 06:03:34 +04:00
NS_TIMELINE_STOP_TIMER ( " PR_LoadLibrary " ) ;
2001-11-17 23:23:48 +03:00
NS_TIMELINE_MARK_TIMER1 ( " PR_LoadLibrary " , mResolvedPath . get ( ) ) ;
1999-12-22 06:01:08 +03:00
if ( * _retval )
return NS_OK ;
return NS_ERROR_NULL_POINTER ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-07-24 22:38:25 +04:00
nsLocalFile : : Remove ( PRBool recursive )
1999-12-04 04:13:44 +03:00
{
2003-08-25 22:28:10 +04:00
// NOTE:
//
// if the working path points to a shortcut, then we will only
// delete the shortcut itself. even if the shortcut points to
// a directory, we will not recurse into that directory or
// delete that directory itself. likewise, if the shortcut
// points to a normal file, we will not delete the real file.
// this is done to be consistent with the other platforms that
// behave this way. we do this even if the followLinks attribute
// is set to true. this helps protect against misuse that could
// lead to security bugs (e.g., bug 210588).
//
2004-06-17 20:37:25 +04:00
// Since shortcut files are no longer permitted to be used as unix-like
// symlinks interspersed in the path (e.g. "c:/file.lnk/foo/bar.txt")
// this processing is a lot simpler. Even if the shortcut file is
// pointing to a directory, only the mWorkingPath value is used and so
// only the shortcut file will be deleted.
2003-08-25 22:28:10 +04:00
2004-06-17 20:37:25 +04:00
PRBool isDir , isLink ;
nsresult rv ;
isDir = PR_FALSE ;
rv = IsSymlink ( & isLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// only check to see if we have a directory if it isn't a link
if ( ! isLink )
2003-08-25 22:28:10 +04:00
{
rv = IsDirectory ( & isDir ) ;
if ( NS_FAILED ( rv ) )
return rv ;
}
1999-12-04 04:13:44 +03:00
if ( isDir )
{
if ( recursive )
{
2003-08-25 22:28:10 +04:00
nsDirEnumerator dirEnum ;
rv = dirEnum . Init ( this ) ;
if ( NS_FAILED ( rv ) )
return rv ;
1999-12-04 04:13:44 +03:00
PRBool more ;
2003-08-25 22:28:10 +04:00
while ( NS_SUCCEEDED ( dirEnum . HasMoreElements ( & more ) ) & & more )
1999-12-04 04:13:44 +03:00
{
nsCOMPtr < nsISupports > item ;
2003-08-25 22:28:10 +04:00
dirEnum . GetNext ( getter_AddRefs ( item ) ) ;
nsCOMPtr < nsIFile > file = do_QueryInterface ( item ) ;
2002-07-18 09:09:10 +04:00
if ( file )
file - > Remove ( recursive ) ;
1999-12-04 04:13:44 +03:00
}
}
2004-06-17 20:37:25 +04:00
rv = rmdir ( mWorkingPath . get ( ) ) ;
1999-12-04 04:13:44 +03:00
}
else
{
2004-06-17 20:37:25 +04:00
rv = remove ( mWorkingPath . get ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2003-08-25 22:28:10 +04:00
// fixup error code if necessary...
2004-04-13 23:30:51 +04:00
if ( rv = = ( nsresult ) - 1 )
2003-08-25 22:28:10 +04:00
rv = NSRESULT_FOR_ERRNO ( ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
MakeDirty ( ) ;
2002-01-26 03:38:37 +03:00
return rv ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : GetLastModifiedTime ( PRInt64 * aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2001-11-26 11:05:05 +03:00
NS_ENSURE_ARG ( aLastModifiedTime ) ;
2004-06-17 20:37:25 +04:00
// get the modified time of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as GetLastModifiedTimeOfLink)
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// microseconds -> milliseconds
2004-06-17 20:37:25 +04:00
PRInt64 usecPerMsec ;
LL_I2L ( usecPerMsec , PR_USEC_PER_MSEC ) ;
LL_DIV ( * aLastModifiedTime , mFileInfo64 . modifyTime , usecPerMsec ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : GetLastModifiedTimeOfLink ( PRInt64 * aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2001-11-26 11:05:05 +03:00
NS_ENSURE_ARG ( aLastModifiedTime ) ;
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
PRFileInfo64 info ;
if ( PR_GetFileInfo64 ( mWorkingPath . get ( ) , & info ) ! = PR_SUCCESS )
return NSRESULT_FOR_ERRNO ( ) ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// microseconds -> milliseconds
2004-06-17 20:37:25 +04:00
PRInt64 usecPerMsec ;
LL_I2L ( usecPerMsec , PR_USEC_PER_MSEC ) ;
LL_DIV ( * aLastModifiedTime , info . modifyTime , usecPerMsec ) ;
2000-02-22 00:51:47 +03:00
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : SetLastModifiedTime ( PRInt64 aLastModifiedTime )
2000-02-22 00:51:47 +03:00
{
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// set the modified time of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetLastModifiedTimeOfLink)
rv = SetModDate ( aLastModifiedTime , mResolvedPath . get ( ) ) ;
if ( NS_SUCCEEDED ( rv ) )
MakeDirty ( ) ;
return rv ;
1999-12-04 04:13:44 +03:00
}
2000-02-22 00:51:47 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2001-11-26 11:05:05 +03:00
nsLocalFile : : SetLastModifiedTimeOfLink ( PRInt64 aLastModifiedTime )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = SetModDate ( aLastModifiedTime , mWorkingPath . get ( ) ) ;
if ( NS_SUCCEEDED ( rv ) )
MakeDirty ( ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
return rv ;
}
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult
nsLocalFile : : SetModDate ( PRInt64 aLastModifiedTime , const char * filePath )
{
HANDLE file = CreateFile ( filePath , // pointer to name of the file
GENERIC_WRITE , // access (write) mode
0 , // share mode
NULL , // pointer to security attributes
OPEN_EXISTING , // how to create
0 , // file attributes
NULL ) ;
2005-01-31 00:33:47 +03:00
2004-06-17 20:37:25 +04:00
if ( file = = INVALID_HANDLE_VALUE )
1999-12-04 04:13:44 +03:00
{
2000-03-22 04:37:52 +03:00
return ConvertWinError ( GetLastError ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2000-03-28 07:39:02 +04:00
FILETIME lft , ft ;
SYSTEMTIME st ;
PRExplodedTime pret ;
2003-09-29 22:15:52 +04:00
2000-05-09 23:11:14 +04:00
// PR_ExplodeTime expects usecs...
2001-11-26 11:05:05 +03:00
PR_ExplodeTime ( aLastModifiedTime * PR_USEC_PER_MSEC , PR_LocalTimeParameters , & pret ) ;
2003-09-29 22:15:52 +04:00
st . wYear = pret . tm_year ;
2000-03-28 07:39:02 +04:00
st . wMonth = pret . tm_month + 1 ; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
2003-09-29 22:15:52 +04:00
st . wDayOfWeek = pret . tm_wday ;
st . wDay = pret . tm_mday ;
2000-03-28 07:39:02 +04:00
st . wHour = pret . tm_hour ;
2003-09-29 22:15:52 +04:00
st . wMinute = pret . tm_min ;
2000-03-28 07:39:02 +04:00
st . wSecond = pret . tm_sec ;
st . wMilliseconds = pret . tm_usec / 1000 ;
2004-06-17 20:37:25 +04:00
nsresult rv = NS_OK ;
if ( 0 ! = SystemTimeToFileTime ( & st , & lft )
| | 0 ! = LocalFileTimeToFileTime ( & lft , & ft )
| | 0 ! = SetFileTime ( file , NULL , & ft , & ft ) )
1999-12-04 04:13:44 +03:00
{
2000-03-22 04:37:52 +03:00
rv = ConvertWinError ( GetLastError ( ) ) ;
1999-12-04 04:13:44 +03:00
}
2000-03-28 07:39:02 +04:00
2004-06-17 20:37:25 +04:00
CloseHandle ( file ) ;
2000-03-22 04:37:52 +03:00
return rv ;
2000-02-22 00:51:47 +03:00
}
2000-03-28 07:39:02 +04:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetPermissions ( PRUint32 * aPermissions )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aPermissions ) ;
// get the permissions of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as GetPermissionsOfLink)
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
PRBool isWritable , isExecutable ;
IsWritable ( & isWritable ) ;
IsExecutable ( & isExecutable ) ;
* aPermissions = PR_IRUSR | PR_IRGRP | PR_IROTH ; // all read
if ( isWritable )
* aPermissions | = PR_IWUSR | PR_IWGRP | PR_IWOTH ; // all write
if ( isExecutable )
* aPermissions | = PR_IXUSR | PR_IXGRP | PR_IXOTH ; // all execute
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-06-17 20:37:25 +04:00
nsLocalFile : : GetPermissionsOfLink ( PRUint32 * aPermissions )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aPermissions ) ;
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link. It is not
// possible for a link file to be executable.
DWORD word = GetFileAttributes ( mWorkingPath . get ( ) ) ;
if ( word = = INVALID_FILE_ATTRIBUTES )
return NS_ERROR_FILE_INVALID_PATH ;
PRBool isWritable = ! ( word & FILE_ATTRIBUTE_READONLY ) ;
* aPermissions = PR_IRUSR | PR_IRGRP | PR_IROTH ; // all read
if ( isWritable )
* aPermissions | = PR_IWUSR | PR_IWGRP | PR_IWOTH ; // all write
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : SetPermissions ( PRUint32 aPermissions )
{
2004-06-17 20:37:25 +04:00
// set the permissions of the target as determined by mFollowSymlinks
// If PR_TRUE, then this will be for the target of the shortcut file,
// otherwise it will be for the shortcut file itself (i.e. the same
// results as SetPermissionsOfLink)
nsresult rv = ResolveAndStat ( ) ;
2000-02-22 00:51:47 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// windows only knows about the following permissions
int mode = 0 ;
if ( aPermissions & ( PR_IRUSR | PR_IRGRP | PR_IROTH ) ) // any read
mode | = _S_IREAD ;
if ( aPermissions & ( PR_IWUSR | PR_IWGRP | PR_IWOTH ) ) // any write
mode | = _S_IWRITE ;
if ( chmod ( mResolvedPath . get ( ) , mode ) = = - 1 )
2000-02-22 00:51:47 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : SetPermissionsOfLink ( PRUint32 aPermissions )
{
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// windows only knows about the following permissions
int mode = 0 ;
if ( aPermissions & ( PR_IRUSR | PR_IRGRP | PR_IROTH ) ) // any read
mode | = _S_IREAD ;
if ( aPermissions & ( PR_IWUSR | PR_IWGRP | PR_IWOTH ) ) // any write
mode | = _S_IWRITE ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
if ( chmod ( mWorkingPath . get ( ) , mode ) = = - 1 )
2000-02-22 00:51:47 +03:00
return NS_ERROR_FAILURE ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetFileSize ( PRInt64 * aFileSize )
{
NS_ENSURE_ARG ( aFileSize ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2000-02-22 00:51:47 +03:00
* aFileSize = mFileInfo64 . size ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-06-17 20:37:25 +04:00
nsLocalFile : : GetFileSizeOfLink ( PRInt64 * aFileSize )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( aFileSize ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// The caller is assumed to have already called IsSymlink
// and to have found that this file is a link.
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
PRFileInfo64 info ;
if ( ! PR_GetFileInfo64 ( mWorkingPath . get ( ) , & info ) )
return NS_ERROR_FILE_INVALID_PATH ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
* aFileSize = info . size ;
return NS_OK ;
}
NS_IMETHODIMP
nsLocalFile : : SetFileSize ( PRInt64 aFileSize )
{
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
HANDLE hFile = CreateFile ( mResolvedPath . get ( ) , // pointer to name of the file
GENERIC_WRITE , // access (write) mode
FILE_SHARE_READ , // share mode
NULL , // pointer to security attributes
OPEN_EXISTING , // how to create
FILE_ATTRIBUTE_NORMAL , // file attributes
NULL ) ;
1999-12-04 04:13:44 +03:00
if ( hFile = = INVALID_HANDLE_VALUE )
2000-01-25 00:28:28 +03:00
{
2004-06-17 20:37:25 +04:00
return ConvertWinError ( GetLastError ( ) ) ;
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
// seek the file pointer to the new, desired end of file
// and then truncate the file at that position
rv = NS_ERROR_FAILURE ;
aFileSize = MyFileSeek64 ( hFile , aFileSize , FILE_BEGIN ) ;
if ( aFileSize ! = - 1 & & SetEndOfFile ( hFile ) )
{
MakeDirty ( ) ;
rv = NS_OK ;
}
1999-12-04 04:13:44 +03:00
CloseHandle ( hFile ) ;
2004-06-17 20:37:25 +04:00
return rv ;
1999-12-04 04:13:44 +03:00
}
2005-01-31 00:33:47 +03:00
typedef BOOL ( WINAPI * fpGetDiskFreeSpaceExA ) ( LPCSTR lpDirectoryName ,
2004-06-17 20:37:25 +04:00
PULARGE_INTEGER lpFreeBytesAvailableToCaller ,
PULARGE_INTEGER lpTotalNumberOfBytes ,
PULARGE_INTEGER lpTotalNumberOfFreeBytes ) ;
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetDiskSpaceAvailable ( PRInt64 * aDiskSpaceAvailable )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
1999-12-04 04:13:44 +03:00
NS_ENSURE_ARG ( aDiskSpaceAvailable ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
ResolveAndStat ( ) ;
// Attempt to check disk space using the GetDiskFreeSpaceExA function.
// --- FROM MSDN ---
// The GetDiskFreeSpaceEx function is available beginning with Windows 95 OEM Service
// Release 2 (OSR2). To determine whether GetDiskFreeSpaceEx is available, call
// GetModuleHandle to get the handle to Kernel32.dll. Then you can call GetProcAddress.
// It is not necessary to call LoadLibrary on Kernel32.dll because it is already loaded
// into every process address space.
fpGetDiskFreeSpaceExA pGetDiskFreeSpaceExA = ( fpGetDiskFreeSpaceExA )
GetProcAddress ( GetModuleHandle ( " kernel32.dll " ) , " GetDiskFreeSpaceExA " ) ;
if ( pGetDiskFreeSpaceExA )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
ULARGE_INTEGER liFreeBytesAvailableToCaller , liTotalNumberOfBytes ;
2005-01-31 00:33:47 +03:00
if ( pGetDiskFreeSpaceExA ( mResolvedPath . get ( ) ,
& liFreeBytesAvailableToCaller ,
& liTotalNumberOfBytes ,
NULL ) )
2004-06-17 20:37:25 +04:00
{
* aDiskSpaceAvailable = liFreeBytesAvailableToCaller . QuadPart ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// use the old method of getting available disk space
char aDrive [ _MAX_DRIVE + 2 ] ;
_splitpath ( mResolvedPath . get ( ) , aDrive , NULL , NULL , NULL ) ;
strcat ( aDrive , " \\ " ) ;
DWORD dwSecPerClus , dwBytesPerSec , dwFreeClus , dwTotalClus ;
2005-01-31 00:33:47 +03:00
2004-06-17 20:37:25 +04:00
if ( GetDiskFreeSpace ( aDrive , & dwSecPerClus , & dwBytesPerSec , & dwFreeClus , & dwTotalClus ) )
1999-12-04 04:13:44 +03:00
{
2004-06-17 20:37:25 +04:00
__int64 bytes = dwFreeClus ;
bytes * = dwSecPerClus ;
bytes * = dwBytesPerSec ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* aDiskSpaceAvailable = bytes ;
return NS_OK ;
2002-02-07 17:46:10 +03:00
}
2005-01-31 00:33:47 +03:00
# endif
// WINCE FIX
* aDiskSpaceAvailable = 0 ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : GetParent ( nsIFile * * aParent )
{
NS_ENSURE_ARG_POINTER ( aParent ) ;
2002-04-27 09:33:09 +04:00
nsCAutoString parentPath ( mWorkingPath ) ;
1999-12-04 04:13:44 +03:00
2000-04-26 07:57:34 +04:00
// cannot use nsCString::RFindChar() due to 0x5c problem
2001-03-02 12:26:57 +03:00
PRInt32 offset = ( PRInt32 ) ( _mbsrchr ( ( const unsigned char * ) parentPath . get ( ) , ' \\ ' )
- ( const unsigned char * ) parentPath . get ( ) ) ;
2004-05-20 21:46:35 +04:00
// adding this offset check that was removed in bug 241708 fixes mail
// directories that aren't relative to/underneath the profile dir.
// e.g., on a different drive. Before you remove them, please make
// sure local mail directories that aren't underneath the profile dir work.
if ( offset < 0 )
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
2004-04-29 12:16:50 +04:00
if ( offset = = 1 & & parentPath [ 0 ] = = ' \\ ' ) {
aParent = nsnull ;
return NS_OK ;
}
if ( offset > 0 )
parentPath . Truncate ( offset ) ;
else
2004-06-17 04:13:25 +04:00
parentPath . AssignLiteral ( " \\ \\ . " ) ;
1999-12-04 04:13:44 +03:00
2000-01-25 00:28:28 +03:00
nsCOMPtr < nsILocalFile > localFile ;
2004-04-29 12:16:50 +04:00
nsresult rv = NS_NewNativeLocalFile ( parentPath , mFollowSymlinks , getter_AddRefs ( localFile ) ) ;
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
if ( NS_SUCCEEDED ( rv ) & & localFile )
{
2002-04-27 09:33:09 +04:00
return CallQueryInterface ( localFile , aParent ) ;
2000-01-25 00:28:28 +03:00
}
return rv ;
1999-12-04 04:13:44 +03:00
}
2000-01-25 00:28:28 +03:00
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : Exists ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
2004-06-17 20:37:25 +04:00
* _retval = PR_FALSE ;
2000-01-25 00:28:28 +03:00
2000-04-25 06:39:42 +04:00
MakeDirty ( ) ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
* _retval = NS_SUCCEEDED ( rv ) ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2004-07-30 03:25:32 +04:00
nsLocalFile : : IsWritable ( PRBool * aIsWritable )
1999-12-04 04:13:44 +03:00
{
2004-07-30 03:25:32 +04:00
//TODO: extend to support NTFS file permissions
// The read-only attribute on a FAT directory only means that it can't
// be deleted. It is still possible to modify the contents of the directory.
nsresult rv = IsDirectory ( aIsWritable ) ;
if ( NS_FAILED ( rv ) )
return rv ;
if ( * aIsWritable )
return NS_OK ;
// writable if the file doesn't have the readonly attribute
rv = HasFileAttribute ( FILE_ATTRIBUTE_READONLY , aIsWritable ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
2003-09-29 22:15:52 +04:00
return rv ;
2004-07-30 03:25:32 +04:00
* aIsWritable = ! * aIsWritable ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsReadable ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
* _retval = PR_TRUE ;
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsExecutable ( PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
nsresult rv ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// only files can be executables
PRBool isFile ;
rv = IsFile ( & isFile ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2004-06-17 20:37:25 +04:00
if ( ! isFile )
return NS_OK ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
//TODO: shouldn't we be checking mFollowSymlinks here?
1999-12-04 04:13:44 +03:00
PRBool symLink ;
rv = IsSymlink ( & symLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsCAutoString path ;
1999-12-04 04:13:44 +03:00
if ( symLink )
2002-04-27 09:33:09 +04:00
GetNativeTarget ( path ) ;
1999-12-04 04:13:44 +03:00
else
2002-04-27 09:33:09 +04:00
GetNativePath ( path ) ;
1999-12-04 04:13:44 +03:00
2005-02-12 02:13:38 +03:00
// kill trailing dots and spaces.
PRInt32 filePathLen = path . Length ( ) - 1 ;
while ( filePathLen > 0 & & ( path [ filePathLen ] = = ' ' | | path [ filePathLen ] = = ' . ' ) )
{
path . Truncate ( filePathLen - - ) ;
}
2001-05-23 10:03:59 +04:00
// Get extension.
2004-06-17 20:37:25 +04:00
char * ext = ( char * ) _mbsrchr ( ( unsigned char * ) path . BeginWriting ( ) , ' . ' ) ;
2001-05-23 10:03:59 +04:00
if ( ext ) {
// Convert extension to lower case.
2004-06-17 20:37:25 +04:00
for ( unsigned char * p = ( unsigned char * ) ext ; * p ; p + + )
* p = _mbctolower ( * p ) ;
2005-01-31 00:33:47 +03:00
2001-05-23 10:03:59 +04:00
// Search for any of the set of executable extensions.
2004-05-11 07:36:01 +04:00
const char * const executableExts [ ] = {
" .ad " ,
" .adp " ,
" .asp " ,
" .bas " ,
" .bat " ,
" .chm " ,
" .cmd " ,
" .com " ,
" .cpl " ,
" .crt " ,
" .exe " ,
" .hlp " ,
" .hta " ,
" .inf " ,
" .ins " ,
" .isp " ,
" .js " ,
" .jse " ,
" .lnk " ,
" .mdb " ,
" .mde " ,
" .msc " ,
" .msi " ,
" .msp " ,
" .mst " ,
" .pcd " ,
" .pif " ,
" .reg " ,
" .scr " ,
" .sct " ,
" .shb " ,
" .shs " ,
" .url " ,
" .vb " ,
" .vbe " ,
" .vbs " ,
" .vsd " ,
" .vss " ,
" .vst " ,
" .vsw " ,
" .ws " ,
" .wsc " ,
" .wsf " ,
" .wsh " ,
0 } ;
2001-05-23 10:03:59 +04:00
for ( int i = 0 ; executableExts [ i ] ; i + + ) {
if ( : : strcmp ( executableExts [ i ] , ext ) = = 0 ) {
// Found a match. Set result and quit.
* _retval = PR_TRUE ;
break ;
}
}
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsDirectory ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( _retval ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
2000-02-22 00:51:47 +03:00
* _retval = ( mFileInfo64 . type = = PR_FILE_DIRECTORY ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsFile ( PRBool * _retval )
{
2000-02-22 00:51:47 +03:00
NS_ENSURE_ARG ( _retval ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2000-02-22 00:51:47 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* _retval = ( mFileInfo64 . type = = PR_FILE_FILE ) ;
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsHidden ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
return HasFileAttribute ( FILE_ATTRIBUTE_HIDDEN , _retval ) ;
}
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
nsresult
nsLocalFile : : HasFileAttribute ( DWORD fileAttrib , PRBool * _retval )
{
NS_ENSURE_ARG ( _retval ) ;
2003-09-29 22:15:52 +04:00
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
1999-12-04 04:13:44 +03:00
if ( NS_FAILED ( rv ) )
return rv ;
2002-11-27 00:37:58 +03:00
2004-06-17 20:37:25 +04:00
// get the file attributes for the correct item depending on following symlinks
const char * filePath = mFollowSymlinks ? mResolvedPath . get ( ) : mWorkingPath . get ( ) ;
DWORD word = GetFileAttributes ( filePath ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
* _retval = ( ( word & fileAttrib ) ! = 0 ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsSymlink ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
NS_ENSURE_ARG ( _retval ) ;
1999-12-04 04:13:44 +03:00
2004-06-17 20:37:25 +04:00
// unless it is a valid shortcut path it's not a symlink
if ( ! IsShortcutPath ( mWorkingPath . get ( ) ) )
{
2003-08-25 22:28:10 +04:00
* _retval = PR_FALSE ;
2004-06-17 20:37:25 +04:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
2004-06-17 20:37:25 +04:00
// we need to know if this is a file or directory
nsresult rv = ResolveAndStat ( ) ;
if ( NS_FAILED ( rv ) )
return rv ;
// it's only a shortcut if it is a file
* _retval = ( mFileInfo64 . type = = PR_FILE_FILE ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
1999-12-04 04:13:44 +03:00
nsLocalFile : : IsSpecial ( PRBool * _retval )
{
2004-06-17 20:37:25 +04:00
return HasFileAttribute ( FILE_ATTRIBUTE_SYSTEM , _retval ) ;
1999-12-04 04:13:44 +03:00
}
NS_IMETHODIMP
nsLocalFile : : Equals ( nsIFile * inFile , PRBool * _retval )
{
NS_ENSURE_ARG ( inFile ) ;
NS_ENSURE_ARG ( _retval ) ;
2002-04-27 09:33:09 +04:00
nsCAutoString inFilePath ;
inFile - > GetNativePath ( inFilePath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
* _retval = inFilePath . Equals ( mWorkingPath ) ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
NS_IMETHODIMP
2000-01-29 02:53:59 +03:00
nsLocalFile : : Contains ( nsIFile * inFile , PRBool recur , PRBool * _retval )
1999-12-04 04:13:44 +03:00
{
2000-01-29 02:53:59 +03:00
* _retval = PR_FALSE ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
nsCAutoString myFilePath ;
if ( NS_FAILED ( GetNativeTarget ( myFilePath ) ) )
GetNativePath ( myFilePath ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
PRInt32 myFilePathLen = myFilePath . Length ( ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
nsCAutoString inFilePath ;
if ( NS_FAILED ( inFile - > GetNativeTarget ( inFilePath ) ) )
inFile - > GetNativePath ( inFilePath ) ;
2000-01-29 03:00:21 +03:00
2003-04-18 09:43:41 +04:00
if ( strnicmp ( myFilePath . get ( ) , inFilePath . get ( ) , myFilePathLen ) = = 0 )
1999-12-08 02:31:25 +03:00
{
2000-01-25 00:28:28 +03:00
// now make sure that the |inFile|'s path has a trailing
// separator.
1999-12-08 02:31:25 +03:00
2000-01-29 03:00:21 +03:00
if ( inFilePath [ myFilePathLen ] = = ' \\ ' )
1999-12-08 02:31:25 +03:00
{
2000-01-25 00:28:28 +03:00
* _retval = PR_TRUE ;
1999-12-08 02:31:25 +03:00
}
}
2000-01-25 00:28:28 +03:00
return NS_OK ;
1999-12-04 04:13:44 +03:00
}
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : GetNativeTarget ( nsACString & _retval )
2003-09-29 22:15:52 +04:00
{
2002-04-27 09:33:09 +04:00
_retval . Truncate ( ) ;
2003-09-29 22:15:52 +04:00
# if STRICT_FAKE_SYMLINKS
1999-12-04 04:13:44 +03:00
PRBool symLink ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
nsresult rv = IsSymlink ( & symLink ) ;
if ( NS_FAILED ( rv ) )
return rv ;
if ( ! symLink )
{
return NS_ERROR_FILE_INVALID_PATH ;
}
1999-12-08 02:31:25 +03:00
# endif
2004-06-17 20:37:25 +04:00
ResolveAndStat ( ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
_retval = mResolvedPath ;
1999-12-04 04:13:44 +03:00
return NS_OK ;
}
2000-07-13 03:31:31 +04:00
/* attribute PRBool followLinks; */
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-07-13 03:31:31 +04:00
nsLocalFile : : GetFollowLinks ( PRBool * aFollowLinks )
{
* aFollowLinks = mFollowSymlinks ;
return NS_OK ;
}
2003-09-29 22:15:52 +04:00
NS_IMETHODIMP
2000-07-13 03:31:31 +04:00
nsLocalFile : : SetFollowLinks ( PRBool aFollowLinks )
{
MakeDirty ( ) ;
mFollowSymlinks = aFollowLinks ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
NS_IMETHODIMP
nsLocalFile : : GetDirectoryEntries ( nsISimpleEnumerator * * entries )
{
nsresult rv ;
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
* entries = nsnull ;
2004-05-23 02:15:22 +04:00
if ( mWorkingPath . EqualsLiteral ( " \\ \\ . " ) ) {
2004-04-29 12:16:50 +04:00
nsDriveEnumerator * drives = new nsDriveEnumerator ;
if ( ! drives )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( drives ) ;
rv = drives - > Init ( ) ;
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( drives ) ;
return rv ;
}
* entries = drives ;
return NS_OK ;
}
1999-12-04 04:13:44 +03:00
PRBool isDir ;
rv = IsDirectory ( & isDir ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
return rv ;
if ( ! isDir )
return NS_ERROR_FILE_NOT_DIRECTORY ;
nsDirEnumerator * dirEnum = new nsDirEnumerator ( ) ;
if ( dirEnum = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( dirEnum ) ;
rv = dirEnum - > Init ( this ) ;
2003-09-29 22:15:52 +04:00
if ( NS_FAILED ( rv ) )
1999-12-04 04:13:44 +03:00
{
NS_RELEASE ( dirEnum ) ;
return rv ;
}
2003-09-29 22:15:52 +04:00
1999-12-04 04:13:44 +03:00
* entries = dirEnum ;
return NS_OK ;
}
2000-07-17 19:03:05 +04:00
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : GetPersistentDescriptor ( nsACString & aPersistentDescriptor )
2000-07-17 19:03:05 +04:00
{
2002-04-27 09:33:09 +04:00
return GetNativePath ( aPersistentDescriptor ) ;
2000-07-17 19:03:05 +04:00
}
NS_IMETHODIMP
2002-04-27 09:33:09 +04:00
nsLocalFile : : SetPersistentDescriptor ( const nsACString & aPersistentDescriptor )
2000-07-17 19:03:05 +04:00
{
2003-09-29 22:15:52 +04:00
return InitWithNativePath ( aPersistentDescriptor ) ;
2000-07-17 19:03:05 +04:00
}
2001-01-30 08:02:48 +03:00
NS_IMETHODIMP
nsLocalFile : : Reveal ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2004-06-02 12:19:42 +04:00
// make sure mResolvedPath is set
2004-06-17 20:37:25 +04:00
nsresult rv = ResolveAndStat ( ) ;
2004-06-02 12:19:42 +04:00
if ( NS_FAILED ( rv ) & & rv ! = NS_ERROR_FILE_NOT_FOUND )
return rv ;
2002-02-20 08:41:34 +03:00
2004-06-02 12:19:42 +04:00
// use the full path to explorer for security
nsCOMPtr < nsILocalFile > winDir ;
rv = GetSpecialSystemDirectory ( Win_WindowsDirectory , getter_AddRefs ( winDir ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsCAutoString explorerPath ;
rv = winDir - > GetNativePath ( explorerPath ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
explorerPath . Append ( " \\ explorer.exe " ) ;
// Always open a new window for files because Win2K doesn't appear to select
// the file if a window showing that folder was already open. If the resolved
// path is a directory then instead of opening the parent and selecting it,
// we open the directory itself.
nsCAutoString explorerParams ;
if ( mFileInfo64 . type ! = PR_FILE_DIRECTORY ) // valid because we ResolveAndStat above
explorerParams . Append ( " /n,/select, " ) ;
explorerParams . Append ( ' \" ' ) ;
explorerParams . Append ( mResolvedPath ) ;
explorerParams . Append ( ' \" ' ) ;
2005-01-31 00:33:47 +03:00
if ( : : ShellExecute ( NULL , " open " , explorerPath . get ( ) , explorerParams . get ( ) , NULL , SW_SHOWNORMAL ) < = ( HINSTANCE ) 32 )
2004-06-02 12:19:42 +04:00
return NS_ERROR_FAILURE ;
2005-01-31 00:33:47 +03:00
# endif
2004-06-02 12:19:42 +04:00
2002-02-20 08:41:34 +03:00
return NS_OK ;
2001-01-30 08:02:48 +03:00
}
NS_IMETHODIMP
nsLocalFile : : Launch ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2003-09-29 22:15:52 +04:00
const nsCString & path = mWorkingPath ;
2001-01-30 08:02:48 +03:00
2003-09-29 22:15:52 +04:00
// use the app registry name to launch a shell execute....
LONG r = ( LONG ) : : ShellExecute ( NULL , NULL , path . get ( ) , NULL , NULL , SW_SHOWNORMAL ) ;
// if the file has no association, we launch windows' "what do you want to do" dialog
if ( r = = SE_ERR_NOASSOC ) {
nsCAutoString shellArg ;
shellArg . Assign ( NS_LITERAL_CSTRING ( " shell32.dll,OpenAs_RunDLL " ) + path ) ;
r = ( LONG ) : : ShellExecute ( NULL , NULL , " RUNDLL32.EXE " , shellArg . get ( ) ,
NULL , SW_SHOWNORMAL ) ;
2003-09-27 18:37:16 +04:00
}
2003-09-29 22:15:52 +04:00
if ( r < 32 ) {
switch ( r ) {
case 0 :
case SE_ERR_OOM :
return NS_ERROR_OUT_OF_MEMORY ;
case ERROR_FILE_NOT_FOUND :
return NS_ERROR_FILE_NOT_FOUND ;
case ERROR_PATH_NOT_FOUND :
return NS_ERROR_FILE_UNRECOGNIZED_PATH ;
case ERROR_BAD_FORMAT :
return NS_ERROR_FILE_CORRUPTED ;
case SE_ERR_ACCESSDENIED :
return NS_ERROR_FILE_ACCESS_DENIED ;
case SE_ERR_ASSOCINCOMPLETE :
case SE_ERR_NOASSOC :
return NS_ERROR_UNEXPECTED ;
case SE_ERR_DDEBUSY :
case SE_ERR_DDEFAIL :
case SE_ERR_DDETIMEOUT :
return NS_ERROR_NOT_AVAILABLE ;
case SE_ERR_DLLNOTFOUND :
return NS_ERROR_FAILURE ;
case SE_ERR_SHARE :
return NS_ERROR_FILE_IS_LOCKED ;
default :
return NS_ERROR_FILE_EXECUTION_FAILED ;
}
}
2005-01-31 00:33:47 +03:00
# endif
2003-09-29 22:15:52 +04:00
return NS_OK ;
2001-01-30 08:02:48 +03:00
}
1999-12-04 04:13:44 +03:00
2003-09-29 22:15:52 +04:00
nsresult
2002-04-27 09:33:09 +04:00
NS_NewNativeLocalFile ( const nsACString & path , PRBool followLinks , nsILocalFile * * result )
2000-01-25 00:28:28 +03:00
{
nsLocalFile * file = new nsLocalFile ( ) ;
if ( file = = nsnull )
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF ( file ) ;
2000-07-13 03:31:31 +04:00
file - > SetFollowLinks ( followLinks ) ;
2003-09-29 22:15:52 +04:00
2002-04-27 09:33:09 +04:00
if ( ! path . IsEmpty ( ) ) {
nsresult rv = file - > InitWithNativePath ( path ) ;
2000-07-17 19:03:05 +04:00
if ( NS_FAILED ( rv ) ) {
NS_RELEASE ( file ) ;
return rv ;
}
2000-01-25 00:28:28 +03:00
}
2003-09-29 22:15:52 +04:00
2000-01-25 00:28:28 +03:00
* result = file ;
return NS_OK ;
}
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// UCS2 interface
//-----------------------------------------------------------------------------
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : InitWithPath ( const nsAString & filePath )
2002-02-01 00:55:01 +03:00
{
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( filePath , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return InitWithNativePath ( tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : Append ( const nsAString & node )
2002-02-01 00:55:01 +03:00
{
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( node , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return AppendNative ( tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : AppendRelativePath ( const nsAString & node )
2002-02-01 00:55:01 +03:00
{
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( node , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return AppendRelativeNativePath ( tmp ) ;
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : GetLeafName ( nsAString & aLeafName )
2002-02-01 00:55:01 +03:00
{
2002-04-27 09:33:09 +04:00
nsCAutoString tmp ;
nsresult rv = GetNativeLeafName ( tmp ) ;
2002-10-06 04:29:46 +04:00
if ( NS_SUCCEEDED ( rv ) )
rv = NS_CopyNativeToUnicode ( tmp , aLeafName ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : SetLeafName ( const nsAString & aLeafName )
2002-02-01 00:55:01 +03:00
{
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( aLeafName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return SetNativeLeafName ( tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : GetPath ( nsAString & _retval )
2002-02-01 00:55:01 +03:00
{
2002-10-06 04:29:46 +04:00
return NS_CopyNativeToUnicode ( mWorkingPath , _retval ) ;
2002-02-01 00:55:01 +03:00
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : CopyTo ( nsIFile * newParentDir , const nsAString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2005-01-04 22:31:31 +03:00
return CopyToNative ( newParentDir , EmptyCString ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return CopyToNative ( newParentDir , tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : CopyToFollowingLinks ( nsIFile * newParentDir , const nsAString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2005-01-04 22:31:31 +03:00
return CopyToFollowingLinksNative ( newParentDir , EmptyCString ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return CopyToFollowingLinksNative ( newParentDir , tmp ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : MoveTo ( nsIFile * newParentDir , const nsAString & newName )
2002-02-01 00:55:01 +03:00
{
2002-05-08 03:07:19 +04:00
if ( newName . IsEmpty ( ) )
2005-01-04 22:31:31 +03:00
return MoveToNative ( newParentDir , EmptyCString ( ) ) ;
2003-09-29 22:15:52 +04:00
2002-10-06 04:29:46 +04:00
nsCAutoString tmp ;
nsresult rv = NS_CopyUnicodeToNative ( newName , tmp ) ;
2002-02-01 00:55:01 +03:00
if ( NS_SUCCEEDED ( rv ) )
2002-04-27 09:33:09 +04:00
return MoveToNative ( newParentDir , tmp ) ;
2002-02-01 00:55:01 +03:00
return rv ;
}
2002-04-27 09:33:09 +04:00
nsresult
2002-05-08 03:07:19 +04:00
nsLocalFile : : GetTarget ( nsAString & _retval )
2002-02-01 00:55:01 +03:00
{
2002-04-27 09:33:09 +04:00
nsCAutoString tmp ;
nsresult rv = GetNativeTarget ( tmp ) ;
2002-10-06 04:29:46 +04:00
if ( NS_SUCCEEDED ( rv ) )
rv = NS_CopyNativeToUnicode ( tmp , _retval ) ;
2003-09-29 22:15:52 +04:00
2002-02-01 00:55:01 +03:00
return rv ;
}
2003-09-29 22:15:52 +04:00
nsresult
2002-05-08 03:07:19 +04:00
NS_NewLocalFile ( const nsAString & path , PRBool followLinks , nsILocalFile * * result )
2002-02-01 00:55:01 +03:00
{
2003-07-29 01:02:45 +04:00
nsCAutoString buf ;
nsresult rv = NS_CopyUnicodeToNative ( path , buf ) ;
if ( NS_FAILED ( rv ) ) {
* result = nsnull ;
return rv ;
}
return NS_NewNativeLocalFile ( buf , followLinks , result ) ;
2002-02-01 00:55:01 +03:00
}
2000-01-25 00:28:28 +03:00
2002-04-27 09:33:09 +04:00
//-----------------------------------------------------------------------------
// nsLocalFile <static members>
//-----------------------------------------------------------------------------
2000-01-25 00:28:28 +03:00
2002-04-27 09:33:09 +04:00
void
nsLocalFile : : GlobalInit ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-04-27 09:33:09 +04:00
nsresult rv = NS_CreateShortcutResolver ( ) ;
NS_ASSERTION ( NS_SUCCEEDED ( rv ) , " Shortcut resolver could not be created " ) ;
2005-01-31 00:33:47 +03:00
# endif
2002-04-27 09:33:09 +04:00
}
void
nsLocalFile : : GlobalShutdown ( )
{
2005-01-31 00:33:47 +03:00
# ifndef WINCE
2002-04-27 09:33:09 +04:00
NS_DestroyShortcutResolver ( ) ;
2005-01-31 00:33:47 +03:00
# endif
2002-04-27 09:33:09 +04:00
}
2004-04-29 12:16:50 +04:00
2004-05-13 08:08:34 +04:00
NS_IMPL_ISUPPORTS1 ( nsDriveEnumerator , nsISimpleEnumerator )
2004-04-29 12:16:50 +04:00
nsDriveEnumerator : : nsDriveEnumerator ( )
: mLetter ( 0 )
{
}
nsDriveEnumerator : : ~ nsDriveEnumerator ( )
{
}
nsresult nsDriveEnumerator : : Init ( )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
return NS_OK ;
# else
2004-04-29 12:16:50 +04:00
/* If the length passed to GetLogicalDriveStrings is smaller
* than the length of the string it would return , it returns
* the length required for the string . */
DWORD length = GetLogicalDriveStrings ( 0 , 0 ) ;
/* The string is null terminated */
mDrives . SetLength ( length + 1 ) ;
if ( ! GetLogicalDriveStrings ( length , mDrives . BeginWriting ( ) ) )
return NS_ERROR_FAILURE ;
mLetter = mDrives . get ( ) ;
return NS_OK ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
}
NS_IMETHODIMP nsDriveEnumerator : : HasMoreElements ( PRBool * aHasMore )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
* aHasMore = FALSE ;
# else
2004-04-29 12:16:50 +04:00
* aHasMore = * mLetter ! = ' \0 ' ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
return NS_OK ;
}
NS_IMETHODIMP nsDriveEnumerator : : GetNext ( nsISupports * * aNext )
{
2005-01-31 00:33:47 +03:00
# ifdef WINCE
nsILocalFile * file ;
nsresult rv = NS_NewNativeLocalFile ( nsDependentCString ( " \\ " ) , PR_FALSE , & file ) ;
* aNext = file ;
# else
2004-04-29 12:16:50 +04:00
/* GetLogicalDrives stored in mLetter is a concatenation
* of null terminated strings , followed by a null terminator . */
if ( ! * mLetter ) {
* aNext = nsnull ;
return NS_OK ;
}
const char * drive = mLetter ;
mLetter + = strlen ( drive ) + 1 ;
nsILocalFile * file ;
nsresult rv =
NS_NewNativeLocalFile ( nsDependentCString ( drive ) , PR_FALSE , & file ) ;
* aNext = file ;
2005-01-31 00:33:47 +03:00
# endif
2004-04-29 12:16:50 +04:00
return rv ;
}