nsFileSpec.cpp revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsFileSpec.h"
#include "nsDebug.h"
#include "nsEscape.h"
#include "nsMemory.h"
#include "prtypes.h"
#include "plstr.h"
#include "plbase64.h"
#include "prmem.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsILocalFile.h"
#include <string.h>
#include <stdio.h>
#if defined(XP_WIN)
#include <mbstring.h>
#endif
#ifdef XP_OS2
extern unsigned char* _mbsrchr( const unsigned char*, int);
#endif
// return pointer to last instance of the given separator
{
#else
#endif
}
#if defined(XP_MACOSX)
#endif
#include <Aliases.h>
#include <TextUtils.h>
#endif
//========================================================================================
// class nsSimpleCharString
//========================================================================================
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (inString)
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = inString;
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
AddRefData();
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
ReleaseData();
} // nsSimpleCharString::nsSimpleCharString
//----------------------------------------------------------------------------------------
void nsSimpleCharString::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
if (inString)
else
SetToEmpty();
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (!mData)
return;
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return;
ReleaseData();
AddRefData();
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
void nsSimpleCharString::operator += (const char* inOther)
//----------------------------------------------------------------------------------------
{
if (!inOther)
return;
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
nsSimpleCharString result(*this);
return result;
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (!inString2)
{
*this += inString1;
return;
}
} // nsSimpleCharString::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (!inData)
return;
if (!mData)
return;
if (inLength != 0) {
}
} // nsSimpleCharString::CopyFrom
//----------------------------------------------------------------------------------------
void nsSimpleCharString::SetToEmpty()
//----------------------------------------------------------------------------------------
{
ReleaseData();
} // nsSimpleCharString::SetToEmpty
//----------------------------------------------------------------------------------------
void nsSimpleCharString::Unescape()
//----------------------------------------------------------------------------------------
{
if (!mData)
return;
if (!mData)
return;
} // nsSimpleCharString::Unescape
//----------------------------------------------------------------------------------------
void nsSimpleCharString::AddRefData()
//----------------------------------------------------------------------------------------
{
if (mData)
} // nsSimpleCharString::AddRefData
//----------------------------------------------------------------------------------------
void nsSimpleCharString::ReleaseData()
//----------------------------------------------------------------------------------------
{
if (!mData)
return;
} // nsSimpleCharString::ReleaseData
//----------------------------------------------------------------------------------------
// Round up to the next multiple of 256.
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
// Reallocate mData to a new length. Since this presumably precedes a change to the string,
// we want to detach ourselves if the data is shared by another string, even if the length
// requested would not otherwise require a reallocation.
//----------------------------------------------------------------------------------------
{
if (mData)
{
{
// We are the sole owner, so just change its length, if necessary.
if (newAllocLength > oldAllocLength)
return;
}
}
if (inLength < copyLength)
// If data was already allocated when we get to here, then we are cloning the data
// from a shared pointer.
if (mData)
{
}
else
} // nsSimpleCharString::ReleaseData
//========================================================================================
//========================================================================================
{
enum
, kMaxAltDigitLength = 5
};
#if !defined(XP_MAC)
#endif
#endif
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return nativeErr ?
: NS_OK;
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// Find the existing leaf name
if (IsEmpty())
return;
if (!inLeafName)
{
SetToEmpty();
return;
}
if (trailingSeparator)
{
char savedCh = *lastSeparator;
char *savedLastSeparator = lastSeparator;
*lastSeparator = '\0';
}
if (lastSeparator)
lastSeparator++; // point at the trailing string
else
int newLength =
if (trailingSeparator)
{
// If the original ended in a slash, then the new one should, too.
*sepStr = inSeparator;
}
} // nsSimpleCharString::LeafReplace
//----------------------------------------------------------------------------------------
// Returns a pointer to an allocated string representing the leaf.
//----------------------------------------------------------------------------------------
{
if (IsEmpty())
return nsnull;
// If there was no separator, then return a copy of our path.
if (!lastSeparator)
// So there's at least one separator. What's just after it?
// If the separator was not the last character, return the trailing string.
if (*leafPointer)
// So now, separator was the last character. Poke in a null instead.
// Restore the poked null before returning.
*(char*)lastSeparator = inSeparator;
// If it's a drive letter use the colon notation.
#endif
return result;
} // nsSimpleCharString::GetLeaf
#if 0
#pragma mark -
#endif
//----------------------------------------------------------------------------------------
// Make the path a valid one by creating all the intermediate directories. Does NOT
// make the leaf into a directory. This should be a unix path.
//----------------------------------------------------------------------------------------
{
if (!inPath)
return;
if (!pathCopy)
return;
const int kSkipFirst = 1;
// Either this is a relative path, or we ensure that it has
// a drive letter specifier.
"Not a UNC path and no drive letter!" );
#endif
char* currentStart = pathCopy;
if (currentEnd)
{
*currentEnd = '\0';
/*
if we have a drive letter path, we must make sure that the inital path has a '/' on it, or
Canonify will turn "/c|" into a path relative to the running executable.
*/
{
}
else
{
// move after server name and share name in UNC path
if (pathCopy[0] == '/' &&
{
*currentEnd = '/';
if (currentEnd)
*currentEnd = '\0';
}
}
#else
#endif
do
{
// If the node doesn't exist, and it is not the initial node in a full path,
// then make a directory (We cannot make the initial (volume) node).
currentStart = ++currentEnd;
if (!currentEnd)
break;
*currentEnd = '\0';
} while (currentEnd);
}
} // nsFileSpecHelpers::MakeAllDirectories
#endif // XP_UNIX || XP_WIN || XP_OS2 || XP_BEOS
#if 0
#pragma mark -
#endif
#if defined(XP_WIN)
#include "nsFileSpecWin.cpp" // Windows-specific implementations
//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
// we include the .cpp file in the project now.
#include "nsFileSpecBeOS.cpp" // BeOS-specific implementations
#include "nsFileSpecUnix.cpp" // Unix-specific implementations
#include "nsFileSpecOS2.cpp" // OS/2-specific implementations
#endif
//========================================================================================
// nsFileURL implementation
//========================================================================================
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (!inString)
return;
// Make canonical and absolute. Since it's a parameter to this constructor,
// inString is escaped. We want to make an nsFilePath, which requires
// an unescaped string.
*this = path;
} // nsFileURL::nsFileURL
#endif
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return;
"Not a URL!");
// Make canonical and absolute. Since it's a parameter to this constructor,
// inString is escaped. We want to make an nsFilePath, which requires
// an unescaped string.
*this = path;
} // nsFileURL::nsFileURL
#endif
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
#if defined(XP_MAC)
#endif
{
} // nsFileURL::nsFileURL
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = inOther;
} // nsFileURL::nsFileURL
#endif
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = inOther;
} // nsFileURL::nsFileURL
#endif
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// XXX is this called by nsFileSpecImpl.cpp::SetURLString?
// if so, there's a bug...
} // nsFileURL::operator =
#endif
//----------------------------------------------------------------------------------------
void nsFileURL::operator +=(const char* inRelativeUnixPath)
//----------------------------------------------------------------------------------------
{
mURL += escapedPath;
#if defined(XP_MAC)
#endif
} // nsFileURL::operator +=
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return result;
} // nsFileURL::operator +
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
#if defined(XP_MAC)
#endif
} // nsFileURL::operator =
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// because we don't want to escape the '|' character, change it to a letter.
// Note that a UNC path will not have a '|' character.
#else
#endif
if (escapedPath)
mURL += escapedPath;
} // nsFileURL::operator =
#endif
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = nsFilePath(inOther);
mURL += "/";
} // nsFileURL::operator =
#endif
#if 0
#pragma mark -
#endif
//========================================================================================
// nsFilePath implementation
//========================================================================================
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
#if defined(XP_MAC)
#endif
{
}
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return;
#endif
// Make canonical and absolute.
// Assert native path is of one of these forms:
// - regular: X:\some\path
// - UNC: \\some_machine\some\path
"unexpected canonical path" );
#endif
}
#endif
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return;
NS_ASSERTION(strstr((const char*)mPath, kFileURLPrefix) != (const char*)mPath, "URL passed as path");
#endif
// Make canonical and absolute.
"unexpected canonical path" );
#endif
}
#endif
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
#endif
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
#endif // XP_UNIX
//----------------------------------------------------------------------------------------
nsFilePath::~nsFilePath()
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// XXX bug here, again if.
}
#endif // XP_UNIX
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
return;
#endif
// Make canonical and absolute.
#endif
}
#endif // XP_MAC
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
#endif
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
#if defined(XP_MAC)
#endif
}
//----------------------------------------------------------------------------------------
void nsFilePath::operator +=(const char* inRelativeUnixPath)
//----------------------------------------------------------------------------------------
{
mPath += escapedPath;
#if defined(XP_MAC)
#endif
} // nsFilePath::operator +=
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
nsFilePath resultPath(*this);
return resultPath;
} // nsFilePath::operator +
#if 0
#pragma mark -
#endif
//========================================================================================
// nsFileSpec implementation
//========================================================================================
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
}
//----------------------------------------------------------------------------------------
void nsFileSpec::Clear()
//----------------------------------------------------------------------------------------
{
mPath.SetToEmpty();
}
#endif
//----------------------------------------------------------------------------------------
nsFileSpec::~nsFileSpec()
//----------------------------------------------------------------------------------------
{
// mPath cleans itself up
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = inDescriptor;
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName && *inSuggestedLeafName)
MakeUnique();
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsFileSpec::MakeUnique()
//----------------------------------------------------------------------------------------
{
if (!Exists())
return;
char* leafName = GetLeafName();
if (!leafName)
return;
char* suffix = "";
if (lastDot)
{
}
const int kMaxRootLength
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
}
if (*suffix)
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// Decode descriptor into a Handle (which is actually an AliasHandle)
return; // not enough memory?
#endif
#if defined(XP_MAC)
mPath.SetToEmpty();
::DisposeHandle(aliasH);
return;
#else
#endif
}
//========================================================================================
// UNIX & WIN nsFileSpec implementation
//========================================================================================
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
#endif //XP_UNIX
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
// Make canonical and absolute.
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
// Make canonical and absolute.
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
void nsFileSpec::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
// Make canonical and absolute.
}
#endif //XP_UNIX,XP_WIN,XP_OS2,XP_BEOS
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
nsFileSpec resultSpec = *this;
return resultSpec;
} // nsFileSpec::operator +
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
#if defined(XP_MAC)
return PR_TRUE;
#else
if (amEmpty) // we're the same if he's empty...
return heEmpty;
if (heEmpty) // ('cuz I'm not...)
return PR_FALSE;
// Length() is size of buffer, not length of string
/* windows does not care about case. */
#ifdef XP_OS2
#define DIR_STRCMP strcmp
#else
#define DIR_STRCMP _stricmp
#endif
#else
#define DIR_SEPARATOR '/'
#if defined(VMS)
#define DIR_STRCMP strcasecmp
#else
#define DIR_STRCMP strcmp
#endif
#endif
return PR_TRUE;
#endif
return PR_FALSE;
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
return (! (*this == inOther) );
}
#if !defined(XP_MAC)
//----------------------------------------------------------------------------------------
// This is the only automatic conversion to const char*
// that is provided, and it allows the
// path to be "passed" to NSPR file routines. This practice
// is VERY EVIL and should only be used to support legacy
// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do
// not even think of deleting (or freeing) it.
const char* nsFileSpec::GetCString() const
//----------------------------------------------------------------------------------------
{
return mPath;
}
#endif
//----------------------------------------------------------------------------------------
// Is our spec a child of the provided parent?
//----------------------------------------------------------------------------------------
{
#ifdef DEBUG
int depth = 0;
#endif
while (1) {
#ifdef DEBUG
// sanity
if (depth > 100)
return PR_FALSE;
#endif
if (iter == possibleParent)
return PR_TRUE;
return PR_FALSE;
return PR_FALSE;
#ifdef DEBUG
depth++;
#endif
}
// not reached, but I bet some compiler will whine
return PR_FALSE;
}
#if 0
#pragma mark -
#endif
//========================================================================================
// class nsPersistentFileDescriptor
//========================================================================================
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
*this = inSpec;
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
#if defined(XP_MAC)
return;
return;
return;
return;
return;
#else
#endif // XP_MAC
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
{
}
//========================================================================================
// class nsNSPRPath
//========================================================================================
//----------------------------------------------------------------------------------------
nsNSPRPath::operator const char*() const
// NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR
// cannot be changed, so we have to do the dirty work.
//----------------------------------------------------------------------------------------
{
if (!modifiedNSPRPath)
{
// If this is the first call, initialize modifiedNSPRPath. Start by cloning
// mFilePath, but strip the leading separator, if present
if (!unixPath)
return nsnull;
((nsNSPRPath*)this)->modifiedNSPRPath
// Replace the bar
// Remove the ending separator only if it is not the last separator
}
return modifiedNSPRPath;
#else
return (const char*)mFilePath;
#endif
}
//----------------------------------------------------------------------------------------
nsNSPRPath::~nsNSPRPath()
//----------------------------------------------------------------------------------------
{
if (modifiedNSPRPath)
#endif
}
{
if (!file) return NS_ERROR_FAILURE;
#if defined(XP_MAC)
{
}
#else
// XP_MACOSX: do this for OS X to preserve long filenames
#endif
return NS_OK;
}