summaryrefslogtreecommitdiff
path: root/tools/source/fsys
diff options
context:
space:
mode:
Diffstat (limited to 'tools/source/fsys')
-rw-r--r--tools/source/fsys/comdep.cxx47
-rw-r--r--tools/source/fsys/comdep.hxx159
-rw-r--r--tools/source/fsys/dirent.cxx3197
-rw-r--r--tools/source/fsys/filecopy.cxx489
-rw-r--r--tools/source/fsys/fstat.cxx422
-rw-r--r--tools/source/fsys/makefile.mk67
-rw-r--r--tools/source/fsys/os2.cxx885
-rw-r--r--tools/source/fsys/os2.hxx94
-rw-r--r--tools/source/fsys/tdir.cxx769
-rw-r--r--tools/source/fsys/tempfile.cxx303
-rw-r--r--tools/source/fsys/unx.cxx663
-rw-r--r--tools/source/fsys/unx.hxx98
-rw-r--r--tools/source/fsys/urlobj.cxx5575
-rw-r--r--tools/source/fsys/wldcrd.cxx146
-rw-r--r--tools/source/fsys/wntmsc.cxx1083
-rw-r--r--tools/source/fsys/wntmsc.hxx105
16 files changed, 14102 insertions, 0 deletions
diff --git a/tools/source/fsys/comdep.cxx b/tools/source/fsys/comdep.cxx
new file mode 100644
index 000000000000..2278e8dd1357
--- /dev/null
+++ b/tools/source/fsys/comdep.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#include "comdep.hxx"
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include <tools/fsys.hxx>
+
+DBG_NAMEEX( DirEntry )
+
+#if defined UNX
+#include "unx.cxx"
+#elif defined WNT
+#include "wntmsc.cxx"
+#elif defined OS2
+#include "os2.cxx"
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/comdep.hxx b/tools/source/fsys/comdep.hxx
new file mode 100644
index 000000000000..286557167ae7
--- /dev/null
+++ b/tools/source/fsys/comdep.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _COMDEP_HXX
+#define _COMDEP_HXX
+
+#include <tools/fsys.hxx>
+
+#define ACCESSDELIM(e) ( (e == FSYS_STYLE_MAC) ? ":" : \
+ ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
+ e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
+ ? "\\" : "/" )
+#define ACCESSDELIM_C(e)(char)\
+ ( (e == FSYS_STYLE_MAC) ? ':' : \
+ ( ( e == FSYS_STYLE_VFAT || e == FSYS_STYLE_HPFS || \
+ e == FSYS_STYLE_FAT ) || e == FSYS_STYLE_NTFS ) \
+ ? '\\' : '/' )
+#define SEARCHDELIM(e) ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ":" \
+ : ";" )
+#define SEARCHDELIM_C(e)(char)\
+ ( (e == FSYS_STYLE_SYSV || e == FSYS_STYLE_BSD) ? ':' \
+ : ';' )
+#define ACTPARENT(e) ( (e == FSYS_STYLE_MAC) ? ":" : ".." )
+#define ACTCURRENT(e) ( (e == FSYS_STYLE_MAC) ? "" : "." )
+
+#if defined UNX
+#include "unx.hxx"
+#elif defined WNT
+#include "wntmsc.hxx"
+#elif defined OS2
+#include "os2.hxx"
+#endif
+
+//--------------------------------------------------------------------
+
+#ifndef LINUX
+DIR *opendir( const char* pPfad );
+dirent *readdir( DIR *pDir );
+int closedir( DIR *pDir );
+char *volumeid( const char* pPfad );
+#endif
+
+//--------------------------------------------------------------------
+
+struct DirReader_Impl
+{
+ Dir* pDir;
+ DIR* pDosDir;
+ dirent* pDosEntry;
+ DirEntry* pParent;
+ String aPath;
+ ByteString aBypass;
+ BOOL bReady;
+ BOOL bInUse;
+
+ DirReader_Impl( Dir &rDir )
+ : pDir( &rDir ),
+ pDosEntry( 0 ),
+ pParent( 0 ),
+ aPath( GUI2FSYS(rDir.GetFull()) ),
+ bReady ( FALSE ),
+ bInUse( FALSE )
+ {
+#ifndef BOOTSTRAP
+ // Redirection
+ FSysRedirector::DoRedirect( aPath );
+#endif
+
+ // nur den String der Memer-Var nehmen!
+
+#if defined(UNX) || defined(OS2) //for further exlpanation see DirReader_Impl::Read() in unx.cxx
+ pDosDir = NULL;
+#else
+ aBypass = ByteString(aPath, osl_getThreadTextEncoding());
+ pDosDir = opendir( (char*) aBypass.GetBuffer() );
+#endif
+
+ // Parent f"ur die neuen DirEntries ermitteln
+ pParent = pDir->GetFlag() == FSYS_FLAG_NORMAL ||
+ pDir->GetFlag() == FSYS_FLAG_ABSROOT
+ ? pDir
+ : pDir->GetParent();
+
+ }
+
+ ~DirReader_Impl()
+ { if( pDosDir ) closedir( pDosDir ); }
+
+ // die folgenden sind systemabh"angig implementiert
+ USHORT Init(); // initialisiert, liest ggf. devices
+ USHORT Read(); // liest 1 Eintrag, F2ugt ein falls ok
+};
+
+//--------------------------------------------------------------------
+
+struct FileCopier_Impl
+{
+ FSysAction nActions; // was zu tun ist (Copy/Move/recur)
+ Link aErrorLink; // bei Fehlern zu rufen
+ ErrCode eErr; // aktueller Fehlercode im Error-Handler
+ const DirEntry* pErrSource; // fuer Error-Handler falls Source-Fehler
+ const DirEntry* pErrTarget; // fuer Error-Handler falls Target-Fehler
+
+ FileCopier_Impl()
+ : nActions( 0 ), eErr( 0 ),
+ pErrSource( 0 ), pErrTarget( 0 )
+ {}
+ FileCopier_Impl( const FileCopier_Impl &rOrig )
+ : nActions( rOrig.nActions ), eErr( 0 ),
+ pErrSource( 0 ), pErrTarget( 0 )
+ {}
+
+ FileCopier_Impl& operator=( const FileCopier_Impl &rOrig )
+ {
+ nActions = rOrig.nActions;
+ eErr = 0; pErrSource = 0; pErrTarget = 0;
+ return *this;
+ }
+};
+
+//--------------------------------------------------------------------
+
+#if defined WNT || defined OS2
+BOOL IsRedirectable_Impl( const ByteString &rPath );
+#else
+#define IsRedirectable_Impl( rPath ) TRUE
+#endif
+
+//--------------------------------------------------------------------
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/dirent.cxx b/tools/source/fsys/dirent.cxx
new file mode 100644
index 000000000000..debb0fa44ad5
--- /dev/null
+++ b/tools/source/fsys/dirent.cxx
@@ -0,0 +1,3197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+
+#if !defined UNX
+#include <io.h>
+#include <process.h>
+#endif
+
+#if defined(UNX) || defined(OS2)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include "comdep.hxx"
+#include <tools/fsys.hxx>
+#define _TOOLS_HXX
+#include <tools/urlobj.hxx>
+
+#ifdef UNX
+#define _MAX_PATH 260
+#endif
+#include <tools/stream.hxx>
+
+#include <osl/mutex.hxx>
+
+#include <osl/file.hxx>
+#include <rtl/instance.hxx>
+
+
+using namespace osl;
+using namespace rtl;
+
+int ApiRet2ToSolarError_Impl( int nApiRet );
+
+//--------------------------------------------------------------------
+int Sys2SolarError_Impl( int nSysErr )
+{
+ switch ( nSysErr )
+ {
+#ifdef WNT
+ case NO_ERROR: return ERRCODE_NONE;
+ case ERROR_INVALID_FUNCTION: return ERRCODE_IO_GENERAL;
+ case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_INVALID_HANDLE: return ERRCODE_IO_GENERAL;
+ case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
+ case ERROR_INVALID_BLOCK: return ERRCODE_IO_GENERAL;
+// case ERROR_BAD_ENVIRONMENT: return ERRCODE_IO_;
+ case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_INVALID_ACCESS: return ERRCODE_IO_ACCESSDENIED;
+// case ERROR_INVALID_DATA: return ERRCODE_IO_;
+ case ERROR_INVALID_DRIVE: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_CURRENTDIR;
+ case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_NOTSAMEDEVICE;
+// case ERROR_NO_MORE_FILES: return ERRCODE_IO_;
+ case ERROR_WRITE_PROTECT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_READY: return ERRCODE_IO_DEVICENOTREADY;
+ case ERROR_BAD_COMMAND: return ERRCODE_IO_GENERAL;
+ case ERROR_CRC: return ERRCODE_IO_BADCRC;
+ case ERROR_BAD_LENGTH: return ERRCODE_IO_INVALIDLENGTH;
+ case ERROR_SEEK: return ERRCODE_IO_CANTSEEK;
+ case ERROR_NOT_DOS_DISK: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_SECTOR_NOT_FOUND: return ERRCODE_IO_GENERAL;
+ case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
+ case ERROR_GEN_FAILURE: return ERRCODE_IO_GENERAL;
+ case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_WRONG_DISK: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
+#else
+ case 0: return ERRCODE_NONE;
+ case ENOENT: return ERRCODE_IO_NOTEXISTS;
+ case EACCES: return ERRCODE_IO_ACCESSDENIED;
+ case EEXIST: return ERRCODE_IO_ALREADYEXISTS;
+ case EINVAL: return ERRCODE_IO_INVALIDPARAMETER;
+ case EMFILE: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ENOMEM: return ERRCODE_IO_OUTOFMEMORY;
+ case ENOSPC: return ERRCODE_IO_OUTOFSPACE;
+#endif
+ }
+
+ DBG_TRACE1( "FSys: unknown system error %d occured", nSysErr );
+ return FSYS_ERR_UNKNOWN;
+}
+
+//--------------------------------------------------------------------
+
+#ifndef BOOTSTRAP
+
+FSysRedirector* FSysRedirector::_pRedirector = 0;
+BOOL FSysRedirector::_bEnabled = TRUE;
+#ifdef UNX
+BOOL bInRedirection = TRUE;
+#else
+BOOL bInRedirection = FALSE;
+#endif
+static osl::Mutex* pRedirectMutex = 0;
+
+//------------------------------------------------------------------------
+void FSysRedirector::Register( FSysRedirector *pRedirector )
+{
+ if ( pRedirector )
+ pRedirectMutex = new osl::Mutex;
+ else
+ DELETEZ( pRedirectMutex );
+ _pRedirector = pRedirector;
+}
+
+//------------------------------------------------------------------------
+
+void FSysRedirector::DoRedirect( String &rPath )
+{
+ String aURL(rPath);
+
+ // if redirection is disabled or not even registered do nothing
+ if ( !_bEnabled || !pRedirectMutex )
+ return;
+
+ // redirect only removable or remote volumes
+ if ( !IsRedirectable_Impl( ByteString( aURL, osl_getThreadTextEncoding() ) ) )
+ return;
+
+ // Redirection is acessible only by one thread per time
+ // dont move the guard behind the bInRedirection check!!!
+ // think of nested calls (when called from callback)
+ osl::MutexGuard aGuard( pRedirectMutex );
+
+ // if already in redirection, dont redirect
+ if ( bInRedirection )
+ return;
+
+ // dont redirect on nested calls
+ bInRedirection = TRUE;
+
+ // convert to URL
+#ifndef UNX
+ for ( sal_Unicode *p = (sal_Unicode*)aURL.GetBuffer(); *p; ++p )
+ if ( '\\' == *p ) *p = '/';
+ else if ( ':' == *p ) *p = '|';
+#endif
+
+ aURL.Insert( String("file:///", osl_getThreadTextEncoding()), 0 );
+
+ // do redirection
+ Redirector();
+
+ bInRedirection = FALSE;
+ return;
+}
+
+//------------------------------------------------------------------------
+
+FSysRedirector* FSysRedirector::Redirector()
+{
+ if ( !_pRedirector )
+ Register( new FSysRedirector );
+ return _pRedirector;
+}
+
+#endif // BOOTSTRAP
+
+//--------------------------------------------------------------------
+
+class DirEntryStack: public List
+{
+public:
+ DirEntryStack() {};
+ ~DirEntryStack();
+
+ inline void Push( DirEntry *pEntry );
+ inline DirEntry* Pop();
+ inline DirEntry* Top();
+ inline DirEntry* Bottom();
+};
+
+inline void DirEntryStack::Push( DirEntry *pEntry )
+{
+ List::Insert( pEntry, LIST_APPEND );
+}
+
+inline DirEntry* DirEntryStack::Pop()
+{
+ return (DirEntry*) List::Remove( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Top()
+{
+ return (DirEntry*) List::GetObject( Count() - 1 );
+}
+
+inline DirEntry* DirEntryStack::Bottom()
+{
+ return (DirEntry*) List::GetObject( 0 );
+}
+
+//--------------------------------------------------------------------
+
+DBG_NAME( DirEntry );
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntryStack()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 04.07.91
+|*
+*************************************************************************/
+
+DirEntryStack::~DirEntryStack()
+{
+ while ( Count() )
+ delete Pop();
+}
+
+/*************************************************************************
+|*
+|* ImpCheckDirEntry()
+|*
+|* Beschreibung Pruefung eines DirEntry fuer DBG_UTIL
+|* Parameter void* p Zeiger auf den DirEntry
+|* Return-Wert char* Fehlermeldungs-TExtension oder NULL
+|* Ersterstellung MI 16.07.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+#ifdef DBG_UTIL
+const char* ImpCheckDirEntry( const void* p )
+{
+ DirEntry* p0 = (DirEntry*)p;
+
+ if ( p0->pParent )
+ DBG_CHKOBJ( p0->pParent, DirEntry, ImpCheckDirEntry );
+
+ return NULL;
+}
+#endif
+
+/*************************************************************************
+|*
+|* ImplCutPath()
+|*
+|* Beschreibung Fuegt ... ein, damit maximal nMaxChars lang
+|* Ersterstellung MI 06.04.94
+|* Letzte Aenderung DV 24.06.96
+|*
+*************************************************************************/
+
+ByteString ImplCutPath( const ByteString& rStr, USHORT nMax, char cAccDel )
+{
+ USHORT nMaxPathLen = nMax;
+ ByteString aCutPath( rStr );
+ BOOL bInsertPrefix = FALSE;
+ USHORT nBegin = aCutPath.Search( cAccDel );
+
+ if( nBegin == STRING_NOTFOUND )
+ nBegin = 0;
+ else
+ nMaxPathLen += 2; // fuer Prefix <Laufwerk>:
+
+ while( aCutPath.Len() > nMaxPathLen )
+ {
+ USHORT nEnd = aCutPath.Search( cAccDel, nBegin + 1 );
+ USHORT nCount;
+
+ if ( nEnd != STRING_NOTFOUND )
+ {
+ nCount = nEnd - nBegin;
+ aCutPath.Erase( nBegin, nCount );
+ bInsertPrefix = TRUE;
+ }
+ else
+ break;
+ }
+
+ if ( aCutPath.Len() > nMaxPathLen )
+ {
+ for ( USHORT n = nMaxPathLen; n > nMaxPathLen/2; --n )
+ if ( !ByteString(aCutPath.GetChar(n)).IsAlphaNumericAscii() )
+ {
+ aCutPath.Erase( n );
+ aCutPath += "...";
+ break;
+ }
+ }
+
+ if ( bInsertPrefix )
+ {
+ ByteString aIns( cAccDel );
+ aIns += "...";
+ aCutPath.Insert( aIns, nBegin );
+ }
+
+ return aCutPath;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseOs2Name()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 23.06.95
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseOs2Name( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ String aPfad( rPfad, osl_getThreadTextEncoding() );
+ DirEntryStack aStack;
+
+ do
+ {
+ // den Namen vor dem ersten "\\" abspalten,
+ // falls '\\' am Anfang, ist der Name '\\',
+ // der Rest immer ohne die fuehrenden '\\'.
+ // ein ":" trennt ebenfalls, gehoert aber zum Namen
+ // den ersten '\\', '/' oder ':' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && //?O
+ aPfad.GetChar(nPos) != '\\' && aPfad.GetChar(nPos) != '/' && //?O
+ aPfad.GetChar(nPos) != ':'; //?O
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name ein UNC Pathname?
+ if ( nPos == 0 && aPfad.Len() > 1 &&
+ ( ( aPfad.GetChar(0) == '\\' && aPfad.GetChar(1) == '\\' ) ||
+ ( aPfad.GetChar(0) == '/' && aPfad.GetChar(1) == '/' ) ) )
+ {
+ for ( nPos = 2; aPfad.Len() > nPos; ++nPos )
+ if ( aPfad.GetChar(nPos) == '\\' || aPfad.GetChar(nPos) == '/' )
+ break;
+ aName = ByteString( aPfad.Copy( 2, nPos-2 ), osl_getThreadTextEncoding() );
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ // ist der Name die Root des aktuellen Drives?
+ else if ( nPos == 0 && aPfad.Len() > 0 &&
+ ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // ist der Name ein Drive?
+ if ( nPos < aPfad.Len() && aPfad.GetChar(nPos) == ':' )
+ {
+ aName = ByteString( aPfad.Copy( 0, nPos + 1 ), osl_getThreadTextEncoding() );
+
+ // ist der Name die Root des Drives
+ if ( (nPos + 1) < aPfad.Len() &&
+ ( aPfad.GetChar(nPos+1) == '\\' || aPfad.GetChar(nPos+1) == '/' ) )
+ {
+ // schon was auf dem Stack?
+ // oder Novell-Format? (not supported wegen URLs)
+ if ( aStack.Count() || aName.Len() > 2 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ // Root-Directory des Drive
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_ABSROOT, eStyle ) );
+ }
+ else
+ {
+ // liegt ein anderes Drive auf dem Stack?
+ if ( aStack.Count() &&
+ COMPARE_EQUAL != aStack.Bottom()->aName.CompareIgnoreCaseToAscii(aName) )
+ aStack.Clear();
+
+ // liegt jetzt nichts mehr auf dem Stack?
+ if ( !aStack.Count() )
+ aStack.Push( new DirEntry( aName, FSYS_FLAG_RELROOT, eStyle ) );
+ }
+ }
+
+ // es ist kein Drive
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = ByteString( aPfad.Copy( 0, nPos ), osl_getThreadTextEncoding() );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_RELROOT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( FSYS_FLAG_PARENT ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ // die hat keine Parent-Directory
+ aName = rPfad;
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+
+ else
+ {
+ if ( eStyle == FSYS_STYLE_FAT )
+ {
+ // ist der Name grundsaetzlich ungueltig?
+ int nPunkte = 0;
+ const char *pChar;
+ for ( pChar = aName.GetBuffer();
+ nPunkte < 2 && *pChar != 0;
+ pChar++ )
+ {
+ if ( *pChar == ';' )
+ nPunkte = 0;
+ else
+ nPunkte += ( *pChar == '.' ) ? 1 : 0;
+ }
+ if ( nPunkte > 1 )
+ {
+ aName = rPfad;
+ return FSYS_ERR_MISPLACEDCHAR;
+ }
+ }
+
+ // normalen Entries kommen auf den Stack
+ DirEntry *pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '\\' || aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ ULONG nErr = ERRCODE_NONE;
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ nErr = aStack.Top()->nError;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent; // Zeiger auf den Member pParent setzen
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+
+ // Zeiger auf den Member pParent des eigenen Parent setzen
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ // wird damit ein Volume beschrieben?
+ if ( !pParent && eFlag == FSYS_FLAG_RELROOT && aName.Len() )
+ eFlag = FSYS_FLAG_VOLUME;
+
+ // bei gesetztem ErrorCode den Namen komplett "ubernehmen
+ if ( nErr )
+ aName = rPfad;
+ return nErr;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.08.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseName( const ByteString& rbInitName,
+ FSysPathStyle eStyle )
+{
+ String rInitName( rbInitName, osl_getThreadTextEncoding() );
+ if ( eStyle == FSYS_STYLE_HOST )
+ eStyle = DEFSTYLE;
+
+ // KI-Division of FSys
+ if ( eStyle == FSYS_STYLE_DETECT )
+ {
+ sal_Unicode cFirst = rInitName.GetChar(0);
+ if ( rInitName.Len() == 2 && rInitName.GetChar(1) == ':' &&
+ ((cFirst >= 'A' && cFirst <= 'Z') ||
+ (cFirst >= 'a' && cFirst <= 'z')))
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Len() > 2 && rInitName.GetChar(1) == ':' )
+ {
+ if ( rInitName.Search( ':', 2 ) == STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else
+ eStyle = FSYS_STYLE_MAC;
+ }
+ else if ( rInitName.Search( '/' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_BSD;
+ else if ( rInitName.Search( '\\' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_HPFS;
+ else if ( rInitName.Search( ':' ) != STRING_NOTFOUND )
+ eStyle = FSYS_STYLE_MAC;
+ else
+ eStyle = FSYS_STYLE_HPFS;
+ }
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ return ImpParseOs2Name( rbInitName, eStyle );
+
+ case FSYS_STYLE_BSD:
+ case FSYS_STYLE_SYSV:
+ return ImpParseUnixName( rbInitName, eStyle );
+
+ case FSYS_STYLE_MAC:
+ return FSYS_ERR_OK;
+
+ default:
+ return FSYS_ERR_UNKNOWN;
+ }
+}
+
+/*************************************************************************
+|*
+|* GetStyle()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 15.11.91
+|* Letzte Aenderung MI 15.11.91
+|*
+*************************************************************************/
+
+static FSysPathStyle GetStyle( FSysPathStyle eStyle )
+{
+ if ( eStyle == FSYS_STYLE_HOST || eStyle == FSYS_STYLE_DETECT )
+ return DEFSTYLE;
+ else
+ return eStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpTrim()
+|*
+|* Beschreibung bringt den Namen auf Betriebssystem-Norm
+|* z.B. 8.3 lower beim MS-DOS Formatter
+|* wirkt nicht rekursiv
+|* Ersterstellung MI 12.08.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+void DirEntry::ImpTrim( FSysPathStyle eStyle )
+{
+ // Wildcards werden nicht geclipt
+ if ( ( aName.Search( '*' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( '?' ) != STRING_NOTFOUND ) ||
+ ( aName.Search( ';' ) != STRING_NOTFOUND ) )
+ return;
+
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ {
+ USHORT nPunktPos = aName.Search( '.' );
+ if ( nPunktPos == STRING_NOTFOUND )
+ {
+ if ( aName.Len() > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8 );
+ }
+ }
+ else
+ {
+ if ( nPunktPos > 8 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 8, nPunktPos - 8 );
+ nPunktPos = 8;
+ }
+ if ( aName.Len() > nPunktPos + 3 )
+ {
+ if ( aName.Len() - nPunktPos > 4 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( nPunktPos + 4 );
+ }
+ }
+ }
+ aName.ToLowerAscii();
+ break;
+ }
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ if ( aName.Len() > 254 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 254 );
+ }
+
+ if ( eStyle == FSYS_STYLE_HPFS &&
+ ( eFlag == FSYS_FLAG_ABSROOT || eFlag == FSYS_FLAG_RELROOT ) )
+ aName.ToUpperAscii();
+ break;
+
+ case FSYS_STYLE_SYSV:
+ if ( aName.Len() > 14 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 14 );
+ }
+ break;
+
+ case FSYS_STYLE_BSD:
+ if ( aName.Len() > 250 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 250 );
+ }
+ break;
+
+ case FSYS_STYLE_MAC:
+ if ( eFlag & ( FSYS_FLAG_ABSROOT | FSYS_FLAG_VOLUME ) )
+ {
+ if ( aName.Len() > 27 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 27 );
+ }
+ }
+ else
+ {
+ if ( aName.Len() > 31 )
+ {
+ nError = ERRCODE_IO_MISPLACEDCHAR|ERRCODE_WARNING_MASK;
+ aName.Erase( 31 );
+ }
+ }
+ break;
+
+ default:
+ /* kann nicht sein */;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rName, DirEntryFlag eDirFlag,
+ FSysPathStyle eStyle ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( 0 ),
+#endif
+ aName( rName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+ eFlag = eDirFlag;
+ nError = FSYS_ERR_OK;
+
+ ImpTrim( eStyle );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const DirEntry& rOrig ) :
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pStat( rOrig.pStat ? new FileStat(*rOrig.pStat) : 0 ),
+#endif
+ aName( rOrig.aName )
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = rOrig.eFlag;
+ nError = rOrig.nError;
+
+ if ( rOrig.pParent )
+ {
+ pParent = new DirEntry( *rOrig.pParent );
+ }
+ else
+ {
+ pParent = NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( const String& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len())
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName(rInitName, osl_getThreadTextEncoding());
+ if( eStyle == FSYS_STYLE_URL || aTmpName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif // BOOTSTRAP
+ }
+ else
+ {
+ ::rtl::OUString aTmp;
+ ::rtl::OUString aOInitName;
+ if ( FileBase::getFileURLFromSystemPath( OUString( rInitName ), aTmp ) == FileBase::E_None )
+ {
+ aOInitName = OUString( rInitName );
+ aTmpName = ByteString( String(aOInitName), osl_getThreadTextEncoding() );
+ }
+
+#ifdef DBG_UTIL
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ aTmpName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += aTmpName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+ }
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************/
+
+DirEntry::DirEntry( const ByteString& rInitName, FSysPathStyle eStyle )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ pParent = NULL;
+
+ // schnelle Loesung fuer Leerstring
+ if ( !rInitName.Len() )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ nError = FSYS_ERR_OK;
+ return;
+ }
+
+ ByteString aTmpName( rInitName );
+ if( eStyle == FSYS_STYLE_URL || rInitName.CompareIgnoreCaseToAscii("file:",5 ) == COMPARE_EQUAL )
+ {
+#ifndef BOOTSTRAP
+ DBG_WARNING( "File URLs are not permitted but accepted" );
+ aTmpName = ByteString(String(INetURLObject( rInitName ).PathToFileName()), osl_getThreadTextEncoding());
+ eStyle = FSYS_STYLE_HOST;
+#endif
+ }
+#ifdef DBG_UTIL
+ else
+ // ASF nur bei Default eStyle, nicht z.B. aus MakeShortName()
+ if( eStyle == FSYS_STYLE_HOST &&
+ rInitName.Search( "://" ) != STRING_NOTFOUND )
+ {
+ ByteString aErr = "DirEntries akzeptieren nur File URLS: ";
+ aErr += rInitName;
+ DBG_WARNING( aErr.GetBuffer() );
+ }
+#endif
+
+ nError = ImpParseName( aTmpName, eStyle );
+
+ if ( nError != FSYS_ERR_OK )
+ eFlag = FSYS_FLAG_INVALID;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::DirEntry( DirEntryFlag eDirFlag )
+#ifdef FEAT_FSYS_DOUBLESPEED
+ : pStat( 0 )
+#endif
+{
+ DBG_CTOR( DirEntry, ImpCheckDirEntry );
+
+ eFlag = eDirFlag;
+ nError = ( eFlag == FSYS_FLAG_INVALID ) ? FSYS_ERR_UNKNOWN : FSYS_ERR_OK;
+ pParent = NULL;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::~DirEntry()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry::~DirEntry()
+{
+ DBG_DTOR( DirEntry, ImpCheckDirEntry );
+
+ delete pParent;
+#ifdef FEAT_FSYS_DOUBLESPEED
+ delete pStat;
+#endif
+
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr() const
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+const DirEntry* DirEntry::ImpGetTopPtr() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetTopPtr()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ while ( pTemp->pParent )
+ pTemp = pTemp->pParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpGetPreTopPtr()
+|*
+|* Beschreibung liefert einen Pointer auf den vorletzten Entry
+|* Ersterstellung MI 01.11.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpGetPreTopPtr()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = this;
+ if ( pTemp->pParent )
+ {
+ while ( pTemp->pParent->pParent )
+ pTemp = pTemp->pParent;
+ }
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpChangeParent()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+DirEntry* DirEntry::ImpChangeParent( DirEntry* pNewParent, BOOL bNormalize )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry *pTemp = pParent;
+ if ( bNormalize && pNewParent &&
+ pNewParent->eFlag == FSYS_FLAG_RELROOT && !pNewParent->aName.Len() )
+ {
+ pParent = 0;
+ delete pNewParent;
+ }
+ else
+ pParent = pNewParent;
+
+ return pTemp;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Exists()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 24.09.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::Exists( FSysAccess nAccess ) const
+{
+#ifndef BOOTSTRAP
+ static osl::Mutex aLocalMutex;
+ osl::MutexGuard aGuard( aLocalMutex );
+#endif
+ if ( !IsValid() )
+ return FALSE;
+
+#if defined WNT || defined OS2
+ // spezielle Filenamen sind vom System da
+ if ( ( aName.CompareIgnoreCaseToAscii("CLOCK$") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("CON") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("AUX") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("COM4") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT1") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT2") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("LPT3") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("NUL") == COMPARE_EQUAL ||
+ aName.CompareIgnoreCaseToAscii("PRN") == COMPARE_EQUAL ) )
+ return TRUE;
+#endif
+
+ FSysFailOnErrorImpl();
+ DirEntryKind eKind = FileStat( *this, nAccess ).GetKind();
+ if ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) )
+ {
+ return TRUE;
+ }
+
+#if defined WNT || defined OS2
+ if ( 0 != ( eKind & FSYS_KIND_DEV ) )
+ {
+ return DRIVE_EXISTS( ImpGetTopPtr()->aName.GetChar(0) );
+ }
+#endif
+
+ return 0 != ( eKind & ( FSYS_KIND_FILE | FSYS_KIND_DIR ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::First()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 15.01.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::First()
+{
+ FSysFailOnErrorImpl();
+
+ String aUniPathName( GetPath().GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aUniPathName );
+ ByteString aPathName(aUniPathName, osl_getThreadTextEncoding());
+#else
+ ByteString aPathName(aUniPathName, gsl_getSystemTextEncoding());
+#endif
+ aPathName = GUI2FSYS( aPathName );
+
+ DIR *pDir = opendir( (char*) aPathName.GetBuffer() );
+ if ( pDir )
+ {
+#ifndef BOOTSTRAP
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), osl_getThreadTextEncoding()) );
+#else
+ WildCard aWildeKarte( String(CMP_LOWER( aName ), gsl_getSystemTextEncoding()) );
+#endif
+ for ( dirent* pEntry = readdir( pDir );
+ pEntry;
+ pEntry = readdir( pDir ) )
+ {
+ ByteString aFound( FSYS2GUI( ByteString( pEntry->d_name ) ) );
+ if ( aWildeKarte.Matches( String(CMP_LOWER( aFound ), osl_getThreadTextEncoding())))
+ {
+ aName = aFound;
+ closedir( pDir );
+ return TRUE;
+ }
+ }
+ closedir( pDir );
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetFull()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetFull( FSysPathStyle eStyle, BOOL bWithDelimiter,
+ USHORT nMaxChars ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+ if ( pParent )
+ {
+ if ( ( pParent->eFlag == FSYS_FLAG_ABSROOT ||
+ pParent->eFlag == FSYS_FLAG_RELROOT ||
+ pParent->eFlag == FSYS_FLAG_VOLUME ) )
+ {
+ aRet = ByteString(pParent->GetName( eStyle ), osl_getThreadTextEncoding());
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ else
+ {
+ aRet = ByteString(pParent->GetFull( eStyle ), osl_getThreadTextEncoding());
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+ }
+ else
+ {
+ aRet = ByteString(GetName( eStyle ), osl_getThreadTextEncoding());
+ }
+
+ if ( ( eStyle == FSYS_STYLE_MAC ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_VOLUME ) &&
+ ( ImpGetTopPtr()->eFlag != FSYS_FLAG_ABSROOT ) &&
+ ( aRet.GetChar(0) != ':' ) )
+ aRet.Insert( ACCESSDELIM_C(eStyle), 0 );
+
+ //! Hack
+ if ( bWithDelimiter )
+ if ( aRet.GetChar( aRet.Len()-1 ) != ACCESSDELIM_C(eStyle) )
+ aRet += ACCESSDELIM_C(eStyle);
+
+ //! noch ein Hack
+ if ( nMaxChars < STRING_MAXLEN )
+ aRet = ImplCutPath( aRet, nMaxChars, ACCESSDELIM_C(eStyle) );
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::GetPath() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( pParent )
+ return DirEntry( *pParent );
+
+ return DirEntry();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetExtension( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(
+ aName.Copy( static_cast< xub_StrLen >(p1 - p0 + 1) ),
+ osl_getThreadTextEncoding());
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::GetBase( char cSep ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ // es wurde ein cSep an der Position p1 gefunden
+ return String(
+ aName.Copy( 0, static_cast< xub_StrLen >(p1 - p0) ),
+ osl_getThreadTextEncoding());
+
+ else
+ // es wurde kein cSep gefunden
+ return String(aName, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:47
+|*
+*************************************************************************/
+
+String DirEntry::GetName( FSysPathStyle eStyle ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ ByteString aRet;
+ eStyle = GetStyle( eStyle );
+
+ switch( eFlag )
+ {
+ case FSYS_FLAG_PARENT:
+ aRet = ACTPARENT(eStyle);
+ break;
+
+ case FSYS_FLAG_ABSROOT:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+
+#ifndef UNX
+ if ( aName.Len())
+ {
+ if ( aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+ else
+ {
+ aRet.Insert( '/', 5 );
+ }
+ aRet += "/";
+ }
+#endif
+ }
+ else if ( eStyle != FSYS_STYLE_MAC &&
+ aName.Len() > 1 && aName.GetChar( 1 ) != ':' )
+ {
+ // UNC-Pathname
+ aRet = ACCESSDELIM_C(eStyle);
+ aRet += ACCESSDELIM_C(eStyle);
+ aRet += aName ;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ else
+ {
+ aRet = aName;
+ aRet += ACCESSDELIM_C(eStyle);
+ }
+ break;
+ }
+
+ case FSYS_FLAG_INVALID:
+ case FSYS_FLAG_VOLUME:
+ {
+ if ( eStyle == FSYS_STYLE_URL )
+ {
+ aRet = "file:///";
+ aRet += aName;
+#ifndef UNX
+ if ( aName.Len() && aName.GetChar(aName.Len()-1) == ':' )
+ {
+ aRet.SetChar(aRet.Len()-1, '|');
+ }
+#endif
+ }
+ else
+ {
+ aRet = aName;
+ }
+
+ break;
+ }
+
+ case FSYS_FLAG_RELROOT:
+ if ( !aName.Len() )
+ {
+ aRet = ACTCURRENT(eStyle);
+ break;
+ }
+
+ default:
+ aRet = aName;
+ }
+
+ return String(aRet, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+bool DirEntry::IsAbs() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+#ifdef UNX
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT );
+#else
+ return ( pParent ? pParent->IsAbs() : eFlag == FSYS_FLAG_ABSROOT && aName.Len() > 0 );
+#endif
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+String DirEntry::CutName( FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ eStyle = GetStyle( eStyle );
+
+ String aOldName( GetName( eStyle ) );
+
+ if ( pParent )
+ {
+ DirEntry *pOldParent = pParent;
+ if ( pOldParent )
+ {
+ pParent = pOldParent->pParent;
+ eFlag = pOldParent->eFlag;
+ aName = pOldParent->aName;
+ pOldParent->pParent = NULL;
+ delete pOldParent;
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ }
+ else
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ delete pParent;
+ pParent = NULL;
+ }
+
+ return aOldName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::NameCompare
+|*
+|* Beschreibung Vergleich nur die Namen (ohne Pfad, aber mit Gross/Klein)
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+StringCompare DirEntry::NameCompare( const DirEntry &rWith ) const
+{
+ ByteString aThisName;
+ ByteString aParameterName;
+
+#ifdef UNX
+ aThisName = aName;
+ aParameterName = rWith.aName;
+#else
+ aThisName = ByteString(aName).ToLowerAscii();
+ aParameterName = ByteString(rWith.aName).ToLowerAscii();
+#endif
+
+ return aThisName.CompareTo( aParameterName );
+}
+
+
+/*************************************************************************
+|*
+|* DirEntry::operator==()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::operator==( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // test wheather the contents are textual the same
+
+ if ( nError && ( nError == rEntry.nError ) )
+ return TRUE;
+ if ( nError || rEntry.nError ||
+ ( eFlag == FSYS_FLAG_INVALID ) ||
+ ( rEntry.eFlag == FSYS_FLAG_INVALID ) )
+ return FALSE;
+
+#ifndef OS2
+ const
+#endif
+ DirEntry *pThis = (DirEntry *)this;
+#ifndef OS2
+ const
+#endif
+ DirEntry *pWith = (DirEntry *)&rEntry;
+ while( pThis && pWith && (pThis->eFlag == pWith->eFlag) )
+ {
+ if ( CMP_LOWER(pThis->aName) != CMP_LOWER(pWith->aName) )
+ break;
+ pThis = pThis->pParent;
+ pWith = pWith->pParent;
+ }
+
+ return ( !pThis && !pWith );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry& DirEntry::operator=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( this == &rEntry )
+ return *this;
+ if ( rEntry.nError != FSYS_ERR_OK ) {
+ DBG_ERROR("Zuweisung mit invalidem DirEntry");
+ nError = rEntry.nError;
+ return *this;
+ }
+
+ // Name und Typ uebernehmen, Refs beibehalten
+ aName = rEntry.aName;
+ eFlag = rEntry.eFlag;
+ nError = FSYS_ERR_OK;
+
+ DirEntry *pOldParent = pParent;
+ if ( rEntry.pParent )
+ pParent = new DirEntry( *rEntry.pParent );
+ else
+ pParent = NULL;
+
+ if ( pOldParent )
+ delete pOldParent;
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry DirEntry::operator+( const DirEntry& rEntry ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+#ifdef DBG_UTIL
+ static BOOL bTested = FALSE;
+ if ( !bTested )
+ {
+ bTested = TRUE;
+ FSysTest();
+ }
+#endif
+
+ const DirEntry *pEntryTop = rEntry.ImpGetTopPtr();
+ const DirEntry *pThisTop = ImpGetTopPtr();
+
+ // "." + irgendwas oder irgendwas + "d:irgendwas"
+/* TPF:org
+ if ( ( eFlag == FSYS_FLAG_RELROOT && !aName ) ||
+ ( pEntryTop->aName.Len() &&
+ ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME ) ) )
+ return rEntry;
+*/
+
+ if (
+ (eFlag == FSYS_FLAG_RELROOT && !aName.Len()) ||
+ (
+ (pEntryTop->aName.Len() ||
+ ((rEntry.Level()>1)?(rEntry[rEntry.Level()-2].aName.CompareIgnoreCaseToAscii(RFS_IDENTIFIER)==COMPARE_EQUAL):FALSE))
+ &&
+ (pEntryTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_RELROOT ||
+ pEntryTop->eFlag == FSYS_FLAG_VOLUME)
+ )
+ )
+ {
+ return rEntry;
+ }
+
+ // irgendwas + "." (=> pEntryTop == &rEntry)
+ if ( pEntryTop->eFlag == FSYS_FLAG_RELROOT && !pEntryTop->aName.Len() )
+ {
+ DBG_ASSERT( pEntryTop == &rEntry, "DirEntry::op+ buggy" );
+ return *this;
+ }
+
+ // root += ".." (=> unmoeglich)
+ if ( pEntryTop->eFlag == FSYS_FLAG_PARENT && pThisTop == this &&
+ ( eFlag == FSYS_FLAG_ABSROOT ) )
+ return DirEntry( FSYS_FLAG_INVALID );
+
+ // irgendwas += abs (=> nur Device uebernehmen falls vorhanden)
+ if ( pEntryTop->eFlag == FSYS_FLAG_ABSROOT )
+ {
+ ByteString aDevice;
+ if ( pThisTop->eFlag == FSYS_FLAG_ABSROOT )
+ aDevice = pThisTop->aName;
+ DirEntry aRet = rEntry;
+ if ( aDevice.Len() )
+ aRet.ImpGetTopPtr()->aName = aDevice;
+ return aRet;
+ }
+
+ // irgendwas += ".." (=> aufloesen)
+ if ( eFlag == FSYS_FLAG_NORMAL && pEntryTop->eFlag == FSYS_FLAG_PARENT )
+ {
+ String aConcated( GetFull() );
+ aConcated += ACCESSDELIM_C(FSYS_STYLE_HOST);
+ aConcated += rEntry.GetFull();
+ return DirEntry( aConcated );
+ }
+
+ // sonst einfach hintereinander haengen
+ DirEntry aRet( rEntry );
+ DirEntry *pTop = aRet.ImpGetTopPtr();
+ pTop->pParent = new DirEntry( *this );
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator+=()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+DirEntry &DirEntry::operator+=( const DirEntry& rEntry )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ return *this = *this + rEntry;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetAccessDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.05.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetAccessDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ACCESSDELIM_C( GetStyle( eFormatter ) ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 02.08.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetExtension( const String& rExtension, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // do not set extensions for drives
+ if(eFlag == FSYS_FLAG_ABSROOT)
+ {
+ nError = FSYS_ERR_NOTSUPPORTED;
+ return;
+ }
+
+ // cSep im Namen suchen
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase(
+ static_cast< xub_StrLen >(
+ p1 - p0 + 1 - ( rExtension.Len() ? 0 : 1 )) );
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+ else if ( rExtension.Len() )
+ {
+ // es wurde kein cSep gefunden
+ aName += cSep;
+ aName += ByteString(rExtension, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutExtension()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.07.93
+|* Letzte Aenderung MI 23.07.93
+|*
+*************************************************************************/
+
+String DirEntry::CutExtension( char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( static_cast< xub_StrLen >(p1-p0) );
+ return String(p1 + 1, osl_getThreadTextEncoding());
+ }
+
+ return String();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.09.93
+|* Letzte Aenderung MI 04.09.93
+|*
+*************************************************************************/
+
+void DirEntry::SetName( const String& rName, FSysPathStyle eFormatter )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( eFormatter == FSYS_STYLE_HOST || eFormatter == FSYS_STYLE_DETECT )
+ eFormatter = DEFSTYLE;
+ ByteString aAccDelim( ACCESSDELIM_C( eFormatter ) );
+
+ if ( (eFlag != FSYS_FLAG_NORMAL) ||
+ (aName.Search( ':' ) != STRING_NOTFOUND) ||
+ (aName.Search( aAccDelim ) != STRING_NOTFOUND) ||
+ (eFormatter == FSYS_STYLE_FAT && (aName.GetTokenCount( '.' ) > 2) ) )
+ {
+ eFlag = FSYS_FLAG_INVALID;
+ }
+ else
+ {
+ aName = ByteString(rName, osl_getThreadTextEncoding());
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Find()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+BOOL DirEntry::Find( const String& rPfad, char cDelim )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( ImpGetTopPtr()->eFlag == FSYS_FLAG_ABSROOT )
+ return TRUE;
+
+ BOOL bWild = aName.Search( '*' ) != STRING_NOTFOUND ||
+ aName.Search( '?' ) != STRING_NOTFOUND;
+ if ( !cDelim )
+ cDelim = SEARCHDELIM(DEFSTYLE)[0];
+
+ USHORT nTokenCount = rPfad.GetTokenCount( cDelim );
+ USHORT nIndex = 0;
+ ByteString aThis = ACCESSDELIM(DEFSTYLE);
+ aThis += ByteString(GetFull(), osl_getThreadTextEncoding());
+ for ( USHORT nToken = 0; nToken < nTokenCount; ++nToken )
+ {
+ ByteString aPath = ByteString(rPfad, osl_getThreadTextEncoding()).GetToken( 0, cDelim, nIndex );
+
+ if ( aPath.Len() )
+ {
+ if (aPath.GetChar(aPath.Len()-1)== ACCESSDELIM(DEFSTYLE)[0])
+ aPath.Erase(aPath.Len()-1);
+ aPath += aThis;
+ DirEntry aEntry( String(aPath, osl_getThreadTextEncoding()));
+ if ( aEntry.ToAbs() &&
+ ( ( !bWild && aEntry.Exists() ) || ( bWild && aEntry.First() ) ) )
+ {
+ (*this) = aEntry;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpToRel()
+|*
+|* Beschreibung
+|* Ersterstellung MI 17.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ImpToRel( String aCurStr )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aThis(*this);
+ aThis.ToAbs();
+ String aThisStr( aThis.GetFull( FSYS_STYLE_HPFS ) );
+
+ // #109512 preserve case of path even if caseinsensitive
+ String aThisCompareStr( aThisStr ), aCurCompareStr( aCurStr );
+ if ( ! IsCaseSensitive() )
+ {
+ aThisCompareStr.ToLowerAscii();
+ aCurCompareStr.ToLowerAscii();
+ }
+
+ // "Ubereinstimmung pr"ufen
+ USHORT nPos = aThisCompareStr.Match( aCurCompareStr );
+ if ( nPos == STRING_MATCH && aThisStr.Len() != aCurStr.Len() )
+ nPos = Min( aThisStr.Len(), aCurStr.Len() );
+
+ // Sonderfall, die DirEntries sind identisch
+ if ( nPos == STRING_MATCH )
+ {
+ // dann ist der relative Pfad das aktuelle Verzeichnis
+ *this = DirEntry();
+ return TRUE;
+ }
+
+ // Sonderfall, die DirEntries sind total verschieden
+ if ( nPos == 0 )
+ {
+ // dann ist der relativste Pfad absolut
+ *this = aThis;
+ return FALSE;
+ }
+
+ // sonst nehmen wir die identischen Einzelteile vorne weg
+ while ( nPos > 0 && aThisStr.GetChar(nPos) != '\\' )
+ --nPos;
+ aThisStr.Erase( 0, nPos + ( ( aThisStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+ aCurStr.Erase( 0, nPos + ( ( aCurStr.GetChar(nPos) == '\\' ) ? 1 : 0 ) );
+
+ // und fuellen mit dem Level der Directories auf
+ for ( nPos = 0; nPos < aCurStr.Len(); ++nPos )
+ if ( aCurStr.GetChar(nPos) == '\\' )
+ aThisStr.Insert( String( "..\\", osl_getThreadTextEncoding() ), 0 );
+
+ // das ist dann unser relativer Pfad
+ *this = DirEntry( aThisStr, FSYS_STYLE_HPFS );
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CutRelParents()
+|*
+|* Beschreibung
+|* Ersterstellung MI 01.08.95
+|* Letzte Aenderung MI 01.08.95
+|*
+*************************************************************************/
+
+USHORT DirEntry::CutRelParents()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // erstes '..' finden
+ DirEntry *pDir = 0;
+ DirEntry *pPar;
+
+ for ( pPar = this;
+ pPar && pPar->eFlag != FSYS_FLAG_PARENT;
+ pPar = pPar->pParent )
+ pDir = pPar;
+
+ // '..' zaehlen
+ USHORT nParCount = 0;
+ while ( pPar && pPar->eFlag == FSYS_FLAG_PARENT )
+ {
+ ++nParCount;
+ pPar = pPar->pParent;
+ }
+
+ // cutten
+ if ( pDir )
+ DELETEZ(pDir->pParent);
+ else
+ eFlag = FSYS_FLAG_CURRENT;
+
+ return nParCount;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.06.93
+|* Letzte Aenderung MI 17.06.93
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aCur;
+ aCur.ToAbs();
+ return ImpToRel( aCur.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToRel()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToRel( const DirEntry& rStart )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aStart( rStart );
+ aStart.ToAbs();
+ return ImpToRel( aStart.GetFull( FSYS_STYLE_HPFS ) );
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetDevice()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+#ifndef UNX
+
+DirEntry DirEntry::GetDevice() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const DirEntry *pTop = ImpGetTopPtr();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT || pTop->eFlag == FSYS_FLAG_RELROOT ) &&
+ pTop->aName.Len() )
+ return DirEntry( pTop->aName, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ else
+ return DirEntry( ByteString(), FSYS_FLAG_INVALID, FSYS_STYLE_HOST );
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::SetBase()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 23.10.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+void DirEntry::SetBase( const String& rBase, char cSep )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ const char *p0 = ( aName.GetBuffer() );
+ const char *p1 = p0 + aName.Len() - 1;
+ while ( p1 >= p0 && *p1 != cSep )
+ p1--;
+
+ if ( p1 >= p0 )
+ {
+ // es wurde ein cSep an der Position p1 gefunden
+ aName.Erase( 0, static_cast< xub_StrLen >(p1 - p0) );
+ aName.Insert( ByteString(rBase, osl_getThreadTextEncoding()), 0 );
+ }
+ else
+ aName = ByteString(rBase, osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetSearchDelimiter()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 10.06.93
+|* Letzte Aenderung MI 10.06.93
+|*
+*************************************************************************/
+
+String DirEntry::GetSearchDelimiter( FSysPathStyle eFormatter )
+{
+ return String( ByteString(SEARCHDELIM( GetStyle( eFormatter ) ) ), osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetMaxNameLen()
+|*
+|* Beschreibung Liefert die maximale Anzahl von Zeichen in
+|* einzelnen Namensteile. Bei FileSystmen mit
+|* fester Extension (FAT) zaehlt diese nicht mit.
+|* Bei unbekannten FileSytemen und FSYS_STYLE_URL
+|* wird USHRT_MAX zurueckgegeben.
+|* Ersterstellung MI 17.06.97
+|* Letzte Aenderung MI 17.06.97
+|*
+*************************************************************************/
+
+USHORT DirEntry::GetMaxNameLen( FSysPathStyle eFormatter )
+{
+ eFormatter = GetStyle( eFormatter );
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC: return 31;
+
+ case FSYS_STYLE_FAT: return 8;
+
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS: return 255;
+
+
+ case FSYS_STYLE_SYSV: return 14;
+
+ case FSYS_STYLE_BSD: return 250;
+
+ default:
+ return USHRT_MAX;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::TempName()
+|*
+|* Beschreibung FSYS.SDW - Aha, wo?
+|* Ersterstellung VB 06.09.93 (im SWG)
+|* Letzte Aenderung MI 06.02.98
+|*
+*************************************************************************/
+namespace { struct TempNameBase_Impl : public rtl::Static< DirEntry, TempNameBase_Impl > {}; }
+
+const DirEntry& DirEntry::SetTempNameBase( const String &rBase )
+{
+ DirEntry aTempDir = DirEntry().TempName().GetPath();
+ aTempDir += DirEntry( rBase );
+#ifdef UNX
+ ByteString aName( aTempDir.GetFull(), osl_getThreadTextEncoding());
+ if ( access( aName.GetBuffer(), W_OK | X_OK | R_OK ) )
+ {
+ // Create the directory and only on success give all rights to
+ // everyone. Use mkdir instead of DirEntry::MakeDir because
+ // this returns TRUE even if directory already exists.
+
+ if ( !mkdir( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO ) )
+ chmod( aName.GetBuffer(), S_IRWXU | S_IRWXG | S_IRWXO );
+
+ // This will not create a directory but perhaps FileStat called
+ // there modifies the DirEntry
+
+ aTempDir.MakeDir();
+ }
+#else
+ aTempDir.MakeDir();
+#endif
+ DirEntry &rEntry = TempNameBase_Impl::get();
+ rEntry = aTempDir.TempName( FSYS_KIND_DIR );
+ return rEntry;
+}
+
+DirEntry DirEntry::TempName( DirEntryKind eKind ) const
+{
+ // ggf. Base-Temp-Dir verwenden (macht Remote keinen Sinn => vorher)
+ const DirEntry &rEntry = TempNameBase_Impl::get();
+ if ( !pParent && FSYS_FLAG_CURRENT != rEntry.eFlag && FSYS_FLAG_ABSROOT != eFlag )
+
+ {
+ DirEntry aFactory( rEntry );
+ aFactory += GetName();
+ return aFactory.TempName();
+ }
+
+ ByteString aDirName; // hiermit hatte MPW C++ Probleme - immmer noch??
+ char *ret_val;
+ size_t i;
+
+ // dertermine Directory, Prefix and Extension
+ char pfx[6];
+ char ext[5];
+ const char *dir;
+ const char *pWild = strchr( aName.GetBuffer(), '*' );
+ if ( !pWild )
+ pWild = strchr( aName.GetBuffer(), '?' );
+
+ if ( pWild )
+ {
+ if ( pParent )
+ aDirName = ByteString(pParent->GetFull(), osl_getThreadTextEncoding());
+ strncpy( pfx, aName.GetBuffer(), Min( (int)5, (int)(pWild-aName.GetBuffer()) ) );
+ pfx[ pWild-aName.GetBuffer() ] = 0;
+ const char *pExt = strchr( pWild, '.' );
+ if ( pExt )
+ {
+ strncpy( ext, pExt, 4 );
+ ext[4] = 0;
+ }
+ else
+ strcpy( ext, ".tmp" );
+ }
+ else
+ {
+ aDirName = ByteString(GetFull(), osl_getThreadTextEncoding());
+ strcpy( pfx, "sv" );
+ strcpy( ext, ".tmp" );
+ }
+ dir = aDirName.GetBuffer();
+
+ // wurde kein Dir angegeben, dann nehmen wir ein passendes TEMP-Verz.
+ char sBuf[_MAX_PATH];
+ if ( eFlag == FSYS_FLAG_CURRENT || ( !pParent && pWild ) )
+ dir = TempDirImpl(sBuf);
+
+ // ab hier leicht modifizierter Code von VB
+ DirEntry aRet(FSYS_FLAG_INVALID);
+ i = strlen(dir);
+ // need to add ?\\? + prefix + number + pid + .ext + '\0'
+# define TMPNAME_SIZE ( 1 + 5 + 5 + 10 + 4 + 1 )
+ ret_val = new char[i + TMPNAME_SIZE ];
+ if (ret_val)
+ {
+ strcpy(ret_val,dir);
+
+ /* Make sure directory ends with a separator */
+#if defined(WNT) || defined(OS2)
+ if ( i>0 && ret_val[i-1] != '\\' && ret_val[i-1] != '/' &&
+ ret_val[i-1] != ':')
+ ret_val[i++] = '\\';
+#elif defined UNX
+ if (i>0 && ret_val[i-1] != '/')
+ ret_val[i++] = '/';
+#else
+#error unknown operating system
+#endif
+
+ strncpy(ret_val + i, pfx, 5);
+ ret_val[i + 5] = '\0'; /* strncpy doesn't put a 0 if more */
+ i = strlen(ret_val); /* than 'n' chars. */
+
+ /* Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
+ * Welcome to the 21st century, we can have longer filenames now ;)
+ * New format: pfx + "5 char milli/micro second res" + "current pid" + ".tmp"
+ */
+#if (defined MSC || defined __MINGW32__) && defined WNT
+ /* Milliseconds !! */
+ static unsigned long u = GetTickCount();
+ unsigned long mypid = static_cast<unsigned long>(_getpid());
+#else
+ /* Microseconds !! */
+ static unsigned long u = clock();
+ unsigned long mypid = static_cast<unsigned long>(getpid());
+#endif
+ for ( unsigned long nOld = u; ++u != nOld; ) /* Hae??? */
+ {
+ u %= 100000; /* on *NIX repeats every 100ms, maybe less if CLOCKS_PER_SEC > 10^6 */
+ snprintf(ret_val+i, TMPNAME_SIZE, "%05lu%lu", u, mypid);
+
+ strcat(ret_val,ext);
+
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( String( ret_val, osl_getThreadTextEncoding()),
+ STREAM_WRITE|STREAM_SHARE_DENYALL );
+ if ( aStream.IsOpen() )
+ {
+ aStream.Seek( STREAM_SEEK_TO_END );
+ if ( 0 == aStream.Tell() )
+ {
+ aRet = DirEntry( String( ret_val, osl_getThreadTextEncoding()));
+ break;
+ }
+ aStream.Close();
+ }
+ }
+ else
+ {
+ // Redirect
+ String aRetVal(ret_val, osl_getThreadTextEncoding());
+ String aRedirected (aRetVal);
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aRedirected );
+#endif
+ if ( FSYS_KIND_DIR == eKind )
+ {
+ if ( 0 == _mkdir( ByteString(aRedirected.GetBuffer(), osl_getThreadTextEncoding()).GetBuffer() ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+ }
+ else
+ {
+#if defined(UNX) || defined(OS2)
+ if( access( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), F_OK ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#else
+ struct stat aStat;
+ if ( stat( ByteString(aRedirected, osl_getThreadTextEncoding()).GetBuffer(), &aStat ) )
+ {
+ aRet = DirEntry( aRetVal );
+ break;
+ }
+#endif
+ }
+ }
+ }
+
+ delete[] ret_val;
+ ret_val = 0;
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::operator[]()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+const DirEntry &DirEntry::operator[]( USHORT nParentLevel ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ //TPF: maybe to be implemented (FastFSys)
+
+ const DirEntry *pRes = this;
+ while ( pRes && nParentLevel-- )
+ pRes = pRes->pParent;
+
+ return *pRes;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ImpParseUnixName()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 26.05.93
+|*
+*************************************************************************/
+
+FSysError DirEntry::ImpParseUnixName( const ByteString& rPfad, FSysPathStyle eStyle )
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // die einzelnen Namen auf einen Stack packen
+ DirEntryStack aStack;
+ ByteString aPfad( rPfad );
+ do
+ {
+ // den Namen vor dem ersten "/" abspalten,
+ // falls '/' am Anfang, ist der Name '/',
+ // der Rest immer ohne die fuehrenden '/'.
+ // den ersten '/' suchen
+ USHORT nPos;
+ for ( nPos = 0;
+ nPos < aPfad.Len() && aPfad.GetChar(nPos) != '/';
+ nPos++ )
+ /* do nothing */;
+
+ // ist der Name die Root des aktuellen Drives?
+ if ( nPos == 0 && aPfad.Len() > 0 && ( aPfad.GetChar(0) == '/' ) )
+ {
+ // Root-Directory des aktuellen Drives
+ aStack.Push( new DirEntry( FSYS_FLAG_ABSROOT ) );
+ }
+ else
+ {
+ // den Namen ohne Trenner abspalten
+ aName = aPfad.Copy( 0, nPos );
+
+ // stellt der Name die aktuelle Directory dar?
+ if ( aName == "." )
+ /* do nothing */;
+
+#ifdef UNX
+ // stellt der Name das User-Dir dar?
+ else if ( aName == "~" )
+ {
+ DirEntry aHome( String( (const char *) getenv( "HOME" ), osl_getThreadTextEncoding()) );
+ for ( USHORT n = aHome.Level(); n; --n )
+ aStack.Push( new DirEntry( aHome[ (USHORT) n-1 ] ) );
+ }
+#endif
+
+ // stellt der Name die Parent-Directory dar?
+ else if ( aName == ".." )
+ {
+ // ist nichts, ein Parent oder eine relative Root
+ // auf dem Stack?
+ if ( ( aStack.Count() == 0 ) ||
+ ( aStack.Top()->eFlag == FSYS_FLAG_PARENT ) )
+ // fuehrende Parents kommen auf den Stack
+ aStack.Push( new DirEntry( ByteString(), FSYS_FLAG_PARENT, eStyle ) );
+
+ // ist es eine absolute Root
+ else if ( aStack.Top()->eFlag == FSYS_FLAG_ABSROOT ) {
+ // die hat keine Parent-Directory
+ return FSYS_ERR_NOTEXISTS;
+ }
+ else
+ // sonst hebt der Parent den TOS auf
+ delete aStack.Pop();
+ }
+ else
+ {
+ DirEntry *pNew = NULL;
+ // normalen Entries kommen auf den Stack
+ pNew = new DirEntry( aName, FSYS_FLAG_NORMAL, eStyle );
+ if ( !pNew->IsValid() )
+ {
+ aName = rPfad;
+ ErrCode eErr = pNew->GetError();
+ delete pNew;
+ return eErr;
+ }
+ aStack.Push( pNew );
+ }
+ }
+
+ // den Restpfad bestimmen
+ aPfad.Erase( 0, nPos + 1 );
+ while ( aPfad.Len() && ( aPfad.GetChar(0) == '/' ) )
+ aPfad.Erase( 0, 1 );
+ }
+ while ( aPfad.Len() );
+
+ // Haupt-Entry (selbst) zuweisen
+ if ( aStack.Count() == 0 )
+ {
+ eFlag = FSYS_FLAG_CURRENT;
+ aName.Erase();
+ }
+ else
+ {
+ eFlag = aStack.Top()->eFlag;
+ aName = aStack.Top()->aName;
+ delete aStack.Pop();
+ }
+
+ // die Parent-Entries vom Stack holen
+ DirEntry** pTemp = &pParent;
+ while ( aStack.Count() )
+ {
+ *pTemp = aStack.Pop();
+ pTemp = &( (*pTemp)->pParent );
+ }
+
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MakeShortName()
+|*
+|* Beschreibung
+|* Ersterstellung TLX
+|* Letzte Aenderung PB 21.08.97 (in CreateEntry_Impl())
+|*
+*************************************************************************/
+
+ErrCode CreateEntry_Impl( const DirEntry &rPath, DirEntryKind eKind )
+{
+ // versuchen, anzulegen (ausser bei FSYS_KIND_ALL)
+ ErrCode eErr = ERRCODE_NONE;
+ if ( FSYS_KIND_FILE == eKind )
+ {
+ SvFileStream aStream( rPath.GetFull(), STREAM_STD_WRITE );
+ aStream.WriteLine( "" );
+ eErr = aStream.GetError();
+ }
+ else if ( FSYS_KIND_ALL != eKind )
+ eErr = rPath.MakeDir() ? ERRCODE_NONE : ERRCODE_IO_UNKNOWN;
+
+ // erfolgreich?
+ if ( !rPath.Exists() )
+ eErr = ERRCODE_IO_UNKNOWN; // Doch was schiefgegangen ?
+
+ // ggf. wieder l"oschen
+ if ( FSYS_KIND_NONE == eKind )
+ rPath.Kill();
+
+ // Fehlercode zur?ckliefern
+ return eErr;
+}
+
+BOOL IsValidEntry_Impl( const DirEntry &rPath,
+ const String &rLongName,
+ DirEntryKind eKind,
+ BOOL bIsShortened,
+ BOOL bUseDelim )
+{
+ // Parameter-Pr"uefung
+ DBG_ASSERT( eKind == FSYS_KIND_NONE || eKind == FSYS_KIND_ALL ||
+ eKind == FSYS_KIND_FILE || eKind == FSYS_KIND_DIR,
+ "invalid entry-kind" );
+
+ // Alle von MSDOS erreichbaren FSYS_STYLES muessen den
+ // MSDOS Filenamenanforderungen genuegen. Sonst wird probiert,
+ // ob sich eine Datei des gewuenschten Names anlegen laesst.
+ FSysPathStyle eStyle = DirEntry::GetPathStyle( rPath.GetDevice().GetName() );
+ DirEntry aPath(rPath);
+ DirEntry aName(rLongName, eStyle);
+ if ( !aName.IsValid() || aName.Level() != 1 )
+ return FALSE;
+ aPath += aName;
+ if ( 1 == aPath.Level() )
+ return FALSE;
+ if ( eStyle == FSYS_STYLE_FAT || eStyle == FSYS_STYLE_NWFS ||
+ eStyle == FSYS_STYLE_UNKNOWN )
+ {
+ DirEntry aDosEntry( rLongName, FSYS_STYLE_FAT );
+ if ( !aDosEntry.IsValid() )
+ return FALSE;
+ }
+
+ // Pfad-Trenner sind nicht erlaubt (bei ungek"urzten auch nicht FSYS_SHORTNAME_DELIMITER)
+ char cDelim = bUseDelim == 2 ? FSYS_SHORTNAME_DELIMITER : char(0);
+ if (
+ rLongName.Search(DirEntry::GetAccessDelimiter()) != STRING_NOTFOUND ||
+ (!bIsShortened && rLongName.Search(cDelim) != STRING_NOTFOUND)
+ )
+ {
+ return FALSE;
+ }
+
+ // MI: Abfrage nach 'CON:' etc. wird jetzt in Exists() mitgemacht
+ if ( aPath.Exists() )
+ return FALSE;
+
+ return (ERRCODE_NONE == CreateEntry_Impl( aPath, eKind ));
+}
+
+//-------------------------------------------------------------------------
+
+#define MAX_EXT_FAT 3
+#define MAX_LEN_FAT 8
+#define INVALID_CHARS_FAT "\\/\"':|^<>[]?* "
+
+#define MAX_EXT_MAC 16 // nur wegen sinnvoller Namensk"rzung
+#define MAX_LEN_MAC 31
+#define INVALID_CHARS_MAC "\":"
+
+#define MAX_EXT_MAX 250
+#define MAX_LEN_MAX 255
+#define INVALID_CHARS_DEF "\\/\"':|^<>?*"
+
+BOOL DirEntry::MakeShortName( const String& rLongName, DirEntryKind eKind,
+ BOOL bUseDelim, FSysPathStyle eStyle )
+{
+ String aLongName(rLongName);
+
+ // Alle '#' aus den Dateinamen entfernen, weil das INetURLObject
+ // damit Probleme hat. Siehe auch #51246#
+ aLongName.EraseAllChars( '#' );
+ ByteString bLongName(aLongName, osl_getThreadTextEncoding());
+
+ // Auf Novell-Servern (wegen der rottigen Clients) nur 7bit ASCII
+
+ // bei FSYS_KIND_ALL den alten Namen merken und abh"angen (rename)
+ ByteString aOldName;
+ if ( FSYS_KIND_ALL == eKind )
+ {
+ aOldName = ByteString(CutName(), osl_getThreadTextEncoding());
+ aOldName = CMP_LOWER(aOldName);
+ }
+
+ // ist der Langname direkt verwendbar?
+ if ( IsValidEntry_Impl( *this, aLongName, eKind, FALSE, bUseDelim ) )
+ {
+ operator+=( DirEntry(aLongName) );
+ return TRUE;
+ }
+
+ // max L"angen feststellen
+ USHORT nMaxExt, nMaxLen;
+ if ( FSYS_STYLE_DETECT == eStyle )
+ eStyle = DirEntry::GetPathStyle( GetDevice().GetName() );
+ ByteString aInvalidChars;
+ switch ( eStyle )
+ {
+ case FSYS_STYLE_FAT:
+ nMaxExt = MAX_EXT_FAT;
+ nMaxLen = MAX_LEN_FAT;
+ aInvalidChars = INVALID_CHARS_FAT;
+ break;
+
+ case FSYS_STYLE_MAC:
+ nMaxExt = MAX_EXT_MAC;
+ nMaxLen = MAX_LEN_MAC;
+ aInvalidChars = INVALID_CHARS_MAC;
+ break;
+
+ default:
+ nMaxExt = MAX_EXT_MAX;
+ nMaxLen = MAX_LEN_MAX;
+ aInvalidChars = INVALID_CHARS_DEF;
+ }
+
+ // Extension abschneiden und kuerzen
+ ByteString aExt;
+ ByteString aFName = bLongName;
+ if ( FSYS_STYLE_MAC != eStyle )
+ {
+ DirEntry aUnparsed;
+ aUnparsed.aName = bLongName;
+ aExt = ByteString(aUnparsed.CutExtension(), osl_getThreadTextEncoding());
+ aFName = aUnparsed.aName;
+ if ( aExt.Len() > nMaxExt )
+ {
+ char c = aExt.GetChar( aExt.Len() - 1 );
+ aExt.Erase(nMaxExt-1);
+ aExt += c;
+ }
+ }
+
+ if ( FSYS_STYLE_FAT != eStyle )
+ {
+ // ausser auf einem FAT-System geh"ort die Extension zur
+ // Maxl"ange. Muss also vorher mit dem Punkt abgezogen werden.
+ nMaxLen -= ( aExt.Len() + 1 );
+ }
+
+ // Name k"urzen
+ ByteString aSName;
+ for ( const char *pc = aFName.GetBuffer(); aSName.Len() < nMaxLen && *pc; ++pc )
+ {
+ if ( STRING_NOTFOUND == aInvalidChars.Search( *pc ) &&
+ (unsigned char) *pc >= (unsigned char) 32 &&
+ ( !aSName.Len() || *pc != ' ' || aSName.GetChar(aSName.Len()-1) != ' ' ) )
+ aSName += *pc;
+ }
+ aSName.EraseTrailingChars();
+
+ // HRO: #74246# Also cut leading spaces
+ aSName.EraseLeadingChars();
+
+ if ( !aSName.Len() )
+ aSName = "noname";
+
+ // kommt dabei der alte Name raus?
+ ByteString aNewName = aSName;
+ if ( aExt.Len() )
+ ( aNewName += '.' ) += aExt;
+ operator+=( DirEntry(String(aNewName, osl_getThreadTextEncoding())) );
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(aName) == aOldName )
+ if ( FSYS_KIND_ALL == eKind && CMP_LOWER(ByteString(GetName(), osl_getThreadTextEncoding())) == aOldName )
+ return TRUE;
+
+ // kann der gek"urzte Name direkt verwendet werden?
+ if ( !Exists() && (ERRCODE_NONE == CreateEntry_Impl( *this, eKind )) )
+ return TRUE;
+
+ // darf '?##' verwendet werden, um eindeutigen Name zu erzeugen?
+ if ( bUseDelim )
+ {
+ // eindeutigen Namen per '?##' erzeugen
+ aSName.Erase( nMaxLen-3 );
+ if ( bUseDelim != 2 )
+ aSName += FSYS_SHORTNAME_DELIMITER;
+ for ( int n = 1; n < 99; ++n )
+ {
+ // Name zusammensetzen
+ ByteString aTmpStr( aSName );
+ aTmpStr += ByteString::CreateFromInt32(n);
+ if ( aExt.Len() )
+ ( aTmpStr += '.' ) += aExt;
+
+ // noch nicht vorhanden?
+ SetName( String(aTmpStr, osl_getThreadTextEncoding()) );
+
+ if ( !Exists() )
+ {
+ // Fehler setzen !!!
+ nError = CreateEntry_Impl( *this, eKind );
+ return (ERRCODE_NONE == nError);
+ }
+ }
+ }
+
+ // keine ## mehr frei / ?## soll nicht verwendet werden
+ nError = ERRCODE_IO_ALREADYEXISTS;
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CreatePath()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::MakeDir( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ // Schnellpruefung, ob vorhanden
+ if ( FileStat( *this ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ if ( bSloppy && pParent )
+ if ( FileStat( *pParent ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+
+ const DirEntry *pNewDir = bSloppy ? pParent : this;
+ if ( pNewDir )
+ {
+ // den Path zum Dir erzeugen
+ if ( pNewDir->pParent && !pNewDir->pParent->MakeDir(FALSE) )
+ return FALSE;
+
+ // das Dir selbst erzeugen
+ if ( pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_ABSROOT ||
+ pNewDir->eFlag == FSYS_FLAG_VOLUME )
+ return TRUE;
+ else
+ {
+ //? nError = ???
+ if ( FileStat( *pNewDir ).IsKind( FSYS_KIND_DIR ) )
+ return TRUE;
+ else
+ {
+ FSysFailOnErrorImpl();
+ String aDirName(pNewDir->GetFull());
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aDirName );
+#endif
+ ByteString bDirName( aDirName, osl_getThreadTextEncoding() );
+ bDirName = GUI2FSYS( bDirName );
+
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ BOOL bResult = (0 == _mkdir( (char*) bDirName.GetBuffer() ));
+ if ( !bResult )
+ {
+ // Wer hat diese Methode const gemacht ?
+#ifdef WIN32
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( GetLastError() ) );
+#else
+ ((DirEntry *)this)->SetError( Sys2SolarError_Impl( errno ) );
+#endif
+ }
+
+ return bResult;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::CopyTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::CopyTo( const DirEntry& rDest, FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_ACTION_COPYFILE != (nActions & FSYS_ACTION_COPYFILE) )
+#ifdef UNX
+ {
+ // Hardlink anlegen
+ HACK(redirection missing)
+ ByteString aThis(GUI2FSYS(GetFull()), osl_getThreadTextEncoding());
+ ByteString aDest(GUI2FSYS(rDest.GetFull()), osl_getThreadTextEncoding());
+ if (link( aThis.GetBuffer(), aDest.GetBuffer() ) == -1)
+ return Sys2SolarError_Impl( errno );
+ else
+ return FSYS_ERR_OK;
+ }
+#else
+ return FSYS_ERR_NOTSUPPORTED;
+#endif
+
+ FileCopier fc(*this, rDest);
+ return fc.Execute(nActions);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MoveTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung HRO 24.03.99
+|*
+*************************************************************************/
+
+#if defined WNT || defined UNX || defined OS2
+
+FSysError DirEntry::MoveTo( const DirEntry& rNewName ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+/*
+ FileStat aSourceStat(*this);
+ if ( !aSourceStat.IsKind(FSYS_KIND_FILE) )
+ return FSYS_ERR_NOTAFILE;
+*/
+
+ DirEntry aDest(rNewName);
+ FileStat aDestStat(rNewName);
+ if ( aDestStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aDest += String(aName, osl_getThreadTextEncoding());
+ }
+ if ( aDest.Exists() )
+ {
+ return FSYS_ERR_ALREADYEXISTS;
+ }
+
+#if defined(OS2)
+ if ( FileStat(*this).IsKind(FSYS_KIND_DIR) && aDest.GetPath() != GetPath() )
+ {
+ return FSYS_ERR_NOTSUPPORTED;
+ }
+#endif
+
+ FSysFailOnErrorImpl();
+ String aFrom( GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aFrom);
+#endif
+
+ String aTo( aDest.GetFull() );
+
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect(aTo);
+#endif
+
+ ByteString bFrom(aFrom, osl_getThreadTextEncoding());
+ ByteString bTo(aTo, osl_getThreadTextEncoding());
+ bFrom = GUI2FSYS(bFrom);
+ bTo = GUI2FSYS(bTo);
+
+#ifdef WNT
+ // MoveTo nun atomar
+ SetLastError(0);
+
+ DirEntry aFromDevice(String(bFrom, osl_getThreadTextEncoding()));
+ DirEntry aToDevice(String(bTo,osl_getThreadTextEncoding()));
+ aFromDevice.ToAbs();
+ aToDevice.ToAbs();
+ aFromDevice=aFromDevice.GetDevice();
+ aToDevice=aToDevice.GetDevice();
+
+ //Quelle und Ziel auf gleichem device?
+ if (aFromDevice==aToDevice)
+ {
+ // ja, also intra-device-move mit MoveFile
+ MoveFile( bFrom.GetBuffer(), bTo.GetBuffer() );
+ // MoveFile ist buggy bei cross-device operationen.
+ // Der R?ckgabewert ist auch dann TRUE, wenn nur ein Teil der Operation geklappt hat.
+ // Zudem zeigt MoveFile unterschiedliches Verhalten bei unterschiedlichen NT-Versionen.
+ return Sys2SolarError_Impl( GetLastError() );
+ }
+ else
+ {
+ //nein, also inter-device-move mit copy/delete
+ FSysError nCopyError = CopyTo(rNewName, FSYS_ACTION_COPYFILE);
+
+ DirEntry aKill(String(bTo, osl_getThreadTextEncoding()));
+ FileStat aKillStat(String(bTo, osl_getThreadTextEncoding()));
+ if ( aKillStat.IsKind(FSYS_KIND_DIR ) )
+ {
+ aKill += String(aName, osl_getThreadTextEncoding());
+ }
+
+ if (nCopyError==FSYS_ERR_OK)
+ {
+ if (Kill()==FSYS_ERR_OK)
+ {
+ return FSYS_ERR_OK;
+ }
+ else
+ {
+ aKill.Kill();
+ return FSYS_ERR_ACCESSDENIED;
+ }
+ }
+ else
+ {
+ aKill.Kill();
+ return nCopyError;
+ }
+ }
+#else
+ // #68639#
+ // on some nfs connections rename with from == to
+ // leads to destruction of file
+ if ( ( aFrom != aTo ) && ( 0 != rename( bFrom.GetBuffer(), bTo.GetBuffer() ) ) )
+#if !defined(UNX) && !defined(OS2)
+ return Sys2SolarError_Impl( GetLastError() );
+#else
+ {
+ if( errno == EXDEV )
+// cross device geht latuernich nicht mit rename
+ {
+ FILE *fpIN = fopen( bFrom.GetBuffer(), "r" );
+ FILE *fpOUT = fopen( bTo.GetBuffer(), "w" );
+ if( fpIN && fpOUT )
+ {
+ char pBuf[ 16384 ];
+ int nBytes, nWritten, nErr = 0;
+ errno = 0;
+ while( ( nBytes = fread( pBuf, 1, sizeof(pBuf), fpIN ) ) && ! nErr )
+ {
+ nWritten = fwrite( pBuf, 1, nBytes, fpOUT );
+ // Fehler im fwrite ?
+ if( nWritten < nBytes )
+ {
+ nErr = errno;
+ break;
+ }
+ }
+ fclose( fpIN );
+ fclose( fpOUT );
+ if ( nErr )
+ {
+ unlink( bTo.GetBuffer() );
+ return Sys2SolarError_Impl( nErr );
+ }
+ else
+ {
+ unlink( bFrom.GetBuffer() );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( EXDEV );
+ }
+ }
+ else
+ {
+ return Sys2SolarError_Impl( errno );
+ }
+ }
+#endif
+#endif
+ return ERRCODE_NONE;
+}
+
+#endif
+
+/*************************************************************************
+|*
+|* DirEntry::Kill()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 07.08.96
+|*
+*************************************************************************/
+
+FSysError DirEntry::Kill( FSysAction nActions ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ FSysError eError = FSYS_ERR_OK;
+ FSysFailOnErrorImpl();
+
+ // Name als doppelt 0-terminierter String
+ String aTmpName( GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aTmpName );
+#endif
+ ByteString bTmpName( aTmpName, osl_getThreadTextEncoding());
+ bTmpName = GUI2FSYS(bTmpName);
+
+ char *pName = new char[bTmpName.Len()+2];
+ strcpy( pName, bTmpName.GetBuffer() );
+ pName[bTmpName.Len()+1] = (char) 0;
+
+ //read-only files sollen auch geloescht werden koennen
+ BOOL isReadOnly = FileStat::GetReadOnlyFlag(*this);
+ if (isReadOnly)
+ {
+ FileStat::SetReadOnlyFlag(*this, FALSE);
+ }
+
+ // directory?
+ if ( FileStat( *this ).IsKind(FSYS_KIND_DIR) )
+ {
+ // Inhalte recursiv loeschen?
+ if ( FSYS_ACTION_RECURSIVE == (nActions & FSYS_ACTION_RECURSIVE) )
+ {
+ Dir aDir( *this, FSYS_KIND_DIR|FSYS_KIND_FILE );
+ for ( USHORT n = 0; eError == FSYS_ERR_OK && n < aDir.Count(); ++n )
+ {
+ const DirEntry &rSubDir = aDir[n];
+ DirEntryFlag flag = rSubDir.GetFlag();
+ if ( flag != FSYS_FLAG_CURRENT && flag != FSYS_FLAG_PARENT )
+ eError = rSubDir.Kill(nActions);
+ }
+ }
+
+ // das Dir selbst loeschen
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( eError == FSYS_ERR_OK && 0 != _rmdir( (char*) pName ) )
+ //
+ {
+ // falls L"oschen nicht ging, CWD umsetzen
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ if ( eError )
+ {
+ GetPath().SetCWD();
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if (_rmdir( (char*) pName) != 0)
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = FSYS_ERR_OK;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( FSYS_ACTION_USERECYCLEBIN == (nActions & FSYS_ACTION_USERECYCLEBIN) )
+ {
+#ifdef OS2
+ eError = ApiRet2ToSolarError_Impl( DosDelete( (PSZ) pName ) );
+#elif defined(WNT)
+ SHFILEOPSTRUCT aOp;
+ aOp.hwnd = 0;
+ aOp.wFunc = FO_DELETE;
+ aOp.pFrom = pName;
+ aOp.pTo = 0;
+ aOp.fFlags = FOF_ALLOWUNDO|FOF_SILENT|FOF_NOCONFIRMATION;
+ aOp.hNameMappings = 0;
+ aOp.lpszProgressTitle = 0;
+ eError = Sys2SolarError_Impl( SHFileOperation( &aOp ) );
+#else
+ eError = ERRCODE_IO_NOTSUPPORTED;
+#endif
+ }
+ else
+ {
+#ifdef WIN32
+ SetLastError(0);
+#endif
+ if ( 0 != _unlink( (char*) pName ) )
+ {
+#ifdef WIN32
+ eError = Sys2SolarError_Impl( GetLastError() );
+#else
+ eError = Sys2SolarError_Impl( errno );
+#endif
+ }
+ else
+ {
+ eError = ERRCODE_NONE;
+ }
+ }
+ }
+
+ //falls Fehler, originales read-only flag wieder herstellen
+ if ( isReadOnly && (eError!=ERRCODE_NONE) )
+ {
+ FileStat::SetReadOnlyFlag(*this, isReadOnly);
+ }
+
+ delete[] pName;
+ return eError;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Contains()
+|*
+|* Beschreibung ob rSubEntry direkt oder indirect in *this liegt
+|* Ersterstellung MI 20.03.97
+|* Letzte Aenderung MI 20.03.97
+|*
+*************************************************************************/
+
+BOOL DirEntry::Contains( const DirEntry &rSubEntry ) const
+{
+ DBG_ASSERT( IsAbs() && rSubEntry.IsAbs(), "must be absolute entries" );
+
+ USHORT nThisLevel = Level();
+ USHORT nSubLevel = rSubEntry.Level();
+ if ( nThisLevel < nSubLevel )
+ {
+ for ( ; nThisLevel; --nThisLevel, --nSubLevel )
+ if ( (*this)[nThisLevel-1] != rSubEntry[nSubLevel-1] )
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::Level()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 03.03.92
+|* Letzte Aenderung MI 03.03.92
+|*
+*************************************************************************/
+
+USHORT DirEntry::Level() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ USHORT nLevel = 0;
+ const DirEntry *pRes = this;
+ while ( pRes )
+ {
+ pRes = pRes->pParent;
+ nLevel++;
+ }
+
+ return nLevel;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertNameToSystem()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertNameToSystem( const String &rName )
+{
+ return rName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ConvertSystemToName()
+|*
+|* Beschreibung
+|* Ersterstellung DV 29.03.96
+|* Letzte Aenderung DV 29.03.96
+|*
+*************************************************************************/
+
+String DirEntry::ConvertSystemToName( const String &rName )
+{
+ return rName;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsValid()
+|*
+|* Beschreibung
+|* Ersterstellung MI 18.09.93
+|* Letzte Aenderung TPF 18.09.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsValid() const
+{
+ return (nError == FSYS_ERR_OK);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsRFSAvailable()
+|*
+|* Beschreibung
+|* Ersterstellung TPF 21.10.98
+|* Letzte Aenderung TPF 21.10.98
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsRFSAvailable()
+{
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* IsLongNameOnFAT()
+|*
+|* Beschreibung ?berpr?ft , ob das DirEntry einen langen
+|* Filenamen auf einer FAT-Partition enth?lt (EAs).
+|* (eigentlich nur f?r OS2 interessant)
+|* Ersterstellung TPF 02.10.98
+|* Letzte Aenderung TPF 01.03.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsLongNameOnFAT() const
+{
+ // FAT-System?
+ DirEntry aTempDirEntry(*this);
+ aTempDirEntry.ToAbs();
+ if (DirEntry::GetPathStyle(aTempDirEntry.GetDevice().GetName().GetChar(0)) != FSYS_STYLE_FAT)
+ {
+ return FALSE; // nein, also false
+ }
+
+ // DirEntry-Kette auf lange Dateinamen pr?fen
+ for( USHORT iLevel = this->Level(); iLevel > 0; iLevel-- )
+ {
+ const DirEntry& rEntry = (const DirEntry&) (*this)[iLevel-1];
+ String aBase( rEntry.GetBase() );
+ String aExtension( rEntry.GetExtension() );
+
+ if (aBase.Len()>8) // Name > 8?
+ {
+ return TRUE;
+ }
+
+ if (aExtension.Len()>3) // Extension > 3?
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//========================================================================
+
+#if defined(DBG_UTIL)
+
+void FSysTest()
+{
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/filecopy.cxx b/tools/source/fsys/filecopy.cxx
new file mode 100644
index 000000000000..826ffeab31f5
--- /dev/null
+++ b/tools/source/fsys/filecopy.cxx
@@ -0,0 +1,489 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#if defined WNT
+#ifndef _SVWIN_H
+#include <io.h>
+#include <tools/svwin.h>
+#endif
+
+#elif defined(OS2)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <share.h>
+#include <io.h>
+
+#elif defined UNX
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+#include "comdep.hxx"
+#include <tools/fsys.hxx>
+#include <tools/stream.hxx>
+#include <osl/file.hxx>
+
+using namespace ::osl;
+
+/*************************************************************************
+|*
+|* FileCopier::FileCopier()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier::FileCopier() :
+
+ nBytesTotal ( 0 ),
+ nBytesCopied( 0 ),
+ nBlockSize ( 4096 ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+// -----------------------------------------------------------------------
+
+FileCopier::FileCopier( const DirEntry& rSource, const DirEntry& rTarget ) :
+
+ aSource ( rSource ),
+ aTarget ( rTarget ),
+ nBytesTotal ( 0 ),
+ nBytesCopied( 0 ),
+ nBlockSize ( 4096 ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+// -----------------------------------------------------------------------
+
+FileCopier::FileCopier( const FileCopier& rCopier ) :
+
+ aSource ( rCopier.aSource ),
+ aTarget ( rCopier.aTarget ),
+ nBytesTotal ( 0 ),
+ nBytesCopied ( 0 ),
+ aProgressLink ( rCopier.aProgressLink ),
+ nBlockSize ( 4096 ),
+ pImp ( new FileCopier_Impl )
+
+{
+}
+
+/*************************************************************************
+|*
+|* FileCopier::~FileCopier()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier::~FileCopier()
+{
+ delete pImp;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::operator =()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+FileCopier& FileCopier::operator = ( const FileCopier &rCopier )
+{
+ aSource = rCopier.aSource;
+ aTarget = rCopier.aTarget;
+ nBytesTotal = rCopier.nBytesTotal;
+ nBytesCopied = rCopier.nBytesCopied;
+ nBytesCopied = rCopier.nBytesCopied;
+ nBlockSize = rCopier.nBlockSize;
+ aProgressLink = rCopier.aProgressLink;
+ *pImp = *(rCopier.pImp);
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::Progress()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung MI 13.04.94
+|*
+*************************************************************************/
+
+BOOL FileCopier::Progress()
+{
+ if ( !aProgressLink )
+ return TRUE;
+ else
+ {
+ if ( aProgressLink.Call( this ) )
+ return TRUE;
+ return ( 0 == Error( ERRCODE_ABORT, 0, 0 ) );
+ }
+}
+
+//---------------------------------------------------------------------------
+
+ErrCode FileCopier::Error( ErrCode eErr, const DirEntry* pSource, const DirEntry* pTarget )
+{
+ // kein Fehler oder kein ErrorHandler?
+ if ( !eErr || !pImp->aErrorLink )
+ // => Error beibehalten
+ return eErr;
+
+ // sonst gesetzten ErrorHandler fragen
+ pImp->pErrSource = pSource;
+ pImp->pErrTarget = pTarget;
+ pImp->eErr = eErr;
+ ErrCode eRet = (ErrCode) pImp->aErrorLink.Call( this );
+ pImp->pErrSource = 0;
+ pImp->pErrTarget = 0;
+ return eRet;
+}
+
+//---------------------------------------------------------------------------
+
+const DirEntry* FileCopier::GetErrorSource() const
+{
+ return pImp->pErrSource;
+}
+
+//---------------------------------------------------------------------------
+
+const DirEntry* FileCopier::GetErrorTarget() const
+{
+ return pImp->pErrTarget;
+}
+
+//---------------------------------------------------------------------------
+
+ErrCode FileCopier::GetError() const
+{
+ return pImp->eErr;
+}
+
+//---------------------------------------------------------------------------
+
+void FileCopier::SetErrorHdl( const Link &rLink )
+{
+ pImp->aErrorLink = rLink;
+}
+
+//---------------------------------------------------------------------------
+
+const Link& FileCopier::GetErrorHdl() const
+{
+ return pImp->aErrorLink ;
+}
+
+/*************************************************************************
+|*
+|* FileCopier::Execute()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 13.04.94
+|* Letzte Aenderung PB 16.06.00
+|*
+*************************************************************************/
+
+FSysError FileCopier::DoCopy_Impl(
+ const DirEntry &rSource, const DirEntry &rTarget )
+{
+ FSysError eRet = FSYS_ERR_OK;
+ ErrCode eWarn = FSYS_ERR_OK;
+
+ // HPFS->FAT?
+ FSysPathStyle eSourceStyle = DirEntry::GetPathStyle( rSource.ImpGetTopPtr()->GetName() );
+ FSysPathStyle eTargetStyle = DirEntry::GetPathStyle( rTarget.ImpGetTopPtr()->GetName() );
+ BOOL bMakeShortNames = ( eSourceStyle == FSYS_STYLE_HPFS && eTargetStyle == FSYS_STYLE_FAT );
+
+ // Zieldateiname ggf. kuerzen
+ DirEntry aTgt;
+ if ( bMakeShortNames )
+ {
+ aTgt = rTarget.GetPath();
+ aTgt.MakeShortName( rTarget.GetName() );
+ }
+ else
+ aTgt = rTarget;
+
+ // kein Move wenn Namen gekuerzt werden muessten
+ if ( bMakeShortNames && FSYS_ACTION_MOVE == ( pImp->nActions & FSYS_ACTION_MOVE ) && aTgt != rTarget )
+ return ERRCODE_IO_NAMETOOLONG;
+
+ // source is directory?
+ FileStat aSourceFileStat( rSource );
+ if ( aSourceFileStat.IsKind( FSYS_KIND_DIR ) )
+ {
+#ifdef OS2
+ CHAR szSource[CCHMAXPATHCOMP];
+ HOBJECT hSourceObject;
+
+ strcpy(szSource, ByteString(rSource.GetFull(), osl_getThreadTextEncoding()).GetBuffer());
+ hSourceObject = WinQueryObject(szSource);
+
+ if ( hSourceObject )
+ {
+ PSZ pszSourceName;
+ PSZ pszTargetName;
+ CHAR szTarget[CCHMAXPATHCOMP];
+ HOBJECT hTargetObject;
+ HOBJECT hReturn = NULLHANDLE;
+
+ strcpy(szTarget, ByteString(rTarget.GetFull(), osl_getThreadTextEncoding()).GetBuffer());
+ pszTargetName = strrchr(szTarget, '\\');
+ pszSourceName = strrchr(szSource, '\\');
+
+ hTargetObject = WinQueryObject(szTarget);
+
+ if ( hTargetObject )
+ WinDestroyObject(hTargetObject);
+
+ if ( pszTargetName && pszSourceName )
+ {
+ *pszTargetName = '\0';
+ pszSourceName++;
+ pszTargetName++;
+
+ if(strcmp(pszSourceName, pszTargetName) == 0)
+ {
+ hTargetObject = WinQueryObject(szTarget);
+
+ if(pImp->nActions & FSYS_ACTION_MOVE)
+ {
+ hReturn = WinMoveObject(hSourceObject, hTargetObject, 0);
+ }
+ else
+ {
+ hReturn = WinCopyObject(hSourceObject, hTargetObject, 0);
+ }
+ if ( bMakeShortNames && aTarget.Exists() )
+ aTarget.Kill();
+ return hReturn ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN;
+ }
+ }
+ }
+#endif
+ // recursive copy
+ eRet = Error( aTgt.MakeDir() ? FSYS_ERR_OK : FSYS_ERR_UNKNOWN, 0, &aTgt );
+ Dir aSourceDir( rSource, FSYS_KIND_DIR|FSYS_KIND_FILE );
+ for ( USHORT n = 0; ERRCODE_TOERROR(eRet) == FSYS_ERR_OK && n < aSourceDir.Count(); ++n )
+ {
+ const DirEntry &rSubSource = aSourceDir[n];
+ DirEntryFlag eFlag = rSubSource.GetFlag();
+ if ( eFlag != FSYS_FLAG_CURRENT && eFlag != FSYS_FLAG_PARENT )
+ {
+ DirEntry aSubTarget( aTgt );
+ aSubTarget += rSubSource.GetName();
+ eRet = DoCopy_Impl( rSubSource, aSubTarget );
+ if ( eRet && !eWarn )
+ eWarn = eRet;
+ }
+ }
+ }
+ else if ( aSourceFileStat.IsKind(FSYS_KIND_FILE) )
+ {
+ if ( ( FSYS_ACTION_KEEP_EXISTING == ( pImp->nActions & FSYS_ACTION_KEEP_EXISTING ) ) &&
+ aTgt.Exists() )
+ {
+ // Do not overwrite existing file in target folder.
+ return ERRCODE_NONE;
+ }
+
+ // copy file
+ nBytesCopied = 0;
+ nBytesTotal = FileStat( rSource ).GetSize();
+
+ ::rtl::OUString aFileName;
+ FileBase::getFileURLFromSystemPath( ::rtl::OUString(rSource.GetFull()), aFileName );
+ SvFileStream aSrc( aFileName, STREAM_READ|STREAM_NOCREATE|STREAM_SHARE_DENYNONE );
+
+ if ( !aSrc.GetError() )
+ {
+#ifdef UNX
+ struct stat buf;
+ if ( fstat( aSrc.GetFileHandle(), &buf ) == -1 )
+ eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTgt );
+#endif
+ ::rtl::OUString aTargetFileName;
+ FileBase::getFileURLFromSystemPath( ::rtl::OUString(aTgt.GetFull()), aTargetFileName );
+
+ SvFileStream aTargetStream( aTargetFileName, STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYWRITE );
+ if ( !aTargetStream.GetError() )
+ {
+#ifdef UNX
+ if ( fchmod( aTargetStream.GetFileHandle(), buf.st_mode ) == -1 )
+ eRet = Error( FSYS_ERR_ACCESSDENIED, 0, &aTgt );
+#endif
+ size_t nAllocSize = 0, nSize = 0;
+ char *pBuf = 0;
+ while ( Progress() && nSize == nAllocSize && eRet == FSYS_ERR_OK )
+ {
+ // adjust the block-size
+ if ( nBlockSize > nAllocSize )
+ {
+ delete[] pBuf;
+ nAllocSize = nBlockSize;
+ pBuf = new char[nAllocSize];
+ }
+
+ // copy one block
+ nSize = aSrc.Read( pBuf, nBlockSize );
+ aTargetStream.Write( pBuf, nSize );
+ if ( aTargetStream.GetError() )
+ eRet = Error( aTargetStream.GetError(), 0, &aTgt );
+
+ // adjust counters
+ nBytesCopied += nSize;
+ if ( nBytesCopied > nBytesTotal )
+ nBytesTotal = nBytesCopied;
+ }
+ delete[] pBuf;
+ }
+ else
+ eRet = Error( aTargetStream.GetError(), 0, &aTgt );
+
+ // unvollstaendiges File wieder loeschen
+ aTargetStream.Close();
+
+ if ( nBytesCopied != nBytesTotal )
+ {
+ aTgt.Kill();
+ }
+ }
+ else
+ eRet = Error( aSrc.GetError(), &rSource, 0 );
+ }
+ else if ( aSourceFileStat.IsKind(FSYS_KIND_NONE) )
+ eRet = Error( ERRCODE_IO_NOTEXISTS, &rSource, 0 );
+ else
+ eRet = Error( ERRCODE_IO_NOTSUPPORTED, &rSource, 0 );
+
+#ifdef WNT
+ // Set LastWriteTime and Attributes of the target identical with the source
+
+ if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) )
+ {
+ WIN32_FIND_DATA fdSource;
+ ByteString aFullSource(aSource.GetFull(), osl_getThreadTextEncoding());
+ ByteString aFullTarget(aTgt.GetFull(), osl_getThreadTextEncoding());
+ HANDLE hFind = FindFirstFile( aFullSource.GetBuffer() , &fdSource );
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ FindClose( hFind );
+
+ HANDLE hFile = CreateFile( aFullTarget.GetBuffer(), GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ SetFileTime( hFile, NULL, NULL, &fdSource.ftLastWriteTime );
+ CloseHandle( hFile );
+ }
+
+ SetFileAttributes( aFullTarget.GetBuffer(), fdSource.dwFileAttributes );
+ }
+ }
+#endif
+ // bei Move ggf. das File/Dir loeschen
+ if ( FSYS_ERR_OK == ERRCODE_TOERROR(eRet) && ( pImp->nActions & FSYS_ACTION_MOVE ) )
+ {
+ ErrCode eKillErr = Error( rSource.Kill() | ERRCODE_WARNING_MASK, &rSource, 0 );
+ if ( eKillErr != ERRCODE_WARNING_MASK )
+ {
+ if ( rSource.Exists() )
+ // loeschen ging nicht => dann die Kopie wieder loeschen
+ aTgt.Kill( pImp->nActions );
+ if ( !eWarn )
+ eWarn = eKillErr;
+ }
+ }
+
+ return !eRet ? eWarn : eRet;
+}
+
+// -----------------------------------------------------------------------
+
+FSysError FileCopier::Execute( FSysAction nActions )
+{
+ return ExecuteExact( nActions );
+}
+
+// -----------------------------------------------------------------------
+
+FSysError FileCopier::ExecuteExact( FSysAction nActions, FSysExact eExact )
+{
+ DirEntry aAbsSource = DirEntry( aSource);
+ DirEntry aAbsTarget = DirEntry( aTarget );
+ pImp->nActions = nActions;
+
+ // check if both pathes are accessible and source and target are different
+ if ( !aAbsTarget.ToAbs() || !aAbsSource.ToAbs() || aAbsTarget == aAbsSource )
+ return FSYS_ERR_ACCESSDENIED;
+
+ // check if copy would be endless recursive into itself
+ if ( FSYS_ACTION_RECURSIVE == ( nActions & FSYS_ACTION_RECURSIVE ) &&
+ aAbsSource.Contains( aAbsTarget ) )
+ return ERRCODE_IO_RECURSIVE;
+
+ // target is directory?
+ if ( eExact == FSYS_NOTEXACT &&
+ FileStat( aAbsTarget ).IsKind(FSYS_KIND_DIR) && FileStat( aAbsSource ).IsKind(FSYS_KIND_FILE) )
+ // append name of source
+ aAbsTarget += aSource.GetName();
+
+ // recursive copy
+ return DoCopy_Impl( aAbsSource, aAbsTarget );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/fstat.cxx b/tools/source/fsys/fstat.cxx
new file mode 100644
index 000000000000..468fdb6082ea
--- /dev/null
+++ b/tools/source/fsys/fstat.cxx
@@ -0,0 +1,422 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#if defined( WIN)
+#include <stdio.h>
+#include <dos.h>
+#endif
+
+#ifdef UNX
+#include <errno.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+
+#include "comdep.hxx"
+#include <tools/fsys.hxx>
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MI 11.06.91
+|*
+*************************************************************************/
+
+FileStat::FileStat()
+: // don't use Default-Ctors!
+ aDateCreated( ULONG(0) ),
+ aTimeCreated( ULONG(0) ),
+ aDateModified( ULONG(0) ),
+ aTimeModified( ULONG(0) ),
+ aDateAccessed( ULONG(0) ),
+ aTimeAccessed( ULONG(0) )
+{
+ nSize = 0;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MI 11.06.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const DirEntry& rDirEntry, FSysAccess nAccess )
+: // don't use Default-Ctors!
+ aDateCreated( ULONG(0) ),
+ aTimeCreated( ULONG(0) ),
+ aDateModified( ULONG(0) ),
+ aTimeModified( ULONG(0) ),
+ aDateAccessed( ULONG(0) ),
+ aTimeAccessed( ULONG(0) )
+{
+ BOOL bCached = FSYS_ACCESS_CACHED == (nAccess & FSYS_ACCESS_CACHED);
+ BOOL bFloppy = FSYS_ACCESS_FLOPPY == (nAccess & FSYS_ACCESS_FLOPPY);
+
+#ifdef FEAT_FSYS_DOUBLESPEED
+ const FileStat *pStatFromDir = bCached ? rDirEntry.ImpGetStat() : 0;
+ if ( pStatFromDir )
+ {
+ nError = pStatFromDir->nError;
+ nKindFlags = pStatFromDir->nKindFlags;
+ nSize = pStatFromDir->nSize;
+ aCreator = pStatFromDir->aCreator;
+ aType = pStatFromDir->aType;
+ aDateCreated = pStatFromDir->aDateCreated;
+ aTimeCreated = pStatFromDir->aTimeCreated;
+ aDateModified = pStatFromDir->aDateModified;
+ aTimeModified = pStatFromDir->aTimeModified;
+ aDateAccessed = pStatFromDir->aDateAccessed;
+ aTimeAccessed = pStatFromDir->aTimeAccessed;
+ }
+ else
+#endif
+ Update( rDirEntry, bFloppy );
+}
+
+/*************************************************************************
+|*
+|* FileStat::IsYounger()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 11.11.91
+|* Letzte Aenderung MA 11.11.91
+|*
+*************************************************************************/
+
+// TRUE wenn die Instanz j"unger als rIsOlder ist.
+// FALSE wenn die Instanz "alter oder gleich alt wie rIsOlder ist.
+
+BOOL FileStat::IsYounger( const FileStat& rIsOlder ) const
+{
+ if ( aDateModified > rIsOlder.aDateModified )
+ return TRUE;
+ if ( ( aDateModified == rIsOlder.aDateModified ) &&
+ ( aTimeModified > rIsOlder.aTimeModified ) )
+ return TRUE;
+
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* FileStat::IsKind()
+|*
+|* Ersterstellung MA 11.11.91 (?)
+|* Letzte Aenderung KH 16.01.95
+|*
+*************************************************************************/
+
+BOOL FileStat::IsKind( DirEntryKind nKind ) const
+{
+ BOOL bRet = ( ( nKind == FSYS_KIND_UNKNOWN ) &&
+ ( nKindFlags == FSYS_KIND_UNKNOWN ) ) ||
+ ( ( nKindFlags & nKind ) == nKind );
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* FileStat::HasReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 01.07.98
+|*
+*************************************************************************/
+
+BOOL FileStat::HasReadOnlyFlag()
+{
+#if defined WNT || defined UNX || defined OS2
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/*************************************************************************
+|*
+|* FileStat::GetReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 02.07.98
+|*
+*************************************************************************/
+
+BOOL FileStat::GetReadOnlyFlag( const DirEntry &rEntry )
+{
+
+ ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
+#if defined WNT
+ DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
+ return ULONG_MAX != nRes &&
+ ( FILE_ATTRIBUTE_READONLY & nRes ) == FILE_ATTRIBUTE_READONLY;
+#elif defined OS2
+ FILESTATUS3 aFileStat;
+ APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
+ switch ( nRet )
+ {
+ case NO_ERROR:
+ return FILE_READONLY == ( aFileStat.attrFile & FILE_READONLY );
+ default:
+ return FALSE;
+ }
+#elif defined UNX
+ /* could we stat the object? */
+ struct stat aBuf;
+ if (stat(aFPath.GetBuffer(), &aBuf))
+ return FALSE;
+ /* jupp, is writable for user? */
+ return((aBuf.st_mode & S_IWUSR) != S_IWUSR);
+#else
+ return FALSE;
+#endif
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetReadOnlyFlag()
+|*
+|* Ersterstellung MI 06.03.97
+|* Letzte Aenderung UT 01.07.98
+|*
+*************************************************************************/
+
+ULONG FileStat::SetReadOnlyFlag( const DirEntry &rEntry, BOOL bRO )
+{
+
+ ByteString aFPath(rEntry.GetFull(), osl_getThreadTextEncoding());
+
+#if defined WNT
+ DWORD nRes = GetFileAttributes( (LPCTSTR) aFPath.GetBuffer() );
+ if ( ULONG_MAX != nRes )
+ nRes = SetFileAttributes( (LPCTSTR) aFPath.GetBuffer(),
+ ( nRes & ~FILE_ATTRIBUTE_READONLY ) |
+ ( bRO ? FILE_ATTRIBUTE_READONLY : 0 ) );
+ return ( ULONG_MAX == nRes ) ? ERRCODE_IO_UNKNOWN : 0;
+#elif defined OS2
+ FILESTATUS3 aFileStat;
+ APIRET nRet = DosQueryPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat) );
+ if ( !nRet )
+ {
+ aFileStat.attrFile = ( aFileStat.attrFile & ~FILE_READONLY ) |
+ ( bRO ? FILE_READONLY : 0 );
+ nRet = DosSetPathInfo( (PSZ)aFPath.GetBuffer(), 1, &aFileStat, sizeof(aFileStat), 0 );
+ }
+ switch ( nRet )
+ {
+ case NO_ERROR:
+ return ERRCODE_NONE;
+
+ case ERROR_SHARING_VIOLATION:
+ return ERRCODE_IO_LOCKVIOLATION;
+
+ default:
+ return ERRCODE_IO_NOTEXISTS;
+ }
+#elif defined UNX
+ /* first, stat the object to get permissions */
+ struct stat aBuf;
+ if (stat(aFPath.GetBuffer(), &aBuf))
+ return ERRCODE_IO_NOTEXISTS;
+ /* set or clear write bit for user */
+ mode_t nMode;
+ if (bRO)
+ {
+ nMode = aBuf.st_mode & ~S_IWUSR;
+ nMode = aBuf.st_mode & ~S_IWGRP;
+ nMode = aBuf.st_mode & ~S_IWOTH;
+ }
+ else
+ nMode = aBuf.st_mode | S_IWUSR;
+ /* change it on fs */
+ if (chmod(aFPath.GetBuffer(), nMode))
+ {
+ switch (errno)
+ {
+ case EPERM :
+ case EROFS :
+ return ERRCODE_IO_ACCESSDENIED;
+ default :
+ return ERRCODE_IO_NOTEXISTS;
+ }
+ }
+ else
+ return ERRCODE_NONE;
+#else
+ return ERRCODE_IO_NOTSUPPORTED;
+#endif
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetDateTime
+|*
+|* Ersterstellung PB 27.06.97
+|* Letzte Aenderung
+|*
+*************************************************************************/
+#if defined WNT || defined OS2
+
+void FileStat::SetDateTime( const String& rFileName,
+ const DateTime& rNewDateTime )
+{
+ ByteString aFileName(rFileName, osl_getThreadTextEncoding());
+
+ Date aNewDate = rNewDateTime;
+ Time aNewTime = rNewDateTime;
+
+#if defined WNT
+ TIME_ZONE_INFORMATION aTZI;
+ DWORD dwTZI = GetTimeZoneInformation( &aTZI );
+
+ if ( dwTZI != (DWORD)-1 && dwTZI != TIME_ZONE_ID_UNKNOWN )
+ {
+ // 1. Korrektur der Zeitzone
+ LONG nDiff = aTZI.Bias;
+ Time aOldTime = aNewTime; // alte Zeit merken
+
+ // 2. evt. Korrektur Sommer-/Winterzeit
+ if ( dwTZI == TIME_ZONE_ID_DAYLIGHT )
+ nDiff += aTZI.DaylightBias;
+
+ Time aDiff( abs( nDiff / 60 /*Min -> Std*/ ), 0 );
+
+ if ( nDiff > 0 )
+ {
+ aNewTime += aDiff; // Stundenkorrektur
+
+ // bei "Uberlauf korrigieren
+ if ( aNewTime >= Time( 24, 0 ) )
+ aNewTime -= Time( 24, 0 );
+
+ // Tages"uberlauf?
+ if ( aOldTime == Time( 0, 0 ) || // 00:00 -> 01:00
+ aNewTime < aOldTime ) // 23:00 -> 00:00 | 01:00 ...
+ aNewDate++;
+ }
+ else if ( nDiff < 0 )
+ {
+ aNewTime -= aDiff; // Stundenkorrektur
+
+ // negative Zeit (-1:00) korrigieren: 23:00
+ if (aNewTime < Time( 0, 0 ) )
+ aNewTime += Time( 24, 0 );
+
+ // Tagesunterlauf ?
+ if ( aOldTime == Time( 0, 0 ) || // 00:00 -> 23:00
+ aNewTime > aOldTime ) // 01:00 -> 23:00 | 22:00 ...
+ aNewDate--;
+ }
+ }
+
+
+ SYSTEMTIME aTime;
+ aTime.wYear = aNewDate.GetYear();
+ aTime.wMonth = aNewDate.GetMonth();
+ aTime.wDayOfWeek = 0;
+ aTime.wDay = aNewDate.GetDay();
+ aTime.wHour = aNewTime.GetHour();
+ aTime.wMinute = aNewTime.GetMin();
+ aTime.wSecond = aNewTime.GetSec();
+ aTime.wMilliseconds = 0;
+ FILETIME aFileTime;
+ SystemTimeToFileTime( &aTime, &aFileTime );
+
+ HANDLE hFile = CreateFile( aFileName.GetBuffer(), GENERIC_WRITE, 0, 0,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
+
+ if ( hFile != INVALID_HANDLE_VALUE )
+ {
+ SetFileTime( hFile, &aFileTime, &aFileTime, &aFileTime );
+ CloseHandle( hFile );
+ }
+#elif defined OS2
+
+ // open file
+ ULONG nAction = FILE_EXISTED;
+ HFILE hFile = 0;
+ ULONG nFlags = OPEN_FLAGS_WRITE_THROUGH |
+ OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE |
+ OPEN_FLAGS_RANDOM | OPEN_FLAGS_NOINHERIT |
+ OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE;
+
+ APIRET nRet = DosOpen((PSZ)aFileName.GetBuffer(), &hFile, (PULONG)&nAction,
+ 0/*size*/, FILE_NORMAL,
+ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
+ nFlags, 0/*ea*/);
+
+ if ( nRet == 0 )
+ {
+ FILESTATUS3 FileInfoBuffer;
+
+ nRet = DosQueryFileInfo(
+ hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
+
+ if ( nRet == 0 )
+ {
+ FDATE aNewDate;
+ FTIME aNewTime;
+
+ // create date and time words
+ aNewDate.day = rNewDateTime.GetDay();
+ aNewDate.month = rNewDateTime.GetMonth();
+ aNewDate.year = rNewDateTime.GetYear() - 1980;
+ aNewTime.twosecs = rNewDateTime.GetSec() / 2;
+ aNewTime.minutes = rNewDateTime.GetMin();
+ aNewTime.hours = rNewDateTime.GetHour();
+
+ // set file date and time
+ FileInfoBuffer.fdateCreation = aNewDate;
+ FileInfoBuffer.ftimeCreation = aNewTime;
+ FileInfoBuffer.fdateLastAccess = aNewDate;
+ FileInfoBuffer.ftimeLastAccess = aNewTime;
+ FileInfoBuffer.fdateLastWrite = aNewDate;
+ FileInfoBuffer.ftimeLastWrite = aNewTime;
+
+ DosSetFileInfo(hFile, 1, &FileInfoBuffer, sizeof(FileInfoBuffer));
+ }
+ DosClose(hFile);
+ }
+#endif
+
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/makefile.mk b/tools/source/fsys/makefile.mk
new file mode 100644
index 000000000000..b1d34d6347f3
--- /dev/null
+++ b/tools/source/fsys/makefile.mk
@@ -0,0 +1,67 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=tools
+TARGET=fsys
+ENABLE_EXCEPTIONS=true
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+.IF "$(COM)"=="GCC"
+CFLAGSCXX+=-fexceptions
+.ENDIF
+
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/tempfile.obj \
+ $(SLO)$/wldcrd.obj \
+ $(SLO)$/fstat.obj \
+ $(SLO)$/comdep.obj \
+ $(SLO)$/filecopy.obj \
+ $(SLO)$/dirent.obj \
+ $(SLO)$/tdir.obj \
+ $(SLO)$/urlobj.obj
+
+OBJFILES= $(OBJ)$/wldcrd.obj \
+ $(OBJ)$/fstat.obj \
+ $(OBJ)$/comdep.obj \
+ $(OBJ)$/filecopy.obj \
+ $(OBJ)$/dirent.obj \
+ $(OBJ)$/tdir.obj \
+ $(OBJ)$/urlobj.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/tools/source/fsys/os2.cxx b/tools/source/fsys/os2.cxx
new file mode 100644
index 000000000000..ca57f7dd9ca9
--- /dev/null
+++ b/tools/source/fsys/os2.cxx
@@ -0,0 +1,885 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_DOSEXCEPTIONS
+
+#include <stdlib.h>
+
+#ifdef __BORLANDC__
+#include <alloc.h>
+#else
+#include <malloc.h>
+#endif
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include <tools/bigint.hxx>
+#include <tools/fsys.hxx>
+#include "comdep.hxx"
+
+#ifdef OS2
+#include <osl/mutex.hxx>
+#endif
+
+int Sys2SolarError_Impl( int nSysErr );
+
+DECLARE_LIST( DirEntryList, DirEntry* );
+DECLARE_LIST( FSysSortList, FSysSort* );
+DECLARE_LIST( FileStatList, FileStat* );
+
+static char sCaseMap[256];
+static BOOL bCaseMap = FALSE;
+static BOOL bDriveMap = FALSE;
+
+struct DriveMapItem
+{
+ DirEntryKind nKind;
+ char cName;
+ FSysPathStyle nStyle;
+};
+
+void CreateCaseMapImpl();
+void CreateDriveMapImpl();
+
+static DriveMapItem aDriveMap[26];
+
+static BOOL bLastCaseSensitive = FALSE;
+
+//====================================================================
+
+int ApiRet2ToSolarError_Impl( int nApiRet )
+{
+ switch ( nApiRet )
+ {
+ case NO_ERROR: return ERRCODE_NONE;
+ case ERROR_FILE_NOT_FOUND: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_PATH_NOT_FOUND: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_TOO_MANY_OPEN_FILES: return ERRCODE_IO_TOOMANYOPENFILES;
+ case ERROR_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_NOT_ENOUGH_MEMORY: return ERRCODE_IO_OUTOFMEMORY;
+ case ERROR_BAD_FORMAT: return ERRCODE_IO_WRONGFORMAT;
+ case ERROR_NOT_SAME_DEVICE: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_WRITE_PROTECT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_BAD_UNIT: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_CRC: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_NOT_DOS_DISK: return ERRCODE_IO_INVALIDDEVICE;
+ case ERROR_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_READ_FAULT: return ERRCODE_IO_CANTREAD;
+ case ERROR_SHARING_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCK_VIOLATION: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_WRONG_DISK: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_HANDLE_DISK_FULL: return ERRCODE_IO_OUTOFSPACE;
+ case ERROR_NOT_SUPPORTED: return ERRCODE_IO_NOTSUPPORTED;
+ case ERROR_DUP_NAME: return ERRCODE_IO_ALREADYEXISTS;
+ case ERROR_BAD_NETPATH: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_DEV_NOT_EXIST: return ERRCODE_IO_NOTEXISTS;
+ case ERROR_NETWORK_ACCESS_DENIED: return ERRCODE_IO_ACCESSDENIED;
+ case ERROR_INVALID_PARAMETER: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_NET_WRITE_FAULT: return ERRCODE_IO_CANTWRITE;
+ case ERROR_DEVICE_IN_USE: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_DISK_FULL: return ERRCODE_IO_OUTOFSPACE;
+ case ERROR_BAD_ARGUMENTS: return ERRCODE_IO_INVALIDPARAMETER;
+ case ERROR_BAD_PATHNAME: return ERRCODE_IO_NOTEXISTSPATH;
+ case ERROR_LOCK_FAILED: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_LOCKED: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_DUPLICATE_NAME: return ERRCODE_IO_ALREADYEXISTS;
+ case ERROR_DIRECTORY_IN_CDS: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_CURRENT_DIRECTORY: return ERRCODE_IO_LOCKVIOLATION;
+ case ERROR_FILENAME_EXCED_RANGE: return ERRCODE_IO_NAMETOOLONG;
+ }
+
+ DBG_TRACE1( "FSys: unknown apiret error %d occured", nApiRet );
+ return FSYS_ERR_UNKNOWN;
+}
+
+//--------------------------------------------------------------------
+
+char* volumeid( const char* pPfad )
+{
+ static FSINFO aFSInfoBuf;
+ ULONG ulFSInfoLevel = FSIL_VOLSER;
+ ULONG nDriveNumber;
+
+ nDriveNumber = toupper(*pPfad) - 'A' + 1;
+
+ if ( nDriveNumber >= 3 )
+ {
+ APIRET rc = DosQueryFSInfo(
+ nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) );
+ if ( rc )
+ return 0;
+ return (char*) aFSInfoBuf.vol.szVolLabel;
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:30
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ return TRUE;
+
+ char sBuf[_MAX_PATH + 1];
+ *this = DirEntry( String( getcwd( sBuf, _MAX_PATH ), osl_getThreadTextEncoding() ) ) + *this;
+
+ return IsAbs();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.03.92
+|* Letzte Aenderung MI 04.03.92
+|*
+*************************************************************************/
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ String aRet;
+ const DirEntry *pTop = ImpGetTopPtr();
+ ByteString aName = ByteString( pTop->aName ).ToLowerAscii();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME )
+ && aName != "a:" && aName != "b:" && Exists() )
+ {
+ const char *pVol;
+ pVol = volumeid( (char*) pTop->aName.GetBuffer() );
+ if (pVol)
+ aRet = String( pVol, osl_getThreadTextEncoding());
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( eFlag == FSYS_FLAG_CURRENT && !aName.Len() )
+ return TRUE;
+
+ if ( !chdir(ByteString(GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ //nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ if ( bSloppy && pParent &&
+ !chdir(ByteString(pParent->GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ //nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ //nError = FSYS_ERR_NOTADIRECTORY;
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::MoveTo()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 14:07
+|*
+*************************************************************************/
+
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ // Block-Devices auflisten?
+ if ( pDir->eAttrMask & FSYS_KIND_BLOCK )
+ {
+ CreateDriveMapImpl();
+ // CWD merken
+ DirEntry aCurrentDir;
+ aCurrentDir.ToAbs();
+
+ // einzeln auf Existenz und Masken-konformit"at pr"ufen
+ USHORT nRead = 0;
+ char sDrive[3] = { '?', ':', 0 };
+ char sRoot[4] = { '?', ':', '\\', 0 };
+ for ( char c = 'a'; c <= 'z'; c++ )
+ {
+ sDrive[0] = c;
+ sRoot[0] = c;
+ DirEntry* pDrive = new DirEntry( sDrive, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ if ( pDir->aNameMask.Matches( String( ByteString(sDrive), osl_getThreadTextEncoding()))
+ && aDriveMap[c-'a'].nKind != FSYS_KIND_UNKNOWN )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( *pDrive );
+ pDir->ImpSortedInsert( pDrive, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pDrive, NULL );
+ ++nRead;
+ }
+ else
+ delete pDrive;
+ }
+
+ // CWD restaurieren
+ aCurrentDir.SetCWD();
+ return nRead;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ if (!pDosDir)
+ {
+ pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
+ }
+
+ if (!pDosDir)
+ {
+ bReady = TRUE;
+ return 0;
+ }
+
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
+ if ( pDir->aNameMask.Matches( aD_Name ) )
+ {
+ DirEntryFlag eFlag =
+ 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
+ : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE);
+ FileStat aStat( *pTemp );
+ if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+ ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
+ !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
+ pDosEntry->d_name[0] == '.' ) )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );;
+ return 1;
+ }
+ else
+ delete pTemp;
+ }
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *pInfo, // struct dirent
+ const void * ): // dummy
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+ struct dirent *pDirent = (struct dirent*) pInfo;
+
+ nSize = pDirent->d_size;
+
+ aDateCreated = MsDos2Date( (FDATE*) &pDirent->d_date );
+ aTimeCreated = MsDos2Time( (FTIME*) &pDirent->d_time );
+ aDateModified = aDateModified;
+ aTimeModified = aTimeModified;
+ aDateAccessed = aDateModified;
+ aTimeAccessed = aTimeModified;
+
+ nKindFlags = FSYS_KIND_FILE;
+ if ( pDirent->d_type & DOS_DIRECT )
+ nKindFlags = FSYS_KIND_DIR;
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+struct _FSYS_FSQBUFFER
+{
+ FSQBUFFER2 aBuf;
+ UCHAR sBuf[256];
+};
+
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL bAccessRemovableDevice )
+{
+ nSize = 0;
+ FSysPathStyle eStyle = FSYS_STYLE_UNKNOWN;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if ( !rDirEntry.IsValid() )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root ohne Laufwerk handelt
+ if ( !rDirEntry.aName.Len() && rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ nKindFlags = FSYS_KIND_DIR;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
+ if ( strchr( aTempName.GetBuffer(), '?' ) ||
+ strchr( aTempName.GetBuffer(), '*' ) ||
+ strchr( aTempName.GetBuffer(), ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root handelt
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME ||
+ rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = FSYS_KIND_DEV;
+ else
+ nKindFlags = FSYS_KIND_DIR;
+
+ if ( rDirEntry.aName.Len() == 2 )
+ {
+ if ( !bDriveMap )
+ CreateDriveMapImpl();
+
+ ByteString rDirEntryUpperCase = ByteString( rDirEntry.aName ).ToUpperAscii();
+ DriveMapItem &rItem = aDriveMap[rDirEntryUpperCase.GetChar(0) - 'A'];
+ if ( !rItem.nKind )
+ {
+ nError = ERRCODE_IO_INVALIDDEVICE;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ return FALSE;
+ }
+ else
+ {
+ if ( rDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags |= FSYS_KIND_BLOCK | rItem.nKind;
+ eStyle = rItem.nStyle;
+ }
+ }
+
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // disable error-boxes for hard-errors
+ DosError(FERR_DISABLEHARDERR);
+
+ // Statusinformation vom Betriebssystem holen
+ DirEntry aTempDirEntry( rDirEntry );
+ char* p;
+
+ aTempDirEntry.ToAbs();
+ ByteString aFullName( aTempDirEntry.GetFull(), osl_getThreadTextEncoding() );
+
+ p = (char *) aFullName.GetBuffer();
+
+ FILESTATUS3 filestat;
+ memset( &filestat, 0, sizeof( filestat ) );
+ if( DosQueryPathInfo( (PSZ)p, 1, &filestat, sizeof( filestat ) ) )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ return FALSE;
+ }
+
+ nError = FSYS_ERR_OK;
+ nSize = filestat.cbFile;
+
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ if( filestat.attrFile & FILE_DIRECTORY )
+ nKindFlags |= FSYS_KIND_DIR;
+ if ( nKindFlags == FSYS_KIND_UNKNOWN )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+
+ aDateModified = Date( filestat.fdateLastWrite.day,
+ filestat.fdateLastWrite.month,
+ filestat.fdateLastWrite.year + 1980 );
+
+ aTimeModified = Time( filestat.ftimeLastWrite.hours,
+ filestat.ftimeLastWrite.minutes,
+ filestat.ftimeLastWrite.twosecs*2 );
+
+ if ( filestat.fdateCreation.day )
+ {
+ aDateCreated = Date( filestat.fdateCreation.day,
+ filestat.fdateCreation.month,
+ filestat.fdateCreation.year + 1980 );
+
+ aTimeCreated = Time( filestat.ftimeCreation.hours,
+ filestat.ftimeCreation.minutes,
+ filestat.ftimeCreation.twosecs*2 );
+ }
+ else
+ {
+ aDateCreated = aDateModified;
+ aTimeCreated = aTimeModified;
+ }
+
+ if ( filestat.fdateLastAccess.day > 0 )
+ {
+ aDateAccessed = Date( filestat.fdateLastAccess.day,
+ filestat.fdateLastAccess.month,
+ filestat.fdateLastAccess.year + 1980 );
+
+ aTimeAccessed = Time( filestat.ftimeLastAccess.hours,
+ filestat.ftimeLastAccess.minutes,
+ filestat.ftimeLastAccess.twosecs*2 );
+ }
+ else
+ {
+ aDateAccessed = aDateModified;
+ aTimeAccessed = aTimeModified;
+ }
+
+ return TRUE;
+}
+
+BOOL IsRedirectable_Impl( const ByteString &rPath )
+{
+ if ( rPath.Len() >= 3 && ':' == rPath.GetBuffer()[1] )
+ {
+ ByteString aVolume = rPath.Copy( 0, 3 );
+ DriveMapItem &rItem = aDriveMap[toupper(aVolume.GetChar(0)) - 'A'];
+ return FSYS_KIND_FIXED != rItem.nKind;
+ }
+ return FALSE;
+}
+
+
+/*************************************************************************
+|*
+|* TempDirImpl()
+|*
+|* Beschreibung liefert den Namens des Directories fuer temporaere
+|* Dateien
+|* Ersterstellung MI 16.03.94
+|* Letzte Aenderung MI 16.03.94
+|*
+*************************************************************************/
+
+const char* TempDirImpl( char *pBuf )
+{
+ PSZ pVar;
+ USHORT nRet;
+ BOOL bAppendTemp = FALSE; // mu\s noch \\temp angeh"angt werden
+
+ // Erstmal sehen, ob TEMP oder TMP gesetzt sind
+ nRet = DosScanEnv( (PSZ)"TEMP", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"temp", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"TMP", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"tmp", &pVar );
+ if( nRet )
+ nRet = DosScanEnv( (PSZ)"TMPDIR", &pVar );
+
+ // falls das geklappt hat, und ein Backslash dranhaengt,
+ // oder falls es bisher nicht geklappt hat,
+ // muessen wir nachher einen Backslash entfernen
+ BOOL bRemoveBS = nRet || *(pVar+strlen(pVar)-1) == '\\';
+
+ // Keine temp-Variable gefunden, dann gehen wir mal auf die Suche
+ // nach dem System-Laufwerk
+ if( nRet )
+ {
+ nRet = DosScanEnv( (PSZ)"USER_INI",&pVar );
+ bAppendTemp = (0 == nRet);
+ }
+ if( nRet )
+ {
+ nRet = DosScanEnv( (PSZ)"SYSTEM_INI", &pVar );
+ bAppendTemp = (0 == nRet);
+ }
+ if( nRet )
+ // Wenn das immer noch nicht reicht nehmen wir eben die Root von C:
+#ifdef __BORLANDC__
+ pVar = (PSZ)"c:\\temp\\";
+#else
+ pVar = (PCSZ)"c:\\temp\\";
+#endif
+ strcpy( pBuf, (const char*)pVar );
+
+ // jetzt haengt ggf. ein Backlash dran, den wir abschneiden,
+ // ggf. inklusive dahinter haengendem Dateinamen
+ if ( bRemoveBS )
+ {
+ char *pTail = pBuf + strlen(pBuf) - 1;
+ for ( char cLast = *pTail; cLast != '\\'; cLast = *(--pTail) )
+ *pTail = 0;
+ }
+
+ if ( bAppendTemp )
+ strcat( pBuf, "\\temp" );
+ DirEntry( pBuf ).MakeDir();
+
+ return pBuf;
+}
+
+#define CURRENT_COUNTRY 0
+#define NLS_CODEPAGE 850
+
+/*====================================================================
+ * CreateDriveMapImpl()
+ * creates a map of drive-infos like FileSystem (style) and Kind (remote)
+ *--------------------------------------------------------------------*/
+typedef struct _FSQBUFFER_
+{
+ FSQBUFFER2 aBuf;
+ UCHAR sBuf[64];
+} FSQBUFFER_;
+
+void CreateDriveMapImpl()
+{
+#ifdef POWERPC
+ // !!!!! Hack, da der untere Teil mit Beta 2 noch abstuertzt !!!!!
+ BYTE nFloppies = 1;
+ for ( USHORT nDrive = 0; nDrive < 26; ++nDrive )
+ {
+ if ( nDrive < nFloppies )
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
+ }
+ else
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
+ }
+ }
+
+ aDriveMap[2].nKind = FSYS_KIND_FIXED;
+ aDriveMap[2].nStyle = FSYS_STYLE_FAT;
+#else
+ FSQBUFFER_ aBuf;
+ ULONG nBufLen;
+ APIRET nRet;
+ USHORT nDrive;
+
+ // disable error-boxes for hard-errors
+ DosError(FERR_DISABLEHARDERR);
+
+ // determine number of floppy-drives
+ BYTE nFloppies;
+ nRet = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
+
+ // reset the map
+ for ( nDrive = 0; nDrive < 26; ++nDrive )
+ {
+ if ( nDrive < nFloppies )
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_FAT;
+ }
+ else
+ {
+ aDriveMap[nDrive].nKind = FSYS_KIND_UNKNOWN;
+ aDriveMap[nDrive].nStyle = FSYS_STYLE_UNKNOWN;
+ }
+ }
+
+ // determine file-system via DosOpen/DocDevIOCtrl
+ for ( nDrive = 2; nDrive < 26; ++nDrive )
+ {
+ // open drive
+ BOOL bFixed;
+ HFILE nDevHandle;
+ char pDriveName[3] = "#:";
+ pDriveName[0] = nDrive+'a';
+ ULONG nAction;
+ nRet = DosOpen( (PSZ) pDriveName, &nDevHandle,
+ &nAction, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_FLAGS_DASD|OPEN_SHARE_DENYNONE|OPEN_ACCESS_READONLY,
+ 0 );
+
+ // exists?
+ if ( !nRet )
+ {
+ // removeable?
+ BYTE nDriveId = nDrive;
+ ULONG nParaOutLen, nDataOutLen;
+ nRet = DosDevIOCtl(nDevHandle, 8, 0x20,
+ &nDriveId, sizeof(nDriveId), &nParaOutLen,
+ &bFixed, sizeof(bFixed), &nDataOutLen );
+
+ // prepare the drive-map
+ if ( !nRet && !bFixed )
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE;
+
+ // close drive
+ DosClose(nDevHandle);
+ }
+ else if ( nRet == ERROR_NOT_READY )
+ aDriveMap[nDrive].nKind = FSYS_KIND_REMOVEABLE | FSYS_KIND_CDROM;
+ }
+
+ // determine file-system via FSAttach
+ nRet = 0;
+ for ( USHORT n = 3; nRet != ERROR_NO_MORE_ITEMS; ++n )
+ {
+ nBufLen = sizeof( aBuf );
+ nRet = DosQueryFSAttach( 0, n, FSAIL_DRVNUMBER,
+ (_FSQBUFFER2*) &aBuf, &nBufLen );
+ if ( !nRet )
+ {
+ nDrive = toupper(aBuf.aBuf.szName[0]) - 'A';
+
+ if ( aDriveMap[nDrive].nKind == FSYS_KIND_UNKNOWN )
+ aDriveMap[nDrive].nKind =
+ aBuf.aBuf.iType == 3 ? FSYS_KIND_FIXED :
+ aBuf.aBuf.iType == 4 ? FSYS_KIND_REMOTE :
+ FSYS_KIND_UNKNOWN;
+
+ char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1);
+ aDriveMap[nDrive].nStyle =
+ strcmp( pType, "FAT" ) == 0 ? FSYS_STYLE_FAT :
+ strcmp( pType, "FAT32" ) == 0 ? FSYS_STYLE_VFAT :
+ strcmp( pType, "NTFS" ) == 0 ? FSYS_STYLE_NTFS :
+ strcmp( pType, "HPFS" ) == 0 ? FSYS_STYLE_HPFS :
+ strcmp( pType, "JFS" ) == 0 ? FSYS_STYLE_HPFS :
+ strcmp( pType, "RAMFS" ) == 0 ? FSYS_STYLE_HPFS :
+ strcmp( pType, "NDFS32" ) == 0 ? FSYS_STYLE_HPFS :
+ strcmp( pType, "NWFS" ) == 0 ? FSYS_STYLE_NWFS :
+ strcmp( pType, "EXT2" ) == 0 ? FSYS_STYLE_UNX :
+ strcmp( pType, "NFS" ) == 0 ? FSYS_STYLE_UNX :
+ FSYS_STYLE_UNKNOWN;
+ if ( strcmp( pType, "CDFS" ) == 0 )
+ aDriveMap[nDrive].nKind = FSYS_KIND_CDROM|FSYS_KIND_REMOVEABLE;
+ }
+ }
+#endif
+
+ bDriveMap = TRUE;
+}
+
+Time MsDos2Time( const time_t *pTimeT )
+{
+ tm *pTm = localtime( pTimeT );
+ if ( pTm )
+ return Time( pTm->tm_hour, pTm->tm_min, pTm->tm_sec );
+ else
+ return Time(0);
+}
+
+Date MsDos2Date( const time_t *pTimeT )
+{
+ tm *pTm = localtime( pTimeT );
+ if ( pTm )
+ return Date( pTm->tm_mday, pTm->tm_mon + 1, pTm->tm_year );
+ else
+ return Date(0);
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
+{
+ ByteString aRootDir(rDevice, osl_getThreadTextEncoding());
+ // UNC-Pathname?
+ if ( aRootDir.Len()==0 || ( aRootDir.Len() > 1 && aRootDir.GetChar(1) != ':' ) )
+ return FSYS_STYLE_UNKNOWN;
+
+ if ( !bDriveMap )
+ CreateDriveMapImpl();
+ return aDriveMap[toupper(aRootDir.GetChar(0)) - 'A'].nStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsCaseSensitive() const
+|*
+|* Beschreibung
+|* Ersterstellung TPF 26.02.1999
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+ if (GetPathStyle(GetDevice().GetName()) == FSYS_STYLE_UNX)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ BOOL isCaseSensitive = FALSE; // ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = FALSE; // ich bin unter OS2, also ist der default im Zweifelsfall case insensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+
+
+
+//=========================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &rPath,
+ BigInt &rFreeBytes, BigInt &rTotalBytes )
+{
+ FSALLOCATE aFSInfoBuf;
+ ByteString aVol( DirEntry(rPath).ImpGetTopPtr()->GetName(), osl_getThreadTextEncoding());
+ ULONG nDriveNumber = toupper( aVol.GetChar(0) ) - 'A' + 1;
+
+ APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC,
+ &aFSInfoBuf, sizeof(aFSInfoBuf) );
+ if ( rc )
+ return Sys2SolarError_Impl( rc );
+
+ BigInt aBytesPerCluster( BigInt(aFSInfoBuf.cbSector) *
+ BigInt(aFSInfoBuf.cSectorUnit) );
+ rFreeBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnitAvail);
+ rTotalBytes = aBytesPerCluster * BigInt(aFSInfoBuf.cUnit);
+ return 0;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL bEnable )
+{
+ DosError( bEnable ? 0 : FERR_DISABLEHARDERR );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/os2.hxx b/tools/source/fsys/os2.hxx
new file mode 100644
index 000000000000..be74befe36b5
--- /dev/null
+++ b/tools/source/fsys/os2.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _os2_hxx
+#define _os2_hxx
+
+
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSFILEMGR
+#define INCL_DOSPROCESS
+#define INCL_DOSDEVICES
+#define INCL_DOSERRORS
+#define INCL_DOSMISC
+#define INCL_DOSNLS /* National Language Support values */
+#include <svpm.h>
+
+#include <dirent.h>
+#include <string.h>
+
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <emx/syscalls.h>
+
+#define FSYS_UNIX FALSE
+
+#define DOS_DIRECT _A_SUBDIR
+#define DOS_VOLUMEID _A_VOLID
+
+#define _mkdir(p) mkdir(p, 0777)
+
+const char* TempDirImpl( char *pBuf );
+String ToLowerImpl( const String& );
+
+#define DEFSTYLE FSYS_STYLE_OS2
+#define MKDIR( p ) mkdir( (unsigned char*) p )
+#define CMP_LOWER(s) ( s.ToLowerAscii() )
+
+#define START_DRV 'a'
+
+inline BOOL DRIVE_EXISTS( char c )
+{
+ ULONG nCur, nMap;
+ APIRET nRet = DosQueryCurrentDisk( &nCur, &nMap );
+ return ( nMap & 1 << (c - 'a') ) != 0;
+}
+
+#include <time.h>
+
+inline Time MsDos2Time( FTIME* aTime )
+{
+ return Time( aTime->hours, aTime->minutes, 2*aTime->twosecs );
+}
+
+inline Date MsDos2Date( FDATE* aDate )
+{
+ return Date( aDate->day, aDate->month, aDate->year );
+}
+
+Time MsDos2Time( const time_t *pTimeT );
+
+Date MsDos2Date( const time_t *pTimeT );
+
+#define FSysFailOnErrorImpl()
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/tdir.cxx b/tools/source/fsys/tdir.cxx
new file mode 100644
index 000000000000..93b67d9c7b2d
--- /dev/null
+++ b/tools/source/fsys/tdir.cxx
@@ -0,0 +1,769 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#define _DIR_CXX
+
+#include <stdlib.h>
+#include <cstdarg>
+#include <limits.h>
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+
+#include "comdep.hxx"
+#include <tools/fsys.hxx>
+
+
+DBG_NAME( Dir )
+
+DECLARE_LIST( DirEntryList, DirEntry* )
+DECLARE_LIST( FSysSortList, FSysSort* )
+DECLARE_LIST( FileStatList, FileStat* )
+
+#define APPEND (USHORT) 65535
+
+/*************************************************************************
+|*
+|* Dir::InsertPointReached()
+|*
+|* Beschreibung stellt fest, ob eingefuegt werden musz
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+BOOL Dir::ImpInsertPointReached( const DirEntry& rNewEntry,
+ const FileStat& rNewStat,
+ ULONG nCurPos, ULONG nSortIndex ) const
+{
+#define VALUE( nKindFlags ) \
+ ( ( FSYS_KIND_FILE | FSYS_KIND_DIR | FSYS_KIND_DEV | \
+ FSYS_KIND_CHAR | FSYS_KIND_BLOCK ) & nKindFlags )
+
+ // einfache Dinge erfordern einfache Loesungen
+ if ( !pLst->Count() )
+ return TRUE;
+
+ FSysSort nSort = *( pSortLst->GetObject( nSortIndex ) );
+ FileStat *pOldStat = NULL;
+ DirEntry *pCurLstObj = pLst->GetObject( nCurPos );
+ if ( pStatLst )
+ pOldStat = pStatLst->GetObject( nCurPos );
+
+ switch( nSort )
+ {
+ case FSYS_SORT_NAME:
+ case (FSYS_SORT_NAME | FSYS_SORT_ASCENDING):
+ if ( pCurLstObj->aName > rNewEntry.aName )
+ return TRUE;
+ if ( !(pCurLstObj->aName == rNewEntry.aName) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_NAME | FSYS_SORT_DESCENDING):
+ if ( pCurLstObj->aName < rNewEntry.aName )
+ return TRUE;
+ if ( !(pCurLstObj->aName == rNewEntry.aName) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_EXT:
+ case (FSYS_SORT_EXT | FSYS_SORT_ASCENDING):
+ {
+ if ( pCurLstObj->GetExtension() > rNewEntry.GetExtension() )
+ return TRUE;
+ if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
+ return FALSE;
+ break;
+ }
+ case (FSYS_SORT_EXT | FSYS_SORT_DESCENDING):
+ {
+ if ( pCurLstObj->GetExtension() < rNewEntry.GetExtension() )
+ return TRUE;
+ if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) )
+ return FALSE;
+ break;
+ }
+
+ case FSYS_SORT_KIND:
+ case (FSYS_SORT_KIND | FSYS_SORT_ASCENDING ):
+ if ( VALUE(pOldStat->nKindFlags) > VALUE(rNewStat.nKindFlags) )
+ return TRUE;
+ if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_KIND | FSYS_SORT_DESCENDING):
+ if ( VALUE(pOldStat->nKindFlags) < VALUE(rNewStat.nKindFlags) )
+ return TRUE;
+ if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_SIZE:
+ case (FSYS_SORT_SIZE | FSYS_SORT_ASCENDING):
+ if ( pOldStat->nSize > rNewStat.nSize )
+ return TRUE;
+ if ( !(pOldStat->nSize == rNewStat.nSize) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_SIZE | FSYS_SORT_DESCENDING):
+ if ( pOldStat->nSize < rNewStat.nSize )
+ return TRUE;
+ if ( !(pOldStat->nSize == rNewStat.nSize) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_MODIFYED:
+ case (FSYS_SORT_MODIFYED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateModified >= rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified > rNewStat.aTimeModified) )
+ return TRUE;
+ if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_MODIFYED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateModified <= rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified < rNewStat.aTimeModified) )
+ return TRUE;
+ if ( !((pOldStat->aDateModified == rNewStat.aDateModified) &&
+ (pOldStat->aTimeModified == rNewStat.aTimeModified)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_CREATED:
+ case (FSYS_SORT_CREATED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateCreated >= rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated > rNewStat.aTimeCreated) )
+ return TRUE;
+ if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_CREATED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateCreated <= rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated < rNewStat.aTimeCreated) )
+ return TRUE;
+ if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) &&
+ (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) )
+ return FALSE;
+ break;
+
+ case FSYS_SORT_ACCESSED:
+ case (FSYS_SORT_ACCESSED | FSYS_SORT_ASCENDING):
+ if ( (pOldStat->aDateAccessed >= rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed > rNewStat.aTimeAccessed) )
+ return TRUE;
+ if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
+ return FALSE;
+ break;
+ case (FSYS_SORT_ACCESSED | FSYS_SORT_DESCENDING):
+ if ( (pOldStat->aDateAccessed <= rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed < rNewStat.aTimeAccessed) )
+ return TRUE;
+ if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) &&
+ (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) )
+ return FALSE;
+ break;
+ default: /* Kann nicht sein */;
+ }
+
+ if ( nSortIndex == ( pSortLst->Count() - 1 ) )
+ return TRUE;
+ else
+ //Rekursion
+ return ImpInsertPointReached( rNewEntry, rNewStat,
+ nCurPos, nSortIndex + 1 );
+#undef VALUE
+}
+
+/*************************************************************************
+|*
+|* Dir::ImpSortedInsert()
+|*
+|* Beschreibung fuegt sortiert ein
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 03.12.91
+|*
+*************************************************************************/
+
+void Dir::ImpSortedInsert( const DirEntry *pNewEntry, const FileStat *pNewStat )
+{
+ //Sonderfall, keine Sortierung gewuenscht.
+ if ( !pSortLst ) {
+ pLst->Insert( (DirEntry*)pNewEntry, APPEND );
+ return;
+ }
+
+ pLst->First();
+ do {
+ if ( ImpInsertPointReached( *pNewEntry, *pNewStat, pLst->GetCurPos(),
+ (ULONG)0 ) )
+ {
+ if ( pStatLst )
+ pStatLst->Insert( (FileStat*)pNewStat, pLst->GetCurPos() );
+ pLst->Insert( (DirEntry*)pNewEntry );
+ return;
+ }
+ } while( pLst->Next() );
+
+ if ( pStatLst )
+ pStatLst->Insert( (FileStat*)pNewStat, APPEND );
+ pLst->Insert( (DirEntry*)pNewEntry, APPEND );
+}
+
+/*************************************************************************
+|*
+|* Dir::Construct()
+|*
+|* Beschreibung gemeinsame Implementation der Ctoren
+|* Ersterstellung MI 02.06.93
+|* Letzte Aenderung MI 02.06.93
+|*
+*************************************************************************/
+
+void Dir::Construct( DirEntryKind nKindFlags )
+{
+ pLst = NULL;
+ pSortLst = NULL;
+ pStatLst = NULL;
+ eAttrMask = nKindFlags;
+ ByteString aTempName( GetName(), osl_getThreadTextEncoding() );
+ if ( aTempName.Search( "*" ) != STRING_NOTFOUND ||
+ aTempName.Search( "?" ) != STRING_NOTFOUND )
+#if defined( WNT ) && !defined( WTC )
+ {
+ ByteString aTStr(CutName(), osl_getThreadTextEncoding());
+ char* pBuffer = new char[aTStr.Len()+1];
+ strcpy( pBuffer, aTStr.GetBuffer() );
+ CharLowerBuff( pBuffer, aTStr.Len() );
+ aNameMask = WildCard( String(pBuffer, osl_getThreadTextEncoding()), ';' );
+ delete [] pBuffer;
+ }
+#else
+ aNameMask = WildCard( CutName(), ';' );
+#endif
+ else
+ aNameMask = String("*", osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* Dir::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 19.09.96
+|*
+*************************************************************************/
+
+BOOL Dir::Update()
+{
+ Reset();
+ return Scan( USHRT_MAX ) > 0;
+}
+
+/*************************************************************************
+|*
+|* Dir::Reset()
+|*
+|* Beschreibung
+|* Ersterstellung MI 22.10.96
+|* Letzte Aenderung MI 22.10.96
+|*
+*************************************************************************/
+
+void Dir::Reset()
+{
+ // ggf. alten Reader l"oschen
+ if ( pReader && pReader->bInUse )
+ DELETEZ(pReader);
+
+ // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
+ if ( pLst )
+ {
+ DirEntry* pEntry = pLst->First();
+ while (pEntry)
+ {
+ DirEntry* pNext = pLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pLst->Clear();
+ }
+ else
+ pLst = new DirEntryList();
+
+ // Alte File-Stat's Loeschen
+ if ( pStatLst )
+ {
+ //Erstmal die alten Loeschen
+ FileStat* pEntry = pStatLst->First();
+ while (pEntry)
+ {
+ FileStat* pNext = pStatLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pStatLst->Clear();
+ delete pStatLst;
+ }
+
+ // Verlangen die Sortierkriterien FileStat's?
+ if ( pSortLst )
+ {
+ pSortLst->First();
+ do
+ {
+ if ( *( pSortLst->GetCurObject() ) &
+ ( FSYS_SORT_KIND | FSYS_SORT_SIZE |
+ FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_ACCESSED ) )
+ pStatLst = new FileStatList();
+ } while ( !pStatLst && pSortLst->Next() );
+ }
+
+#ifndef BOOTSTRAP
+ // ggf. einen neuen Reader aufsetzen
+ if ( !pReader )
+ pReader = new DirReader_Impl( *this );
+#endif
+
+ // gibt es das zu oeffnende Verzeichnis ueberhaupt?
+#if !defined(UNX) && !defined(OS2) //explanation: see DirReader_Impl::Read() in unx.cxx
+ if( !pReader->pDosDir )
+ {
+ nError = FSYS_ERR_NOTADIRECTORY;
+ DELETEZ( pReader );
+ return;
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* Dir::Scan()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 18.09.96
+|* Letzte Aenderung MI 19.09.96
+|*
+*************************************************************************/
+
+USHORT Dir::Scan( USHORT nCount )
+{
+
+ USHORT nRead = 0; // Anzahl in dieser Runde gelesener Eintr"age
+ FSysFailOnErrorImpl();
+
+ // noch nicht fertig gewesen
+ if ( pReader )
+ {
+ // frischer Reader?
+ if ( !pLst->Count() )
+ {
+ // dann ggf. Laufwerke scannen
+ pReader->bInUse = TRUE;
+ nRead = pReader->Init();
+ }
+
+ // weiterlesen...
+ while ( nRead <= nCount && !pReader->bReady )
+ nRead = nRead + pReader->Read();
+
+ // fertig?
+ if ( pReader && pReader->bReady )
+ DELETEZ( pReader );
+ }
+
+ // Anzahl der gelesenen zur"uckgeben
+ return nRead;
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 04.03.92
+|*
+*************************************************************************/
+
+Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags, FSysSort nSort, ... ):
+ DirEntry( rDirEntry ),
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ Construct( nKindFlags );
+
+ std::va_list pArgs;
+ va_start( pArgs, nSort );
+ ImpSetSort( pArgs, nSort );
+
+ Reset();
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 02.06.93
+|* Letzte Aenderung MI 02.06.93
+|*
+*************************************************************************/
+
+Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags ):
+ DirEntry( rDirEntry ),
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ Construct( nKindFlags );
+ Reset();
+}
+
+/*************************************************************************
+|*
+|* Dir::Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MA 04.11.91
+|*
+*************************************************************************/
+
+Dir::Dir():
+ pReader( 0 )
+{
+ DBG_CTOR( Dir, NULL );
+
+ pLst = NULL;
+ pSortLst = NULL;
+ pStatLst = NULL;
+ eAttrMask = FSYS_KIND_ALL;
+ aNameMask = String("*", osl_getThreadTextEncoding());
+}
+
+/*************************************************************************
+|*
+|* Dir::~Dir()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MA 04.11.91
+|*
+*************************************************************************/
+
+Dir::~Dir()
+{
+ DBG_DTOR( Dir, NULL );
+
+ // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
+ if ( pLst )
+ {
+ DirEntry* pEntry = pLst->First();
+ while (pEntry)
+ {
+ DirEntry* pNext = pLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pLst->Clear();
+
+ delete pLst;
+ }
+
+ // alle Sorts aus der Liste entfernen und deren Speicher freigeben
+ if ( pSortLst )
+ {
+ FSysSort* pEntry = pSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pSortLst->Clear();
+
+ delete pSortLst;
+ }
+
+ // alle FileStat's aus der Liste entfernen und deren Speicher freigeben
+ if ( pStatLst )
+ {
+ FileStat* pEntry = pStatLst->First();
+ while (pEntry)
+ {
+ FileStat* pNext = pStatLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pStatLst->Clear();
+ delete pStatLst;
+ }
+
+ // ggf. laufenden Reader freigeben
+ delete pReader;
+}
+
+/*************************************************************************
+|*
+|* Dir::ImpSetSort()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 04.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+FSysError Dir::ImpSetSort( std::va_list pArgs, int nFirstSort )
+{
+ BOOL bLast;
+ FSysSort *pSort;
+ FSysSortList *pNewSortLst = new FSysSortList;
+
+ *( pSort = new FSysSort ) = nFirstSort;
+ do
+ {
+ // letztes Kriterium?
+ bLast = FSYS_SORT_END == (*pSort & FSYS_SORT_END);
+ *pSort &= ~FSYS_SORT_END;
+
+ FSysSort nSort = *pSort & ~(USHORT)FSYS_SORT_ASCENDING
+ & ~(USHORT)FSYS_SORT_DESCENDING;
+
+ // g"utliges Sortierkriterium?
+ if ( ( nSort == FSYS_SORT_NAME ) ||
+ ( nSort == FSYS_SORT_SIZE ) ||
+ ( nSort == FSYS_SORT_EXT ) ||
+ ( nSort == FSYS_SORT_CREATED ) ||
+ ( nSort == FSYS_SORT_MODIFYED ) ||
+ ( nSort == FSYS_SORT_ACCESSED ) ||
+ ( nSort == FSYS_SORT_KIND ) )
+ {
+ pNewSortLst->Insert( pSort, APPEND );
+ *(pSort = new FSysSort) = va_arg( pArgs, FSysSort );
+ }
+ else
+ { // ungueltiger Sort oder FSYS_SORT_NONE
+ FSysSort* pEntry = pNewSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pNewSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pNewSortLst->Clear();
+ delete pNewSortLst;
+ if ( *pSort == FSYS_SORT_NONE )
+ {
+ delete pSort;
+ if ( pSortLst )
+ delete pSortLst;
+ return FSYS_ERR_OK;
+ }
+ else
+ {
+ delete pSort;
+ return FSYS_ERR_NOTSUPPORTED;
+ }
+ }
+ } while ( !bLast );
+
+ va_end( pArgs );
+ delete pSort; // JP:6.3.00 - delete the initial pointer
+
+ //Enfernen der alten Sort-Elemente
+ if ( pSortLst )
+ {
+ FSysSort* pEntry = pSortLst->First();
+ while (pEntry)
+ {
+ FSysSort* pNext = pSortLst->Next();
+ delete pEntry;
+ pEntry = pNext;
+ }
+ pSortLst->Clear();
+ delete pSortLst;
+ }
+ pSortLst = pNewSortLst;
+
+ //Jetzt noch neu Sortieren...
+
+ //Wenn keine FileStats da sind, aber nun welche gebraucht werden,
+ //ist der Aufruf von Update() die einfachste Moeglichkeit
+ if ( !pStatLst && pSortLst )
+ {
+ pSortLst->First();
+ do
+ {
+ if ( *(pSortLst->GetCurObject()) &
+ ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE |
+ FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) )
+ {
+ Update();
+ return FSYS_ERR_OK;
+ }
+ } while ( !pStatLst && pSortLst->Next() );
+ }
+
+ if ( pLst ) { //Keine DirEntry's, kein Sort.
+ DirEntryList *pOldLst = pLst; //alte Liste merken
+ pLst = new DirEntryList(); //neue Liste (zu Sortieren)
+
+ FileStatList *pOldStatLst = NULL; //alte StatListe merken
+ if ( pStatLst ) {
+ pOldStatLst = pStatLst;
+ pStatLst = new FileStatList(); //neue StatListe (zu Sortieren)
+ }
+ pOldLst->First();
+ do
+ {
+ //Sortiertes Einfuegen der Elemente aus den gemerkten Listen
+ //in die 'richtigen' Listen
+ if ( pOldStatLst )
+ ImpSortedInsert( pOldLst->GetCurObject(),
+ pOldStatLst->GetObject( pOldLst->GetCurPos() ) );
+ else
+ ImpSortedInsert( pOldLst->GetCurObject(), NULL );
+ } while( pOldLst->Next() );
+
+ delete pOldLst;
+ if ( pOldStatLst )
+ delete pOldStatLst;
+ }
+ return FSYS_ERR_OK;
+}
+
+/*************************************************************************
+|*
+|* Dir::SetSort()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 04.11.91
+|* Letzte Aenderung MI 05.02.92
+|*
+*************************************************************************/
+
+FSysError Dir::SetSort( FSysSort nSort, ... )
+{
+ std::va_list pArgs;
+ va_start( pArgs, nSort );
+ return ImpSetSort( pArgs, nSort );
+}
+
+/*************************************************************************
+|*
+|* Dir::operator[]()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 16.05.91
+|*
+*************************************************************************/
+
+DirEntry& Dir::operator[] ( USHORT nIndex ) const
+{
+ DBG_ASSERT( nIndex < Count(), "Dir::operator[] : nIndex > Count()" );
+
+ DirEntry *pEntry = pLst->GetObject( nIndex );
+ return *pEntry;
+}
+
+/*************************************************************************
+|*
+|* Dir::operator+= ()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 16.05.91
+|*
+*************************************************************************/
+
+Dir& Dir::operator+=( const Dir& rDir )
+{
+ // ggf. erst den Rest lesen
+ if ( pReader )
+ Scan( USHRT_MAX );
+ DBG_ASSERT( !rDir.pReader, "Dir::+= with incomplete Dir" );
+
+ // ggf. initiale Liste erzeugen
+ if ( !pLst )
+ pLst = new DirEntryList();
+
+ //Verlangen die Sortierkriterien FileStat's?
+ BOOL bStat = FALSE;
+ if ( pSortLst ) {
+ pSortLst->First();
+ do {
+ if ( *(pSortLst->GetCurObject()) &
+ ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE |
+ FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) )
+ bStat = TRUE;
+ } while ( !bStat && pSortLst->Next() );
+ }
+ FileStat * stat = NULL;
+ for ( USHORT nNr = 0; nNr < rDir.Count(); nNr++ )
+ {
+ if ( bStat )
+ {
+ if ( rDir.pStatLst )
+ stat = new FileStat( *rDir.pStatLst->GetObject(nNr) );
+ else
+ stat = new FileStat( rDir[nNr] );
+ }
+ ImpSortedInsert( new DirEntry( rDir[nNr] ), stat );
+ }
+ return *this;
+}
+
+/*************************************************************************
+|*
+|* Dir::Count()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 16.05.91
+|* Letzte Aenderung MI 18.09.96
+|*
+*************************************************************************/
+
+
+USHORT Dir::Count( BOOL bUpdated ) const
+{
+ // ggf. erst den Rest lesen
+ if ( bUpdated && pReader )
+ ((Dir*)this)->Scan( USHRT_MAX );
+
+ return pLst == NULL ? 0 : (USHORT) pLst->Count();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/tempfile.cxx b/tools/source/fsys/tempfile.cxx
new file mode 100644
index 000000000000..36e06b05bf17
--- /dev/null
+++ b/tools/source/fsys/tempfile.cxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#include <tools/tempfile.hxx>
+#include "comdep.hxx"
+
+#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
+#include <rtl/instance.hxx>
+#include <tools/time.hxx>
+#include <tools/debug.hxx>
+#include <stdio.h>
+
+#ifdef UNX
+#define _MAX_PATH 260
+#endif
+
+using namespace osl;
+
+namespace { struct TempNameBase_Impl : public rtl::Static< ::rtl::OUString, TempNameBase_Impl > {}; }
+
+struct TempFile_Impl
+{
+ String aName;
+ sal_Bool bIsDirectory;
+};
+
+String GetSystemTempDir_Impl()
+{
+ char sBuf[_MAX_PATH];
+ const char *pDir = TempDirImpl(sBuf);
+
+ ::rtl::OString aTmpA( pDir );
+ ::rtl::OUString aTmp = ::rtl::OStringToOUString( aTmpA, osl_getThreadTextEncoding() );
+ rtl::OUString aRet;
+ FileBase::getFileURLFromSystemPath( aTmp, aRet );
+ String aName = aRet;
+ if( aName.GetChar(aName.Len()-1) != '/' )
+ aName += '/';
+ return aName;
+}
+
+#define TMPNAME_SIZE ( 1 + 5 + 5 + 4 + 1 )
+String ConstructTempDir_Impl( const String* pParent )
+{
+ String aName;
+ if ( pParent && pParent->Len() )
+ {
+ // if parent given try to use it
+ rtl::OUString aTmp( *pParent );
+ rtl::OUString aRet;
+
+ // test for valid filename
+ {
+ ::osl::DirectoryItem aItem;
+ sal_Int32 i = aRet.getLength();
+ if ( aRet[i-1] == '/' )
+ i--;
+
+ if ( DirectoryItem::get( ::rtl::OUString( aRet, i ), aItem ) == FileBase::E_None )
+ aName = aRet;
+ }
+ }
+
+ if ( !aName.Len() )
+ {
+ // if no parent or invalid parent : use system directory
+ ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
+ if ( !rTempNameBase_Impl.getLength() )
+ rTempNameBase_Impl = GetSystemTempDir_Impl();
+ aName = rTempNameBase_Impl;
+ }
+
+ // Make sure that directory ends with a separator
+ xub_StrLen i = aName.Len();
+ if( i>0 && aName.GetChar(i-1) != '/' )
+ aName += '/';
+
+ return aName;
+}
+
+void CreateTempName_Impl( String& rName, sal_Bool bKeep, sal_Bool bDir = sal_True )
+{
+ // add a suitable tempname
+ // Prefix can have 5 chars, leaving 3 for numbers. 26 ** 3 == 17576
+ // ER 13.07.00 why not radix 36 [0-9A-Z] ?!?
+ const unsigned nRadix = 26;
+ String aName( rName );
+ aName += String::CreateFromAscii( "sv" );
+
+ rName.Erase();
+ static unsigned long u = Time::GetSystemTicks();
+ for ( unsigned long nOld = u; ++u != nOld; )
+ {
+ u %= (nRadix*nRadix*nRadix);
+ String aTmp( aName );
+ aTmp += String::CreateFromInt32( (sal_Int32) (unsigned) u, nRadix );
+ aTmp += String::CreateFromAscii( ".tmp" );
+
+ if ( bDir )
+ {
+ FileBase::RC err = Directory::create( aTmp );
+ if ( err == FileBase::E_None )
+ {
+ // !bKeep: only for creating a name, not a file or directory
+ if ( bKeep || Directory::remove( aTmp ) == FileBase::E_None )
+ rName = aTmp;
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ {
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ }
+ else
+ {
+ DBG_ASSERT( bKeep, "Too expensive, use directory for creating name!" );
+ File aFile( aTmp );
+ FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
+ if ( err == FileBase::E_None )
+ {
+ rName = aTmp;
+ aFile.close();
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ {
+ // if f.e. name contains invalid chars stop trying to create files
+ break;
+ }
+ }
+ }
+}
+
+String TempFile::CreateTempName( const String* pParent )
+{
+ // get correct directory
+ String aName = ConstructTempDir_Impl( pParent );
+
+ // get TempFile name with default naming scheme
+ CreateTempName_Impl( aName, sal_False );
+
+ // convert to file URL
+ rtl::OUString aTmp;
+ if ( aName.Len() )
+ aTmp = aName;
+ return aTmp;
+}
+
+TempFile::TempFile( const String* pParent, sal_Bool bDirectory )
+ : pImp( new TempFile_Impl )
+ , bKillingFileEnabled( sal_False )
+{
+ pImp->bIsDirectory = bDirectory;
+
+ // get correct directory
+ pImp->aName = ConstructTempDir_Impl( pParent );
+
+ // get TempFile with default naming scheme
+ CreateTempName_Impl( pImp->aName, sal_True, bDirectory );
+}
+
+TempFile::TempFile( const String& rLeadingChars, const String* pExtension, const String* pParent, sal_Bool bDirectory )
+ : pImp( new TempFile_Impl )
+ , bKillingFileEnabled( sal_False )
+{
+ pImp->bIsDirectory = bDirectory;
+
+ // get correct directory
+ String aName = ConstructTempDir_Impl( pParent );
+
+ // now use special naming scheme ( name takes leading chars and an index counting up from zero
+ aName += rLeadingChars;
+ for ( sal_Int32 i=0;; i++ )
+ {
+ String aTmp( aName );
+ aTmp += String::CreateFromInt32( i );
+ if ( pExtension )
+ aTmp += *pExtension;
+ else
+ aTmp += String::CreateFromAscii( ".tmp" );
+ if ( bDirectory )
+ {
+ FileBase::RC err = Directory::create( aTmp );
+ if ( err == FileBase::E_None )
+ {
+ pImp->aName = aTmp;
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ else
+ {
+ File aFile( aTmp );
+ FileBase::RC err = aFile.open(osl_File_OpenFlag_Create);
+ if ( err == FileBase::E_None )
+ {
+ pImp->aName = aTmp;
+ aFile.close();
+ break;
+ }
+ else if ( err != FileBase::E_EXIST )
+ // if f.e. name contains invalid chars stop trying to create dirs
+ break;
+ }
+ }
+}
+
+TempFile::~TempFile()
+{
+ if ( bKillingFileEnabled )
+ {
+ if ( pImp->bIsDirectory )
+ {
+ // at the moment no recursiv algorithm present
+ Directory::remove( pImp->aName );
+ }
+ else
+ {
+ File::remove( pImp->aName );
+ }
+ }
+
+ delete pImp;
+}
+
+sal_Bool TempFile::IsValid() const
+{
+ return pImp->aName.Len() != 0;
+}
+
+String TempFile::GetName() const
+{
+ rtl::OUString aTmp;
+ aTmp = pImp->aName;
+ return aTmp;
+}
+
+String TempFile::SetTempNameBaseDirectory( const String &rBaseName )
+{
+ String aName( rBaseName );
+
+ ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
+
+ FileBase::RC err= Directory::create( aName );
+ if ( err == FileBase::E_None || err == FileBase::E_EXIST )
+ {
+ rTempNameBase_Impl = aName;
+ rTempNameBase_Impl += String( '/' );
+
+ TempFile aBase( NULL, sal_True );
+ if ( aBase.IsValid() )
+ rTempNameBase_Impl = aBase.pImp->aName;
+ }
+
+ rtl::OUString aTmp;
+ aTmp = rTempNameBase_Impl;
+ return aTmp;
+}
+
+String TempFile::GetTempNameBaseDirectory()
+{
+ ::rtl::OUString& rTempNameBase_Impl = TempNameBase_Impl::get();
+ if ( !rTempNameBase_Impl.getLength() )
+ rTempNameBase_Impl = GetSystemTempDir_Impl();
+
+ rtl::OUString aTmp;
+ aTmp = rTempNameBase_Impl;
+ return aTmp;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/unx.cxx b/tools/source/fsys/unx.cxx
new file mode 100644
index 000000000000..b1abae49d8b0
--- /dev/null
+++ b/tools/source/fsys/unx.cxx
@@ -0,0 +1,663 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utime.h>
+#if defined HPUX || defined LINUX
+#include <mntent.h>
+#define mnttab mntent
+#elif defined SCO
+#include <mnttab.h>
+#elif defined AIX
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+extern "C" int mntctl( int cmd, size_t size, char* buf );
+#elif defined(NETBSD)
+#include <sys/mount.h>
+#elif defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD)
+#elif defined DECUNIX
+struct mnttab
+{
+ char *mnt_dir;
+ char *mnt_fsname;
+};
+#else
+#include <sys/mnttab.h>
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include <tools/fsys.hxx>
+#include "comdep.hxx"
+#include <rtl/instance.hxx>
+
+DECLARE_LIST( DirEntryList, DirEntry* )
+DECLARE_LIST( FSysSortList, FSysSort* )
+DECLARE_LIST( FileStatList, FileStat* )
+
+#if defined SOLARIS || defined SINIX
+#define MOUNTSPECIAL mnt_special
+#define MOUNTPOINT mnt_mountp
+#define MOUNTOPTS mnt_mntopts
+#define MOUNTFS mnt_fstype
+#elif defined SCO
+#define MNTTAB "/etc/mnttab"
+#define MOUNTSPECIAL mt_dev
+#define MOUNTPOINT mt_filsys
+#else
+#define MOUNTSPECIAL mnt_fsname
+#define MOUNTPOINT mnt_dir
+#define MOUNTFS mnt_type
+#endif
+
+struct mymnttab
+{
+ dev_t mountdevice;
+ ByteString mountspecial;
+ ByteString mountpoint;
+ ByteString mymnttab_filesystem;
+ mymnttab() { mountdevice = (dev_t) -1; }
+};
+
+
+#if defined(NETBSD) || defined(FREEBSD) || defined(MACOSX) || \
+ defined(OPENBSD)
+BOOL GetMountEntry(dev_t /* dev */, struct mymnttab * /* mytab */ )
+{
+ DBG_WARNING( "Sorry, not implemented: GetMountEntry" );
+ return FALSE;
+}
+
+#elif defined AIX
+BOOL GetMountEntry(dev_t dev, struct mymnttab *mytab)
+{
+ int bufsize;
+ if (mntctl (MCTL_QUERY, sizeof bufsize, (char*) &bufsize))
+ return FALSE;
+
+ char* buffer = (char *)malloc( bufsize * sizeof(char) );
+ if (mntctl (MCTL_QUERY, bufsize, buffer) != -1)
+ for ( char* vmt = buffer;
+ vmt < buffer + bufsize;
+ vmt += ((struct vmount*)vmt)->vmt_length)
+ {
+ struct stat buf;
+ char *mountp = vmt2dataptr((struct vmount*)vmt, VMT_STUB);
+ if ((stat (mountp, &buf) != -1) && (buf.st_dev == dev))
+ {
+ mytab->mountpoint = mountp;
+ mytab->mountspecial
+ = vmt2dataptr((struct vmount*)vmt, VMT_HOSTNAME);
+ if (mytab->mountspecial.Len())
+ mytab->mountspecial += ':';
+ mytab->mountspecial
+ += vmt2dataptr((struct vmount*)vmt, VMT_OBJECT);
+ mytab->mountdevice = dev;
+ free( buffer );
+ return TRUE;
+ }
+ }
+ free( buffer );
+ return FALSE;
+}
+
+#else
+
+
+static BOOL GetMountEntry(dev_t dev, struct mymnttab *mytab)
+{
+#if defined SOLARIS || defined SINIX
+ FILE *fp = fopen (MNTTAB, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while (getmntent (fp, mnt) != -1)
+#elif defined SCO
+ FILE *fp = fopen (MNTTAB, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while (fread (&mnt, sizeof mnt, 1, fp) > 0)
+#elif defined DECUNIX || defined AIX
+ FILE *fp = NULL;
+ if (! fp)
+ return FALSE;
+ struct mnttab mnt[1];
+ while ( 0 )
+#else
+ FILE *fp = setmntent (MOUNTED, "r");
+ if (! fp)
+ return FALSE;
+ struct mnttab *mnt;
+ while ((mnt = getmntent (fp)) != NULL)
+#endif
+ {
+#ifdef SOLARIS
+ char *devopt = NULL;
+ if ( mnt->MOUNTOPTS != NULL )
+ devopt = strstr (mnt->MOUNTOPTS, "dev=");
+ if (devopt)
+ {
+ if (dev != (dev_t) strtoul (devopt+4, NULL, 16))
+ continue;
+ }
+ else
+#endif
+ {
+ struct stat buf;
+ if ((stat (mnt->MOUNTPOINT, &buf) == -1) || (buf.st_dev != dev))
+ continue;
+ }
+# ifdef LINUX
+ /* #61624# File mit setmntent oeffnen und mit fclose schliessen stoesst
+ bei der glibc-2.1 auf wenig Gegenliebe */
+ endmntent( fp );
+# else
+ fclose (fp);
+# endif
+ mytab->mountspecial = mnt->MOUNTSPECIAL;
+ mytab->mountpoint = mnt->MOUNTPOINT;
+ mytab->mountdevice = dev;
+#ifndef SCO
+ mytab->mymnttab_filesystem = mnt->MOUNTFS;
+#else
+ mytab->mymnttab_filesystem = "ext2"; //default ist case sensitiv unter unix
+#endif
+ return TRUE;
+ }
+# ifdef LINUX
+ /* #61624# dito */
+ endmntent( fp );
+# else
+ fclose (fp);
+# endif
+ return FALSE;
+}
+
+#endif
+
+/************************************************************************
+|*
+|* DirEntry::IsCaseSensitive()
+|*
+|* Beschreibung
+|* Ersterstellung TPF 25.02.1999
+|* Letzte Aenderung TPF 25.02.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+#ifdef NETBSD
+ return TRUE;
+#else
+ struct stat buf;
+ DirEntry aPath(*this);
+ aPath.ToAbs();
+
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() == 1)
+ {
+ return TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ }
+ aPath = aPath [1];
+ }
+
+ struct mymnttab fsmnt;
+ GetMountEntry(buf.st_dev, &fsmnt);
+ if ((fsmnt.mymnttab_filesystem.CompareTo("msdos")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("umsdos")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("vfat")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("hpfs")==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("smb") ==COMPARE_EQUAL) ||
+ (fsmnt.mymnttab_filesystem.CompareTo("ncpfs")==COMPARE_EQUAL))
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+#endif
+ }
+ else
+ {
+ BOOL isCaseSensitive = TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = TRUE; // ich bin unter UNIX, also ist der default im Zweifelsfall case sensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+/************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91 13:30
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ return TRUE;
+
+ char sBuf[MAXPATHLEN + 1];
+ *this = DirEntry( String( getcwd( sBuf, MAXPATHLEN ), osl_getThreadTextEncoding() ) ) + *this;
+ return IsAbs();
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 04.03.92
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+namespace { struct mymnt : public rtl::Static< mymnttab, mymnt > {}; }
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aPath( *this );
+ aPath.ToAbs();
+
+ struct stat buf;
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() <= 1)
+ return String();
+ aPath = aPath [1];
+ }
+ mymnttab &rMnt = mymnt::get();
+ return ((buf.st_dev == rMnt.mountdevice ||
+ GetMountEntry(buf.st_dev, &rMnt)) ?
+ String(rMnt.mountspecial, osl_getThreadTextEncoding()) :
+ String());
+}
+
+DirEntry DirEntry::GetDevice() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ DirEntry aPath( *this );
+ aPath.ToAbs();
+
+ struct stat buf;
+ while (stat (ByteString(aPath.GetFull(), osl_getThreadTextEncoding()).GetBuffer(), &buf))
+ {
+ if (aPath.Level() <= 1)
+ return String();
+ aPath = aPath [1];
+ }
+ mymnttab &rMnt = mymnt::get();
+ return ((buf.st_dev == rMnt.mountdevice ||
+ GetMountEntry(buf.st_dev, &rMnt)) ?
+ String( rMnt.mountpoint, osl_getThreadTextEncoding()) :
+ String());
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung DV 04.11.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+
+ ByteString aPath( GetFull(), osl_getThreadTextEncoding());
+ if ( !chdir( aPath.GetBuffer() ) )
+ {
+ return TRUE;
+ }
+ else
+ {
+ if ( bSloppy && !chdir(aPath.GetBuffer()) )
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ if (!pDosDir)
+ {
+ pDosDir = opendir( (char*) ByteString(aPath, osl_getThreadTextEncoding()).GetBuffer() );
+ }
+
+ if (!pDosDir)
+ {
+ bReady = TRUE;
+ return 0;
+ }
+
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR || pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ String aD_Name(pDosEntry->d_name, osl_getThreadTextEncoding());
+ if ( pDir->aNameMask.Matches( aD_Name ) )
+ {
+ DirEntryFlag eFlag =
+ 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
+ : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name), eFlag, FSYS_STYLE_UNX );
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE);
+ FileStat aStat( *pTemp );
+ if ( ( ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+ ( aStat.IsKind( FSYS_KIND_DIR ) ) ) ||
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ !( aStat.IsKind( FSYS_KIND_DIR ) ) ) ) &&
+ !( pDir->eAttrMask & FSYS_KIND_VISIBLE &&
+ pDosEntry->d_name[0] == '.' ) )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ pDir->ImpSortedInsert( pTemp, new FileStat( aStat ) );
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );;
+ return 1;
+ }
+ else
+ delete pTemp;
+ }
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MA 05.11.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *, const void * ):
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 11.06.91
+|* Letzte Aenderung MA 07.11.91
+|*
+*************************************************************************/
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL )
+{
+
+ nSize = 0;
+ nKindFlags = 0;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if ( !rDirEntry.IsValid() )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root handelt
+ if ( rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ nKindFlags = FSYS_KIND_DIR;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ struct stat aStat;
+ ByteString aPath( rDirEntry.GetFull(), osl_getThreadTextEncoding() );
+ if ( stat( (char*) aPath.GetBuffer(), &aStat ) )
+ {
+ // pl: #67851#
+ // do this here, because an existing filename containing "wildcards"
+ // should be handled as a file, not a wildcard
+ // note that this is not a solution, since filenames containing special characters
+ // are handled badly across the whole Office
+
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ ByteString aTempName( rDirEntry.GetName(), osl_getThreadTextEncoding() );
+ if ( strchr( (char*) aTempName.GetBuffer(), '?' ) ||
+ strchr( (char*) aTempName.GetBuffer(), '*' ) ||
+ strchr( (char*) aTempName.GetBuffer(), ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ nError = FSYS_ERR_OK;
+ nSize = aStat.st_size;
+
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ if ( ( aStat.st_mode & S_IFDIR ) == S_IFDIR )
+ nKindFlags = nKindFlags | FSYS_KIND_DIR;
+ if ( ( aStat.st_mode & S_IFREG ) == S_IFREG )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+ if ( ( aStat.st_mode & S_IFCHR ) == S_IFCHR )
+ nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_CHAR;
+ if ( ( aStat.st_mode & S_IFBLK ) == S_IFBLK )
+ nKindFlags = nKindFlags | FSYS_KIND_DEV | FSYS_KIND_BLOCK;
+ if ( nKindFlags == FSYS_KIND_UNKNOWN )
+ nKindFlags = nKindFlags | FSYS_KIND_FILE;
+
+ Unx2DateAndTime( aStat.st_ctime, aTimeCreated, aDateCreated );
+ Unx2DateAndTime( aStat.st_mtime, aTimeModified, aDateModified );
+ Unx2DateAndTime( aStat.st_atime, aTimeAccessed, aDateAccessed );
+
+ return TRUE;
+}
+
+//====================================================================
+
+const char *TempDirImpl( char *pBuf )
+{
+#ifdef MACOSX
+ // P_tmpdir is /var/tmp on Mac OS X, and it is not cleaned up on system
+ // startup
+ strcpy( pBuf, "/tmp" );
+#else
+ const char *pValue = getenv( "TEMP" );
+ if ( !pValue )
+ pValue = getenv( "TMP" );
+ if ( pValue )
+ strcpy( pBuf, pValue );
+ else
+ // auf Solaris und Linux ist P_tmpdir vorgesehen
+ strcpy( pBuf, P_tmpdir );
+ // hart auf "/tmp" sollte wohl nur im Notfall verwendet werden
+ //strcpy( pBuf, "/tmp" );
+#endif /* MACOSX */
+
+ return pBuf;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+FSysPathStyle DirEntry::GetPathStyle( const String & )
+{
+ return FSYS_STYLE_UNX;
+}
+
+/*************************************************************************
+|*
+|* FileStat::SetDateTime
+|*
+|* Ersterstellung PB 27.06.97
+|* Letzte Aenderung
+|*
+*************************************************************************/
+
+void FileStat::SetDateTime( const String& rFileName,
+ const DateTime& rNewDateTime )
+{
+ tm times;
+
+ times.tm_year = rNewDateTime.GetYear() - 1900; // 1997 -> 97
+ times.tm_mon = rNewDateTime.GetMonth() - 1; // 0 == Januar!
+ times.tm_mday = rNewDateTime.GetDay();
+
+ times.tm_hour = rNewDateTime.GetHour();
+ times.tm_min = rNewDateTime.GetMin();
+ times.tm_sec = rNewDateTime.GetSec();
+
+ times.tm_wday = 0;
+ times.tm_yday = 0;
+#ifdef SOLARIS
+ times.tm_isdst = -1;
+#else
+ times.tm_isdst = 0;
+#endif
+
+ time_t time = mktime (&times);
+
+ if (time != (time_t) -1)
+ {
+ struct utimbuf u_time;
+ u_time.actime = time;
+ u_time.modtime = time;
+ utime (ByteString(rFileName, osl_getThreadTextEncoding()).GetBuffer(), &u_time);
+ }
+}
+
+//=========================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &, BigInt &, BigInt & )
+{
+ return ERRCODE_IO_NOTSUPPORTED;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/unx.hxx b/tools/source/fsys/unx.hxx
new file mode 100644
index 000000000000..0436c9284006
--- /dev/null
+++ b/tools/source/fsys/unx.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _unx_hxx
+#define _unx_hxx
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <unistd.h>
+/* #include <sysent.h> */
+
+#define FSYS_UNIX TRUE
+#define DRIVE_EXISTS(c) ( TRUE )
+
+#define _mkdir(p) mkdir(p, 0777)
+#define _rmdir rmdir
+#define _chdir chdir
+#define _unlink unlink
+#define _getcwd getcwd
+#define _access access
+
+#ifdef SYSV3
+#define DEFSTYLE FSYS_STYLE_SYSV
+#else
+#define DEFSTYLE FSYS_STYLE_BSD
+#endif
+
+#define CMP_LOWER(s) (s)
+#define TEMPNAME() tmpnam(0)
+#define LOWER(aString) (aString.Lower())
+
+#include <time.h>
+#include <tools/datetime.hxx>
+
+inline Time Unx2Time( time_t nTime )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nTime, &atm );
+ return Time( pTime->tm_hour,
+ pTime->tm_min,
+ pTime->tm_sec );
+}
+
+inline Date Unx2Date( time_t nDate )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nDate, &atm );
+ return Date( pTime->tm_mday,
+ pTime->tm_mon + 1,
+ pTime->tm_year + 1900 );
+}
+
+inline void Unx2DateAndTime( time_t nDate, Time& rTime, Date& rDate )
+{
+ tm atm;
+ tm *pTime;
+ pTime = localtime_r( &nDate, &atm );
+ rTime = Time( pTime->tm_hour, pTime->tm_min, pTime->tm_sec );
+ rDate = Date( pTime->tm_mday, pTime->tm_mon + 1, pTime->tm_year + 1900 );
+}
+
+const char* TempDirImpl( char *pBuf );
+
+#define FSysFailOnErrorImpl()
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
new file mode 100644
index 000000000000..1f4b67518afe
--- /dev/null
+++ b/tools/source/fsys/urlobj.cxx
@@ -0,0 +1,5575 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+#include <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+#include <tools/inetmime.hxx>
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/util/XStringWidth.hpp"
+#include "osl/diagnose.h"
+#include "osl/file.hxx"
+#include "rtl/string.h"
+#include "rtl/textenc.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#ifndef INCLUDED_ALGORITHM
+#include <algorithm>
+#define INCLUDED_ALGORITHM
+#endif
+#ifndef INCLUDED_LIMITS
+#include <limits>
+#define INCLUDED_LIMITS
+#endif
+
+#include <string.h>
+
+namespace unnamed_tools_urlobj {} using namespace unnamed_tools_urlobj;
+ // unnamed namespaces don't work well yet...
+
+using namespace com::sun;
+
+//============================================================================
+//
+// INetURLObject
+//
+//============================================================================
+
+/* The URI grammar (using RFC 2234 conventions).
+
+ Constructs of the form
+ {reference <rule1> using rule2}
+ stand for a rule matching the given rule1 specified in the given reference,
+ encoded to URI syntax using rule2 (as specified in this URI grammar).
+
+
+ ; RFC 1738, RFC 2396, RFC 2732, private
+ login = [user [":" password] "@"] hostport
+ user = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~")
+ password = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~")
+ hostport = host [":" port]
+ host = incomplete-hostname / hostname / IPv4address / IPv6reference
+ incomplete-hostname = *(domainlabel ".") domainlabel
+ hostname = *(domainlabel ".") toplabel ["."]
+ domainlabel = alphanum [*(alphanum / "-") alphanum]
+ toplabel = ALPHA [*(alphanum / "-") alphanum]
+ IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
+ IPv6reference = "[" hexpart [":" IPv4address] "]"
+ hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ hexseq = hex4 *(":" hex4)
+ hex4 = 1*4HEXDIG
+ port = *DIGIT
+ escaped = "%" HEXDIG HEXDIG
+ reserved = "$" / "&" / "+" / "," / "/" / ":" / ";" / "=" / "?" / "@" / "[" / "]"
+ mark = "!" / "'" / "(" / ")" / "*" / "-" / "." / "_" / "~"
+ alphanum = ALPHA / DIGIT
+ unreserved = alphanum / mark
+ uric = escaped / reserved / unreserved
+ pchar = escaped / unreserved / "$" / "&" / "+" / "," / ":" / "=" / "@"
+
+
+ ; RFC 1738, RFC 2396
+ ftp-url = "FTP://" login ["/" segment *("/" segment) [";TYPE=" ("A" / "D" / "I")]]
+ segment = *pchar
+
+
+ ; RFC 1738, RFC 2396
+ http-url = "HTTP://" hostport ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(pchar / ";")
+
+
+ ; RFC 1738, RFC 2396, <http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q188997&>
+ file-url = "FILE://" [host / "LOCALHOST" / netbios-name] ["/" segment *("/" segment)]
+ segment = *pchar
+ netbios-name = 1*{<alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "^" / "_" / "{" / "}" / "~"> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "_" / "~")}
+
+
+ ; RFC 2368, RFC 2396
+ mailto-url = "MAILTO:" [to] [headers]
+ to = {RFC 822 <#mailbox> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+ headers = "?" header *("&" header)
+ header = hname "=" hvalue
+ hname = {RFC 822 <field-name> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} / "BODY"
+ hvalue = {RFC 822 <field-body> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+
+
+ ; private (see RFC 1738, RFC 2396)
+ vnd-sun-star-webdav-url = "VND.SUN.STAR.WEBDAV://" hostport ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(pchar / ";")
+
+
+ ; RFC 1738, RFC 2396, RFC 2732
+ news-url = "NEWS:" grouppart
+ grouppart = "*" / group / article
+ group = alpha *(alphanum / "+" / "-" / "." / "_")
+ article = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "?" / "_" / "~") "@" host
+
+
+ ; private
+ private-url = "PRIVATE:" path ["?" *uric]
+ path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ vnd-sun-star-help-url = "VND.SUN.STAR.HELP://" name *("/" segment) ["?" *uric]
+ name = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+ segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ https-url = "HTTPS://" hostport ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ slot-url = "SLOT:" path ["?" *uric]
+ path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ macro-url = "MACRO:" path ["?" *uric]
+ path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ javascript-url = "JAVASCRIPT:" *uric
+
+
+ ; private (see RFC 2192)
+ imap-url = "IMAP://" user [";AUTH=" auth] "@" hostport "/" segment *("/" segment) ["/;UID=" nz_number]
+ user = 1*{RFC 2060 <CHAR8> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "=" / "_" / "~")}
+ auth = {RFC 2060 <atom> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "+" / "," / "-" / "." / "=" / "_" / "~")}
+ segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / "=" / "@" / "_" / "~")
+ nz_number = {RFC 2060 <nz_number> using *DIGIT}
+
+
+ ; private
+ pop3-url = "POP3://" login ["/" ["<" *uric ">"]]
+
+
+ ; RFC 2397
+ data-url = "DATA:" [mediatype] [";BASE64"] "," *uric
+ mediatype = [type "/" subtype] *(";" attribute "=" value)
+ type = {RFC 2045 <type> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ subtype = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ attribute = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+ value = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
+
+
+ ; RFC 2392, RFC 2396
+ cid-url = "CID:" {RFC 822 <addr-spec> using *uric}
+
+
+ ; private
+ out-url = "OUT:///~" name ["/" *uric]
+ name = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "?" / "@" / "_" / "~"
+
+
+ ; private
+ vnd-sun-star-hier-url = "VND.SUN.STAR.HIER:" ["//"reg_name] *("/" *pchar)
+ reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+
+ ; private
+ vim-url = "VIM://" +vimc [":" *vimc] ["/" [("INBOX" message) / ("NEWSGROUPS" ["/" [+vimc message]])]]
+ message = ["/" [+vimc [":" +DIGIT "." +DIGIT "." +DIGIT]]]
+ vimc = ("=" HEXDIG HEXDIG) / alphanum
+
+
+ ; private
+ uno-url = ".UNO:" path ["?" *uric]
+ path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ component-url = ".COMPONENT:" path ["?" *uric]
+ path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; private
+ vnd-sun-star-pkg-url = "VND.SUN.STAR.PKG://" reg_name *("/" *pchar) ["?" *uric]
+ reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
+
+
+ ; RFC 2255
+ ldap-url = "LDAP://" [hostport] ["/" [dn ["?" [attrdesct *("," attrdesc)] ["?" ["base" / "one" / "sub"] ["?" [filter] ["?" extension *("," extension)]]]]]]
+ dn = {RFC 2253 <distinguishedName> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ attrdesc = {RFC 2251 <AttributeDescription> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ filter = {RFC 2254 <filter> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+ extension = ["!"] ["X-"] extoken ["=" exvalue]
+ extoken = {RFC 2252 <oid> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
+ exvalue = {RFC 2251 <LDAPString> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
+
+
+ ; private
+ db-url = "DB:" *uric
+
+
+ ; private
+ vnd-sun-star-cmd-url = "VND.SUN.STAR.CMD:" opaque_part
+ opaque_part = uric_no_slash *uric
+ uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
+
+
+ ; private
+ vnd-sun-star-url = "VND.SUN.STAR.ODMA:" ["/" *uric_no_slash]
+ uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
+
+
+ ; RFC 1738
+ telnet-url = "TELNET://" login ["/"]
+
+
+ ; private
+ vnd-sun-star-expand-url = "VND.SUN.STAR.EXPAND:" opaque_part
+ opaque_part = uric_no_slash *uric
+ uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
+
+
+ ; private
+ vnd-sun-star-tdoc-url = "VND.SUN.STAR.TDOC:/" segment *("/" segment)
+ segment = *pchar
+
+
+ ; private
+ unknown-url = scheme ":" 1*uric
+ scheme = ALPHA *(alphanum / "+" / "-" / ".")
+
+
+ ; private (http://ubiqx.org/cifs/Appendix-D.html):
+ smb-url = "SMB://" login ["/" segment *("/" segment) ["?" *uric]]
+ segment = *(pchar / ";")
+ */
+
+//============================================================================
+inline sal_Int32 INetURLObject::SubString::clear()
+{
+ sal_Int32 nDelta = -m_nLength;
+ m_nBegin = -1;
+ m_nLength = 0;
+ return nDelta;
+}
+
+inline sal_Int32 INetURLObject::SubString::set(rtl::OUStringBuffer & rString,
+ rtl::OUString const & rSubString)
+{
+ rtl::OUString sTemp(rString.makeStringAndClear());
+ sal_Int32 nDelta = set(sTemp, rSubString);
+ rString.append(sTemp);
+ return nDelta;
+}
+
+inline sal_Int32 INetURLObject::SubString::set(rtl::OUString & rString,
+ rtl::OUString const & rSubString)
+{
+ sal_Int32 nDelta = rSubString.getLength() - m_nLength;
+
+ rString = rString.replaceAt(m_nBegin, m_nLength, rSubString);
+
+ m_nLength = rSubString.getLength();
+ return nDelta;
+}
+
+inline sal_Int32 INetURLObject::SubString::set(rtl::OUStringBuffer & rString,
+ rtl::OUString const & rSubString,
+ sal_Int32 nTheBegin)
+{
+ m_nBegin = nTheBegin;
+ return set(rString, rSubString);
+}
+
+//============================================================================
+inline void INetURLObject::SubString::operator +=(sal_Int32 nDelta)
+{
+ if (isPresent())
+ m_nBegin = m_nBegin + nDelta;
+}
+
+//============================================================================
+int INetURLObject::SubString::compare(SubString const & rOther,
+ rtl::OUStringBuffer const & rThisString,
+ rtl::OUStringBuffer const & rOtherString) const
+{
+ sal_Int32 len = std::min(m_nLength, rOther.m_nLength);
+ sal_Unicode const * p1 = rThisString.getStr() + m_nBegin;
+ sal_Unicode const * end = p1 + len;
+ sal_Unicode const * p2 = rOtherString.getStr() + rOther.m_nBegin;
+ while (p1 != end) {
+ if (*p1 < *p2) {
+ return -1;
+ } else if (*p1 > *p2) {
+ return 1;
+ }
+ ++p1;
+ ++p2;
+ }
+ return m_nLength < rOther.m_nLength ? -1
+ : m_nLength > rOther.m_nLength ? 1
+ : 0;
+}
+
+//============================================================================
+struct INetURLObject::SchemeInfo
+{
+ sal_Char const * m_pScheme;
+ sal_Char const * m_pPrefix;
+ sal_uInt16 m_nDefaultPort;
+ bool m_bAuthority;
+ bool m_bUser;
+ bool m_bAuth;
+ bool m_bPassword;
+ bool m_bHost;
+ bool m_bPort;
+ bool m_bHierarchical;
+ bool m_bQuery;
+};
+
+//============================================================================
+struct INetURLObject::PrefixInfo
+{
+ enum Kind { OFFICIAL, INTERNAL, EXTERNAL, ALIAS }; // order is important!
+
+ sal_Char const * m_pPrefix;
+ sal_Char const * m_pTranslatedPrefix;
+ INetProtocol m_eScheme;
+ Kind m_eKind;
+};
+
+//============================================================================
+static INetURLObject::SchemeInfo const aSchemeInfoMap[INET_PROT_END]
+ = { { "", "", 0, false, false, false, false, false, false, false,
+ false },
+ { "ftp", "ftp://", 21, true, true, false, true, true, true, true,
+ false },
+ { "http", "http://", 80, true, false, false, false, true, true,
+ true, true },
+ { "file", "file://", 0, true, false, false, false, true, false,
+ true, false },
+ { "mailto", "mailto:", 0, false, false, false, false, false,
+ false, false, true },
+ { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, false,
+ false, false, true, true, true, true },
+ { "news", "news:", 0, false, false, false, false, false, false, false,
+ false },
+ { "private", "private:", 0, false, false, false, false, false,
+ false, false, true },
+ { "vnd.sun.star.help", "vnd.sun.star.help://", 0, true, false, false,
+ false, false, false, true, true },
+ { "https", "https://", 443, true, false, false, false, true, true,
+ true, true },
+ { "slot", "slot:", 0, false, false, false, false, false, false,
+ false, true },
+ { "macro", "macro:", 0, false, false, false, false, false, false,
+ false, true },
+ { "javascript", "javascript:", 0, false, false, false, false,
+ false, false, false, false },
+ { "imap", "imap://", 143, true, true, true, false, true, true,
+ true, false },
+ { "pop3", "pop3://", 110, true, true, false, true, true, true,
+ false, false },
+ { "data", "data:", 0, false, false, false, false, false, false,
+ false, false },
+ { "cid", "cid:", 0, false, false, false, false, false, false,
+ false, false },
+ { "out", "out://", 0, true, false, false, false, false, false,
+ false, false },
+ { "vnd.sun.star.hier", "vnd.sun.star.hier:", 0, true, false, false,
+ false, false, false, true, false },
+ { "vim", "vim://", 0, true, true, false, true, false, false, true,
+ false },
+ { ".uno", ".uno:", 0, false, false, false, false, false, false,
+ false, true },
+ { ".component", ".component:", 0, false, false, false, false,
+ false, false, false, true },
+ { "vnd.sun.star.pkg", "vnd.sun.star.pkg://", 0, true, false, false,
+ false, false, false, true, true },
+ { "ldap", "ldap://", 389, true, false, false, false, true, true,
+ false, true },
+ { "db", "db:", 0, false, false, false, false, false, false, false,
+ false },
+ { "vnd.sun.star.cmd", "vnd.sun.star.cmd:", 0, false, false, false,
+ false, false, false, false, false },
+ { "vnd.sun.star.odma", "vnd.sun.star.odma:", 0, false, false, false,
+ false, false, false, true, false },
+ { "telnet", "telnet://", 23, true, true, false, true, true, true, true,
+ false },
+ { "vnd.sun.star.expand", "vnd.sun.star.expand:", 0, false, false, false,
+ false, false, false, false, false },
+ { "vnd.sun.star.tdoc", "vnd.sun.star.tdoc:", 0, false, false, false,
+ false, false, false, true, false },
+ { "", "", 0, false, false, false, false, true, true, true, false },
+ { "smb", "smb://", 139, true, true, false, true, true, true, true,
+ true } };
+
+// static
+inline INetURLObject::SchemeInfo const &
+INetURLObject::getSchemeInfo(INetProtocol eTheScheme)
+{
+ return aSchemeInfoMap[eTheScheme];
+};
+
+//============================================================================
+inline INetURLObject::SchemeInfo const & INetURLObject::getSchemeInfo() const
+{
+ return getSchemeInfo(m_eScheme);
+}
+
+//============================================================================
+// static
+inline void INetURLObject::appendEscape(rtl::OUStringBuffer & rTheText,
+ sal_Char cEscapePrefix,
+ sal_uInt32 nOctet)
+{
+ rTheText.append(sal_Unicode(cEscapePrefix));
+ rTheText.append(sal_Unicode(INetMIME::getHexDigit(int(nOctet >> 4))));
+ rTheText.append(sal_Unicode(INetMIME::getHexDigit(int(nOctet & 15))));
+}
+
+//============================================================================
+namespace unnamed_tools_urlobj {
+
+enum
+{
+ PA = INetURLObject::PART_OBSOLETE_NORMAL,
+ PB = INetURLObject::PART_OBSOLETE_FILE,
+ PC = INetURLObject::PART_OBSOLETE_PARAM,
+ PD = INetURLObject::PART_USER_PASSWORD,
+ PE = INetURLObject::PART_IMAP_ACHAR,
+ PF = INetURLObject::PART_VIM,
+ PG = INetURLObject::PART_HOST_EXTRA,
+ PH = INetURLObject::PART_FPATH,
+ PI = INetURLObject::PART_AUTHORITY,
+ PJ = INetURLObject::PART_PATH_SEGMENTS_EXTRA,
+ PK = INetURLObject::PART_REL_SEGMENT_EXTRA,
+ PL = INetURLObject::PART_URIC,
+ PM = INetURLObject::PART_HTTP_PATH,
+ PN = INetURLObject::PART_FILE_SEGMENT_EXTRA,
+ PO = INetURLObject::PART_MESSAGE_ID,
+ PP = INetURLObject::PART_MESSAGE_ID_PATH,
+ PQ = INetURLObject::PART_MAILTO,
+ PR = INetURLObject::PART_PATH_BEFORE_QUERY,
+ PS = INetURLObject::PART_PCHAR,
+ PT = INetURLObject::PART_FRAGMENT,
+ PU = INetURLObject::PART_VISIBLE,
+ PV = INetURLObject::PART_VISIBLE_NONSPECIAL,
+ PW = INetURLObject::PART_CREATEFRAGMENT,
+ PX = INetURLObject::PART_UNO_PARAM_VALUE,
+ PY = INetURLObject::PART_UNAMBIGUOUS,
+ PZ = INetURLObject::PART_URIC_NO_SLASH,
+ P1 = INetURLObject::PART_HTTP_QUERY,
+ P2 = INetURLObject::PART_NEWS_ARTICLE_LOCALPART
+};
+
+static sal_uInt32 const aMustEncodeMap[128]
+ = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ PY,
+/* ! */ PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* " */ PU+PV +PY,
+/* # */ PU,
+/* $ */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* % */ PU,
+/* & */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN+PO+PP +PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2,
+/* ' */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* ( */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* ) */ PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* * */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* + */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2,
+/* , */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW +PZ+P1+P2,
+/* - */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* . */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* / */ PA+PB+PC +PH +PJ +PL+PM +PP+PQ+PR +PT+PU+PV +PX +P2,
+/* 0 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 1 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 2 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 3 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 4 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 5 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 6 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 7 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 8 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* 9 */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* : */ PB+PC +PH+PI+PJ +PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX +PZ+P1+P2,
+/* ; */ PC+PD +PI+PJ+PK+PL+PM +PO+PP+PQ+PR +PT+PU +PW +PZ+P1+P2,
+/* < */ PC +PO+PP +PU+PV +PY,
+/* = */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN +PR+PS+PT+PU+PV+PW +PZ+P1+P2,
+/* > */ PC +PO+PP +PU+PV +PY,
+/* ? */ PC +PL +PT+PU +PW+PX +PZ +P2,
+/* @ */ PC +PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1,
+/* A */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* B */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* C */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* D */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* E */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* F */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* G */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* H */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* I */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* J */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* K */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* L */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* M */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* N */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* O */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* P */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* Q */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* R */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* S */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* T */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* U */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* V */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* W */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* X */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* Y */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* Z */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* [ */ PL +PU+PV +PX,
+/* \ */ PB +PU+PV +PY,
+/* ] */ PL +PU+PV +PX,
+/* ^ */ PU+PV +PY,
+/* _ */ PA+PB+PC+PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* ` */ PU+PV +PY,
+/* a */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* b */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* c */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* d */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* e */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* f */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* g */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* h */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* i */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* j */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* k */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* l */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* m */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* n */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* o */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* p */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* q */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* r */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* s */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* t */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* u */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* v */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* w */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* x */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* y */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* z */ PA+PB+PC+PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ+P1+P2,
+/* { */ PU+PV +PY,
+/* | */ PB+PC +PN +PT+PU+PV +PY,
+/* } */ PU+PV +PY,
+/* ~ */ PA+PB+PC+PD+PE +PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR+PS+PT+PU+PV+PW+PX+PY+PZ +P2,
+ 0 };
+
+inline bool mustEncode(sal_uInt32 nUTF32, INetURLObject::Part ePart)
+{
+ return !INetMIME::isUSASCII(nUTF32) || !(aMustEncodeMap[nUTF32] & ePart);
+}
+
+}
+
+//============================================================================
+void INetURLObject::setInvalid()
+{
+ m_aAbsURIRef.setLength(0);
+ m_eScheme = INET_PROT_NOT_VALID;
+ m_aScheme.clear();
+ m_aUser.clear();
+ m_aAuth.clear();
+ m_aHost.clear();
+ m_aPort.clear();
+ m_aPath.clear();
+ m_aQuery.clear();
+ m_aFragment.clear();
+}
+
+//============================================================================
+
+namespace unnamed_tools_urlobj {
+
+INetURLObject::FSysStyle
+guessFSysStyleByCounting(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ INetURLObject::FSysStyle eStyle)
+{
+ DBG_ASSERT(eStyle
+ & (INetURLObject::FSYS_UNX
+ | INetURLObject::FSYS_DOS
+ | INetURLObject::FSYS_MAC),
+ "guessFSysStyleByCounting(): Bad style");
+ DBG_ASSERT(std::numeric_limits< sal_Int32 >::min() < pBegin - pEnd
+ && pEnd - pBegin <= std::numeric_limits< sal_Int32 >::max(),
+ "guessFSysStyleByCounting(): Too big");
+ sal_Int32 nSlashCount
+ = eStyle & INetURLObject::FSYS_UNX ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ sal_Int32 nBackslashCount
+ = eStyle & INetURLObject::FSYS_DOS ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ sal_Int32 nColonCount
+ = eStyle & INetURLObject::FSYS_MAC ?
+ 0 : std::numeric_limits< sal_Int32 >::min();
+ while (pBegin != pEnd)
+ switch (*pBegin++)
+ {
+ case '/':
+ ++nSlashCount;
+ break;
+
+ case '\\':
+ ++nBackslashCount;
+ break;
+
+ case ':':
+ ++nColonCount;
+ break;
+ }
+ return nSlashCount >= nBackslashCount ?
+ nSlashCount >= nColonCount ?
+ INetURLObject::FSYS_UNX : INetURLObject::FSYS_MAC :
+ nBackslashCount >= nColonCount ?
+ INetURLObject::FSYS_DOS : INetURLObject::FSYS_MAC;
+}
+
+rtl::OUString parseScheme(
+ sal_Unicode const ** begin, sal_Unicode const * end,
+ sal_uInt32 fragmentDelimiter)
+{
+ sal_Unicode const * p = *begin;
+ if (p != end && INetMIME::isAlpha(*p)) {
+ do {
+ ++p;
+ } while (p != end
+ && (INetMIME::isAlphanumeric(*p) || *p == '+' || *p == '-'
+ || *p == '.'));
+ // #i34835# To avoid problems with Windows file paths like "C:\foo",
+ // do not accept generic schemes that are only one character long:
+ if (end - p > 1 && p[0] == ':' && p[1] != fragmentDelimiter
+ && p - *begin >= 2)
+ {
+ rtl::OUString scheme(
+ rtl::OUString(*begin, p - *begin).toAsciiLowerCase());
+ *begin = p + 1;
+ return scheme;
+ }
+ }
+ return rtl::OUString();
+}
+
+}
+
+bool INetURLObject::setAbsURIRef(rtl::OUString const & rTheAbsURIRef,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bSmart,
+ FSysStyle eStyle)
+{
+ sal_Unicode const * pPos = rTheAbsURIRef.getStr();
+ sal_Unicode const * pEnd = pPos + rTheAbsURIRef.getLength();
+
+ setInvalid();
+
+ sal_uInt32 nFragmentDelimiter = '#';
+
+ rtl::OUStringBuffer aSynAbsURIRef;
+
+ // Parse <scheme>:
+ sal_Unicode const * p = pPos;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ if (pPrefix)
+ {
+ pPos = p;
+ m_eScheme = pPrefix->m_eScheme;
+
+ rtl::OUString sTemp(rtl::OUString::createFromAscii(pPrefix->m_eKind
+ >= PrefixInfo::EXTERNAL ?
+ pPrefix->m_pTranslatedPrefix :
+ pPrefix->m_pPrefix));
+ aSynAbsURIRef.append(sTemp);
+ m_aScheme = SubString( 0, sTemp.indexOf(static_cast< sal_Unicode >(':')) );
+ }
+ else
+ {
+ if (bSmart)
+ {
+ // For scheme detection, the first (if any) of the following
+ // productions that matches the input string (and for which the
+ // appropriate style bit is set in eStyle, if applicable)
+ // determines the scheme. The productions use the auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // IPv6reference = "[" IPv6address "]"
+ // IPv6address = hexpart [":" IPv4address]
+ // IPv4address = 1*3DIGIT 3("." 1*3DIGIT)
+ // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ // hexseq = hex4 *(":" hex4)
+ // hex4 = 1*4HEXDIG
+ // UCS4 = <any UCS4 character>
+ //
+ // 1st Production (known scheme):
+ // <one of the known schemes, ignoring case> ":" *UCS4
+ //
+ // 2nd Production (mailto):
+ // domain "@" domain
+ //
+ // 3rd Production (ftp):
+ // "FTP" 2*("." label) ["/" *UCS4]
+ //
+ // 4th Production (http):
+ // label 2*("." label) ["/" *UCS4]
+ //
+ // 5th Production (file):
+ // "//" (domain / IPv6reference) ["/" *UCS4]
+ //
+ // 6th Production (Unix file):
+ // "/" *UCS4
+ //
+ // 7th Production (UNC file; FSYS_DOS only):
+ // "\\" domain ["\" *UCS4]
+ //
+ // 8th Production (Unix-like DOS file; FSYS_DOS only):
+ // ALPHA ":" ["/" *UCS4]
+ //
+ // 9th Production (DOS file; FSYS_DOS only):
+ // ALPHA ":" ["\" *UCS4]
+ //
+ // For the 'non URL' file productions 6--9, the interpretation of
+ // the input as a (degenerate) URI is turned off, i.e., escape
+ // sequences and fragments are never detected as such, but are
+ // taken as literal characters.
+
+ sal_Unicode const * p1 = pPos;
+ if (eStyle & FSYS_DOS
+ && pEnd - p1 >= 2
+ && INetMIME::isAlpha(p1[0])
+ && p1[1] == ':'
+ && (pEnd - p1 == 2 || p1[2] == '/' || p1[2] == '\\'))
+ {
+ m_eScheme = INET_PROT_FILE; // 8th, 9th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ else if (pEnd - p1 >= 2 && p1[0] == '/' && p1[1] == '/')
+ {
+ p1 += 2;
+ if ((scanDomain(p1, pEnd) > 0 || scanIPv6reference(p1, pEnd))
+ && (p1 == pEnd || *p1 == '/'))
+ m_eScheme = INET_PROT_FILE; // 5th
+ }
+ else if (p1 != pEnd && *p1 == '/')
+ {
+ m_eScheme = INET_PROT_FILE; // 6th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ else if (eStyle & FSYS_DOS
+ && pEnd - p1 >= 2
+ && p1[0] == '\\'
+ && p1[1] == '\\')
+ {
+ p1 += 2;
+ sal_Int32 n = rtl_ustr_indexOfChar_WithLength(
+ p1, pEnd - p1, '\\');
+ sal_Unicode const * pe = n == -1 ? pEnd : p1 + n;
+ if (
+ parseHostOrNetBiosName(
+ p1, pe, bOctets, ENCODE_ALL, RTL_TEXTENCODING_DONTKNOW,
+ true, NULL) ||
+ (scanDomain(p1, pe) > 0 && p1 == pe)
+ )
+ {
+ m_eScheme = INET_PROT_FILE; // 7th
+ eMechanism = ENCODE_ALL;
+ nFragmentDelimiter = 0x80000000;
+ }
+ }
+ else
+ {
+ sal_Unicode const * pDomainEnd = p1;
+ sal_uInt32 nLabels = scanDomain(pDomainEnd, pEnd);
+ if (nLabels > 0 && pDomainEnd != pEnd && *pDomainEnd == '@')
+ {
+ ++pDomainEnd;
+ if (scanDomain(pDomainEnd, pEnd) > 0
+ && pDomainEnd == pEnd)
+ m_eScheme = INET_PROT_MAILTO; // 2nd
+ }
+ else if (nLabels >= 3
+ && (pDomainEnd == pEnd || *pDomainEnd == '/'))
+ m_eScheme
+ = pDomainEnd - p1 >= 4
+ && (p1[0] == 'f' || p1[0] == 'F')
+ && (p1[1] == 't' || p1[1] == 'T')
+ && (p1[2] == 'p' || p1[2] == 'P')
+ && p1[3] == '.' ?
+ INET_PROT_FTP : INET_PROT_HTTP; // 3rd, 4th
+ }
+ }
+
+ rtl::OUString aSynScheme;
+ if (m_eScheme == INET_PROT_NOT_VALID) {
+ sal_Unicode const * p1 = pPos;
+ aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter);
+ if (aSynScheme.getLength() > 0)
+ {
+ m_eScheme = INET_PROT_GENERIC;
+ pPos = p1;
+ }
+ }
+
+ if (bSmart && m_eScheme == INET_PROT_NOT_VALID && pPos != pEnd
+ && *pPos != nFragmentDelimiter)
+ {
+ m_eScheme = m_eSmartScheme;
+ }
+
+ if (m_eScheme == INET_PROT_NOT_VALID)
+ {
+ setInvalid();
+ return false;
+ }
+
+ if (m_eScheme != INET_PROT_GENERIC) {
+ aSynScheme = rtl::OUString::createFromAscii(getSchemeInfo().m_pScheme);
+ }
+ m_aScheme.set(aSynAbsURIRef, aSynScheme, aSynAbsURIRef.getLength());
+ aSynAbsURIRef.append(sal_Unicode(':'));
+ }
+
+ sal_Char cEscapePrefix = getEscapePrefix();
+ sal_uInt32 nSegmentDelimiter = '/';
+ sal_uInt32 nAltSegmentDelimiter = 0x80000000;
+ bool bSkippedInitialSlash = false;
+
+ // Parse //<user>;AUTH=<auth>@<host>:<port> or
+ // //<user>:<password>@<host>:<port> or
+ // //<reg_name>
+ if (getSchemeInfo().m_bAuthority)
+ {
+ sal_Unicode const * pUserInfoBegin = 0;
+ sal_Unicode const * pUserInfoEnd = 0;
+ sal_Unicode const * pHostPortBegin = 0;
+ sal_Unicode const * pHostPortEnd = 0;
+
+ switch (m_eScheme)
+ {
+ case INET_PROT_VND_SUN_STAR_HELP:
+ {
+ if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ rtl::OUStringBuffer aSynAuthority;
+ while (pPos < pEnd
+ && *pPos != '/' && *pPos != '?'
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAuthority, nUTF32, eEscapeType, bOctets,
+ PART_AUTHORITY, cEscapePrefix, eCharset,
+ false);
+ }
+ m_aHost.set(aSynAbsURIRef,
+ aSynAuthority.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ // misusing m_aHost to store the authority
+ break;
+ }
+
+ case INET_PROT_VND_SUN_STAR_HIER:
+ {
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ pPos += 2;
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ rtl::OUStringBuffer aSynAuthority;
+ while (pPos < pEnd
+ && *pPos != '/' && *pPos != '?'
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos,
+ pEnd,
+ bOctets,
+ cEscapePrefix,
+ eMechanism,
+ eCharset,
+ eEscapeType);
+ appendUCS4(aSynAuthority,
+ nUTF32,
+ eEscapeType,
+ bOctets,
+ PART_AUTHORITY,
+ cEscapePrefix,
+ eCharset,
+ false);
+ }
+ if (aSynAuthority.getLength() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ m_aHost.set(aSynAbsURIRef,
+ aSynAuthority.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ // misusing m_aHost to store the authority
+ }
+ break;
+ }
+
+ case INET_PROT_VND_SUN_STAR_PKG:
+ {
+ if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/')
+ {
+ setInvalid();
+ return false;
+ }
+ aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ rtl::OUStringBuffer aSynAuthority;
+ while (pPos < pEnd
+ && *pPos != '/' && *pPos != '?'
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAuthority, nUTF32, eEscapeType, bOctets,
+ PART_AUTHORITY, cEscapePrefix, eCharset,
+ false);
+ }
+ if (aSynAuthority.getLength() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ m_aHost.set(aSynAbsURIRef,
+ aSynAuthority.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ // misusing m_aHost to store the authority
+ break;
+ }
+
+ case INET_PROT_FILE:
+ if (bSmart)
+ {
+ // The first of the following seven productions that
+ // matches the rest of the input string (and for which the
+ // appropriate style bit is set in eStyle, if applicable)
+ // determines the used notation. The productions use the
+ // auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // IPv6reference = "[" IPv6address "]"
+ // IPv6address = hexpart [":" IPv4address]
+ // IPv4address = 1*3DIGIT 3("." 1*3DIGIT)
+ // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq])
+ // hexseq = hex4 *(":" hex4)
+ // hex4 = 1*4HEXDIG
+ // path = <any UCS4 character except "#">
+ // UCS4 = <any UCS4 character>
+
+ // 1st Production (URL):
+ // "//" [domain / IPv6reference] ["/" *path]
+ // ["#" *UCS4]
+ // becomes
+ // "file://" domain "/" *path ["#" *UCS4]
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ sal_Unicode const * p1 = pPos + 2;
+ while (p1 != pEnd && *p1 != '/' &&
+ *p1 != nFragmentDelimiter)
+ {
+ ++p1;
+ }
+ if (parseHostOrNetBiosName(
+ pPos + 2, p1, bOctets, ENCODE_ALL,
+ RTL_TEXTENCODING_DONTKNOW, true, NULL))
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ pHostPortBegin = pPos + 2;
+ pHostPortEnd = p1;
+ pPos = p1;
+ break;
+ }
+ }
+
+ // 2nd Production (MS IE generated 1; FSYS_DOS only):
+ // "//" ALPHA ":" ["/" *path] ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ //
+ // 3rd Production (MS IE generated 2; FSYS_DOS only):
+ // "//" ALPHA ":" ["\" *path] ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ //
+ // 4th Production (misscounted slashes):
+ // "//" *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ pPos += 2;
+ bSkippedInitialSlash = true;
+ if ((eStyle & FSYS_DOS) != 0
+ && pEnd - pPos >= 2
+ && INetMIME::isAlpha(pPos[0])
+ && pPos[1] == ':'
+ && (pEnd - pPos == 2
+ || pPos[2] == '/' || pPos[2] == '\\'))
+ nAltSegmentDelimiter = '\\';
+ break;
+ }
+
+ // 5th Production (Unix):
+ // "/" *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ if (pPos < pEnd && *pPos == '/')
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ break;
+ }
+
+ // 6th Production (UNC; FSYS_DOS only):
+ // "\\" domain ["\" *path] ["#" *UCS4]
+ // becomes
+ // "file://" domain "/" *path ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ if (eStyle & FSYS_DOS
+ && pEnd - pPos >= 2
+ && pPos[0] == '\\'
+ && pPos[1] == '\\')
+ {
+ sal_Unicode const * p1 = pPos + 2;
+ sal_Unicode const * pe = p1;
+ while (pe < pEnd && *pe != '\\' &&
+ *pe != nFragmentDelimiter)
+ {
+ ++pe;
+ }
+ if (
+ parseHostOrNetBiosName(
+ p1, pe, bOctets, ENCODE_ALL,
+ RTL_TEXTENCODING_DONTKNOW, true, NULL) ||
+ (scanDomain(p1, pe) > 0 && p1 == pe)
+ )
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ pHostPortBegin = pPos + 2;
+ pHostPortEnd = pe;
+ pPos = pe;
+ nSegmentDelimiter = '\\';
+ break;
+ }
+ }
+
+ // 7th Production (Unix-like DOS; FSYS_DOS only):
+ // ALPHA ":" ["/" *path] ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ //
+ // 8th Production (DOS; FSYS_DOS only):
+ // ALPHA ":" ["\" *path] ["#" *UCS4]
+ // becomes
+ // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
+ // replacing "\" by "/" within <*path>
+ if (eStyle & FSYS_DOS
+ && pEnd - pPos >= 2
+ && INetMIME::isAlpha(pPos[0])
+ && pPos[1] == ':'
+ && (pEnd - pPos == 2
+ || pPos[2] == '/'
+ || pPos[2] == '\\'))
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ nAltSegmentDelimiter = '\\';
+ bSkippedInitialSlash = true;
+ break;
+ }
+
+ // 9th Production (any):
+ // *path ["#" *UCS4]
+ // becomes
+ // "file:///" *path ["#" *UCS4]
+ // replacing the delimiter by "/" within <*path>. The
+ // delimiter is that character from the set { "/", "\",
+ // ":" } which appears most often in <*path> (if FSYS_UNX
+ // is not among the style bits, "/" is removed from the
+ // set; if FSYS_DOS is not among the style bits, "\" is
+ // removed from the set; if FSYS_MAC is not among the
+ // style bits, ":" is removed from the set). If two or
+ // more characters appear the same number of times, the
+ // character mentioned first in that set is chosen. If
+ // the first character of <*path> is the delimiter, that
+ // character is not copied.
+ if (eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC))
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ switch (guessFSysStyleByCounting(pPos, pEnd, eStyle))
+ {
+ case FSYS_UNX:
+ nSegmentDelimiter = '/';
+ break;
+
+ case FSYS_DOS:
+ nSegmentDelimiter = '\\';
+ break;
+
+ case FSYS_MAC:
+ nSegmentDelimiter = ':';
+ break;
+
+ default:
+ DBG_ERROR(
+ "INetURLObject::setAbsURIRef():"
+ " Bad guessFSysStyleByCounting");
+ break;
+ }
+ bSkippedInitialSlash
+ = pPos != pEnd && *pPos != nSegmentDelimiter;
+ break;
+ }
+ }
+ default:
+ {
+ // For INET_PROT_FILE, allow an empty authority ("//") to be
+ // missing if the following path starts with an explicit "/"
+ // (Java is notorious in generating such file URLs, so be
+ // liberal here):
+ if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/')
+ pPos += 2;
+ else if (!bSmart
+ && !(m_eScheme == INET_PROT_FILE
+ && pPos != pEnd && *pPos == '/'))
+ {
+ setInvalid();
+ return false;
+ }
+ aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+
+ sal_Unicode const * pAuthority = pPos;
+ sal_uInt32 c = getSchemeInfo().m_bQuery ? '?' : 0x80000000;
+ while (pPos < pEnd && *pPos != '/' && *pPos != c
+ && *pPos != nFragmentDelimiter)
+ ++pPos;
+ if (getSchemeInfo().m_bUser)
+ if (getSchemeInfo().m_bHost)
+ {
+ sal_Unicode const * p1 = pAuthority;
+ while (p1 < pPos && *p1 != '@')
+ ++p1;
+ if (p1 == pPos)
+ {
+ pHostPortBegin = pAuthority;
+ pHostPortEnd = pPos;
+ }
+ else
+ {
+ pUserInfoBegin = pAuthority;
+ pUserInfoEnd = p1;
+ pHostPortBegin = p1 + 1;
+ pHostPortEnd = pPos;
+ }
+ }
+ else
+ {
+ pUserInfoBegin = pAuthority;
+ pUserInfoEnd = pPos;
+ }
+ else if (getSchemeInfo().m_bHost)
+ {
+ pHostPortBegin = pAuthority;
+ pHostPortEnd = pPos;
+ }
+ else if (pPos != pAuthority)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (pUserInfoBegin)
+ {
+ Part ePart = m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD;
+ bool bSupportsPassword = getSchemeInfo().m_bPassword;
+ bool bSupportsAuth
+ = !bSupportsPassword && getSchemeInfo().m_bAuth;
+ bool bHasAuth = false;
+ rtl::OUStringBuffer aSynUser;
+ sal_Unicode const * p1 = pUserInfoBegin;
+ while (p1 < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets,
+ cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ {
+ if (nUTF32 == ':' && bSupportsPassword)
+ {
+ bHasAuth = true;
+ break;
+ }
+ else if (nUTF32 == ';' && bSupportsAuth
+ && pUserInfoEnd - p1
+ > RTL_CONSTASCII_LENGTH("auth=")
+ && INetMIME::equalIgnoreCase(
+ p1,
+ p1 + RTL_CONSTASCII_LENGTH("auth="),
+ "auth="))
+ {
+ p1 += RTL_CONSTASCII_LENGTH("auth=");
+ bHasAuth = true;
+ break;
+ }
+ }
+ appendUCS4(aSynUser, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, false);
+ }
+ m_aUser.set(aSynAbsURIRef, aSynUser.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ if (bHasAuth)
+ {
+ if (bSupportsPassword)
+ {
+ aSynAbsURIRef.append(sal_Unicode(':'));
+ rtl::OUStringBuffer aSynAuth;
+ while (p1 < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets,
+ cEscapePrefix,
+ eMechanism, eCharset,
+ eEscapeType);
+ appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets,
+ ePart, cEscapePrefix, eCharset, false);
+ }
+ m_aAuth.set(aSynAbsURIRef, aSynAuth.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ }
+ else
+ {
+ aSynAbsURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM(";AUTH="));
+ rtl::OUStringBuffer aSynAuth;
+ while (p1 < pUserInfoEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, bOctets,
+ cEscapePrefix,
+ eMechanism, eCharset,
+ eEscapeType);
+ if (!INetMIME::isIMAPAtomChar(nUTF32))
+ {
+ setInvalid();
+ return false;
+ }
+ appendUCS4(aSynAuth, nUTF32, eEscapeType, bOctets,
+ ePart, cEscapePrefix, eCharset, false);
+ }
+ m_aAuth.set(aSynAbsURIRef, aSynAuth.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ }
+ }
+ if (pHostPortBegin)
+ aSynAbsURIRef.append(sal_Unicode('@'));
+ }
+
+ if (pHostPortBegin)
+ {
+ sal_Unicode const * pPort = pHostPortEnd;
+ if ( getSchemeInfo().m_bPort && pHostPortBegin < pHostPortEnd )
+ {
+ sal_Unicode const * p1 = pHostPortEnd - 1;
+ while (p1 > pHostPortBegin && INetMIME::isDigit(*p1))
+ --p1;
+ if (*p1 == ':')
+ pPort = p1;
+ }
+ bool bNetBiosName = false;
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ // If the host equals "LOCALHOST" (unencoded and ignoring
+ // case), turn it into an empty host:
+ if (INetMIME::equalIgnoreCase(pHostPortBegin, pPort,
+ "localhost"))
+ pHostPortBegin = pPort;
+ bNetBiosName = true;
+ break;
+
+ case INET_PROT_LDAP:
+ case INET_PROT_SMB:
+ if (pHostPortBegin == pPort && pPort != pHostPortEnd)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ default:
+ if (pHostPortBegin == pPort)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ rtl::OUStringBuffer aSynHost;
+ if (!parseHostOrNetBiosName(
+ pHostPortBegin, pPort, bOctets, eMechanism, eCharset,
+ bNetBiosName, &aSynHost))
+ {
+ setInvalid();
+ return false;
+ }
+ m_aHost.set(aSynAbsURIRef, aSynHost.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ if (pPort != pHostPortEnd)
+ {
+ aSynAbsURIRef.append(sal_Unicode(':'));
+ m_aPort.set(aSynAbsURIRef,
+ rtl::OUString(pPort + 1, pHostPortEnd - (pPort + 1)),
+ aSynAbsURIRef.getLength());
+ }
+ }
+ }
+
+ // Parse <path>
+ rtl::OUStringBuffer aSynPath;
+ if (!parsePath(m_eScheme, &pPos, pEnd, bOctets, eMechanism, eCharset,
+ bSkippedInitialSlash, nSegmentDelimiter,
+ nAltSegmentDelimiter,
+ getSchemeInfo().m_bQuery ? '?' : 0x80000000,
+ nFragmentDelimiter, aSynPath))
+ {
+ setInvalid();
+ return false;
+ }
+ m_aPath.set(aSynAbsURIRef, aSynPath.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+
+ // Parse ?<query>
+ if (getSchemeInfo().m_bQuery && pPos < pEnd && *pPos == '?')
+ {
+ aSynAbsURIRef.append(sal_Unicode('?'));
+ rtl::OUStringBuffer aSynQuery;
+ for (++pPos; pPos < pEnd && *pPos != nFragmentDelimiter;)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aSynQuery, nUTF32, eEscapeType, bOctets,
+ PART_URIC, cEscapePrefix, eCharset, true);
+ }
+ m_aQuery.set(aSynAbsURIRef, aSynQuery.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ }
+
+ // Parse #<fragment>
+ if (pPos < pEnd && *pPos == nFragmentDelimiter)
+ {
+ aSynAbsURIRef.append(sal_Unicode(nFragmentDelimiter));
+ rtl::OUStringBuffer aSynFragment;
+ for (++pPos; pPos < pEnd;)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aSynFragment, nUTF32, eEscapeType, bOctets, PART_URIC,
+ cEscapePrefix, eCharset, true);
+ }
+ m_aFragment.set(aSynAbsURIRef, aSynFragment.makeStringAndClear(),
+ aSynAbsURIRef.getLength());
+ }
+
+ if (pPos != pEnd)
+ {
+ setInvalid();
+ return false;
+ }
+
+ m_aAbsURIRef = aSynAbsURIRef;
+
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::convertRelToAbs(rtl::OUString const & rTheRelURIRef,
+ bool bOctets,
+ INetURLObject & rTheAbsURIRef,
+ bool & rWasAbsolute,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bIgnoreFragment, bool bSmart,
+ bool bRelativeNonURIs, FSysStyle eStyle)
+ const
+{
+ sal_Unicode const * p = rTheRelURIRef.getStr();
+ sal_Unicode const * pEnd = p + rTheRelURIRef.getLength();
+
+ sal_Unicode const * pPrefixBegin = p;
+ PrefixInfo const * pPrefix = getPrefix(pPrefixBegin, pEnd);
+ bool hasScheme = pPrefix != 0;
+ if (!hasScheme) {
+ pPrefixBegin = p;
+ hasScheme = parseScheme(&pPrefixBegin, pEnd, '#').getLength() > 0;
+ }
+
+ sal_uInt32 nSegmentDelimiter = '/';
+ sal_uInt32 nQueryDelimiter
+ = !bSmart || getSchemeInfo().m_bQuery ? '?' : 0x80000000;
+ sal_uInt32 nFragmentDelimiter = '#';
+ Part ePart = PART_VISIBLE;
+
+ if (!hasScheme && bSmart)
+ {
+ // If the input matches any of the following productions (for which
+ // the appropriate style bit is set in eStyle), it is assumed to be an
+ // absolute file system path, rather than a relative URI reference.
+ // (This is only a subset of the productions used for scheme detection
+ // in INetURLObject::setAbsURIRef(), because most of those productions
+ // interfere with the syntax of relative URI references.) The
+ // productions use the auxiliary rules
+ //
+ // domain = label *("." label)
+ // label = alphanum [*(alphanum / "-") alphanum]
+ // alphanum = ALPHA / DIGIT
+ // UCS4 = <any UCS4 character>
+ //
+ // 1st Production (UNC file; FSYS_DOS only):
+ // "\\" domain ["\" *UCS4]
+ //
+ // 2nd Production (Unix-like DOS file; FSYS_DOS only):
+ // ALPHA ":" ["/" *UCS4]
+ //
+ // 3rd Production (DOS file; FSYS_DOS only):
+ // ALPHA ":" ["\" *UCS4]
+ if (eStyle & FSYS_DOS)
+ {
+ bool bFSys = false;
+ sal_Unicode const * q = p;
+ if (pEnd - q >= 2
+ && INetMIME::isAlpha(q[0])
+ && q[1] == ':'
+ && (pEnd - q == 2 || q[2] == '/' || q[2] == '\\'))
+ bFSys = true; // 2nd, 3rd
+ else if (pEnd - q >= 2 && q[0] == '\\' && q[1] == '\\')
+ {
+ q += 2;
+ sal_Int32 n = rtl_ustr_indexOfChar_WithLength(
+ q, pEnd - q, '\\');
+ sal_Unicode const * qe = n == -1 ? pEnd : q + n;
+ if (parseHostOrNetBiosName(
+ q, qe, bOctets, ENCODE_ALL, RTL_TEXTENCODING_DONTKNOW,
+ true, NULL))
+ {
+ bFSys = true; // 1st
+ }
+ }
+ if (bFSys)
+ {
+ INetURLObject aNewURI;
+ aNewURI.setAbsURIRef(rTheRelURIRef, bOctets, eMechanism,
+ eCharset, true, eStyle);
+ if (!aNewURI.HasError())
+ {
+ rTheAbsURIRef = aNewURI;
+ rWasAbsolute = true;
+ return true;
+ }
+ }
+ }
+
+ // When the base URL is a file URL, accept relative file system paths
+ // using "\" or ":" as delimiter (and ignoring URI conventions for "%"
+ // and "#"), as well as relative URIs using "/" as delimiter:
+ if (m_eScheme == INET_PROT_FILE)
+ switch (guessFSysStyleByCounting(p, pEnd, eStyle))
+ {
+ case FSYS_UNX:
+ nSegmentDelimiter = '/';
+ break;
+
+ case FSYS_DOS:
+ nSegmentDelimiter = '\\';
+ bRelativeNonURIs = true;
+ break;
+
+ case FSYS_MAC:
+ nSegmentDelimiter = ':';
+ bRelativeNonURIs = true;
+ break;
+
+ default:
+ DBG_ERROR("INetURLObject::convertRelToAbs():"
+ " Bad guessFSysStyleByCounting");
+ break;
+ }
+
+ if (bRelativeNonURIs)
+ {
+ eMechanism = ENCODE_ALL;
+ nQueryDelimiter = 0x80000000;
+ nFragmentDelimiter = 0x80000000;
+ ePart = PART_VISIBLE_NONSPECIAL;
+ }
+ }
+
+ // If the relative URI has the same scheme as the base URI, and that
+ // scheme is hierarchical, then ignore its presence in the relative
+ // URI in order to be backward compatible (cf. RFC 2396 section 5.2
+ // step 3):
+ if (pPrefix && pPrefix->m_eScheme == m_eScheme
+ && getSchemeInfo().m_bHierarchical)
+ {
+ hasScheme = false;
+ while (p != pEnd && *p++ != ':') ;
+ }
+ rWasAbsolute = hasScheme;
+
+ // Fast solution for non-relative URIs:
+ if (hasScheme)
+ {
+ INetURLObject aNewURI(rTheRelURIRef, eMechanism, eCharset);
+ if (aNewURI.HasError())
+ {
+ rWasAbsolute = false;
+ return false;
+ }
+
+ if (bIgnoreFragment)
+ aNewURI.clearFragment();
+ rTheAbsURIRef = aNewURI;
+ return true;
+ }
+
+ enum State { STATE_AUTH, STATE_ABS_PATH, STATE_REL_PATH, STATE_FRAGMENT,
+ STATE_DONE };
+
+ rtl::OUStringBuffer aSynAbsURIRef;
+ // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme
+ // is empty ("") in that case, so take the scheme from m_aAbsURIRef
+ if (m_eScheme != INET_PROT_GENERIC)
+ {
+ aSynAbsURIRef.appendAscii(getSchemeInfo().m_pScheme);
+ }
+ else
+ {
+ sal_Unicode const * pSchemeBegin
+ = m_aAbsURIRef.getStr();
+ sal_Unicode const * pSchemeEnd = pSchemeBegin;
+ while (pSchemeEnd[0] != ':')
+ {
+ ++pSchemeEnd;
+ }
+ aSynAbsURIRef.append(pSchemeBegin, pSchemeEnd - pSchemeBegin);
+ }
+ aSynAbsURIRef.append(sal_Unicode(':'));
+
+ sal_Char cEscapePrefix = getEscapePrefix();
+
+ State eState = STATE_AUTH;
+ bool bSameDoc = true;
+
+ if (getSchemeInfo().m_bAuthority)
+ {
+ if (pEnd - p >= 2 && p[0] == '/' && p[1] == '/')
+ {
+ aSynAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ p += 2;
+ eState = STATE_ABS_PATH;
+ bSameDoc = false;
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ {
+ if (nUTF32 == nSegmentDelimiter)
+ break;
+ else if (nUTF32 == nFragmentDelimiter)
+ {
+ eState = STATE_FRAGMENT;
+ break;
+ }
+ }
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets,
+ PART_VISIBLE, cEscapePrefix, eCharset, true);
+ }
+ }
+ else
+ {
+ SubString aAuthority(getAuthority());
+ aSynAbsURIRef.append(m_aAbsURIRef.getStr()
+ + aAuthority.getBegin(),
+ aAuthority.getLength());
+ }
+ }
+
+ if (eState == STATE_AUTH)
+ {
+ if (p == pEnd)
+ eState = STATE_DONE;
+ else if (*p == nFragmentDelimiter)
+ {
+ ++p;
+ eState = STATE_FRAGMENT;
+ }
+ else if (*p == nSegmentDelimiter)
+ {
+ ++p;
+ eState = STATE_ABS_PATH;
+ bSameDoc = false;
+ }
+ else
+ {
+ eState = STATE_REL_PATH;
+ bSameDoc = false;
+ }
+ }
+
+ if (eState == STATE_ABS_PATH)
+ {
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ eState = STATE_DONE;
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ {
+ if (nUTF32 == nFragmentDelimiter)
+ {
+ eState = STATE_FRAGMENT;
+ break;
+ }
+ else if (nUTF32 == nSegmentDelimiter)
+ nUTF32 = '/';
+ }
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+ }
+ else if (eState == STATE_REL_PATH)
+ {
+ if (!getSchemeInfo().m_bHierarchical)
+ {
+ // Detect cases where a relative input could not be made absolute
+ // because the given base URL is broken (most probably because it is
+ // empty):
+ OSL_ASSERT(!HasError());
+ rWasAbsolute = false;
+ return false;
+ }
+
+ sal_Unicode const * pBasePathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pBasePathEnd
+ = pBasePathBegin + m_aPath.getLength();
+ while (pBasePathEnd != pBasePathBegin)
+ if (*(--pBasePathEnd) == '/')
+ {
+ ++pBasePathEnd;
+ break;
+ }
+
+ sal_Int32 nPathBegin = aSynAbsURIRef.getLength();
+ aSynAbsURIRef.append(pBasePathBegin, pBasePathEnd - pBasePathBegin);
+ DBG_ASSERT(aSynAbsURIRef.getLength() > nPathBegin
+ && aSynAbsURIRef.charAt(aSynAbsURIRef.getLength() - 1) == '/',
+ "INetURLObject::convertRelToAbs(): Bad base path");
+
+ while (p != pEnd && *p != nQueryDelimiter && *p != nFragmentDelimiter)
+ {
+ if (*p == '.')
+ {
+ if (pEnd - p == 1
+ || p[1] == nSegmentDelimiter
+ || p[1] == nQueryDelimiter
+ || p[1] == nFragmentDelimiter)
+ {
+ ++p;
+ if (p != pEnd && *p == nSegmentDelimiter)
+ ++p;
+ continue;
+ }
+ else if (pEnd - p >= 2
+ && p[1] == '.'
+ && (pEnd - p == 2
+ || p[2] == nSegmentDelimiter
+ || p[2] == nQueryDelimiter
+ || p[2] == nFragmentDelimiter)
+ && aSynAbsURIRef.getLength() - nPathBegin > 1)
+ {
+ p += 2;
+ if (p != pEnd && *p == nSegmentDelimiter)
+ ++p;
+
+ sal_Int32 i = aSynAbsURIRef.getLength() - 2;
+ while (i > nPathBegin && aSynAbsURIRef.charAt(i) != '/')
+ --i;
+ aSynAbsURIRef.setLength(i + 1);
+ DBG_ASSERT(
+ aSynAbsURIRef.getLength() > nPathBegin
+ && aSynAbsURIRef.charAt(aSynAbsURIRef.getLength() - 1)
+ == '/',
+ "INetURLObject::convertRelToAbs(): Bad base path");
+ continue;
+ }
+ }
+
+ while (p != pEnd
+ && *p != nSegmentDelimiter
+ && *p != nQueryDelimiter
+ && *p != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+ if (p != pEnd && *p == nSegmentDelimiter)
+ {
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ ++p;
+ }
+ }
+
+ while (p != pEnd && *p != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, true);
+ }
+
+ if (p == pEnd)
+ eState = STATE_DONE;
+ else
+ {
+ ++p;
+ eState = STATE_FRAGMENT;
+ }
+ }
+ else if (bSameDoc)
+ {
+ aSynAbsURIRef.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(),
+ m_aPath.getLength());
+ if (m_aQuery.isPresent())
+ aSynAbsURIRef.append(m_aAbsURIRef.getStr()
+ + m_aQuery.getBegin() - 1,
+ m_aQuery.getLength() + 1);
+ }
+
+ if (eState == STATE_FRAGMENT && !bIgnoreFragment)
+ {
+ aSynAbsURIRef.append(sal_Unicode('#'));
+ while (p != pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32
+ = getUTF32(p, pEnd, bOctets, cEscapePrefix, eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, bOctets,
+ PART_VISIBLE, cEscapePrefix, eCharset, true);
+ }
+ }
+
+ INetURLObject aNewURI(aSynAbsURIRef.makeStringAndClear());
+ if (aNewURI.HasError())
+ {
+ // Detect cases where a relative input could not be made absolute
+ // because the given base URL is broken (most probably because it is
+ // empty):
+ OSL_ASSERT(!HasError());
+ rWasAbsolute = false;
+ return false;
+ }
+
+ rTheAbsURIRef = aNewURI;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::convertAbsToRel(rtl::OUString const & rTheAbsURIRef,
+ bool bOctets, rtl::OUString & rTheRelURIRef,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle) const
+{
+ // Check for hierarchical base URL:
+ if (!getSchemeInfo().m_bHierarchical)
+ {
+ rTheRelURIRef
+ = decode(rTheAbsURIRef,
+ getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)),
+ eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // Convert the input (absolute or relative URI ref) to an absolute URI
+ // ref:
+ INetURLObject aSubject;
+ bool bWasAbsolute;
+ if (!convertRelToAbs(rTheAbsURIRef, bOctets, aSubject, bWasAbsolute,
+ eEncodeMechanism, eCharset, false, false, false,
+ eStyle))
+ {
+ rTheRelURIRef
+ = decode(rTheAbsURIRef,
+ getEscapePrefix(CompareProtocolScheme(rTheAbsURIRef)),
+ eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // Check for differing scheme or authority parts:
+ if ((m_aScheme.compare(
+ aSubject.m_aScheme, m_aAbsURIRef, aSubject.m_aAbsURIRef)
+ != 0)
+ || (m_aUser.compare(
+ aSubject.m_aUser, m_aAbsURIRef, aSubject.m_aAbsURIRef)
+ != 0)
+ || (m_aAuth.compare(
+ aSubject.m_aAuth, m_aAbsURIRef, aSubject.m_aAbsURIRef)
+ != 0)
+ || (m_aHost.compare(
+ aSubject.m_aHost, m_aAbsURIRef, aSubject.m_aAbsURIRef)
+ != 0)
+ || (m_aPort.compare(
+ aSubject.m_aPort, m_aAbsURIRef, aSubject.m_aAbsURIRef)
+ != 0))
+ {
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ sal_Unicode const * pBasePathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pBasePathEnd = pBasePathBegin + m_aPath.getLength();
+ sal_Unicode const * pSubjectPathBegin
+ = aSubject.m_aAbsURIRef.getStr() + aSubject.m_aPath.getBegin();
+ sal_Unicode const * pSubjectPathEnd
+ = pSubjectPathBegin + aSubject.m_aPath.getLength();
+
+ // Make nMatch point past the last matching slash, or past the end of the
+ // paths, in case they are equal:
+ sal_Unicode const * pSlash = 0;
+ sal_Unicode const * p1 = pBasePathBegin;
+ sal_Unicode const * p2 = pSubjectPathBegin;
+ for (;;)
+ {
+ if (p1 == pBasePathEnd || p2 == pSubjectPathEnd)
+ {
+ if (p1 == pBasePathEnd && p2 == pSubjectPathEnd)
+ pSlash = p1;
+ break;
+ }
+
+ sal_Unicode c = *p1++;
+ if (c != *p2++)
+ break;
+ if (c == '/')
+ pSlash = p1;
+ }
+ if (!pSlash)
+ {
+ // One of the paths does not start with '/':
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+ sal_Int32 nMatch = pSlash - pBasePathBegin;
+
+ // If the two URLs are DOS file URLs starting with different volumes
+ // (e.g., file:///a:/... and file:///b:/...), the subject is not made
+ // relative (it could be, but some people do not like that):
+ if (m_eScheme == INET_PROT_FILE
+ && nMatch <= 1
+ && hasDosVolume(eStyle)
+ && aSubject.hasDosVolume(eStyle)) //TODO! ok to use eStyle for these?
+ {
+ rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset);
+ return false;
+ }
+
+ // For every slash in the base path after nMatch, a prefix of "../" is
+ // added to the new relative URL (if the common prefix of the two paths is
+ // only "/"---but see handling of file URLs above---, the complete subject
+ // path could go into the new relative URL instead, but some people don't
+ // like that):
+ rtl::OUStringBuffer aSynRelURIRef;
+// if (nMatch <= 1) nMatch = 0; else // see comment above
+ for (sal_Unicode const * p = pBasePathBegin + nMatch; p != pBasePathEnd;
+ ++p)
+ {
+ if (*p == '/')
+ aSynRelURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("../"));
+ }
+
+ // If the new relative URL would start with "//" (i.e., it would be
+ // mistaken for a relative URL starting with an authority part), or if the
+ // new relative URL would neither be empty nor start with <"/"> nor start
+ // with <1*rseg> (i.e., it could be mistaken for an absolute URL starting
+ // with a scheme part), then the new relative URL is prefixed with "./":
+ if (aSynRelURIRef.getLength() == 0)
+ {
+ if (pSubjectPathEnd - pSubjectPathBegin >= nMatch + 2
+ && pSubjectPathBegin[nMatch] == '/'
+ && pSubjectPathBegin[nMatch + 1] == '/')
+ {
+ aSynRelURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("./"));
+ }
+ else
+ {
+ for (sal_Unicode const * p = pSubjectPathBegin + nMatch;
+ p != pSubjectPathEnd && *p != '/'; ++p)
+ {
+ if (mustEncode(*p, PART_REL_SEGMENT_EXTRA))
+ {
+ aSynRelURIRef.
+ appendAscii(RTL_CONSTASCII_STRINGPARAM("./"));
+ break;
+ }
+ }
+ }
+ }
+
+ // The remainder of the subject path, starting at nMatch, is appended to
+ // the new relative URL:
+ sal_Char cEscapePrefix = getEscapePrefix();
+ aSynRelURIRef.append(decode(pSubjectPathBegin + nMatch, pSubjectPathEnd,
+ cEscapePrefix, eDecodeMechanism, eCharset));
+
+ // If the subject has defined query or fragment parts, they are appended
+ // to the new relative URL:
+ if (aSubject.m_aQuery.isPresent())
+ {
+ aSynRelURIRef.append(sal_Unicode('?'));
+ aSynRelURIRef.append(aSubject.decode(aSubject.m_aQuery, cEscapePrefix,
+ eDecodeMechanism, eCharset));
+ }
+ if (aSubject.m_aFragment.isPresent())
+ {
+ aSynRelURIRef.append(sal_Unicode('#'));
+ aSynRelURIRef.append(aSubject.decode(aSubject.m_aFragment,
+ cEscapePrefix, eDecodeMechanism, eCharset));
+ }
+
+ rTheRelURIRef = aSynRelURIRef.makeStringAndClear();
+ return true;
+}
+
+//============================================================================
+// static
+bool INetURLObject::convertIntToExt(rtl::OUString const & rTheIntURIRef,
+ bool bOctets, rtl::OUString & rTheExtURIRef,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset)
+{
+ sal_Char cEscapePrefix
+ = getEscapePrefix(CompareProtocolScheme(rTheIntURIRef));
+ rtl::OUString aSynExtURIRef(encodeText(rTheIntURIRef, bOctets, PART_VISIBLE,
+ cEscapePrefix, NOT_CANONIC, eCharset,
+ true));
+ sal_Unicode const * pBegin = aSynExtURIRef.getStr();
+ sal_Unicode const * pEnd = pBegin + aSynExtURIRef.getLength();
+ sal_Unicode const * p = pBegin;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::INTERNAL;
+ if (bConvert)
+ {
+ aSynExtURIRef =
+ aSynExtURIRef.replaceAt(0, p - pBegin,
+ rtl::OUString::createFromAscii(pPrefix->m_pTranslatedPrefix));
+ }
+ rTheExtURIRef = decode(aSynExtURIRef, cEscapePrefix, eDecodeMechanism,
+ eCharset);
+ return bConvert;
+}
+
+//============================================================================
+// static
+bool INetURLObject::convertExtToInt(rtl::OUString const & rTheExtURIRef,
+ bool bOctets, rtl::OUString & rTheIntURIRef,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset)
+{
+ sal_Char cEscapePrefix
+ = getEscapePrefix(CompareProtocolScheme(rTheExtURIRef));
+ rtl::OUString aSynIntURIRef(encodeText(rTheExtURIRef, bOctets, PART_VISIBLE,
+ cEscapePrefix, NOT_CANONIC, eCharset,
+ true));
+ sal_Unicode const * pBegin = aSynIntURIRef.getStr();
+ sal_Unicode const * pEnd = pBegin + aSynIntURIRef.getLength();
+ sal_Unicode const * p = pBegin;
+ PrefixInfo const * pPrefix = getPrefix(p, pEnd);
+ bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::EXTERNAL;
+ if (bConvert)
+ {
+ aSynIntURIRef =
+ aSynIntURIRef.replaceAt(0, p - pBegin,
+ rtl::OUString::createFromAscii(pPrefix->m_pTranslatedPrefix));
+ }
+ rTheIntURIRef = decode(aSynIntURIRef, cEscapePrefix, eDecodeMechanism,
+ eCharset);
+ return bConvert;
+}
+
+//============================================================================
+// static
+INetURLObject::PrefixInfo const *
+INetURLObject::getPrefix(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd)
+{
+ static PrefixInfo const aMap[]
+ = { // dummy entry at front needed, because pLast may point here:
+ { 0, 0, INET_PROT_NOT_VALID, PrefixInfo::INTERNAL },
+ { ".component:", "staroffice.component:", INET_PROT_COMPONENT,
+ PrefixInfo::INTERNAL },
+ { ".uno:", "staroffice.uno:", INET_PROT_UNO,
+ PrefixInfo::INTERNAL },
+ { "cid:", 0, INET_PROT_CID, PrefixInfo::OFFICIAL },
+ { "data:", 0, INET_PROT_DATA, PrefixInfo::OFFICIAL },
+ { "db:", "staroffice.db:", INET_PROT_DB, PrefixInfo::INTERNAL },
+ { "file:", 0, INET_PROT_FILE, PrefixInfo::OFFICIAL },
+ { "ftp:", 0, INET_PROT_FTP, PrefixInfo::OFFICIAL },
+ { "http:", 0, INET_PROT_HTTP, PrefixInfo::OFFICIAL },
+ { "https:", 0, INET_PROT_HTTPS, PrefixInfo::OFFICIAL },
+ { "imap:", 0, INET_PROT_IMAP, PrefixInfo::OFFICIAL },
+ { "javascript:", 0, INET_PROT_JAVASCRIPT, PrefixInfo::OFFICIAL },
+ { "ldap:", 0, INET_PROT_LDAP, PrefixInfo::OFFICIAL },
+ { "macro:", "staroffice.macro:", INET_PROT_MACRO,
+ PrefixInfo::INTERNAL },
+ { "mailto:", 0, INET_PROT_MAILTO, PrefixInfo::OFFICIAL },
+ { "news:", 0, INET_PROT_NEWS, PrefixInfo::OFFICIAL },
+ { "out:", "staroffice.out:", INET_PROT_OUT,
+ PrefixInfo::INTERNAL },
+ { "pop3:", "staroffice.pop3:", INET_PROT_POP3,
+ PrefixInfo::INTERNAL },
+ { "private:", "staroffice.private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:factory/", "staroffice.factory:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "private:helpid/", "staroffice.helpid:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:java/", "staroffice.java:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::INTERNAL },
+ { "private:searchfolder:", "staroffice.searchfolder:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "private:trashcan:", "staroffice.trashcan:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::INTERNAL },
+ { "slot:", "staroffice.slot:", INET_PROT_SLOT,
+ PrefixInfo::INTERNAL },
+ { "smb:", 0, INET_PROT_SMB, PrefixInfo::OFFICIAL },
+ { "staroffice.component:", ".component:", INET_PROT_COMPONENT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.db:", "db:", INET_PROT_DB, PrefixInfo::EXTERNAL },
+ { "staroffice.factory:", "private:factory/",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.helpid:", "private:helpid/", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.java:", "private:java/", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.macro:", "macro:", INET_PROT_MACRO,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.out:", "out:", INET_PROT_OUT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.pop3:", "pop3:", INET_PROT_POP3,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.private:", "private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.searchfolder:", "private:searchfolder:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.slot:", "slot:", INET_PROT_SLOT,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.trashcan:", "private:trashcan:",
+ INET_PROT_PRIV_SOFFICE, PrefixInfo::EXTERNAL },
+ { "staroffice.uno:", ".uno:", INET_PROT_UNO,
+ PrefixInfo::EXTERNAL },
+ { "staroffice.vim:", "vim:", INET_PROT_VIM,
+ PrefixInfo::EXTERNAL },
+ { "staroffice:", "private:", INET_PROT_PRIV_SOFFICE,
+ PrefixInfo::EXTERNAL },
+ { "telnet:", 0, INET_PROT_TELNET, PrefixInfo::OFFICIAL },
+ { "vim:", "staroffice.vim:", INET_PROT_VIM,
+ PrefixInfo::INTERNAL },
+ { "vnd.sun.star.cmd:", 0, INET_PROT_VND_SUN_STAR_CMD,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.expand:", 0, INET_PROT_VND_SUN_STAR_EXPAND,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.help:", 0, INET_PROT_VND_SUN_STAR_HELP,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.hier:", 0, INET_PROT_VND_SUN_STAR_HIER,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.odma:", 0, INET_PROT_VND_SUN_STAR_ODMA,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.pkg:", 0, INET_PROT_VND_SUN_STAR_PKG,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.tdoc:", 0, INET_PROT_VND_SUN_STAR_TDOC,
+ PrefixInfo::OFFICIAL },
+ { "vnd.sun.star.webdav:", 0, INET_PROT_VND_SUN_STAR_WEBDAV,
+ PrefixInfo::OFFICIAL } };
+ PrefixInfo const * pFirst = aMap + 1;
+ PrefixInfo const * pLast = aMap + sizeof aMap / sizeof (PrefixInfo) - 1;
+ PrefixInfo const * pMatch = 0;
+ sal_Unicode const * pMatched = rBegin;
+ sal_Unicode const * p = rBegin;
+ sal_Int32 i = 0;
+ for (; pFirst < pLast; ++i)
+ {
+ if (pFirst->m_pPrefix[i] == '\0')
+ {
+ pMatch = pFirst++;
+ pMatched = p;
+ }
+ if (p >= pEnd)
+ break;
+ sal_uInt32 nChar = INetMIME::toLowerCase(*p++);
+ while (pFirst <= pLast && sal_uChar(pFirst->m_pPrefix[i]) < nChar)
+ ++pFirst;
+ while (pFirst <= pLast && sal_uChar(pLast->m_pPrefix[i]) > nChar)
+ --pLast;
+ }
+ if (pFirst == pLast)
+ {
+ sal_Char const * q = pFirst->m_pPrefix + i;
+ while (p < pEnd && *q != '\0'
+ && INetMIME::toLowerCase(*p) == sal_uChar(*q))
+ {
+ ++p;
+ ++q;
+ }
+ if (*q == '\0')
+ {
+ rBegin = p;
+ return pFirst;
+ }
+ }
+ rBegin = pMatched;
+ return pMatch;
+}
+
+//============================================================================
+sal_Int32 INetURLObject::getAuthorityBegin() const
+{
+ DBG_ASSERT(getSchemeInfo().m_bAuthority,
+ "INetURLObject::getAuthority(): Bad scheme");
+ sal_Int32 nBegin;
+ if (m_aUser.isPresent())
+ nBegin = m_aUser.getBegin();
+ else if (m_aHost.isPresent())
+ nBegin = m_aHost.getBegin();
+ else
+ nBegin = m_aPath.getBegin();
+ nBegin -= RTL_CONSTASCII_LENGTH("//");
+ DBG_ASSERT(m_aAbsURIRef.charAt(nBegin) == '/'
+ && m_aAbsURIRef.charAt(nBegin + 1) == '/',
+ "INetURLObject::getAuthority(): Bad authority");
+ return nBegin;
+}
+
+//============================================================================
+INetURLObject::SubString INetURLObject::getAuthority() const
+{
+ sal_Int32 nBegin = getAuthorityBegin();
+ sal_Int32 nEnd = m_aPort.isPresent() ? m_aPort.getEnd() :
+ m_aHost.isPresent() ? m_aHost.getEnd() :
+ m_aAuth.isPresent() ? m_aAuth.getEnd() :
+ m_aUser.isPresent() ? m_aUser.getEnd() :
+ nBegin + RTL_CONSTASCII_LENGTH("//");
+ return SubString(nBegin, nEnd - nBegin);
+}
+
+//============================================================================
+bool INetURLObject::setUser(rtl::OUString const & rTheUser,
+ bool bOctets, EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (
+ !getSchemeInfo().m_bUser ||
+ (m_eScheme == INET_PROT_IMAP && rTheUser.getLength() == 0)
+ )
+ {
+ return false;
+ }
+
+ rtl::OUString aNewUser(encodeText(rTheUser, bOctets,
+ m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism, eCharset,
+ false));
+ sal_Int32 nDelta;
+ if (m_aUser.isPresent())
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser);
+ else if (m_aHost.isPresent())
+ {
+ m_aAbsURIRef.insert(m_aHost.getBegin(), sal_Unicode('@'));
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aHost.getBegin()) + 1;
+ }
+ else if (getSchemeInfo().m_bHost)
+ return false;
+ else
+ nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aPath.getBegin());
+ m_aAuth += nDelta;
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+namespace
+{
+ void lcl_Erase(rtl::OUStringBuffer &rBuf, sal_Int32 index, sal_Int32 count)
+ {
+ rtl::OUString sTemp(rBuf.makeStringAndClear());
+ rBuf.append(sTemp.replaceAt(index, count, rtl::OUString()));
+ }
+}
+
+//============================================================================
+bool INetURLObject::clearPassword()
+{
+ if (!getSchemeInfo().m_bPassword)
+ return false;
+ if (m_aAuth.isPresent())
+ {
+ lcl_Erase(m_aAbsURIRef, m_aAuth.getBegin() - 1,
+ m_aAuth.getLength() + 1);
+ sal_Int32 nDelta = m_aAuth.clear() - 1;
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setPassword(rtl::OUString const & rThePassword,
+ bool bOctets, EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bPassword)
+ return false;
+ rtl::OUString aNewAuth(encodeText(rThePassword, bOctets,
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM : PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism, eCharset,
+ false));
+ sal_Int32 nDelta;
+ if (m_aAuth.isPresent())
+ nDelta = m_aAuth.set(m_aAbsURIRef, aNewAuth);
+ else if (m_aUser.isPresent())
+ {
+ m_aAbsURIRef.insert(m_aUser.getEnd(), sal_Unicode(':'));
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aUser.getEnd() + 1) + 1;
+ }
+ else if (m_aHost.isPresent())
+ {
+ m_aAbsURIRef.insert(m_aHost.getBegin(),
+ rtl::OUString::createFromAscii(":@"));
+ m_aUser.set(m_aAbsURIRef, rtl::OUString(), m_aHost.getBegin());
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aHost.getBegin() + 1) + 2;
+ }
+ else if (getSchemeInfo().m_bHost)
+ return false;
+ else
+ {
+ m_aAbsURIRef.insert(m_aPath.getBegin(), sal_Unicode(':'));
+ m_aUser.set(m_aAbsURIRef, rtl::OUString(), m_aPath.getBegin());
+ nDelta
+ = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aPath.getBegin() + 1) + 1;
+ }
+ m_aHost += nDelta;
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+// static
+bool INetURLObject::parseHost(
+ sal_Unicode const *& rBegin, sal_Unicode const * pEnd,
+ rtl::OUString & rCanonic)
+{
+ // RFC 2373 is inconsistent about how to write an IPv6 address in which an
+ // IPv4 address directly follows the abbreviating "::". The ABNF in
+ // Appendix B suggests ":::13.1.68.3", while an example in 2.2/3 explicitly
+ // mentions "::13:1.68.3". This algorithm accepts both variants:
+ enum State { STATE_INITIAL, STATE_LABEL, STATE_LABEL_HYPHEN,
+ STATE_LABEL_DOT, STATE_TOPLABEL, STATE_TOPLABEL_HYPHEN,
+ STATE_TOPLABEL_DOT, STATE_IP4, STATE_IP4_DOT, STATE_IP6,
+ STATE_IP6_COLON, STATE_IP6_2COLON, STATE_IP6_3COLON,
+ STATE_IP6_HEXSEQ1, STATE_IP6_HEXSEQ1_COLON,
+ STATE_IP6_HEXSEQ1_MAYBE_IP4, STATE_IP6_HEXSEQ2,
+ STATE_IP6_HEXSEQ2_COLON, STATE_IP6_HEXSEQ2_MAYBE_IP4,
+ STATE_IP6_IP4, STATE_IP6_IP4_DOT, STATE_IP6_DONE };
+ rtl::OUStringBuffer aTheCanonic;
+ sal_uInt32 nNumber = 0;
+ int nDigits = 0;
+ int nOctets = 0;
+ State eState = STATE_INITIAL;
+ sal_Unicode const * p = rBegin;
+ for (; p != pEnd; ++p)
+ switch (eState)
+ {
+ case STATE_INITIAL:
+ if (*p == '[')
+ {
+ aTheCanonic.append(sal_Unicode('['));
+ eState = STATE_IP6;
+ }
+ else if (INetMIME::isAlpha(*p) || *p == '_')
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ nOctets = 1;
+ eState = STATE_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_LABEL:
+ if (*p == '.')
+ eState = STATE_LABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_LABEL_HYPHEN;
+ else if (!INetMIME::isAlphanumeric(*p) && *p != '_')
+ goto done;
+ break;
+
+ case STATE_LABEL_HYPHEN:
+ if (INetMIME::isAlphanumeric(*p) || *p == '_')
+ eState = STATE_LABEL;
+ else if (*p != '-')
+ goto done;
+ break;
+
+ case STATE_LABEL_DOT:
+ if (INetMIME::isAlpha(*p) || *p == '_')
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_TOPLABEL:
+ if (*p == '.')
+ eState = STATE_TOPLABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_TOPLABEL_HYPHEN;
+ else if (!INetMIME::isAlphanumeric(*p) && *p != '_')
+ goto done;
+ break;
+
+ case STATE_TOPLABEL_HYPHEN:
+ if (INetMIME::isAlphanumeric(*p) || *p == '_')
+ eState = STATE_TOPLABEL;
+ else if (*p != '-')
+ goto done;
+ break;
+
+ case STATE_TOPLABEL_DOT:
+ if (INetMIME::isAlpha(*p) || *p == '_')
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_IP4:
+ if (*p == '.')
+ if (nOctets < 4)
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ aTheCanonic.append(sal_Unicode('.'));
+ ++nOctets;
+ eState = STATE_IP4_DOT;
+ }
+ else
+ eState = STATE_LABEL_DOT;
+ else if (*p == '-')
+ eState = STATE_LABEL_HYPHEN;
+ else if (INetMIME::isAlpha(*p) || *p == '_')
+ eState = STATE_LABEL;
+ else if (INetMIME::isDigit(*p))
+ if (nDigits < 3)
+ {
+ nNumber = 10 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else
+ eState = STATE_LABEL;
+ else
+ goto done;
+ break;
+
+ case STATE_IP4_DOT:
+ if (INetMIME::isAlpha(*p) || *p == '_')
+ eState = STATE_TOPLABEL;
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6:
+ if (*p == ':')
+ eState = STATE_IP6_COLON;
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_COLON:
+ if (*p == ':')
+ {
+ aTheCanonic.appendAscii(RTL_CONSTASCII_STRINGPARAM("::"));
+ eState = STATE_IP6_2COLON;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_2COLON:
+ if (*p == ']')
+ eState = STATE_IP6_DONE;
+ else if (*p == ':')
+ {
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_3COLON;
+ }
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2_MAYBE_IP4;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_3COLON:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ nOctets = 1;
+ eState = STATE_IP6_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1:
+ if (*p == ']')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_HEXSEQ1_COLON;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1_COLON:
+ if (*p == ':')
+ {
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_2COLON;
+ }
+ else if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1_MAYBE_IP4;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ1_MAYBE_IP4:
+ if (*p == ']')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_HEXSEQ1_COLON;
+ }
+ else if (*p == '.')
+ {
+ nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15)
+ + (nNumber & 15);
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ aTheCanonic.append(sal_Unicode('.'));
+ nOctets = 2;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 16 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ eState = STATE_IP6_HEXSEQ1;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2:
+ if (*p == ']')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_HEXSEQ2_COLON;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2_COLON:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2_MAYBE_IP4;
+ }
+ else if (INetMIME::isHexDigit(*p))
+ {
+ nNumber = INetMIME::getHexWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_HEXSEQ2_MAYBE_IP4:
+ if (*p == ']')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ eState = STATE_IP6_DONE;
+ }
+ else if (*p == ':')
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber), 16));
+ aTheCanonic.append(sal_Unicode(':'));
+ eState = STATE_IP6_HEXSEQ2_COLON;
+ }
+ else if (*p == '.')
+ {
+ nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15)
+ + (nNumber & 15);
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ aTheCanonic.append(sal_Unicode('.'));
+ nOctets = 2;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 16 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else if (INetMIME::isHexDigit(*p) && nDigits < 4)
+ {
+ nNumber = 16 * nNumber + INetMIME::getHexWeight(*p);
+ ++nDigits;
+ eState = STATE_IP6_HEXSEQ2;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_IP4:
+ if (*p == ']')
+ if (nOctets == 4)
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ eState = STATE_IP6_DONE;
+ }
+ else
+ goto done;
+ else if (*p == '.')
+ if (nOctets < 4)
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ aTheCanonic.append(sal_Unicode('.'));
+ ++nOctets;
+ eState = STATE_IP6_IP4_DOT;
+ }
+ else
+ goto done;
+ else if (INetMIME::isDigit(*p) && nDigits < 3)
+ {
+ nNumber = 10 * nNumber + INetMIME::getWeight(*p);
+ ++nDigits;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_IP4_DOT:
+ if (INetMIME::isDigit(*p))
+ {
+ nNumber = INetMIME::getWeight(*p);
+ nDigits = 1;
+ eState = STATE_IP6_IP4;
+ }
+ else
+ goto done;
+ break;
+
+ case STATE_IP6_DONE:
+ goto done;
+ }
+ done:
+ switch (eState)
+ {
+ case STATE_LABEL:
+ case STATE_TOPLABEL:
+ case STATE_TOPLABEL_DOT:
+ aTheCanonic.setLength(0);
+ aTheCanonic.append(rBegin, p - rBegin);
+ rBegin = p;
+ rCanonic = aTheCanonic.makeStringAndClear();
+ return true;
+
+ case STATE_IP4:
+ if (nOctets == 4)
+ {
+ aTheCanonic.append(
+ rtl::OUString::valueOf(sal_Int32(nNumber)));
+ rBegin = p;
+ rCanonic = aTheCanonic.makeStringAndClear();
+ return true;
+ }
+ return false;
+
+ case STATE_IP6_DONE:
+ aTheCanonic.append(sal_Unicode(']'));
+ rBegin = p;
+ rCanonic = aTheCanonic.makeStringAndClear();
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+//============================================================================
+// static
+bool INetURLObject::parseHostOrNetBiosName(
+ sal_Unicode const * pBegin, sal_Unicode const * pEnd, bool bOctets,
+ EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bNetBiosName,
+ rtl::OUStringBuffer* pCanonic)
+{
+ rtl::OUString aTheCanonic;
+ if (pBegin < pEnd)
+ {
+ sal_Unicode const * p = pBegin;
+ if (!parseHost(p, pEnd, aTheCanonic) || p != pEnd)
+ {
+ if (bNetBiosName)
+ {
+ rtl::OUStringBuffer buf;
+ while (pBegin < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, bOctets, '%',
+ eMechanism, eCharset,
+ eEscapeType);
+ if (!INetMIME::isVisible(nUTF32))
+ return false;
+ if (!INetMIME::isAlphanumeric(nUTF32))
+ switch (nUTF32)
+ {
+ case '"':
+ case '*':
+ case '+':
+ case ',':
+ case '/':
+ case ':':
+ case ';':
+ case '<':
+ case '=':
+ case '>':
+ case '?':
+ case '[':
+ case '\\':
+ case ']':
+ case '`':
+ case '|':
+ return false;;
+ }
+ if (pCanonic != NULL) {
+ appendUCS4(
+ buf, nUTF32, eEscapeType, bOctets, PART_URIC, '%',
+ eCharset, true);
+ }
+ }
+ aTheCanonic = buf.makeStringAndClear();
+ }
+ else
+ return false;
+ }
+ }
+ if (pCanonic != NULL) {
+ *pCanonic = aTheCanonic;
+ }
+ return true;
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::encodeHostPort(rtl::OUString const & rTheHostPort,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ sal_Int32 nPort = rTheHostPort.getLength();
+ if (nPort != 0)
+ {
+ sal_Int32 i = nPort - 1;
+ while (i != 0 && INetMIME::isDigit(rTheHostPort.getStr()[i]))
+ --i;
+ if (rTheHostPort.getStr()[i] == ':')
+ nPort = i;
+ }
+ rtl::OUString aResult(encodeText(rTheHostPort.copy(0, nPort), bOctets,
+ PART_HOST_EXTRA, '%', eMechanism, eCharset,
+ true));
+ aResult += rTheHostPort.copy(nPort);
+ return aResult;
+}
+
+//============================================================================
+bool INetURLObject::setHost(rtl::OUString const & rTheHost, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bHost)
+ return false;
+ rtl::OUStringBuffer aSynHost(rTheHost);
+ bool bNetBiosName = false;
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ {
+ rtl::OUString sTemp(aSynHost);
+ if (sTemp.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("localhost")))
+ {
+ aSynHost.setLength(0);
+ }
+ bNetBiosName = true;
+ }
+ break;
+ case INET_PROT_LDAP:
+ if (aSynHost.getLength() == 0 && m_aPort.isPresent())
+ return false;
+ break;
+
+ default:
+ if (aSynHost.getLength() == 0)
+ return false;
+ break;
+ }
+ if (!parseHostOrNetBiosName(
+ aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(),
+ bOctets, eMechanism, eCharset, bNetBiosName, &aSynHost))
+ return false;
+ sal_Int32 nDelta = m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear());
+ m_aPort += nDelta;
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+// static
+bool INetURLObject::parsePath(INetProtocol eScheme,
+ sal_Unicode const ** pBegin,
+ sal_Unicode const * pEnd,
+ bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bSkippedInitialSlash,
+ sal_uInt32 nSegmentDelimiter,
+ sal_uInt32 nAltSegmentDelimiter,
+ sal_uInt32 nQueryDelimiter,
+ sal_uInt32 nFragmentDelimiter,
+ rtl::OUStringBuffer &rSynPath)
+{
+ DBG_ASSERT(pBegin, "INetURLObject::parsePath(): Null output param");
+
+ sal_Unicode const * pPos = *pBegin;
+ rtl::OUStringBuffer aTheSynPath;
+
+ switch (eScheme)
+ {
+ case INET_PROT_NOT_VALID:
+ return false;
+
+ case INET_PROT_FTP:
+ case INET_PROT_IMAP:
+ if (pPos < pEnd && *pPos != '/')
+ return false;
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_HTTP_PATH, '%', eCharset, true);
+ }
+ if (aTheSynPath.getLength() == 0)
+ aTheSynPath.append(sal_Unicode('/'));
+ break;
+
+ case INET_PROT_HTTP:
+ case INET_PROT_VND_SUN_STAR_WEBDAV:
+ case INET_PROT_HTTPS:
+ case INET_PROT_SMB:
+ if (pPos < pEnd && *pPos != '/')
+ return false;
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_HTTP_PATH, '%', eCharset, true);
+ }
+ if (aTheSynPath.getLength() == 0)
+ aTheSynPath.append(sal_Unicode('/'));
+ break;
+
+ case INET_PROT_FILE:
+ {
+ if (bSkippedInitialSlash)
+ aTheSynPath.append(sal_Unicode('/'));
+ else if (pPos < pEnd
+ && *pPos != nSegmentDelimiter
+ && *pPos != nAltSegmentDelimiter)
+ return false;
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO)
+ {
+ if (nUTF32 == nSegmentDelimiter
+ || nUTF32 == nAltSegmentDelimiter)
+ {
+ aTheSynPath.append(sal_Unicode('/'));
+ continue;
+ }
+ else if (nUTF32 == '|'
+ && (pPos == pEnd
+ || *pPos == nFragmentDelimiter
+ || *pPos == nSegmentDelimiter
+ || *pPos == nAltSegmentDelimiter)
+ && aTheSynPath.getLength() == 2
+ && INetMIME::isAlpha(aTheSynPath.charAt(1)))
+ {
+ // A first segment of <ALPHA "|"> is translated to
+ // <ALPHA ":">:
+ aTheSynPath.append(sal_Unicode(':'));
+ continue;
+ }
+ }
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PCHAR, '%', eCharset, true);
+ }
+ if (aTheSynPath.getLength() == 0)
+ aTheSynPath.append(sal_Unicode('/'));
+ break;
+ }
+
+ case INET_PROT_MAILTO:
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_MAILTO, '%', eCharset, true);
+ }
+ break;
+
+ case INET_PROT_NEWS:
+ if (pPos == pEnd || *pPos == nQueryDelimiter
+ || *pPos == nFragmentDelimiter)
+ return false;
+
+ // Match <"*">:
+ if (*pPos == '*'
+ && (pEnd - pPos == 1 || pPos[1] == nQueryDelimiter
+ || pPos[1] == nFragmentDelimiter))
+ {
+ ++pPos;
+ aTheSynPath.append(sal_Unicode('*'));
+ break;
+ }
+
+ // Match <group>:
+ if (INetMIME::isAlpha(*pPos))
+ for (sal_Unicode const * p = pPos + 1;; ++p)
+ if (p == pEnd || *p == nQueryDelimiter
+ || *p == nFragmentDelimiter)
+ {
+ aTheSynPath.setLength(0);
+ aTheSynPath.append(pPos, p - pPos);
+ pPos = p;
+ goto done;
+ }
+ else if (!INetMIME::isAlphanumeric(*p) && *p != '+'
+ && *p != '-' && *p != '.' && *p != '_')
+ break;
+
+ // Match <article>:
+ for (;;)
+ {
+ if (pPos == pEnd || *pPos == nQueryDelimiter
+ || *pPos == nFragmentDelimiter)
+ return false;
+ if (*pPos == '@')
+ break;
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets, '%',
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_NEWS_ARTICLE_LOCALPART, '%', eCharset, true);
+ }
+ if (aTheSynPath.getLength() == 0)
+ return false;
+ ++pPos;
+ aTheSynPath.append(sal_Unicode('@'));
+ {
+ sal_Unicode const * p = pPos;
+ while (p < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ ++p;
+ rtl::OUString aCanonic;
+ if (!parseHost(pPos, p, aCanonic))
+ return false;
+ aTheSynPath.append(aCanonic);
+ }
+
+ done:
+ break;
+
+ case INET_PROT_POP3:
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_MESSAGE_ID_PATH, '%', eCharset,
+ true);
+ }
+ break;
+
+ case INET_PROT_PRIV_SOFFICE:
+ case INET_PROT_SLOT:
+ case INET_PROT_MACRO:
+ case INET_PROT_UNO:
+ case INET_PROT_COMPONENT:
+ case INET_PROT_LDAP:
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PATH_BEFORE_QUERY, '%', eCharset,
+ true);
+ }
+ break;
+
+ case INET_PROT_VND_SUN_STAR_HELP:
+ if (pPos == pEnd
+ || *pPos == nQueryDelimiter
+ || *pPos == nFragmentDelimiter)
+ aTheSynPath.append(sal_Unicode('/'));
+ else
+ {
+ if (*pPos != '/')
+ return false;
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_HTTP_PATH, '%', eCharset, true);
+ }
+ }
+ break;
+
+ case INET_PROT_JAVASCRIPT:
+ case INET_PROT_DATA:
+ case INET_PROT_CID:
+ case INET_PROT_DB:
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC, '%', eCharset, true);
+ }
+ break;
+
+ case INET_PROT_OUT:
+ if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '~')
+ return false;
+ aTheSynPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("/~"));
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC, '%', eCharset, true);
+ }
+ break;
+
+ case INET_PROT_VND_SUN_STAR_HIER:
+ case INET_PROT_VND_SUN_STAR_PKG:
+ if (pPos < pEnd && *pPos != '/'
+ && *pPos != nQueryDelimiter && *pPos != nFragmentDelimiter)
+ return false;
+ while (pPos < pEnd && *pPos != nQueryDelimiter
+ && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aTheSynPath.append(sal_Unicode('/'));
+ else
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PCHAR, '%', eCharset, false);
+ }
+ if (aTheSynPath.getLength() == 0)
+ aTheSynPath.append(sal_Unicode('/'));
+ break;
+
+ case INET_PROT_VIM:
+ {
+/* test had to be taken out to make parsePath static; ok since INET_PROT_VIM is
+ obsolete, anyway
+ if (m_aUser.isEmpty())
+ return false;
+*/
+ sal_Unicode const * pPathEnd = pPos;
+ while (pPathEnd < pEnd && *pPathEnd != nFragmentDelimiter)
+ ++pPathEnd;
+ aTheSynPath.append(sal_Unicode('/'));
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ return false;
+ if (pPos == pPathEnd)
+ break;
+ while (pPos < pPathEnd && *pPos != '/')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ '=', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath,
+ eEscapeType == ESCAPE_NO ?
+ INetMIME::toLowerCase(nUTF32) : nUTF32,
+ eEscapeType, bOctets, PART_VIM, '=',
+ eCharset, false);
+ }
+ bool bInbox;
+ rtl::OUString sCompare(aTheSynPath);
+ if (sCompare.equalsAscii("/inbox"))
+ bInbox = true;
+ else if (sCompare.equalsAscii("/newsgroups"))
+ bInbox = false;
+ else
+ return false;
+ aTheSynPath.append(sal_Unicode('/'));
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ return false;
+ if (!bInbox)
+ {
+ bool bEmpty = true;
+ while (pPos < pPathEnd && *pPos != '/')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ '=', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_VIM, '=', eCharset, false);
+ bEmpty = false;
+ }
+ if (bEmpty)
+ return false;
+ aTheSynPath.append(sal_Unicode('/'));
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != '/')
+ return false;
+ }
+ bool bEmpty = true;
+ while (pPos < pPathEnd && *pPos != ':')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ '=', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_VIM, '=', eCharset, false);
+ bEmpty = false;
+ }
+ if (bEmpty)
+ return false;
+ if (pPos == pPathEnd)
+ break;
+ else if (*pPos++ != ':')
+ return false;
+ aTheSynPath.append(sal_Unicode(':'));
+ for (int i = 0; i < 3; ++i)
+ {
+ if (i != 0)
+ {
+ if (pPos == pPathEnd || *pPos++ != '.')
+ return false;
+ aTheSynPath.append(sal_Unicode('.'));
+ }
+ bEmpty = true;
+ while (pPos < pPathEnd && *pPos != '.')
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pPathEnd, bOctets,
+ '=', eMechanism,
+ eCharset, eEscapeType);
+ if (!INetMIME::isDigit(nUTF32))
+ return false;
+ aTheSynPath.append(sal_Unicode(nUTF32));
+ bEmpty = false;
+ }
+ if (bEmpty)
+ return false;
+ }
+ if (pPos != pPathEnd)
+ return false;
+ break;
+ }
+
+ case INET_PROT_VND_SUN_STAR_CMD:
+ case INET_PROT_VND_SUN_STAR_EXPAND:
+ {
+ if (pPos == pEnd || *pPos == nFragmentDelimiter)
+ return false;
+ Part ePart = PART_URIC_NO_SLASH;
+ while (pPos != pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets, ePart,
+ '%', eCharset, true);
+ ePart = PART_URIC;
+ }
+ break;
+ }
+
+ case INET_PROT_VND_SUN_STAR_ODMA:
+ if (pPos < pEnd)
+ {
+ if (*pPos == '/')
+ ++pPos;
+ else
+ return false;
+ }
+ aTheSynPath.append(sal_Unicode('/'));
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC_NO_SLASH, '%', eCharset, true);
+ }
+ break;
+
+ case INET_PROT_TELNET:
+ if (pPos < pEnd)
+ {
+ if (*pPos != '/' || pEnd - pPos > 1)
+ return false;
+ ++pPos;
+ }
+ aTheSynPath.append(sal_Unicode('/'));
+ break;
+
+ case INET_PROT_VND_SUN_STAR_TDOC:
+ if (pPos == pEnd || *pPos != '/')
+ return false;
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aTheSynPath.append(sal_Unicode('/'));
+ else
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_PCHAR, '%', eCharset, false);
+ }
+ break;
+
+ case INET_PROT_GENERIC:
+ while (pPos < pEnd && *pPos != nFragmentDelimiter)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, bOctets,
+ '%', eMechanism,
+ eCharset, eEscapeType);
+ appendUCS4(aTheSynPath, nUTF32, eEscapeType, bOctets,
+ PART_URIC, '%', eCharset, true);
+ }
+ if (aTheSynPath.getLength() == 0)
+ return false;
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+
+ *pBegin = pPos;
+ rSynPath = aTheSynPath;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setPath(rtl::OUString const & rThePath, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ rtl::OUStringBuffer aSynPath;
+ sal_Unicode const * p = rThePath.getStr();
+ sal_Unicode const * pEnd = p + rThePath.getLength();
+ if (!parsePath(m_eScheme, &p, pEnd, bOctets, eMechanism, eCharset, false,
+ '/', 0x80000000, 0x80000000, 0x80000000, aSynPath)
+ || p != pEnd)
+ return false;
+ sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear());
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::checkHierarchical() const {
+ if (m_eScheme == INET_PROT_VND_SUN_STAR_EXPAND) {
+ OSL_ENSURE(
+ false, "INetURLObject::checkHierarchical vnd.sun.star.expand");
+ return true;
+ } else {
+ return getSchemeInfo().m_bHierarchical;
+ }
+}
+
+//============================================================================
+bool INetURLObject::appendSegment(rtl::OUString const & rTheSegment,
+ bool bOctets, EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ return insertName(rTheSegment, bOctets, false, LAST_SEGMENT, true,
+ eMechanism, eCharset);
+}
+
+//============================================================================
+INetURLObject::SubString INetURLObject::getSegment(sal_Int32 nIndex,
+ bool bIgnoreFinalSlash)
+ const
+{
+ DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT,
+ "INetURLObject::getSegment(): Bad index");
+
+ if (!checkHierarchical())
+ return SubString();
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin;
+ sal_Unicode const * pSegEnd;
+ if (nIndex == LAST_SEGMENT)
+ {
+ pSegEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pSegEnd > pPathBegin && pSegEnd[-1] == '/')
+ --pSegEnd;
+ if (pSegEnd <= pPathBegin)
+ return SubString();
+ pSegBegin = pSegEnd - 1;
+ while (pSegBegin > pPathBegin && *pSegBegin != '/')
+ --pSegBegin;
+ }
+ else
+ {
+ pSegBegin = pPathBegin;
+ while (nIndex-- > 0)
+ do
+ {
+ ++pSegBegin;
+ if (pSegBegin >= pPathEnd)
+ return SubString();
+ }
+ while (*pSegBegin != '/');
+ pSegEnd = pSegBegin + 1;
+ while (pSegEnd < pPathEnd && *pSegEnd != '/')
+ ++pSegEnd;
+ }
+
+ return SubString(pSegBegin - m_aAbsURIRef.getStr(),
+ pSegEnd - pSegBegin);
+}
+
+//============================================================================
+bool INetURLObject::insertName(rtl::OUString const & rTheName, bool bOctets,
+ bool bAppendFinalSlash, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT,
+ "INetURLObject::insertName(): Bad index");
+
+ if (!checkHierarchical())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pPrefixEnd;
+ bool bInsertSlash;
+ sal_Unicode const * pSuffixBegin;
+ if (nIndex == LAST_SEGMENT)
+ {
+ pPrefixEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pPrefixEnd > pPathBegin &&
+ pPrefixEnd[-1] == '/')
+ {
+ --pPrefixEnd;
+ }
+ bInsertSlash = bAppendFinalSlash;
+ pSuffixBegin = pPathEnd;
+ }
+ else if (nIndex == 0)
+ {
+ pPrefixEnd = pPathBegin;
+ bInsertSlash =
+ (pPathBegin < pPathEnd && *pPathBegin != '/') ||
+ (pPathBegin == pPathEnd && bAppendFinalSlash);
+ pSuffixBegin =
+ (pPathEnd - pPathBegin == 1 && *pPathBegin == '/' &&
+ !bAppendFinalSlash && bIgnoreFinalSlash)
+ ? pPathEnd : pPathBegin;
+ }
+ else
+ {
+ pPrefixEnd = pPathBegin;
+ sal_Unicode const * pEnd = pPathEnd;
+ if (bIgnoreFinalSlash && pEnd > pPathBegin && pEnd[-1] == '/')
+ --pEnd;
+ bool bSkip = pPrefixEnd < pEnd && *pPrefixEnd == '/';
+ bInsertSlash = false;
+ pSuffixBegin = pPathEnd;
+ while (nIndex-- > 0)
+ for (;;)
+ {
+ if (bSkip)
+ ++pPrefixEnd;
+ bSkip = true;
+ if (pPrefixEnd >= pEnd)
+ {
+ if (nIndex == 0)
+ {
+ bInsertSlash = bAppendFinalSlash;
+ break;
+ }
+ else
+ return false;
+ }
+ if (*pPrefixEnd == '/')
+ {
+ pSuffixBegin = pPrefixEnd;
+ break;
+ }
+ }
+ }
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pPrefixEnd - pPathBegin);
+ aNewPath.append(sal_Unicode('/'));
+ aNewPath.append(encodeText(rTheName, bOctets, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true));
+ if (bInsertSlash) {
+ aNewPath.append(sal_Unicode('/'));
+ }
+ aNewPath.append(pSuffixBegin, pPathEnd - pSuffixBegin);
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::clearQuery()
+{
+ if (HasError())
+ return false;
+ if (m_aQuery.isPresent())
+ {
+ lcl_Erase(m_aAbsURIRef, m_aQuery.getBegin() - 1,
+ m_aQuery.getLength() + 1);
+ m_aFragment += m_aQuery.clear() - 1;
+ }
+ return false;
+}
+
+//============================================================================
+bool INetURLObject::setQuery(rtl::OUString const & rTheQuery, bool bOctets,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (!getSchemeInfo().m_bQuery)
+ return false;
+ rtl::OUString aNewQuery(encodeText(rTheQuery, bOctets, PART_URIC,
+ getEscapePrefix(), eMechanism, eCharset,
+ true));
+ sal_Int32 nDelta;
+ if (m_aQuery.isPresent())
+ nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery);
+ else
+ {
+ m_aAbsURIRef.insert(m_aPath.getEnd(), sal_Unicode('?'));
+ nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery, m_aPath.getEnd() + 1)
+ + 1;
+ }
+ m_aFragment += nDelta;
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::clearFragment()
+{
+ if (HasError())
+ return false;
+ if (m_aFragment.isPresent())
+ {
+ m_aAbsURIRef.setLength(m_aFragment.getBegin() - 1);
+ m_aFragment.clear();
+ }
+ return true;
+}
+
+//============================================================================
+bool INetURLObject::setFragment(rtl::OUString const & rTheFragment,
+ bool bOctets, EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ if (HasError())
+ return false;
+ rtl::OUString aNewFragment(encodeText(rTheFragment, bOctets, PART_URIC,
+ getEscapePrefix(), eMechanism,
+ eCharset, true));
+ if (m_aFragment.isPresent())
+ m_aFragment.set(m_aAbsURIRef, aNewFragment);
+ else
+ {
+ m_aAbsURIRef.append(sal_Unicode('#'));
+ m_aFragment.set(m_aAbsURIRef, aNewFragment, m_aAbsURIRef.getLength());
+ }
+ return true;
+}
+
+//============================================================================
+INetURLObject::FTPType INetURLObject::getFTPType() const
+{
+ if (m_eScheme == INET_PROT_FTP
+ && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH(";type=") + 1
+ && rtl::OUString(m_aAbsURIRef).copy(
+ m_aPath.getEnd() - (RTL_CONSTASCII_LENGTH(";type=") + 1),
+ RTL_CONSTASCII_LENGTH(";type=")).equalsIgnoreAsciiCaseAscii(";type="))
+ switch (m_aAbsURIRef.charAt(m_aPath.getEnd()))
+ {
+ case 'A':
+ case 'a':
+ return FTP_TYPE_A;
+
+ case 'D':
+ case 'd':
+ return FTP_TYPE_D;
+
+ case 'I':
+ case 'i':
+ return FTP_TYPE_I;
+ }
+ return FTP_TYPE_NONE;
+}
+
+//============================================================================
+bool INetURLObject::hasDosVolume(FSysStyle eStyle) const
+{
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ return (eStyle & FSYS_DOS) != 0
+ && m_aPath.getLength() >= 3
+ && p[0] == '/'
+ && INetMIME::isAlpha(p[1])
+ && p[2] == ':'
+ && (m_aPath.getLength() == 3 || p[3] == '/');
+}
+
+//============================================================================
+sal_uInt32 INetURLObject::getIMAPUID() const
+{
+ if (m_eScheme == INET_PROT_IMAP
+ && m_aPath.getLength() >= RTL_CONSTASCII_LENGTH("/;uid=") + 1)
+ {
+ sal_Unicode const * pBegin = m_aAbsURIRef.getStr()
+ + m_aPath.getBegin()
+ + RTL_CONSTASCII_LENGTH("/;uid=");
+ sal_Unicode const * pEnd = pBegin + m_aPath.getLength();
+ sal_Unicode const * p = pEnd;
+ while (p > pBegin && INetMIME::isDigit(p[-1]))
+ --p;
+ if (p < pEnd && *--p != '0'
+ && rtl::OUString(m_aAbsURIRef).copy(
+ p - RTL_CONSTASCII_LENGTH("/;uid=") - m_aAbsURIRef.getStr(),
+ RTL_CONSTASCII_LENGTH("/;uid=")).equalsIgnoreAsciiCaseAscii("/;uid=")
+ )
+ {
+ sal_uInt32 nUID;
+ if (INetMIME::scanUnsigned(p, pEnd, false, nUID))
+ return nUID;
+ }
+ }
+ return 0;
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::encodeText(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd, bool bOctets,
+ Part ePart, sal_Char cEscapePrefix,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ bool bKeepVisibleEscapes)
+{
+ rtl::OUStringBuffer aResult;
+ while (pBegin < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, bOctets, cEscapePrefix,
+ eMechanism, eCharset, eEscapeType);
+ appendUCS4(aResult, nUTF32, eEscapeType, bOctets, ePart,
+ cEscapePrefix, eCharset, bKeepVisibleEscapes);
+ }
+ return aResult.makeStringAndClear();
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::decode(sal_Unicode const * pBegin,
+ sal_Unicode const * pEnd,
+ sal_Char cEscapePrefix,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ switch (eMechanism)
+ {
+ case NO_DECODE:
+ return rtl::OUString(pBegin, pEnd - pBegin);
+
+ case DECODE_TO_IURI:
+ eCharset = RTL_TEXTENCODING_UTF8;
+ break;
+
+ default:
+ break;
+ }
+ rtl::OUStringBuffer aResult;
+ while (pBegin < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, false, cEscapePrefix,
+ WAS_ENCODED, eCharset, eEscapeType);
+ switch (eEscapeType)
+ {
+ case ESCAPE_NO:
+ aResult.append(sal_Unicode(nUTF32));
+ break;
+
+ case ESCAPE_OCTET:
+ appendEscape(aResult, cEscapePrefix, nUTF32);
+ break;
+
+ case ESCAPE_UTF32:
+ if (
+ INetMIME::isUSASCII(nUTF32) &&
+ (
+ eMechanism == DECODE_TO_IURI ||
+ (
+ eMechanism == DECODE_UNAMBIGUOUS &&
+ mustEncode(nUTF32, PART_UNAMBIGUOUS)
+ )
+ )
+ )
+ {
+ appendEscape(aResult, cEscapePrefix, nUTF32);
+ }
+ else
+ aResult.append(sal_Unicode(nUTF32));
+ break;
+ }
+ }
+ return aResult.makeStringAndClear();
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetURLNoPass(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearPassword();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetURLNoMark(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+rtl::OUString
+INetURLObject::getAbbreviated(
+ star::uno::Reference< star::util::XStringWidth > const & rStringWidth,
+ sal_Int32 nWidth,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+ const
+{
+ OSL_ENSURE(rStringWidth.is(), "specification violation");
+ sal_Char cEscapePrefix = getEscapePrefix();
+ rtl::OUStringBuffer aBuffer;
+ // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme
+ // is empty ("") in that case, so take the scheme from m_aAbsURIRef
+ if (m_eScheme != INET_PROT_GENERIC)
+ {
+ aBuffer.appendAscii(getSchemeInfo().m_pScheme);
+ }
+ else
+ {
+ if (m_aAbsURIRef)
+ {
+ sal_Unicode const * pSchemeBegin
+ = m_aAbsURIRef.getStr();
+ sal_Unicode const * pSchemeEnd = pSchemeBegin;
+
+ while (pSchemeEnd[0] != ':')
+ {
+ ++pSchemeEnd;
+ }
+ aBuffer.append(pSchemeBegin, pSchemeEnd - pSchemeBegin);
+ }
+ }
+ aBuffer.append(static_cast< sal_Unicode >(':'));
+ bool bAuthority = getSchemeInfo().m_bAuthority;
+ sal_Unicode const * pCoreBegin
+ = m_aAbsURIRef.getStr() + (bAuthority ? getAuthorityBegin() :
+ m_aPath.getBegin());
+ sal_Unicode const * pCoreEnd
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin() + m_aPath.getLength();
+ bool bSegment = false;
+ if (getSchemeInfo().m_bHierarchical)
+ {
+ rtl::OUString aRest;
+ if (m_aQuery.isPresent())
+ aRest = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("?..."));
+ else if (m_aFragment.isPresent())
+ aRest = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("#..."));
+ rtl::OUStringBuffer aTrailer;
+ sal_Unicode const * pBegin = pCoreBegin;
+ sal_Unicode const * pEnd = pCoreEnd;
+ sal_Unicode const * pPrefixBegin = pBegin;
+ sal_Unicode const * pSuffixEnd = pEnd;
+ bool bPrefix = true;
+ bool bSuffix = true;
+ do
+ {
+ if (bSuffix)
+ {
+ sal_Unicode const * p = pSuffixEnd - 1;
+ if (pSuffixEnd == pCoreEnd && *p == '/')
+ --p;
+ while (*p != '/')
+ --p;
+ if (bAuthority && p == pCoreBegin + 1)
+ --p;
+ rtl::OUString
+ aSegment(decode(p + (p == pBegin && pBegin != pCoreBegin ?
+ 1 : 0),
+ pSuffixEnd,
+ cEscapePrefix,
+ eMechanism,
+ eCharset));
+ pSuffixEnd = p;
+ rtl::OUStringBuffer aResult(aBuffer);
+ if (pSuffixEnd != pBegin)
+ aResult.appendAscii(RTL_CONSTASCII_STRINGPARAM("..."));
+ aResult.append(aSegment);
+ aResult.append(aTrailer);
+ aResult.append(aRest);
+ if (rStringWidth->
+ queryStringWidth(aResult.makeStringAndClear())
+ <= nWidth)
+ {
+ aTrailer.insert(0, aSegment);
+ bSegment = true;
+ pEnd = pSuffixEnd;
+ }
+ else
+ bSuffix = false;
+ if (pPrefixBegin > pSuffixEnd)
+ pPrefixBegin = pSuffixEnd;
+ if (pBegin == pEnd)
+ break;
+ }
+ if (bPrefix)
+ {
+ sal_Unicode const * p
+ = pPrefixBegin
+ + (bAuthority && pPrefixBegin == pCoreBegin ? 2 :
+ 1);
+ OSL_ASSERT(p <= pEnd);
+ while (p < pEnd && *p != '/')
+ ++p;
+ if (p == pCoreEnd - 1 && *p == '/')
+ ++p;
+ rtl::OUString
+ aSegment(decode(pPrefixBegin
+ + (pPrefixBegin == pCoreBegin ? 0 :
+ 1),
+ p == pEnd ? p : p + 1,
+ cEscapePrefix,
+ eMechanism,
+ eCharset));
+ pPrefixBegin = p;
+ rtl::OUStringBuffer aResult(aBuffer);
+ aResult.append(aSegment);
+ if (pPrefixBegin != pEnd)
+ aResult.appendAscii(RTL_CONSTASCII_STRINGPARAM("..."));
+ aResult.append(aTrailer);
+ aResult.append(aRest);
+ if (rStringWidth->
+ queryStringWidth(aResult.makeStringAndClear())
+ <= nWidth)
+ {
+ aBuffer.append(aSegment);
+ bSegment = true;
+ pBegin = pPrefixBegin;
+ }
+ else
+ bPrefix = false;
+ if (pPrefixBegin > pSuffixEnd)
+ pSuffixEnd = pPrefixBegin;
+ if (pBegin == pEnd)
+ break;
+ }
+ }
+ while (bPrefix || bSuffix);
+ if (bSegment)
+ {
+ if (pPrefixBegin != pBegin || pSuffixEnd != pEnd)
+ aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("..."));
+ aBuffer.append(aTrailer);
+ }
+ }
+ if (!bSegment)
+ aBuffer.append(decode(pCoreBegin,
+ pCoreEnd,
+ cEscapePrefix,
+ eMechanism,
+ eCharset));
+ if (m_aQuery.isPresent())
+ {
+ aBuffer.append(static_cast< sal_Unicode >('?'));
+ aBuffer.append(decode(m_aQuery, cEscapePrefix, eMechanism, eCharset));
+ }
+ if (m_aFragment.isPresent())
+ {
+ aBuffer.append(static_cast< sal_Unicode >('#'));
+ aBuffer.
+ append(decode(m_aFragment, cEscapePrefix, eMechanism, eCharset));
+ }
+ if (aBuffer.getLength() != 0)
+ {
+ rtl::OUStringBuffer aResult(aBuffer);
+ if (rStringWidth->queryStringWidth(aResult.makeStringAndClear())
+ > nWidth)
+ for (sal_Int32 i = aBuffer.getLength();;)
+ {
+ if (i == 0)
+ {
+ aBuffer.setLength(aBuffer.getLength() - 1);
+ if (aBuffer.getLength() == 0)
+ break;
+ }
+ else
+ {
+ aBuffer.setLength(--i);
+ aBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("..."));
+ }
+ aResult = aBuffer;
+ if (rStringWidth->
+ queryStringWidth(aResult.makeStringAndClear())
+ <= nWidth)
+ break;
+ }
+ }
+ return aBuffer.makeStringAndClear();
+}
+
+//============================================================================
+bool INetURLObject::operator ==(INetURLObject const & rObject) const
+{
+ if (m_eScheme != rObject.m_eScheme)
+ return false;
+ if (m_eScheme == INET_PROT_NOT_VALID)
+ return (m_aAbsURIRef == rObject.m_aAbsURIRef) != false;
+ if ((m_aScheme.compare(
+ rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef)
+ != 0)
+ || GetUser(NO_DECODE) != rObject.GetUser(NO_DECODE)
+ || GetPass(NO_DECODE) != rObject.GetPass(NO_DECODE)
+ || !GetHost(NO_DECODE).equalsIgnoreAsciiCase(
+ rObject.GetHost(NO_DECODE))
+ || GetPort() != rObject.GetPort()
+ || HasParam() != rObject.HasParam()
+ || GetParam(NO_DECODE) != rObject.GetParam(NO_DECODE)
+ || GetMsgId(NO_DECODE) != rObject.GetMsgId(NO_DECODE))
+ return false;
+ rtl::OUString aPath1(GetURLPath(NO_DECODE));
+ rtl::OUString aPath2(rObject.GetURLPath(NO_DECODE));
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ {
+ // If the URL paths of two file URLs only differ in that one has a
+ // final '/' and the other has not, take the two paths as
+ // equivalent (this could be usefull for other schemes, too):
+ sal_Int32 nLength = aPath1.getLength();
+ switch (nLength - aPath2.getLength())
+ {
+ case -1:
+ if (aPath2.getStr()[nLength] != '/')
+ return false;
+ break;
+
+ case 0:
+ break;
+
+ case 1:
+ if (aPath1.getStr()[--nLength] != '/')
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+ return aPath1.compareTo(aPath2, nLength) == 0;
+ }
+
+ default:
+ return (aPath1 == aPath2) != false;
+ }
+}
+
+//============================================================================
+bool INetURLObject::operator <(INetURLObject const & rObject) const
+{
+ sal_Int32 nCompare = m_aScheme.compare(
+ rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef);
+ if (nCompare < 0) {
+ return true;
+ } else if (nCompare > 0) {
+ return false;
+ }
+ sal_uInt32 nPort1 = GetPort();
+ sal_uInt32 nPort2 = rObject.GetPort();
+ if (nPort1 < nPort2)
+ return true;
+ else if (nPort1 > nPort2)
+ return false;
+ nCompare = GetUser(NO_DECODE).compareTo(rObject.GetUser(NO_DECODE));
+ if (nCompare < 0)
+ return true;
+ else if (nCompare > 0)
+ return false;
+ nCompare = GetPass(NO_DECODE).compareTo(rObject.GetPass(NO_DECODE));
+ if (nCompare < 0)
+ return true;
+ else if (nCompare > 0)
+ return false;
+ nCompare = GetHost(NO_DECODE).compareTo(rObject.GetHost(NO_DECODE));
+ if (nCompare < 0)
+ return true;
+ else if (nCompare > 0)
+ return false;
+ const rtl::OUString &rPath1(GetURLPath(NO_DECODE));
+ const rtl::OUString &rPath2(rObject.GetURLPath(NO_DECODE));
+ nCompare = rPath1.compareTo(rPath2);
+ if (nCompare < 0)
+ return true;
+ else if (nCompare > 0)
+ return false;
+ nCompare = GetParam(NO_DECODE).compareTo(rObject.GetParam(NO_DECODE));
+ if (nCompare < 0)
+ return true;
+ else if (nCompare > 0)
+ return false;
+ return GetMsgId(NO_DECODE).compareTo(rObject.GetMsgId(NO_DECODE)) < 0;
+}
+
+//============================================================================
+bool INetURLObject::ConcatData(INetProtocol eTheScheme,
+ rtl::OUString const & rTheUser,
+ rtl::OUString const & rThePassword,
+ rtl::OUString const & rTheHost,
+ sal_uInt32 nThePort,
+ rtl::OUString const & rThePath,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ setInvalid();
+ m_eScheme = eTheScheme;
+ if (HasError() || m_eScheme == INET_PROT_GENERIC)
+ return false;
+ m_aAbsURIRef.setLength(0);
+ m_aAbsURIRef.appendAscii(getSchemeInfo().m_pScheme);
+ m_aAbsURIRef.append(sal_Unicode(':'));
+ if (getSchemeInfo().m_bAuthority)
+ {
+ m_aAbsURIRef.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ bool bUserInfo = false;
+ if (getSchemeInfo().m_bUser)
+ {
+ if (m_eScheme == INET_PROT_IMAP && rTheUser.getLength() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ if (rTheUser.getLength() != 0)
+ {
+ m_aUser.set(m_aAbsURIRef,
+ encodeText(rTheUser, false,
+ m_eScheme == INET_PROT_IMAP ?
+ PART_IMAP_ACHAR :
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM :
+ PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism,
+ eCharset, false),
+ m_aAbsURIRef.getLength());
+ bUserInfo = true;
+ }
+ }
+ else if (rTheUser.getLength() != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ if (rThePassword.getLength() != 0)
+ {
+ if (getSchemeInfo().m_bPassword)
+ {
+ m_aAbsURIRef.append(sal_Unicode(':'));
+ m_aAuth.set(m_aAbsURIRef,
+ encodeText(rThePassword, false,
+ m_eScheme == INET_PROT_VIM ?
+ PART_VIM : PART_USER_PASSWORD,
+ getEscapePrefix(), eMechanism,
+ eCharset, false),
+ m_aAbsURIRef.getLength());
+ bUserInfo = true;
+ }
+ else
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ if (bUserInfo && getSchemeInfo().m_bHost)
+ m_aAbsURIRef.append(sal_Unicode('@'));
+ if (getSchemeInfo().m_bHost)
+ {
+ rtl::OUStringBuffer aSynHost(rTheHost);
+ bool bNetBiosName = false;
+ switch (m_eScheme)
+ {
+ case INET_PROT_FILE:
+ {
+ rtl::OUString sTemp(aSynHost);
+ if (sTemp.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("localhost")))
+ {
+ aSynHost.setLength(0);
+ }
+ bNetBiosName = true;
+ }
+ break;
+
+ case INET_PROT_LDAP:
+ if (aSynHost.getLength() == 0 && nThePort != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+
+ default:
+ if (aSynHost.getLength() == 0)
+ {
+ setInvalid();
+ return false;
+ }
+ break;
+ }
+ if (!parseHostOrNetBiosName(
+ aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(),
+ false, eMechanism, eCharset, bNetBiosName, &aSynHost))
+ {
+ setInvalid();
+ return false;
+ }
+ m_aHost.set(m_aAbsURIRef, aSynHost.makeStringAndClear(),
+ m_aAbsURIRef.getLength());
+ if (nThePort != 0)
+ {
+ if (getSchemeInfo().m_bPort)
+ {
+ m_aAbsURIRef.append(sal_Unicode(':'));
+ m_aPort.set(m_aAbsURIRef,
+ rtl::OUString::valueOf(sal_Int64(nThePort)),
+ m_aAbsURIRef.getLength());
+ }
+ else
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ }
+ else if (rTheHost.getLength() != 0 || nThePort != 0)
+ {
+ setInvalid();
+ return false;
+ }
+ }
+ rtl::OUStringBuffer aSynPath;
+ sal_Unicode const * p = rThePath.getStr();
+ sal_Unicode const * pEnd = p + rThePath.getLength();
+ if (!parsePath(m_eScheme, &p, pEnd, false, eMechanism, eCharset, false, '/',
+ 0x80000000, 0x80000000, 0x80000000, aSynPath)
+ || p != pEnd)
+ {
+ setInvalid();
+ return false;
+ }
+ m_aPath.set(m_aAbsURIRef, aSynPath.makeStringAndClear(),
+ m_aAbsURIRef.getLength());
+ return true;
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::GetAbsURL(rtl::OUString const & rTheBaseURIRef,
+ rtl::OUString const & rTheRelURIRef,
+ bool bIgnoreFragment,
+ EncodeMechanism eEncodeMechanism,
+ DecodeMechanism eDecodeMechanism,
+ rtl_TextEncoding eCharset,
+ FSysStyle eStyle)
+{
+ // Backwards compatibility:
+ if (rTheRelURIRef.getLength() == 0 || rTheRelURIRef[0] == '#')
+ return rTheRelURIRef;
+
+ INetURLObject aTheAbsURIRef;
+ bool bWasAbsolute;
+ return INetURLObject(rTheBaseURIRef, eEncodeMechanism, eCharset).
+ convertRelToAbs(rTheRelURIRef, false, aTheAbsURIRef,
+ bWasAbsolute, eEncodeMechanism,
+ eCharset, bIgnoreFragment, false,
+ false, eStyle)
+ || eEncodeMechanism != WAS_ENCODED
+ || eDecodeMechanism != DECODE_TO_IURI
+ || eCharset != RTL_TEXTENCODING_UTF8 ?
+ aTheAbsURIRef.GetMainURL(eDecodeMechanism, eCharset) :
+ rTheRelURIRef;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::getExternalURL(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ rtl::OUString aTheExtURIRef;
+ translateToExternal(
+ rtl::OUString(m_aAbsURIRef), aTheExtURIRef, eMechanism, eCharset);
+ return aTheExtURIRef;
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::GetScheme(INetProtocol eTheScheme)
+{
+ return rtl::OUString::createFromAscii(getSchemeInfo(eTheScheme).m_pPrefix);
+}
+
+//============================================================================
+// static
+INetProtocol INetURLObject::CompareProtocolScheme(rtl::OUString const &
+ rTheAbsURIRef)
+{
+ sal_Unicode const * p = rTheAbsURIRef.getStr();
+ PrefixInfo const * pPrefix = getPrefix(p, p + rTheAbsURIRef.getLength());
+ return pPrefix ? pPrefix->m_eScheme : INET_PROT_NOT_VALID;
+}
+
+//============================================================================
+bool INetURLObject::hasPassword() const
+{
+ return m_aAuth.isPresent() && getSchemeInfo().m_bPassword;
+}
+
+//============================================================================
+void INetURLObject::makeAuthCanonic()
+{
+ if (m_eScheme == INET_PROT_IMAP && m_aAuth.getLength() == 1
+ && m_aAbsURIRef.charAt(m_aAuth.getBegin()) == '*')
+ {
+ lcl_Erase(m_aAbsURIRef, m_aAuth.getBegin()
+ - RTL_CONSTASCII_LENGTH(";AUTH="),
+ RTL_CONSTASCII_LENGTH(";AUTH=*"));
+ sal_Int32 nDelta = m_aAuth.clear() - RTL_CONSTASCII_LENGTH(";AUTH=");
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetHostPort(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ // Check because PROT_VND_SUN_STAR_HELP, PROT_VND_SUN_STAR_HIER, and
+ // PROT_VND_SUN_STAR_PKG misuse m_aHost:
+ if (!getSchemeInfo().m_bHost)
+ return rtl::OUString();
+ rtl::OUStringBuffer aHostPort(decode(m_aHost, getEscapePrefix(),
+ eMechanism, eCharset));
+ if (m_aPort.isPresent())
+ {
+ aHostPort.append(sal_Unicode(':'));
+ aHostPort.append(decode(m_aPort, getEscapePrefix(),
+ eMechanism, eCharset));
+ }
+ return aHostPort.makeStringAndClear();
+}
+
+//============================================================================
+sal_uInt32 INetURLObject::GetPort() const
+{
+ if (m_aPort.isPresent())
+ {
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPort.getBegin();
+ sal_Unicode const * pEnd = p + m_aPort.getLength();
+ sal_uInt32 nThePort;
+ if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd)
+ return nThePort;
+ }
+ return 0;
+}
+
+//============================================================================
+bool INetURLObject::SetPort(sal_uInt32 nThePort)
+{
+ if (getSchemeInfo().m_bPort && m_aHost.isPresent())
+ {
+ rtl::OUString aNewPort(rtl::OUString::valueOf(sal_Int64(nThePort)));
+ sal_Int32 nDelta;
+ if (m_aPort.isPresent())
+ nDelta = m_aPort.set(m_aAbsURIRef, aNewPort);
+ else
+ {
+ m_aAbsURIRef.insert(m_aHost.getEnd(), sal_Unicode(':'));
+ nDelta = m_aPort.set(m_aAbsURIRef, aNewPort, m_aHost.getEnd() + 1)
+ + 1;
+ }
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ return true;
+ }
+ return false;
+}
+
+//============================================================================
+void INetURLObject::makePortCanonic()
+{
+ if (m_aPort.isPresent())
+ {
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPort.getBegin();
+ sal_Unicode const * pEnd = p + m_aPort.getLength();
+ sal_uInt32 nThePort;
+ if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd)
+ {
+ sal_Int32 nDelta;
+ if (nThePort != 0 && nThePort == getSchemeInfo().m_nDefaultPort)
+ {
+ lcl_Erase(m_aAbsURIRef, m_aPort.getBegin() - 1,
+ m_aPort.getLength() + 1);
+ nDelta = m_aPort.clear() - 1;
+ }
+ else
+ nDelta = m_aPort.set(m_aAbsURIRef,
+ rtl::OUString::valueOf(sal_Int64(nThePort)));
+ m_aPath += nDelta;
+ m_aQuery += nDelta;
+ m_aFragment += nDelta;
+ }
+ }
+}
+
+//============================================================================
+sal_Int32 INetURLObject::getSegmentCount(bool bIgnoreFinalSlash) const
+{
+ if (!checkHierarchical())
+ return 0;
+
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ if (bIgnoreFinalSlash && pEnd > p && pEnd[-1] == '/')
+ --pEnd;
+ sal_Int32 n = p == pEnd || *p == '/' ? 0 : 1;
+ while (p != pEnd)
+ if (*p++ == '/')
+ ++n;
+ return n;
+}
+
+//============================================================================
+bool INetURLObject::removeSegment(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(),
+ aSegment.getBegin() - m_aPath.getBegin());
+ if (bIgnoreFinalSlash && aSegment.getEnd() == m_aPath.getEnd())
+ aNewPath.append(sal_Unicode('/'));
+ else
+ aNewPath.append(m_aAbsURIRef.getStr() + aSegment.getEnd(),
+ m_aPath.getEnd() - aSegment.getEnd());
+ if (aNewPath.getLength() == 0 && !aSegment.isEmpty() &&
+ m_aAbsURIRef[aSegment.getBegin()] == '/')
+ {
+ aNewPath.append(sal_Unicode('/'));
+ }
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::getName(sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return rtl::OUString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * p = pSegBegin;
+ while (p != pSegEnd && *p != ';')
+ ++p;
+
+ return decode(pSegBegin, p, getEscapePrefix(), eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setName(rtl::OUString const & rTheName, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * p = pSegBegin;
+ while (p != pSegEnd && *p != ';')
+ ++p;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pSegBegin - pPathBegin);
+ aNewPath.append(encodeText(rTheName, false, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true));
+ aNewPath.append(p, pPathEnd - p);
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::hasExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+ const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ for (sal_Unicode const * p = pSegBegin; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ return true;
+ return false;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::getBase(sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return rtl::OUString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ return decode(pSegBegin, pExtension, getEscapePrefix(), eMechanism,
+ eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setBase(rtl::OUString const & rTheBase, sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pSegBegin - pPathBegin);
+ aNewPath.append(encodeText(rTheBase, false, PART_PCHAR, getEscapePrefix(),
+ eMechanism, eCharset, true));
+ aNewPath.append(pExtension, pPathEnd - pExtension);
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::getExtension(sal_Int32 nIndex,
+ bool bIgnoreFinalSlash,
+ DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return rtl::OUString();
+
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+
+ if (!pExtension)
+ return rtl::OUString();
+
+ return decode(pExtension + 1, p, getEscapePrefix(), eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::setExtension(rtl::OUString const & rTheExtension,
+ sal_Int32 nIndex, bool bIgnoreFinalSlash,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ pExtension = p;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pExtension - pPathBegin);
+ aNewPath.append(sal_Unicode('.'));
+ aNewPath.append(encodeText(rTheExtension, false, PART_PCHAR,
+ getEscapePrefix(), eMechanism, eCharset, true));
+ aNewPath.append(p, pPathEnd - p);
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::removeExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash)
+{
+ SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash));
+ if (!aSegment.isPresent())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ sal_Unicode const * pSegBegin
+ = m_aAbsURIRef.getStr() + aSegment.getBegin();
+ sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength();
+
+ if (pSegBegin < pSegEnd && *pSegBegin == '/')
+ ++pSegBegin;
+ sal_Unicode const * pExtension = 0;
+ sal_Unicode const * p = pSegBegin;
+ for (; p != pSegEnd && *p != ';'; ++p)
+ if (*p == '.' && p != pSegBegin)
+ pExtension = p;
+ if (!pExtension)
+ return true;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pExtension - pPathBegin);
+ aNewPath.append(p, pPathEnd - p);
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::hasFinalSlash() const
+{
+ if (!checkHierarchical())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ return pPathEnd > pPathBegin && pPathEnd[-1] == '/';
+}
+
+//============================================================================
+bool INetURLObject::setFinalSlash()
+{
+ if (!checkHierarchical())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathEnd > pPathBegin && pPathEnd[-1] == '/')
+ return true;
+
+ rtl::OUStringBuffer aNewPath;
+ aNewPath.append(pPathBegin, pPathEnd - pPathBegin);
+ aNewPath.append(sal_Unicode('/'));
+
+ return setPath(aNewPath.makeStringAndClear(), false, NOT_CANONIC,
+ RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+bool INetURLObject::removeFinalSlash()
+{
+ if (!checkHierarchical())
+ return false;
+
+ sal_Unicode const * pPathBegin
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength();
+ if (pPathEnd <= pPathBegin || pPathEnd[-1] != '/')
+ return true;
+
+ --pPathEnd;
+ if (pPathEnd == pPathBegin && *pPathBegin == '/')
+ return false;
+ rtl::OUString aNewPath(pPathBegin, pPathEnd - pPathBegin);
+
+ return setPath(aNewPath, false, NOT_CANONIC, RTL_TEXTENCODING_UTF8);
+}
+
+//============================================================================
+// static
+rtl::OUString INetURLObject::createFragment(rtl::OUString const & rText)
+{
+ rtl::OUString aFragment(rText);
+ for (sal_Int32 i = 0; i < aFragment.getLength();)
+ {
+ sal_Unicode c = aFragment.getStr()[i];
+ if (mustEncode(c, PART_CREATEFRAGMENT))
+ aFragment = aFragment.replaceAt(i, 1, rtl::OUString());
+ else
+ ++i;
+ }
+ return aFragment;
+}
+
+//============================================================================
+bool INetURLObject::setFSysPath(rtl::OUString const & rFSysPath,
+ FSysStyle eStyle)
+{
+ sal_Unicode const * pFSysBegin = rFSysPath.getStr();
+ sal_Unicode const * pFSysEnd = pFSysBegin + rFSysPath.getLength();
+
+ switch ((eStyle & FSYS_VOS ? 1 : 0)
+ + (eStyle & FSYS_UNX ? 1 : 0)
+ + (eStyle & FSYS_DOS ? 1 : 0)
+ + (eStyle & FSYS_MAC ? 1 : 0))
+ {
+ case 0:
+ return false;
+
+ case 1:
+ break;
+
+ default:
+ if (eStyle & FSYS_VOS
+ && pFSysEnd - pFSysBegin >= 2
+ && pFSysBegin[0] == '/'
+ && pFSysBegin[1] == '/')
+ {
+ if (pFSysEnd - pFSysBegin >= 3
+ && pFSysBegin[2] == '.'
+ && (pFSysEnd - pFSysBegin == 3 || pFSysBegin[3] == '/'))
+ {
+ eStyle = FSYS_VOS; // Production T1
+ break;
+ }
+
+ sal_Unicode const * p = pFSysBegin + 2;
+ rtl::OUString aHost;
+ if (parseHost(p, pFSysEnd, aHost)
+ && (p == pFSysEnd || *p == '/'))
+ {
+ eStyle = FSYS_VOS; // Production T2
+ break;
+ }
+ }
+
+ if (eStyle & FSYS_DOS
+ && pFSysEnd - pFSysBegin >= 2
+ && pFSysBegin[0] == '\\'
+ && pFSysBegin[1] == '\\')
+ {
+ sal_Unicode const * p = pFSysBegin + 2;
+ rtl::OUString aHost;
+ if (parseHost(p, pFSysEnd, aHost)
+ && (p == pFSysEnd || *p == '\\'))
+ {
+ eStyle = FSYS_DOS; // Production T3
+ break;
+ }
+ }
+
+ if (eStyle & FSYS_DOS
+ && pFSysEnd - pFSysBegin >= 2
+ && INetMIME::isAlpha(pFSysBegin[0])
+ && pFSysBegin[1] == ':'
+ && (pFSysEnd - pFSysBegin == 2
+ || pFSysBegin[2] == '/'
+ || pFSysBegin[2] == '\\'))
+ {
+ eStyle = FSYS_DOS; // Productions T4, T5
+ break;
+ }
+
+ if (!(eStyle & (FSYS_UNX | FSYS_DOS | FSYS_MAC)))
+ return false;
+
+ eStyle = guessFSysStyleByCounting(pFSysBegin, pFSysEnd, eStyle);
+ // Production T6
+ break;
+ }
+
+ rtl::OUStringBuffer aSynAbsURIRef(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file://")));
+
+ switch (eStyle)
+ {
+ case FSYS_VOS:
+ {
+ sal_Unicode const * p = pFSysBegin;
+ if (pFSysEnd - p < 2 || *p++ != '/' || *p++ != '/')
+ return false;
+ if (p != pFSysEnd && *p == '.'
+ && (pFSysEnd - p == 1 || p[1] == '/'))
+ ++p;
+ for (; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef.append(*p);
+ break;
+ }
+ break;
+ }
+
+ case FSYS_UNX:
+ {
+ sal_Unicode const * p = pFSysBegin;
+ if (p != pFSysEnd && *p != '/')
+ return false;
+ for (; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case '|':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef.append(*p);
+ break;
+ }
+ break;
+ }
+
+ case FSYS_DOS:
+ {
+ sal_uInt32 nAltDelimiter = 0x80000000;
+ sal_Unicode const * p = pFSysBegin;
+ if (pFSysEnd - p >= 3 && p[0] == '\\' && p[1] == '\\')
+ p += 2;
+ else
+ {
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ if (pFSysEnd - p >= 2
+ && INetMIME::isAlpha(p[0])
+ && p[1] == ':'
+ && (pFSysEnd - p == 2 || p[2] == '\\' || p[2] == '/'))
+ nAltDelimiter = '/';
+ }
+ for (; p != pFSysEnd; ++p)
+ if (*p == '\\' || *p == nAltDelimiter)
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ else
+ switch (*p)
+ {
+ case '/':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef.append(*p);
+ break;
+ }
+ break;
+ }
+
+ case FSYS_MAC:
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ {for (sal_Unicode const * p = pFSysBegin; p != pFSysEnd; ++p)
+ switch (*p)
+ {
+ case ':':
+ aSynAbsURIRef.append(sal_Unicode('/'));
+ break;
+
+ case '/':
+ case '|':
+ case '#':
+ case '%':
+ appendEscape(aSynAbsURIRef, '%', *p);
+ break;
+
+ default:
+ aSynAbsURIRef.append(*p);
+ break;
+ }
+ }
+ break;
+
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
+
+ INetURLObject aTemp(aSynAbsURIRef.makeStringAndClear(), WAS_ENCODED,
+ RTL_TEXTENCODING_UTF8);
+ if (aTemp.HasError())
+ return false;
+
+ *this = aTemp;
+ return true;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::getFSysPath(FSysStyle eStyle,
+ sal_Unicode * pDelimiter) const
+{
+ if (m_eScheme != INET_PROT_FILE)
+ return rtl::OUString();
+
+ if ((eStyle & FSYS_VOS ? 1 : 0)
+ + (eStyle & FSYS_UNX ? 1 : 0)
+ + (eStyle & FSYS_DOS ? 1 : 0)
+ + (eStyle & FSYS_MAC ? 1 : 0)
+ > 1)
+ {
+ eStyle = eStyle & FSYS_VOS
+ && m_aHost.isPresent()
+ && m_aHost.getLength() > 0 ?
+ FSYS_VOS :
+ hasDosVolume(eStyle)
+ || ((eStyle & FSYS_DOS) != 0
+ && m_aHost.isPresent()
+ && m_aHost.getLength() > 0) ?
+ FSYS_DOS :
+ eStyle & FSYS_UNX
+ && (!m_aHost.isPresent() || m_aHost.getLength() == 0) ?
+ FSYS_UNX :
+ FSysStyle(0);
+ }
+
+ switch (eStyle)
+ {
+ case FSYS_VOS:
+ {
+ if (pDelimiter)
+ *pDelimiter = '/';
+
+ rtl::OUStringBuffer aSynFSysPath;
+ aSynFSysPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("//"));
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ aSynFSysPath.append(decode(m_aHost, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8));
+ else
+ aSynFSysPath.append(sal_Unicode('.'));
+ aSynFSysPath.append(decode(m_aPath, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8));
+ return aSynFSysPath.makeStringAndClear();
+ }
+
+ case FSYS_UNX:
+ {
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ return rtl::OUString();
+
+ if (pDelimiter)
+ *pDelimiter = '/';
+
+ return decode(m_aPath, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8);
+ }
+
+ case FSYS_DOS:
+ {
+ if (pDelimiter)
+ *pDelimiter = '\\';
+
+ rtl::OUStringBuffer aSynFSysPath;
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ {
+ aSynFSysPath.appendAscii(RTL_CONSTASCII_STRINGPARAM("\\\\"));
+ aSynFSysPath.append(decode(m_aHost, '%', DECODE_WITH_CHARSET,
+ RTL_TEXTENCODING_UTF8));
+ aSynFSysPath.append(sal_Unicode('\\'));
+ }
+ sal_Unicode const * p
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ DBG_ASSERT(p < pEnd && *p == '/',
+ "INetURLObject::getFSysPath(): Bad path");
+ ++p;
+ while (p < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED,
+ RTL_TEXTENCODING_UTF8,
+ eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aSynFSysPath.append(sal_Unicode('\\'));
+ else
+ aSynFSysPath.appendUtf32(nUTF32);
+ }
+ return aSynFSysPath.makeStringAndClear();
+ }
+
+ case FSYS_MAC:
+ {
+ if (m_aHost.isPresent() && m_aHost.getLength() > 0)
+ return rtl::OUString();
+
+ if (pDelimiter)
+ *pDelimiter = ':';
+
+ rtl::OUStringBuffer aSynFSysPath;
+ sal_Unicode const * p
+ = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ DBG_ASSERT(p < pEnd && *p == '/',
+ "INetURLObject::getFSysPath(): Bad path");
+ ++p;
+ while (p < pEnd)
+ {
+ EscapeType eEscapeType;
+ sal_uInt32 nUTF32 = getUTF32(p, pEnd, false, '%', WAS_ENCODED,
+ RTL_TEXTENCODING_UTF8,
+ eEscapeType);
+ if (eEscapeType == ESCAPE_NO && nUTF32 == '/')
+ aSynFSysPath.append(sal_Unicode(':'));
+ else
+ aSynFSysPath.appendUtf32(nUTF32);
+ }
+ return aSynFSysPath.makeStringAndClear();
+ }
+
+ default:
+ return rtl::OUString();
+ }
+}
+
+//============================================================================
+bool INetURLObject::HasMsgId() const
+{
+ if (m_eScheme != INET_PROT_POP3)
+ return false;
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ for (; p < pEnd; ++p)
+ if (*p == '<')
+ return true;
+ return false;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetMsgId(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ if (m_eScheme != INET_PROT_POP3)
+ return rtl::OUString();
+ sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin();
+ sal_Unicode const * pEnd = p + m_aPath.getLength();
+ for (; p < pEnd; ++p)
+ if (*p == '<')
+ return decode(p, pEnd, getEscapePrefix(), eMechanism, eCharset);
+ return rtl::OUString();
+}
+
+//============================================================================
+// static
+void INetURLObject::appendUCS4Escape(rtl::OUStringBuffer & rTheText,
+ sal_Char cEscapePrefix, sal_uInt32 nUCS4)
+{
+ DBG_ASSERT(nUCS4 < 0x80000000,
+ "INetURLObject::appendUCS4Escape(): Bad char");
+ if (nUCS4 < 0x80)
+ appendEscape(rTheText, cEscapePrefix, nUCS4);
+ else if (nUCS4 < 0x800)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 6 | 0xC0);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80);
+ }
+ else if (nUCS4 < 0x10000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 12 | 0xE0);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80);
+ }
+ else if (nUCS4 < 0x200000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 18 | 0xF0);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80);
+ }
+ else if (nUCS4 < 0x4000000)
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 24 | 0xF8);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 18 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80);
+ }
+ else
+ {
+ appendEscape(rTheText, cEscapePrefix, nUCS4 >> 30 | 0xFC);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 24 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 18 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 12 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 >> 6 & 0x3F) | 0x80);
+ appendEscape(rTheText, cEscapePrefix, (nUCS4 & 0x3F) | 0x80);
+ }
+}
+
+//============================================================================
+// static
+void INetURLObject::appendUCS4(rtl::OUStringBuffer& rTheText, sal_uInt32 nUCS4,
+ EscapeType eEscapeType, bool bOctets,
+ Part ePart, sal_Char cEscapePrefix,
+ rtl_TextEncoding eCharset,
+ bool bKeepVisibleEscapes)
+{
+ bool bEscape;
+ rtl_TextEncoding eTargetCharset = RTL_TEXTENCODING_DONTKNOW;
+ switch (eEscapeType)
+ {
+ case ESCAPE_NO:
+ if (mustEncode(nUCS4, ePart))
+ {
+ bEscape = true;
+ eTargetCharset = bOctets ? RTL_TEXTENCODING_ISO_8859_1 :
+ RTL_TEXTENCODING_UTF8;
+ }
+ else
+ bEscape = false;
+ break;
+
+ case ESCAPE_OCTET:
+ bEscape = true;
+ eTargetCharset = RTL_TEXTENCODING_ISO_8859_1;
+ break;
+
+ case ESCAPE_UTF32:
+ if (mustEncode(nUCS4, ePart))
+ {
+ bEscape = true;
+ eTargetCharset = eCharset;
+ }
+ else if (bKeepVisibleEscapes && INetMIME::isVisible(nUCS4))
+ {
+ bEscape = true;
+ eTargetCharset = RTL_TEXTENCODING_ASCII_US;
+ }
+ else
+ bEscape = false;
+ break;
+ default:
+ bEscape = false;
+ }
+
+ if (bEscape)
+ {
+ switch (eTargetCharset)
+ {
+ default:
+ DBG_ERROR("INetURLObject::appendUCS4(): Unsupported charset");
+ case RTL_TEXTENCODING_ASCII_US:
+ case RTL_TEXTENCODING_ISO_8859_1:
+ appendEscape(rTheText, cEscapePrefix, nUCS4);
+ break;
+
+ case RTL_TEXTENCODING_UTF8:
+ appendUCS4Escape(rTheText, cEscapePrefix, nUCS4);
+ break;
+ }
+ }
+ else
+ rTheText.append(sal_Unicode(nUCS4));
+}
+
+//============================================================================
+// static
+sal_uInt32 INetURLObject::getUTF32(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd, bool bOctets,
+ sal_Char cEscapePrefix,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset,
+ EscapeType & rEscapeType)
+{
+ DBG_ASSERT(rBegin < pEnd, "INetURLObject::getUTF32(): Bad sequence");
+ sal_uInt32 nUTF32 = bOctets ? *rBegin++ :
+ INetMIME::getUTF32Character(rBegin, pEnd);
+ switch (eMechanism)
+ {
+ case ENCODE_ALL:
+ rEscapeType = ESCAPE_NO;
+ break;
+
+ case WAS_ENCODED:
+ {
+ int nWeight1;
+ int nWeight2;
+ if (nUTF32 == sal_uChar(cEscapePrefix) && rBegin + 1 < pEnd
+ && (nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0
+ && (nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0)
+ {
+ rBegin += 2;
+ nUTF32 = nWeight1 << 4 | nWeight2;
+ switch (eCharset)
+ {
+ default:
+ DBG_ERROR(
+ "INetURLObject::getUTF32(): Unsupported charset");
+ case RTL_TEXTENCODING_ASCII_US:
+ rEscapeType = INetMIME::isUSASCII(nUTF32) ?
+ ESCAPE_UTF32 : ESCAPE_OCTET;
+ break;
+
+ case RTL_TEXTENCODING_ISO_8859_1:
+ rEscapeType = ESCAPE_UTF32;
+ break;
+
+ case RTL_TEXTENCODING_UTF8:
+ if (INetMIME::isUSASCII(nUTF32))
+ rEscapeType = ESCAPE_UTF32;
+ else
+ {
+ if (nUTF32 >= 0xC0 && nUTF32 <= 0xF4)
+ {
+ sal_uInt32 nEncoded;
+ int nShift;
+ sal_uInt32 nMin;
+ if (nUTF32 <= 0xDF)
+ {
+ nEncoded = (nUTF32 & 0x1F) << 6;
+ nShift = 0;
+ nMin = 0x80;
+ }
+ else if (nUTF32 <= 0xEF)
+ {
+ nEncoded = (nUTF32 & 0x0F) << 12;
+ nShift = 6;
+ nMin = 0x800;
+ }
+ else
+ {
+ nEncoded = (nUTF32 & 0x07) << 18;
+ nShift = 12;
+ nMin = 0x10000;
+ }
+ sal_Unicode const * p = rBegin;
+ bool bUTF8 = true;
+ for (;;)
+ {
+ if (pEnd - p < 3
+ || p[0] != cEscapePrefix
+ || (nWeight1
+ = INetMIME::getHexWeight(p[1]))
+ < 8
+ || nWeight1 > 11
+ || (nWeight2
+ = INetMIME::getHexWeight(p[2]))
+ < 0)
+ {
+ bUTF8 = false;
+ break;
+ }
+ p += 3;
+ nEncoded
+ |= ((nWeight1 & 3) << 4 | nWeight2)
+ << nShift;
+ if (nShift == 0)
+ break;
+ nShift -= 6;
+ }
+ if (bUTF8 && nEncoded >= nMin
+ && !INetMIME::isHighSurrogate(nEncoded)
+ && !INetMIME::isLowSurrogate(nEncoded)
+ && nEncoded <= 0x10FFFF)
+ {
+ rBegin = p;
+ nUTF32 = nEncoded;
+ rEscapeType = ESCAPE_UTF32;
+ break;
+ }
+ }
+ rEscapeType = ESCAPE_OCTET;
+ }
+ break;
+ }
+ }
+ else
+ rEscapeType = ESCAPE_NO;
+ break;
+ }
+
+ case NOT_CANONIC:
+ {
+ int nWeight1;
+ int nWeight2;
+ if (nUTF32 == sal_uChar(cEscapePrefix) && rBegin + 1 < pEnd
+ && ((nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0)
+ && ((nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0))
+ {
+ rBegin += 2;
+ nUTF32 = nWeight1 << 4 | nWeight2;
+ rEscapeType = ESCAPE_OCTET;
+ }
+ else
+ rEscapeType = ESCAPE_NO;
+ break;
+ }
+ }
+ return nUTF32;
+}
+
+//============================================================================
+// static
+sal_uInt32 INetURLObject::scanDomain(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd,
+ bool bEager)
+{
+ enum State { STATE_DOT, STATE_LABEL, STATE_HYPHEN };
+ State eState = STATE_DOT;
+ sal_Int32 nLabels = 0;
+ sal_Unicode const * pLastAlphanumeric = 0;
+ for (sal_Unicode const * p = rBegin;; ++p)
+ switch (eState)
+ {
+ case STATE_DOT:
+ if (p != pEnd && (INetMIME::isAlphanumeric(*p) || *p == '_'))
+ {
+ ++nLabels;
+ eState = STATE_LABEL;
+ break;
+ }
+ if (bEager || nLabels == 0)
+ return 0;
+ rBegin = p - 1;
+ return nLabels;
+
+ case STATE_LABEL:
+ if (p != pEnd)
+ {
+ if (INetMIME::isAlphanumeric(*p) || *p == '_')
+ break;
+ else if (*p == '.')
+ {
+ eState = STATE_DOT;
+ break;
+ }
+ else if (*p == '-')
+ {
+ pLastAlphanumeric = p;
+ eState = STATE_HYPHEN;
+ break;
+ }
+ }
+ rBegin = p;
+ return nLabels;
+
+ case STATE_HYPHEN:
+ if (p != pEnd)
+ {
+ if (INetMIME::isAlphanumeric(*p) || *p == '_')
+ {
+ eState = STATE_LABEL;
+ break;
+ }
+ else if (*p == '-')
+ break;
+ }
+ if (bEager)
+ return 0;
+ rBegin = pLastAlphanumeric;
+ return nLabels;
+ }
+}
+
+//============================================================================
+// static
+bool INetURLObject::scanIPv6reference(sal_Unicode const *& rBegin,
+ sal_Unicode const * pEnd)
+{
+ if (rBegin != pEnd && *rBegin == '[') {
+ sal_Unicode const * p = rBegin + 1;
+ //TODO: check for valid IPv6address (RFC 2373):
+ while (p != pEnd && (INetMIME::isHexDigit(*p) || *p == ':' || *p == '.'))
+ {
+ ++p;
+ }
+ if (p != pEnd && *p == ']') {
+ rBegin = p + 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetPartBeforeLastName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+ const
+{
+ if (!checkHierarchical())
+ return rtl::OUString();
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ aTemp.clearQuery();
+ aTemp.removeSegment(LAST_SEGMENT, false);
+ aTemp.setFinalSlash();
+ return aTemp.GetMainURL(eMechanism, eCharset);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetLastName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ return getName(LAST_SEGMENT, true, eMechanism, eCharset);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetFileExtension(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset) const
+{
+ return getExtension(LAST_SEGMENT, false, eMechanism, eCharset);
+}
+
+//============================================================================
+bool INetURLObject::CutLastName()
+{
+ INetURLObject aTemp(*this);
+ aTemp.clearFragment();
+ aTemp.clearQuery();
+ if (!aTemp.removeSegment(LAST_SEGMENT, false))
+ return false;
+ *this = aTemp;
+ return true;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::PathToFileName() const
+{
+ if (m_eScheme != INET_PROT_FILE)
+ return rtl::OUString();
+ rtl::OUString aSystemPath;
+ if (osl::FileBase::getSystemPathFromFileURL(
+ decode(m_aAbsURIRef.getStr(),
+ m_aAbsURIRef.getStr() + m_aPath.getEnd(),
+ getEscapePrefix(), NO_DECODE, RTL_TEXTENCODING_UTF8),
+ aSystemPath)
+ != osl::FileBase::E_None)
+ return rtl::OUString();
+ return aSystemPath;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetFull() const
+{
+ INetURLObject aTemp(*this);
+ aTemp.removeFinalSlash();
+ return aTemp.PathToFileName();
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetPath() const
+{
+ INetURLObject aTemp(*this);
+ aTemp.removeSegment(LAST_SEGMENT, true);
+ aTemp.removeFinalSlash();
+ return aTemp.PathToFileName();
+}
+
+//============================================================================
+void INetURLObject::SetBase(rtl::OUString const & rTheBase)
+{
+ setBase(rTheBase, LAST_SEGMENT, true, ENCODE_ALL);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::GetBase() const
+{
+ return getBase(LAST_SEGMENT, true, DECODE_WITH_CHARSET);
+}
+
+//============================================================================
+void INetURLObject::SetName(rtl::OUString const & rTheName,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ INetURLObject aTemp(*this);
+ if (aTemp.removeSegment(LAST_SEGMENT, true)
+ && aTemp.insertName(rTheName, false, LAST_SEGMENT, true, eMechanism,
+ eCharset))
+ *this = aTemp;
+}
+
+//============================================================================
+rtl::OUString INetURLObject::CutName(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ rtl::OUString aTheName(getName(LAST_SEGMENT, true, eMechanism, eCharset));
+ return removeSegment(LAST_SEGMENT, true) ? aTheName : rtl::OUString();
+}
+
+//============================================================================
+void INetURLObject::SetExtension(rtl::OUString const & rTheExtension,
+ EncodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ setExtension(rTheExtension, LAST_SEGMENT, false, eMechanism, eCharset);
+}
+
+//============================================================================
+rtl::OUString INetURLObject::CutExtension(DecodeMechanism eMechanism,
+ rtl_TextEncoding eCharset)
+{
+ rtl::OUString aTheExtension(getExtension(LAST_SEGMENT, false, eMechanism,
+ eCharset));
+ return removeExtension(LAST_SEGMENT, false)
+ ? aTheExtension : rtl::OUString();
+}
+
+//============================================================================
+bool INetURLObject::IsCaseSensitive() const
+{
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/wldcrd.cxx b/tools/source/fsys/wldcrd.cxx
new file mode 100644
index 000000000000..183f07d3d6fb
--- /dev/null
+++ b/tools/source/fsys/wldcrd.cxx
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+#include <tools/wldcrd.hxx>
+
+/*************************************************************************
+|*
+|* WildCard::Match()
+|*
+|* Beschreibung WLDCRD.SDW
+|* Ersterstellung MA 19.06.91
+|* Letzte Aenderung MA 03.07.91
+|*
+*************************************************************************/
+
+/* Diese Methode ueberprueft, ob die Wilde Karte in pWild mit dem String
+ * in pStr matscht.
+ * Vertragen sich die beiden, so wird 1 zurueckgegeben, sonst 0.
+ *
+ * ein '*' in pWild bedeutet n beliebige Zeichen, mit n>=0
+ * ein '?' in pWild bedeutet genau ein beliebiges Zeichen
+ *
+ */
+
+USHORT WildCard::ImpMatch( const char *pWild, const char *pStr ) const
+{
+ int pos=0;
+ int flag=0;
+
+ while ( *pWild || flag )
+ {
+ switch (*pWild)
+ {
+ case '?':
+ if ( *pStr == '\0' )
+ return 0;
+ break;
+
+ default:
+ if ( (*pWild == '\\') && ((*(pWild+1)=='?') || (*(pWild+1) == '*')) )
+ pWild++;
+ if ( *pWild != *pStr )
+ if ( !pos )
+ return 0;
+ else
+ pWild += pos;
+ else
+ break; // ACHTUNG laeuft unter bestimmten
+ // Umstaenden in den nachsten case rein!!
+ case '*':
+ while ( *pWild == '*' )
+ pWild++;
+ if ( *pWild == '\0' )
+ return 1;
+ flag = 1;
+ pos = 0;
+ if ( *pStr == '\0' )
+ return ( *pWild == '\0' );
+ while ( *pStr && *pStr != *pWild )
+ {
+ if ( *pWild == '?' ) {
+ pWild++;
+ while ( *pWild == '*' )
+ pWild++;
+ }
+ pStr++;
+ if ( *pStr == '\0' )
+ return ( *pWild == '\0' );
+ }
+ break;
+ }
+ if ( *pWild != '\0' )
+ pWild++;
+ if ( *pStr != '\0' )
+ pStr++;
+ else
+ flag = 0;
+ if ( flag )
+ pos--;
+ }
+ return ( *pStr == '\0' ) && ( *pWild == '\0' );
+}
+
+/*************************************************************************
+|*
+|* WildCard::Matches()
+|*
+|* Beschreibung WLDCRD.SDW
+|* Ersterstellung MA 19.06.91
+|* Letzte Aenderung TH 02.02.96
+|*
+*************************************************************************/
+
+BOOL WildCard::Matches( const String& rString ) const
+{
+ ByteString aTmpWild = aWildString;
+ ByteString aString(rString, osl_getThreadTextEncoding());
+
+ USHORT nSepPos;
+
+ if ( cSepSymbol != '\0' )
+ {
+ while ( (nSepPos = aTmpWild.Search( cSepSymbol )) != STRING_NOTFOUND )
+ {
+ // alle getrennten WildCard's pruefen
+ if ( ImpMatch( aTmpWild.Copy( 0, nSepPos ).GetBuffer(), aString.GetBuffer() ) )
+ return TRUE;
+ aTmpWild.Erase( 0, nSepPos + 1 ); // Trennsymbol entfernen
+ }
+ // und noch den hinter dem letzen Trennsymbol bzw. den einzigen
+ }
+
+ if ( ImpMatch( aTmpWild.GetBuffer(), aString.GetBuffer() ) )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/wntmsc.cxx b/tools/source/fsys/wntmsc.cxx
new file mode 100644
index 000000000000..4d78b575cfdc
--- /dev/null
+++ b/tools/source/fsys/wntmsc.cxx
@@ -0,0 +1,1083 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_tools.hxx"
+
+#ifdef _MSC_VER
+#pragma warning (push,1)
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+#include "wntmsc.hxx"
+#include <tools/errinf.hxx>
+#include <tools/debug.hxx>
+#include <tools/list.hxx>
+#include <tools/wldcrd.hxx>
+#include <tools/fsys.hxx>
+#include <tools/bigint.hxx>
+
+DECLARE_LIST( DirEntryList, DirEntry* );
+DECLARE_LIST( FSysSortList, FSysSort* );
+DECLARE_LIST( FileStatList, FileStat* );
+
+int Sys2SolarError_Impl( int nSysErr );
+
+static BOOL bLastCaseSensitive = FALSE;
+
+//--------------------------------------------------------------------
+
+ByteString Upper_Impl( const ByteString &rStr )
+{
+ ByteString aRet( rStr.GetBuffer() ); // es muss ein neuer String entstehen!
+ CharUpperBuff( (char*) aRet.GetBuffer(), aRet.Len() );
+ return aRet;
+}
+
+//--------------------------------------------------------------------
+
+DIR *opendir( const char* pPfad )
+{
+ DIR *pDir = new DIR;
+ if ( pDir )
+ pDir->p = (char*) pPfad;
+ return pDir;
+}
+
+struct dirent *readdir( DIR *pDir )
+{
+ bool bOk = false;
+ if ( pDir->p )
+ {
+ char *pBuf = new char[ strlen( pDir->p ) + 5 ];
+ if ( pBuf )
+ {
+ // *.* dahinter, ggf mit "\\" abtrennen (falls nicht schon da)
+ strcpy( pBuf, pDir->p );
+ strcat( pBuf, "\\*.*" + ( *(pBuf + strlen( pBuf ) - 1 ) == '\\' ) );
+ CharUpperBuff( pBuf, strlen(pBuf) );
+ pDir->h = FindFirstFile( pBuf, &pDir->aDirEnt );
+ bOk = pDir->h != INVALID_HANDLE_VALUE;
+ pDir->p = NULL;
+ delete [] pBuf;
+ }
+ else
+ pDir->h = INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ bOk = FindNextFile( pDir->h, &pDir->aDirEnt );
+ }
+
+ return bOk ? &pDir->aDirEnt : NULL;
+}
+
+int closedir( DIR *pDir )
+{
+ BOOL bOk = FALSE;
+ if ( pDir )
+ {
+ bOk = 0 != pDir->p || FindClose( pDir->h );
+ delete pDir;
+ }
+ return bOk;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::GetPathStyle() const
+|*
+|* Beschreibung
+|* Ersterstellung MI 11.05.95
+|* Letzte Aenderung MI 11.05.95
+|*
+*************************************************************************/
+
+ErrCode GetPathStyle_Impl( const String &rDevice, FSysPathStyle &rStyle )
+{
+ ByteString aRootDir(rDevice, osl_getThreadTextEncoding());
+ if ( aRootDir.Len() && aRootDir.GetBuffer()[aRootDir.Len()-1] != '\\' )
+ aRootDir += '\\';
+
+ char sVolumeName[256];
+ char sFileSysName[16];
+ DWORD nSerial[2];
+ DWORD nMaxCompLen[2];
+ DWORD nFlags[2];
+
+ // Windows95 hat VFAT, WindowsNT nicht
+ DWORD nVer = GetVersion();
+ BOOL bW95 = ( nVer & 0xFF ) >= 4;
+
+ FSysFailOnErrorImpl();
+ rStyle = FSYS_STYLE_UNKNOWN;
+ if ( GetVolumeInformation(
+ (char*) aRootDir.GetBuffer(),
+ sVolumeName, 256, (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags, sFileSysName, 16 ) )
+ {
+ // FAT/VFAT?
+ if ( 0 == strcmp( "FAT", sFileSysName ) )
+ rStyle = bW95 ? FSYS_STYLE_VFAT : FSYS_STYLE_FAT;
+
+ // NTFS?
+ else if ( 0 == strcmp( "NTFS", sFileSysName ) )
+ rStyle = FSYS_STYLE_NTFS;
+
+ // HPFS?
+ else if ( 0 == strcmp( "HPFS", sFileSysName ) )
+ rStyle = FSYS_STYLE_HPFS;
+
+ // NWCOMPA/NWFS?
+ else if ( 0 == strncmp( "NW", sFileSysName, 2 ) )
+ rStyle = FSYS_STYLE_NWFS;
+
+ return ERRCODE_NONE;
+ }
+
+ return ERRCODE_IO_INVALIDDEVICE;
+}
+
+FSysPathStyle DirEntry::GetPathStyle( const String &rDevice )
+{
+
+ FSysPathStyle eStyle;
+ GetPathStyle_Impl( rDevice, eStyle );
+ return eStyle;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::IsCaseSensitive()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 10.06.93
+|* Letzte Aenderung TPF 26.02.1999
+|*
+*************************************************************************/
+
+BOOL DirEntry::IsCaseSensitive( FSysPathStyle eFormatter ) const
+{
+
+ if (eFormatter==FSYS_STYLE_HOST)
+ {
+/*
+ DirEntry aRoot(*this);
+ aRoot.ToAbs();
+ aRoot = aRoot[Level()-1];
+ String aRootDir = aRoot.GetFull(FSYS_STYLE_HOST, TRUE);
+
+ char sVolumeName[256];
+ DWORD nVolumeSerial;
+ DWORD nMaxCompLen;
+ DWORD nFlags;
+ char sFileSysName[16];
+
+ if ( GetVolumeInformation( (char*) aRootDir.GetStr(),
+ sVolumeName,
+ 256,
+ (LPDWORD) &nVolumeSerial,
+ (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags,
+ sFileSysName,
+ 16 ))
+ {
+ return (nFlags & FS_CASE_SENSITIVE) ? TRUE : FALSE;
+ }
+ else
+ {
+ return FALSE;
+ }
+*/
+ //
+ // guter versuch, aber FS_CASE_SENSITIVE ist D?nnsinn in T?ten:
+ //
+ // sFileSysName FS_CASE_SENSITIVE
+ // FAT FALSE
+ // NTFS TRUE !!!
+ // NWCompat FALSE
+ // Samba FALSE
+ //
+ // NT spricht auch NTFS lediglich case preserving an, also ist unter NT alles case insensitiv
+ //
+
+ return FALSE;
+ }
+ else
+ {
+ BOOL isCaseSensitive = FALSE; // ich bin unter win32, also ist der default case insensitiv
+ switch ( eFormatter )
+ {
+ case FSYS_STYLE_MAC:
+ case FSYS_STYLE_FAT:
+ case FSYS_STYLE_VFAT:
+ case FSYS_STYLE_NTFS:
+ case FSYS_STYLE_NWFS:
+ case FSYS_STYLE_HPFS:
+ case FSYS_STYLE_DETECT:
+ {
+ isCaseSensitive = FALSE;
+ break;
+ }
+ case FSYS_STYLE_SYSV:
+ case FSYS_STYLE_BSD:
+ {
+ isCaseSensitive = TRUE;
+ break;
+ }
+ default:
+ {
+ isCaseSensitive = FALSE; // ich bin unter win32, also ist der default case insensitiv
+ break;
+ }
+ }
+ return isCaseSensitive;
+ }
+}
+
+/*************************************************************************
+|*
+|* DirEntry::ToAbs()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MA 02.12.91
+|*
+*************************************************************************/
+
+BOOL DirEntry::ToAbs()
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ if ( FSYS_FLAG_VOLUME == eFlag )
+ {
+ eFlag = FSYS_FLAG_ABSROOT;
+ return TRUE;
+ }
+
+ if ( IsAbs() )
+ {
+ return TRUE;
+ }
+
+
+ char sBuf[256];
+ char *pOld;
+ ByteString aFullName( GetFull(), osl_getThreadTextEncoding() );
+ FSysFailOnErrorImpl();
+ if ( GetFullPathName((char*)aFullName.GetBuffer(),256,sBuf,&pOld) > 511 )
+ return FALSE;
+
+ *this = DirEntry( String(sBuf, osl_getThreadTextEncoding() ));
+ return TRUE;
+}
+
+
+/*************************************************************************
+|*
+|* DirEntry::GetVolume()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+String DirEntry::GetVolume() const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ String aRet;
+ const DirEntry *pTop = ImpGetTopPtr();
+ ByteString aName = ByteString( pTop->aName ).ToLowerAscii();
+
+ if ( ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME )
+ && aName != "a:" && aName != "b:" && Exists() )
+ {
+ char sFileSysName[256];
+ char sVolumeName[256];
+ DWORD nVolumeNameLen = 256;
+ DWORD nSerial[2];
+ DWORD nMaxCompLen[2];
+ DWORD nFlags[2];
+ ByteString aRootDir = pTop->aName;
+ FSysFailOnErrorImpl();
+
+ // Network-Device zuerst probieren wegen langsamer Samba-Drives
+ if ( !WNetGetConnection( (char*) aRootDir.GetBuffer(),
+ sVolumeName, &nVolumeNameLen ) )
+ aRet = String( sVolumeName, osl_getThreadTextEncoding());
+
+ // dann den VolumeNamen fuer lokale Drives
+ if ( aRet.Len() == 0 )
+ {
+ aRootDir += "\\";
+ if ( GetVolumeInformation( (char*) aRootDir.GetBuffer(),
+ sVolumeName, 256,
+ (LPDWORD) &nSerial, (LPDWORD) &nMaxCompLen,
+ (LPDWORD) &nFlags, sFileSysName, 256 ) )
+ aRet = String( sVolumeName, osl_getThreadTextEncoding());
+ }
+ }
+
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* DirEntry::SetCWD()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 26.04.91
+|* Letzte Aenderung MI 21.05.92
+|*
+*************************************************************************/
+
+BOOL DirEntry::SetCWD( BOOL bSloppy ) const
+{
+ DBG_CHKTHIS( DirEntry, ImpCheckDirEntry );
+
+ FSysFailOnErrorImpl();
+
+ if ( eFlag == FSYS_FLAG_CURRENT && !aName.Len() )
+ return TRUE;
+
+ if ( SetCurrentDirectory(ByteString(GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ return TRUE;
+ }
+
+ if ( bSloppy && pParent &&
+ SetCurrentDirectory(ByteString(pParent->GetFull(), osl_getThreadTextEncoding()).GetBuffer()) )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Init()
+{
+ // Block-Devices auflisten?
+ if ( pDir->eAttrMask & FSYS_KIND_BLOCK )
+ {
+ // CWD merken
+ DirEntry aCurrentDir;
+ aCurrentDir.ToAbs();
+
+ // einzeln auf Existenz und Masken-konformit"at pr"ufen
+ USHORT nRead = 0;
+ char sDrive[3] = { '?', ':', 0 };
+ char sRoot[4] = { '?', ':', '\\', 0 };
+ for ( char c = 'a'; c <= 'z'; c++ )
+ {
+ sDrive[0] = c;
+ sRoot[0] = c;
+ DirEntry* pDrive = new DirEntry( sDrive, FSYS_FLAG_VOLUME, FSYS_STYLE_HOST );
+ if ( pDir->aNameMask.Matches( String( ByteString(sDrive), osl_getThreadTextEncoding())) && GetDriveType( sRoot ) != 1 )
+ {
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( *pDrive );
+ pDir->ImpSortedInsert( pDrive, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pDrive, NULL );
+ ++nRead;
+ }
+ else
+ delete pDrive;
+ }
+
+ // CWD restaurieren
+ aCurrentDir.SetCWD();
+ return nRead;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+
+USHORT DirReader_Impl::Read()
+{
+ // Directories und Files auflisten?
+ if ( ( pDir->eAttrMask & FSYS_KIND_DIR ||
+ pDir->eAttrMask & FSYS_KIND_FILE ) &&
+ ( ( pDosEntry = readdir( pDosDir ) ) != NULL ) )
+ {
+ // Gross/Kleinschreibung nicht beruecksichtigen
+ ByteString aLowerName = pDosEntry->d_name;
+ CharLowerBuff( (char*) aLowerName.GetBuffer(), aLowerName.Len() );
+
+ // Flags pruefen
+ BOOL bIsDirAndWantsDir =
+ ( ( pDir->eAttrMask & FSYS_KIND_DIR ) &&
+#ifdef ICC
+ ( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") ||
+ strcmp(pDosEntry->d_name,"..")) ) );
+#else
+ ( pDosEntry->d_type & DOS_DIRECT ) );
+#endif
+ BOOL bIsFileAndWantsFile =
+ ( ( pDir->eAttrMask & FSYS_KIND_FILE ) &&
+#ifdef ICC
+ !( pDosEntry->d_type & ( strcmp(pDosEntry->d_name,".") ||
+ strcmp(pDosEntry->d_name,"..")) ) &&
+#else
+ !( pDosEntry->d_type & DOS_DIRECT ) &&
+#endif
+ !( pDosEntry->d_type & DOS_VOLUMEID ) );
+ BOOL bIsHidden = (pDosEntry->d_type & _A_HIDDEN) != 0;
+ BOOL bWantsHidden = 0 == ( pDir->eAttrMask & FSYS_KIND_VISIBLE );
+ if ( ( bIsDirAndWantsDir || bIsFileAndWantsFile ) &&
+ ( bWantsHidden || !bIsHidden ) &&
+ pDir->aNameMask.Matches( String(aLowerName, osl_getThreadTextEncoding()) ) )
+ {
+#ifdef DBG_UTIL
+ DbgOutf( "%s %s flags:%x found",
+ pDosEntry->d_name,
+ bIsFileAndWantsFile ? "file" : "dir",
+ pDosEntry->d_type );
+#endif
+ DirEntryFlag eFlag =
+ 0 == strcmp( pDosEntry->d_name, "." ) ? FSYS_FLAG_CURRENT
+ : 0 == strcmp( pDosEntry->d_name, ".." ) ? FSYS_FLAG_PARENT
+ : FSYS_FLAG_NORMAL;
+ DirEntry *pTemp = new DirEntry( ByteString(pDosEntry->d_name),
+ eFlag, FSYS_STYLE_NTFS );
+#ifdef FEAT_FSYS_DOUBLESPEED
+ pTemp->ImpSetStat( new FileStat( (void*) pDosDir, (void*) 0 ) );
+#endif
+ if ( pParent )
+ pTemp->ImpChangeParent( new DirEntry( *pParent ), FALSE );
+ if ( pDir->pStatLst ) //Status fuer Sort gewuenscht?
+ {
+ FileStat *pNewStat = new FileStat( (void*) pDosDir, (void*) 0 );
+ pDir->ImpSortedInsert( pTemp, pNewStat );
+ }
+ else
+ pDir->ImpSortedInsert( pTemp, NULL );
+ return 1;
+ }
+#ifdef DBG_UTIL
+ else
+ DbgOutf( "%s flags:%x skipped",
+ pDosEntry->d_name,
+ pDosEntry->d_type );
+#endif
+
+ }
+ else
+ bReady = TRUE;
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* InitFileStat()
+|*
+|* Beschreibung gemeinsamer Teil der Ctoren fuer FileStat
+|* Ersterstellung MI 28.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+void FileStat::ImpInit( void* p )
+{
+ _WIN32_FIND_DATAA *pDirEnt = (_WIN32_FIND_DATAA*) p;
+
+ nError = FSYS_ERR_OK;
+ nSize = pDirEnt->nFileSizeLow;
+
+ SYSTEMTIME aSysTime;
+ FILETIME aLocTime;
+
+ // use the last write date / time when the creation date / time isn't set
+ if ( ( pDirEnt->ftCreationTime.dwLowDateTime == 0 ) &&
+ ( pDirEnt->ftCreationTime.dwHighDateTime == 0 ) )
+ {
+ pDirEnt->ftCreationTime.dwLowDateTime = pDirEnt->ftLastWriteTime.dwLowDateTime;
+ pDirEnt->ftCreationTime.dwHighDateTime = pDirEnt->ftLastWriteTime.dwHighDateTime;
+ }
+
+ // use the last write date / time when the last accessed date / time isn't set
+ if ( ( pDirEnt->ftLastAccessTime.dwLowDateTime == 0 ) &&
+ ( pDirEnt->ftLastAccessTime.dwHighDateTime == 0 ) )
+ {
+ pDirEnt->ftLastAccessTime.dwLowDateTime = pDirEnt->ftLastWriteTime.dwLowDateTime;
+ pDirEnt->ftLastAccessTime.dwHighDateTime = pDirEnt->ftLastWriteTime.dwHighDateTime;
+ }
+
+ FileTimeToLocalFileTime( &pDirEnt->ftCreationTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateCreated = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeCreated = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ FileTimeToLocalFileTime( &pDirEnt->ftLastWriteTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateModified = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeModified = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ FileTimeToLocalFileTime( &pDirEnt->ftLastAccessTime, &aLocTime );
+ FileTimeToSystemTime( &aLocTime, &aSysTime );
+ aDateAccessed = Date( aSysTime.wDay, aSysTime.wMonth, aSysTime.wYear );
+ aTimeAccessed = Time( aSysTime.wHour, aSysTime.wMinute,
+ aSysTime.wSecond, 0 );
+
+ nKindFlags = FSYS_KIND_FILE;
+ if ( pDirEnt->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ nKindFlags = FSYS_KIND_DIR;
+}
+
+/*************************************************************************
+|*
+|* FileStat::FileStat()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+FileStat::FileStat( const void *pInfo, // struct dirent
+ const void * ): // dummy
+ aDateCreated(0),
+ aTimeCreated(0),
+ aDateModified(0),
+ aTimeModified(0),
+ aDateAccessed(0),
+ aTimeAccessed(0)
+{
+ ImpInit( ( (dirent*) pInfo ) );
+}
+
+/*************************************************************************
+|*
+|* FileStat::Update()
+|*
+|* Beschreibung FSYS.SDW
+|* Ersterstellung MI 27.08.92
+|* Letzte Aenderung MI 28.08.92
+|*
+*************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push, 1)
+#pragma warning(disable: 4917)
+#endif
+#include <shlobj.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#ifdef UNICODE
+#define lstrchr wcschr
+#define lstrncmp wcsncmp
+#else
+#define lstrchr strchr
+#define lstrncmp strncmp
+#endif
+
+//---------------------------------------------------------------------------
+
+void SHFreeMem( void *p )
+{
+ LPMALLOC pMalloc = NULL;
+
+ if ( SUCCEEDED(SHGetMalloc(&pMalloc)) )
+ {
+ pMalloc->Free( p );
+ pMalloc->Release();
+ }
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHGetIDListFromPath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl )
+{
+ if ( IsBadWritePtr(ppidl, sizeof(LPITEMIDLIST)) )
+ return E_INVALIDARG;
+
+ LPSHELLFOLDER pDesktopFolder = NULL;
+
+ HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder );
+ if ( FAILED(hResult) )
+ return hResult;
+
+ ULONG chEaten = lstrlen( pszPath );
+ DWORD dwAttributes = FILE_ATTRIBUTE_DIRECTORY;
+
+#ifdef UNICODE
+ LPOLESTR wszPath = pszPath;
+#else
+ WCHAR wszPath[MAX_PATH];
+ MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszPath, -1, wszPath, MAX_PATH );
+#endif
+
+ hResult = pDesktopFolder->ParseDisplayName( hwndOwner, (LPBC)NULL, wszPath, &chEaten, ppidl, &dwAttributes );
+ pDesktopFolder->Release();
+
+ return hResult;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHGetFolderFromIDList( LPCITEMIDLIST pidl, LPSHELLFOLDER *ppFolder )
+{
+ if ( IsBadWritePtr(ppFolder, sizeof(LPSHELLFOLDER)) )
+ return E_INVALIDARG;
+
+ *ppFolder = NULL;
+
+ LPSHELLFOLDER pDesktopFolder = NULL;
+
+ HRESULT hResult = SHGetDesktopFolder( &pDesktopFolder );
+ if ( FAILED(hResult) )
+ return hResult;
+
+ hResult = pDesktopFolder->BindToObject( pidl, (LPBC)NULL, IID_IShellFolder, (LPVOID *)ppFolder );
+ pDesktopFolder->Release();
+
+ return hResult;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT SHResolvePath( HWND hwndOwner, LPCTSTR pszPath, LPITEMIDLIST *ppidl )
+{
+ // If hwndOwner is NULL, use the desktop window, because dialogs need a parent
+
+#ifdef BOOTSTRAP
+ return NO_ERROR;
+#else
+ if ( !hwndOwner )
+ hwndOwner = GetDesktopWindow();
+
+ HRESULT hResult = NOERROR;
+ LPTSTR pszPathCopy;
+ LPTSTR pszTrailingPath;
+ TCHAR cBackup = 0;
+
+ // First make a copy of the path
+
+ pszPathCopy = new TCHAR[lstrlen(pszPath) + 1];
+ if ( pszPathCopy )
+ lstrcpy( pszPathCopy, pszPath );
+ else
+ return E_OUTOFMEMORY;
+
+ // Determine the first token
+
+ if ( !lstrncmp( pszPathCopy, "\\\\", 2 ) )
+ pszTrailingPath = lstrchr( pszPathCopy + 2, '\\' );
+ else
+ pszTrailingPath = lstrchr( pszPathCopy, '\\' );
+
+ // Now scan the path tokens
+
+ while ( SUCCEEDED(hResult) )
+ {
+ if ( pszTrailingPath )
+ {
+ cBackup = *(++pszTrailingPath);
+ *pszTrailingPath = 0;
+ }
+
+ LPITEMIDLIST pidl = NULL;
+
+ // Make item ID list from leading path
+
+ hResult = SHGetIDListFromPath( hwndOwner, pszPathCopy, &pidl );
+
+ // if path exists try to open it as folder
+
+ if ( SUCCEEDED(hResult) )
+ {
+ // Only open the folder if it was not the last token
+
+ if ( pszTrailingPath )
+ {
+ LPSHELLFOLDER pFolder;
+
+ // Create a folder instance
+ hResult = SHGetFolderFromIDList( pidl, &pFolder);
+
+ // Is it a folder ?
+ if ( SUCCEEDED(hResult) )
+ {
+ // No try to instantiate an enumerator.
+ // This should popup a login dialog if any
+
+ LPENUMIDLIST pEnum = NULL;
+
+ hResult = pFolder->EnumObjects( hwndOwner,
+ SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN,
+ &pEnum );
+
+ // Release the enumerator interface
+ if ( SUCCEEDED(hResult) )
+ pEnum->Release();
+
+ // Release the folder interface
+ pFolder->Release();
+ }
+
+ SHFreeMem( pidl );
+ }
+ else // It was the last token
+ {
+ if ( ppidl )
+ *ppidl = pidl;
+ else
+ SHFreeMem( pidl );
+ }
+ }
+
+
+ // Forward to next token
+
+ if ( pszTrailingPath )
+ {
+ *pszTrailingPath = cBackup;
+ pszTrailingPath = lstrchr( pszTrailingPath, '\\' );
+ }
+ else
+ break;
+ }
+
+ // Free the working copy of the path
+ delete pszPathCopy;
+
+ // NOERROR or OLE error code
+ return hResult;
+#endif
+}
+
+//---------------------------------------------------------------------------
+// The Wrapper
+//---------------------------------------------------------------------------
+
+BOOL Exists_Impl( const ByteString & crPath )
+{
+ // We do not know if OLE was initialized for this thread
+
+ CoInitialize( NULL );
+
+ BOOL bSuccess = SUCCEEDED( SHResolvePath(NULL, crPath.GetBuffer(), NULL) );
+
+ CoUninitialize();
+
+ return bSuccess;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL FileStat::Update( const DirEntry& rDirEntry, BOOL bForceAccess )
+{
+ nSize = 0;
+ nKindFlags = 0;
+ aCreator.Erase();
+ aType.Erase();
+ aDateCreated = Date(0);
+ aTimeCreated = Time(0);
+ aDateModified = Date(0);
+ aTimeModified = Time(0);
+ aDateAccessed = Date(0);
+ aTimeAccessed = Time(0);
+
+ if ( !rDirEntry.IsValid() )
+ {
+ nError = FSYS_ERR_UNKNOWN;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ // Sonderbehandlung falls es sich um eine Root ohne Laufwerk handelt
+
+ if ( !rDirEntry.aName.Len() && rDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ nKindFlags = FSYS_KIND_DIR;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ // keine Error-Boxen anzeigen
+ FSysFailOnErrorImpl();
+
+ // Redirect
+ String aPath( rDirEntry.GetFull() );
+#ifndef BOOTSTRAP
+ FSysRedirector::DoRedirect( aPath );
+#endif
+ DirEntry aDirEntry( aPath );
+
+ // ist ein Medium im Laufwerk?
+ HACK("wie?")
+ BOOL bAccess = TRUE;
+ const DirEntry *pTop = aDirEntry.ImpGetTopPtr();
+ ByteString aName = ByteString(pTop->aName).ToLowerAscii();
+ if ( !bForceAccess &&
+ ( pTop->eFlag == FSYS_FLAG_ABSROOT ||
+ pTop->eFlag == FSYS_FLAG_RELROOT ||
+ pTop->eFlag == FSYS_FLAG_VOLUME ) )
+ if ( aName == "a:" || aName == "b:" )
+ bAccess = FALSE;
+ else
+ DBG_TRACE( "FSys: will access removable device!" );
+ if ( bAccess && ( aName == "a:" || aName == "b:" ) ) {
+ DBG_WARNING( "floppy will clatter" );
+ }
+
+ // Sonderbehandlung, falls es sich um ein Volume handelt
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME ||
+ aDirEntry.eFlag == FSYS_FLAG_ABSROOT )
+ {
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = FSYS_KIND_DEV | ( aDirEntry.aName.Len() == 2
+ ? FSYS_KIND_BLOCK
+ : FSYS_KIND_CHAR );
+ else
+ nKindFlags = FSYS_KIND_DIR;
+
+ if ( !bAccess )
+ {
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags |= FSYS_KIND_REMOVEABLE;
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ ByteString aRootDir = aDirEntry.aName;
+ aRootDir += ByteString( "\\" );
+ UINT nType = GetDriveType( (char *) aRootDir.GetBuffer() ); //TPF: 2i
+ if ( nType == 1 || nType == 0 )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = 0;
+ return FALSE;
+ }
+
+ if ( aDirEntry.eFlag == FSYS_FLAG_VOLUME )
+ nKindFlags = nKindFlags |
+ ( ( nType == DRIVE_REMOVABLE ) ? FSYS_KIND_REMOVEABLE : 0 ) |
+ ( ( nType == DRIVE_FIXED ) ? FSYS_KIND_FIXED : 0 ) |
+ ( ( nType == DRIVE_REMOTE ) ? FSYS_KIND_REMOTE : 0 ) |
+ ( ( nType == DRIVE_RAMDISK ) ? FSYS_KIND_RAM : 0 ) |
+ ( ( nType == DRIVE_CDROM ) ? FSYS_KIND_CDROM : 0 ) |
+ ( ( nType == 0 ) ? FSYS_KIND_UNKNOWN : 0 );
+
+ nError = ERRCODE_NONE;
+
+ return TRUE;
+ }
+
+ // Statusinformation vom Betriebssystem holen
+ HANDLE h; //()
+ _WIN32_FIND_DATAA aEntry = {};
+ DirEntry aAbsEntry( aDirEntry );
+ if ( bAccess && aAbsEntry.ToAbs() )
+ {
+ // im Namen k"onnen auch ';*?' als normale Zeichen vorkommen
+ ByteString aFilePath( aAbsEntry.GetFull(), osl_getThreadTextEncoding() );
+
+ // MI: dann gehen Umlaute auf Novell-Servern nicht / wozu ueberhaupt
+ // CharUpperBuff( (char*) aFilePath.GetStr(), aFilePath.Len() );
+ DBG_TRACE1( "FileStat: %s", aFilePath.GetBuffer() );
+ h = aFilePath.Len() < 230
+ // die Win32-API ist hier sehr schwammig
+ ? FindFirstFile( (char *) aFilePath.GetBuffer(), &aEntry )//TPF: 2i
+ : INVALID_HANDLE_VALUE;
+
+ if ( INVALID_HANDLE_VALUE != h )
+ {
+ if ( !( aEntry.dwFileAttributes & 0x40 ) ) // com1: etc. e.g. not encrypted (means normal)
+ {
+ ByteString aUpperName = Upper_Impl(ByteString(aAbsEntry.GetName(), osl_getThreadTextEncoding()));
+
+ // HRO: #74051# Compare also with short alternate filename
+ if ( aUpperName != Upper_Impl( aEntry.cFileName ) && aUpperName != Upper_Impl( aEntry.cAlternateFileName ) )
+ h = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ if ( INVALID_HANDLE_VALUE == h )
+ {
+ DWORD dwError = GetLastError();
+
+ if ( ERROR_BAD_NET_NAME == dwError )
+ {
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+
+ // UNC-Volume?
+ DirEntry *pTop = aAbsEntry.ImpGetTopPtr();
+ if ( pTop->GetFlag() == FSYS_FLAG_ABSROOT &&
+ ( pTop->aName.Len() > 1 && (pTop->aName.GetBuffer()[1] != ':' )) )
+ {
+ if ( bForceAccess )
+ {
+ if ( Exists_Impl( aFilePath ) )
+ {
+ nKindFlags = FSYS_KIND_DIR|FSYS_KIND_REMOTE;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+ else
+ {
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ nError = FSYS_ERR_NOTEXISTS;
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+ else
+ h = INVALID_HANDLE_VALUE;
+
+ if ( h == INVALID_HANDLE_VALUE )
+ {
+ // Sonderbehandlung falls es sich um eine Wildcard handelt
+ ByteString aTempName( aDirEntry.GetName(), osl_getThreadTextEncoding() );
+ if ( strchr( aTempName.GetBuffer(), '?' ) ||
+ strchr( aTempName.GetBuffer(), '*' ) ||
+ strchr( aTempName.GetBuffer(), ';' ) )
+ {
+ nKindFlags = FSYS_KIND_WILD;
+ nError = FSYS_ERR_OK;
+ return TRUE;
+ }
+
+ if ( bAccess )
+ {
+ nError = FSYS_ERR_NOTEXISTS;
+ nKindFlags = FSYS_KIND_UNKNOWN;
+ }
+ else
+ nKindFlags = FSYS_KIND_REMOVEABLE;
+ }
+ else
+ {
+ ImpInit( &aEntry );
+ FindClose( h );
+ }
+
+ if ( 0 != nError )
+ nKindFlags = 0;
+
+ return 0 == nError;
+
+}
+
+BOOL IsRedirectable_Impl( const ByteString &rPath )
+{
+ if ( rPath.Len() >= 3 && ':' == rPath.GetBuffer()[1] )
+ {
+ ByteString aVolume = rPath.Copy( 0, 3 );
+ UINT nType = GetDriveType( (char *) aVolume.GetBuffer() );
+ SetLastError( ERROR_SUCCESS );
+ return DRIVE_FIXED != nType;
+ }
+ return FALSE;
+}
+
+/*************************************************************************
+|*
+|* TempDirImpl()
+|*
+|* Beschreibung liefert den Namens des Directories fuer temporaere
+|* Dateien
+|* Ersterstellung MI 16.03.94
+|* Letzte Aenderung MI 16.03.94
+|*
+*************************************************************************/
+
+const char* TempDirImpl( char *pBuf )
+{
+ if ( !GetTempPath( MAX_PATH, pBuf ) &&
+ !GetWindowsDirectory( pBuf, MAX_PATH ) &&
+ !GetEnvironmentVariable( "HOMEPATH", pBuf, MAX_PATH ) )
+ return 0;
+
+ return pBuf;
+}
+
+//=======================================================================
+
+ErrCode FileStat::QueryDiskSpace( const String &rPath,
+ BigInt &rFreeBytes, BigInt &rTotalBytes )
+{
+ DWORD nSectorsPerCluster; /* address of sectors per cluster */
+ DWORD nBytesPerSector; /* address of bytes per sector */
+ DWORD nFreeClusters; /* address of number of free clusters */
+ DWORD nClusters; /* address of total number of clusters */
+
+ ByteString aVol( DirEntry(rPath).ImpGetTopPtr()->GetName(), osl_getThreadTextEncoding());
+ bool bOK = GetDiskFreeSpace( aVol.GetBuffer(),
+ &nSectorsPerCluster, &nBytesPerSector,
+ &nFreeClusters, &nClusters );
+ if ( !bOK )
+ return Sys2SolarError_Impl( GetLastError() );
+
+ BigInt aBytesPerCluster( BigInt(nSectorsPerCluster) *
+ BigInt(nBytesPerSector) );
+ rFreeBytes = aBytesPerCluster * BigInt(nFreeClusters);
+ rTotalBytes = aBytesPerCluster * BigInt(nClusters);
+ return 0;
+}
+
+//=========================================================================
+
+void FSysEnableSysErrorBox( BOOL bEnable )
+{ // Preserve other Bits!!
+ sal_uInt32 nErrorMode = SetErrorMode( bEnable ? 0 : SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX );
+ if ( bEnable )
+ nErrorMode &= ~(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ else
+ nErrorMode |= (SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ SetErrorMode( nErrorMode );
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/fsys/wntmsc.hxx b/tools/source/fsys/wntmsc.hxx
new file mode 100644
index 000000000000..b4226a70ec08
--- /dev/null
+++ b/tools/source/fsys/wntmsc.hxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _dosmsc_hxx
+#define _dosmsc_hxx
+
+#include <string.h>
+
+#ifndef ICC
+#include <io.h>
+#endif
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <direct.h>
+
+#include <tools/svwin.h>
+#ifdef _MSC_VER
+#pragma warning (push,1)
+#endif
+#include <winbase.h>
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+#include <tools/solar.h>
+
+#include <tools/string.hxx>
+
+//--------------------------------------------------------------------
+
+#define FSYS_UNIX FALSE
+
+#define DOS_DIRECT _A_SUBDIR
+#define DOS_VOLUMEID 0x08
+#ifndef S_IFBLK
+#define S_IFBLK 0x6000
+#endif
+#define setdrive(n,a) _chdrive(n)
+#define GETDRIVE(n) (n = _getdrive())
+
+#define dirent _WIN32_FIND_DATAA
+#define d_name cFileName
+#define d_type dwFileAttributes
+
+#if defined (TCPP) || defined (tcpp)
+#define _mkdir mkdir
+#define _rmdir rmdir
+#define _chdir chdir
+#define _unlink unlink
+#define _getcwd getcwd
+#define _access access
+#endif
+
+typedef struct
+{
+ _WIN32_FIND_DATAA aDirEnt;
+ HANDLE h;
+ const char *p;
+} DIR;
+
+#define PATHDELIMITER ";"
+#define DEFSTYLE FSYS_STYLE_NTFS
+#define MKDIR( p ) mkdir( p )
+#define CMP_LOWER(s) ( ByteString(s).ToLowerAscii() )
+
+#define START_DRV 'a'
+
+inline BOOL DRIVE_EXISTS(char c)
+{
+ ByteString aDriveRoot( c );
+ aDriveRoot += ":\\";
+ return GetDriveType( aDriveRoot.GetBuffer() ) > 1;
+}
+
+const char* TempDirImpl( char *pBuf );
+
+#define FSysFailOnErrorImpl()
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */