зеркало из https://github.com/mozilla/gecko-dev.git
1446 строки
51 KiB
C++
1446 строки
51 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* 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 Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#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"
|
|
#define NS_IMPL_IDS
|
|
#ifndef XPCOM_STANDALONE
|
|
#include "nsIPlatformCharset.h"
|
|
#include "nsICharsetConverterManager.h"
|
|
#include "nsIUnicodeDecoder.h"
|
|
#endif /* XPCOM_STANDALONE */
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
#include <mbstring.h>
|
|
#endif
|
|
|
|
#ifdef XP_MAC
|
|
#include <Aliases.h>
|
|
#include <TextUtils.h>
|
|
#endif
|
|
|
|
//========================================================================================
|
|
// class nsSimpleCharString
|
|
//========================================================================================
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::nsSimpleCharString()
|
|
//----------------------------------------------------------------------------------------
|
|
: mData(nsnull)
|
|
{
|
|
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::nsSimpleCharString(const char* inString)
|
|
//----------------------------------------------------------------------------------------
|
|
: mData(nsnull)
|
|
{
|
|
if (inString)
|
|
CopyFrom(inString, nsCRT::strlen(inString));
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::nsSimpleCharString(const nsString& inString)
|
|
//----------------------------------------------------------------------------------------
|
|
: mData(nsnull)
|
|
{
|
|
*this = inString;
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::nsSimpleCharString(const nsSimpleCharString& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mData = inOther.mData;
|
|
AddRefData();
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::nsSimpleCharString(const char* inData, PRUint32 inLength)
|
|
//----------------------------------------------------------------------------------------
|
|
: mData(nsnull)
|
|
{
|
|
CopyFrom(inData, inLength);
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString::~nsSimpleCharString()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
ReleaseData();
|
|
} // nsSimpleCharString::nsSimpleCharString
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::operator = (const char* inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (inString)
|
|
CopyFrom(inString, nsCRT::strlen(inString));
|
|
else
|
|
SetToEmpty();
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::operator = (const nsString& inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
PRUint32 len = inString.Length();
|
|
ReallocData(len);
|
|
if (!mData)
|
|
return;
|
|
inString.ToCString(mData->mString, len + 1);
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::operator = (const nsSimpleCharString& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (mData == inOther.mData)
|
|
return;
|
|
ReleaseData();
|
|
mData = inOther.mData;
|
|
AddRefData();
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::operator += (const char* inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!inOther)
|
|
return;
|
|
int newLength = Length() + nsCRT::strlen(inOther);
|
|
ReallocData(newLength);
|
|
strcat(mData->mString, inOther);
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsSimpleCharString nsSimpleCharString::operator + (const char* inOther) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
nsSimpleCharString result(*this);
|
|
result += inOther;
|
|
return result;
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::Catenate(const char* inString1, const char* inString2)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!inString2)
|
|
{
|
|
*this += inString1;
|
|
return;
|
|
}
|
|
int newLength = Length() + nsCRT::strlen(inString1) + nsCRT::strlen(inString2);
|
|
ReallocData(newLength);
|
|
strcat(mData->mString, inString1);
|
|
strcat(mData->mString, inString2);
|
|
} // nsSimpleCharString::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::CopyFrom(const char* inData, PRUint32 inLength)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!inData)
|
|
return;
|
|
ReallocData(inLength);
|
|
if (!mData)
|
|
return;
|
|
nsCRT::memcpy(mData->mString, inData, inLength);
|
|
mData->mString[inLength] = '\0';
|
|
} // nsSimpleCharString::CopyFrom
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::SetToEmpty()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
ReleaseData();
|
|
} // nsSimpleCharString::SetToEmpty
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::Unescape()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!mData)
|
|
return;
|
|
ReallocData(mData->mLength);
|
|
if (!mData)
|
|
return;
|
|
nsUnescape(mData->mString);
|
|
mData->mLength = nsCRT::strlen(mData->mString);
|
|
} // nsSimpleCharString::Unescape
|
|
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::AddRefData()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (mData)
|
|
++mData->mRefCount;
|
|
} // nsSimpleCharString::AddRefData
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::ReleaseData()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!mData)
|
|
return;
|
|
NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
|
|
if (--mData->mRefCount == 0)
|
|
PR_Free(mData);
|
|
mData = nsnull;
|
|
} // nsSimpleCharString::ReleaseData
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
inline PRUint32 CalculateAllocLength(PRUint32 logicalLength)
|
|
// Round up to the next multiple of 256.
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
return ((1 + (logicalLength >> 8)) << 8);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::ReallocData(PRUint32 inLength)
|
|
// 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.
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
PRUint32 newAllocLength = CalculateAllocLength(inLength);
|
|
PRUint32 oldAllocLength = CalculateAllocLength(Length());
|
|
if (mData)
|
|
{
|
|
NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
|
|
if (mData->mRefCount == 1)
|
|
{
|
|
// We are the sole owner, so just change its length, if necessary.
|
|
if (newAllocLength > oldAllocLength)
|
|
mData = (Data*)PR_Realloc(mData, newAllocLength + sizeof(Data));
|
|
mData->mLength = inLength;
|
|
mData->mString[inLength] = '\0'; // we may be truncating
|
|
return;
|
|
}
|
|
}
|
|
PRUint32 copyLength = Length();
|
|
if (inLength < copyLength)
|
|
copyLength = inLength;
|
|
Data* newData = (Data*)PR_Malloc(newAllocLength + sizeof(Data));
|
|
// If data was already allocated when we get to here, then we are cloning the data
|
|
// from a shared pointer.
|
|
if (mData)
|
|
{
|
|
nsCRT::memcpy(newData, mData, sizeof(Data) + copyLength);
|
|
mData->mRefCount--; // Say goodbye
|
|
}
|
|
else
|
|
newData->mString[0] = '\0';
|
|
|
|
mData = newData;
|
|
mData->mRefCount = 1;
|
|
mData->mLength = inLength;
|
|
} // nsSimpleCharString::ReleaseData
|
|
|
|
|
|
//========================================================================================
|
|
NS_NAMESPACE nsFileSpecHelpers
|
|
//========================================================================================
|
|
{
|
|
enum
|
|
{ kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
|
|
, kMaxAltDigitLength = 5
|
|
, kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
|
|
};
|
|
#ifndef XP_MAC
|
|
NS_NAMESPACE_PROTOTYPE void Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs);
|
|
NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
|
|
#endif
|
|
#ifdef XP_PC
|
|
NS_NAMESPACE_PROTOTYPE void NativeToUnix(nsSimpleCharString& ioPath);
|
|
NS_NAMESPACE_PROTOTYPE void UnixToNative(nsSimpleCharString& ioPath);
|
|
#endif
|
|
} NS_NAMESPACE_END
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsresult ns_file_convert_result(PRInt32 nativeErr)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
return nativeErr ?
|
|
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
|
|
: NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsSimpleCharString::LeafReplace(char inSeparator, const char* inLeafName)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
// Find the existing leaf name
|
|
if (IsEmpty())
|
|
return;
|
|
if (!inLeafName)
|
|
{
|
|
SetToEmpty();
|
|
return;
|
|
}
|
|
char* chars = mData->mString;
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
// XXX OS/2 should use strrchr() of DBCS verison, too
|
|
char* lastSeparator = (char*) _mbsrchr((const unsigned char*) chars, inSeparator);
|
|
#else
|
|
char* lastSeparator = strrchr(chars, inSeparator);
|
|
#endif
|
|
int oldLength = Length();
|
|
PRBool trailingSeparator = (lastSeparator + 1 == chars + oldLength);
|
|
if (trailingSeparator)
|
|
{
|
|
char savedCh = *lastSeparator;
|
|
char *savedLastSeparator = lastSeparator;
|
|
*lastSeparator = '\0';
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
// XXX OS/2 should use strrchr() of DBCS verison, too
|
|
lastSeparator = (char*) _mbsrchr((const unsigned char*) chars, inSeparator);
|
|
#else
|
|
lastSeparator = strrchr(chars, inSeparator);
|
|
#endif
|
|
*savedLastSeparator = savedCh;
|
|
}
|
|
if (lastSeparator)
|
|
lastSeparator++; // point at the trailing string
|
|
else
|
|
lastSeparator = chars; // the full monty
|
|
|
|
PRUint32 savedLastSeparatorOffset = (lastSeparator - chars);
|
|
int newLength =
|
|
(lastSeparator - chars) + nsCRT::strlen(inLeafName) + (trailingSeparator != 0);
|
|
ReallocData(newLength);
|
|
|
|
chars = mData->mString; // it might have moved.
|
|
chars[savedLastSeparatorOffset] = '\0'; // strip the current leaf name
|
|
|
|
strcat(chars, inLeafName);
|
|
if (trailingSeparator)
|
|
{
|
|
// If the original ended in a slash, then the new one should, too.
|
|
char sepStr[2] = "/";
|
|
*sepStr = inSeparator;
|
|
strcat(chars, sepStr);
|
|
}
|
|
} // nsSimpleCharString::LeafReplace
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
char* nsSimpleCharString::GetLeaf(char inSeparator) const
|
|
// Returns a pointer to an allocated string representing the leaf.
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (IsEmpty())
|
|
return nsnull;
|
|
|
|
char* chars = mData->mString;
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
const char* lastSeparator = (const char*) _mbsrchr((const unsigned char *) chars, inSeparator);
|
|
#else
|
|
const char* lastSeparator = strrchr(chars, inSeparator);
|
|
#endif
|
|
// If there was no separator, then return a copy of our path.
|
|
if (!lastSeparator)
|
|
return nsCRT::strdup(*this);
|
|
|
|
// So there's at least one separator. What's just after it?
|
|
// If the separator was not the last character, return the trailing string.
|
|
const char* leafPointer = lastSeparator + 1;
|
|
if (*leafPointer)
|
|
return nsCRT::strdup(leafPointer);
|
|
|
|
// So now, separator was the last character. Poke in a null instead.
|
|
*(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
leafPointer = (const char*) _mbsrchr((const unsigned char *) chars, inSeparator);
|
|
#else
|
|
leafPointer = strrchr(chars, inSeparator);
|
|
#endif
|
|
char* result = leafPointer ? nsCRT::strdup(++leafPointer) : nsCRT::strdup(chars);
|
|
// Restore the poked null before returning.
|
|
*(char*)lastSeparator = inSeparator;
|
|
#ifdef XP_PC
|
|
// If it's a drive letter use the colon notation.
|
|
if (!leafPointer && result[2] == 0 && result[1] == '|')
|
|
result[1] = ':';
|
|
#endif
|
|
return result;
|
|
} // nsSimpleCharString::GetLeaf
|
|
|
|
|
|
#ifdef XP_MAC
|
|
#pragma mark -
|
|
#endif
|
|
|
|
#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
|
|
// 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;
|
|
|
|
char* pathCopy = nsCRT::strdup( inPath );
|
|
if (!pathCopy)
|
|
return;
|
|
|
|
const char kSeparator = '/'; // I repeat: this should be a unix-style path.
|
|
const int kSkipFirst = 1;
|
|
|
|
#ifdef XP_PC
|
|
// Either this is a relative path, or we ensure that it has
|
|
// a drive letter specifier.
|
|
NS_ASSERTION( pathCopy[0] != '/' || pathCopy[2] == '|', "No drive letter!" );
|
|
#endif
|
|
char* currentStart = pathCopy;
|
|
char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
|
|
if (currentEnd)
|
|
{
|
|
nsFileSpec spec;
|
|
*currentEnd = '\0';
|
|
|
|
#ifdef XP_PC
|
|
/*
|
|
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.
|
|
*/
|
|
if (pathCopy[0] == '/' && pathCopy[2] == '|')
|
|
{
|
|
char* startDir = (char*)PR_Malloc(nsCRT::strlen(pathCopy) + 2);
|
|
strcpy(startDir, pathCopy);
|
|
strcat(startDir, "/");
|
|
|
|
spec = nsFilePath(startDir, PR_FALSE);
|
|
|
|
PR_Free(startDir);
|
|
}
|
|
else
|
|
{
|
|
spec = nsFilePath(pathCopy, PR_FALSE);
|
|
|
|
}
|
|
#else
|
|
spec = nsFilePath(pathCopy, PR_FALSE);
|
|
#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).
|
|
if (!spec.Exists() && *currentStart != kSeparator)
|
|
spec.CreateDirectory(mode);
|
|
|
|
currentStart = ++currentEnd;
|
|
currentEnd = strchr(currentStart, kSeparator);
|
|
if (!currentEnd)
|
|
break;
|
|
|
|
*currentEnd = '\0';
|
|
|
|
spec += currentStart; // "lengthen" the path, adding the next node.
|
|
} while (currentEnd);
|
|
}
|
|
nsCRT::free(pathCopy);
|
|
} // nsFileSpecHelpers::MakeAllDirectories
|
|
|
|
#endif // XP_PC || XP_UNIX
|
|
|
|
#ifdef XP_MAC
|
|
#pragma mark -
|
|
#endif
|
|
#if defined(XP_OS2)
|
|
#include "nsFileSpecOS2.cpp" // OS/2-specific implementations
|
|
#elif defined(XP_PC)
|
|
#include "nsFileSpecWin.cpp" // Windows-specific implementations
|
|
#elif defined(XP_MAC)
|
|
//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
|
|
// we include the .cpp file in the project now.
|
|
#elif defined(RHAPSODY)
|
|
#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
|
|
#include "nsFileSpecUnix.cpp" // Unix-specific implementations
|
|
#elif defined(XP_BEOS)
|
|
#include "nsFileSpecBeOS.cpp" // BeOS-specific implementations
|
|
#elif defined(XP_UNIX)
|
|
#include "nsFileSpecUnix.cpp" // Unix-specific implementations
|
|
#endif
|
|
|
|
//========================================================================================
|
|
// nsFileURL implementation
|
|
//========================================================================================
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!inString)
|
|
return;
|
|
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "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.
|
|
nsSimpleCharString unescapedPath(inString + kFileURLPrefixLength);
|
|
unescapedPath.Unescape();
|
|
nsFilePath path(unescapedPath, inCreateDirs);
|
|
*this = path;
|
|
} // nsFileURL::nsFileURL
|
|
#endif
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
const nsAutoCString aString(inString);
|
|
const char* aCString = (const char*) aString;
|
|
if (!inString.Length())
|
|
return;
|
|
NS_ASSERTION(strstr(aCString, kFileURLPrefix) == aCString, "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.
|
|
nsSimpleCharString unescapedPath(aCString + kFileURLPrefixLength);
|
|
unescapedPath.Unescape();
|
|
nsFilePath path(unescapedPath, inCreateDirs);
|
|
*this = path;
|
|
} // nsFileURL::nsFileURL
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::nsFileURL(const nsFileURL& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
: mURL(inOther.mURL)
|
|
#ifdef XP_MAC
|
|
, mFileSpec(inOther.GetFileSpec())
|
|
#endif
|
|
{
|
|
} // nsFileURL::nsFileURL
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::nsFileURL(const nsFilePath& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = inOther;
|
|
} // nsFileURL::nsFileURL
|
|
#endif
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::nsFileURL(const nsFileSpec& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = inOther;
|
|
} // nsFileURL::nsFileURL
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL::~nsFileURL()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
}
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileURL::operator = (const char* inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
// XXX is this called by nsFileSpecImpl.cpp::SetURLString?
|
|
// if so, there's a bug...
|
|
|
|
mURL = inString;
|
|
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
|
|
} // nsFileURL::operator =
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileURL::operator +=(const char* inRelativeUnixPath)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
|
|
mURL += escapedPath;
|
|
nsCRT::free(escapedPath);
|
|
#ifdef XP_MAC
|
|
mFileSpec += inRelativeUnixPath;
|
|
#endif
|
|
} // nsFileURL::operator +=
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileURL nsFileURL::operator +(const char* inRelativeUnixPath) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
nsFileURL result(*this);
|
|
result += inRelativeUnixPath;
|
|
return result;
|
|
} // nsFileURL::operator +
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileURL::operator = (const nsFileURL& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mURL = inOther.mURL;
|
|
#ifdef XP_MAC
|
|
mFileSpec = inOther.GetFileSpec();
|
|
#endif
|
|
} // nsFileURL::operator =
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileURL::operator = (const nsFilePath& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mURL = kFileURLPrefix;
|
|
char* original = (char*)(const char*)inOther; // we shall modify, but restore.
|
|
if (!original || !*original) return;
|
|
#ifdef XP_PC
|
|
// because we don't want to escape the '|' character, change it to a letter.
|
|
NS_ASSERTION(original[2] == '|', "No drive letter part!");
|
|
original[2] = 'x';
|
|
char* escapedPath = nsEscape(original, url_Path);
|
|
original[2] = '|'; // restore it
|
|
escapedPath[2] = '|';
|
|
#else
|
|
char* escapedPath = nsEscape(original, url_Path);
|
|
#endif
|
|
if (escapedPath)
|
|
mURL += escapedPath;
|
|
nsCRT::free(escapedPath);
|
|
} // nsFileURL::operator =
|
|
#endif
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileURL::operator = (const nsFileSpec& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = nsFilePath(inOther);
|
|
if (mURL[mURL.Length() - 1] != '/' && inOther.IsDirectory())
|
|
mURL += "/";
|
|
} // nsFileURL::operator =
|
|
#endif
|
|
|
|
#ifdef XP_MAC
|
|
#pragma mark -
|
|
#endif
|
|
|
|
//========================================================================================
|
|
// nsFilePath implementation
|
|
//========================================================================================
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::nsFilePath(const nsFilePath& inPath)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inPath.mPath)
|
|
#ifdef XP_MAC
|
|
, mFileSpec(inPath.mFileSpec)
|
|
#endif
|
|
{
|
|
}
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inString)
|
|
{
|
|
if (mPath.IsEmpty())
|
|
return;
|
|
|
|
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
|
|
|
|
#ifdef XP_PC
|
|
nsFileSpecHelpers::UnixToNative(mPath);
|
|
#endif
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
|
|
#ifdef XP_PC
|
|
NS_ASSERTION( mPath[1] == ':', "unexpected canonical path" );
|
|
nsFileSpecHelpers::NativeToUnix(mPath);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inString)
|
|
{
|
|
if (mPath.IsEmpty())
|
|
return;
|
|
|
|
NS_ASSERTION(strstr((const char*)mPath, kFileURLPrefix) != (const char*)mPath, "URL passed as path");
|
|
#ifdef XP_PC
|
|
nsFileSpecHelpers::UnixToNative(mPath);
|
|
#endif
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
|
|
#ifdef XP_PC
|
|
NS_ASSERTION( mPath[1] == ':', "unexpected canonical path" );
|
|
nsFileSpecHelpers::NativeToUnix(mPath);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::nsFilePath(const nsFileURL& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = (const char*)inOther.mURL + kFileURLPrefixLength;
|
|
mPath.Unescape();
|
|
}
|
|
#endif
|
|
|
|
#if defined XP_UNIX || defined XP_BEOS
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::nsFilePath(const nsFileSpec& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inOther.mPath)
|
|
{
|
|
}
|
|
#endif // XP_UNIX
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath::~nsFilePath()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
}
|
|
|
|
#if defined XP_UNIX || defined XP_BEOS
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFilePath::operator = (const nsFileSpec& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
// XXX bug here, again if.
|
|
|
|
mPath = inOther.mPath;
|
|
}
|
|
#endif // XP_UNIX
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFilePath::operator = (const char* inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
|
|
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
|
|
mPath = inString;
|
|
if (mPath.IsEmpty())
|
|
return;
|
|
#ifdef XP_PC
|
|
nsFileSpecHelpers::UnixToNative(mPath);
|
|
#endif
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
|
|
#ifdef XP_PC
|
|
nsFileSpecHelpers::NativeToUnix(mPath);
|
|
#endif
|
|
}
|
|
#endif // XP_MAC
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFilePath::operator = (const nsFileURL& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = (const char*)nsFilePath(inOther);
|
|
}
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFilePath::operator = (const nsFilePath& inOther)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = inOther.mPath;
|
|
#ifdef XP_MAC
|
|
mFileSpec = inOther.GetFileSpec();
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFilePath::operator +=(const char* inRelativeUnixPath)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
|
|
|
|
char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
|
|
mPath += escapedPath;
|
|
nsCRT::free(escapedPath);
|
|
#ifdef XP_MAC
|
|
mFileSpec += inRelativeUnixPath;
|
|
#endif
|
|
} // nsFilePath::operator +=
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
|
|
|
|
nsFilePath resultPath(*this);
|
|
resultPath += inRelativeUnixPath;
|
|
return resultPath;
|
|
} // nsFilePath::operator +
|
|
|
|
|
|
#ifdef XP_MAC
|
|
#pragma mark -
|
|
#endif
|
|
|
|
//========================================================================================
|
|
// nsFileSpec implementation
|
|
//========================================================================================
|
|
|
|
#ifndef XPCOM_STANDALONE
|
|
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
|
#endif /* XPCOM_STANDALONE */
|
|
|
|
#ifndef XP_MAC
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec()
|
|
//----------------------------------------------------------------------------------------
|
|
: mError(NS_OK) // XXX shouldn't this be NS_ERROR_NOT_INITIALIZED?
|
|
{
|
|
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::Clear()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath.SetToEmpty();
|
|
mError = NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::~nsFileSpec()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
// mPath cleans itself up
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = inDescriptor;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const nsFileURL& inURL)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = nsFilePath(inURL); // convert to unix path first
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (inSuggestedLeafName && *inSuggestedLeafName)
|
|
SetLeafName(inSuggestedLeafName);
|
|
|
|
MakeUnique();
|
|
} // nsFileSpec::MakeUnique
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::MakeUnique()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
if (!Exists())
|
|
return;
|
|
|
|
char* leafName = GetLeafName();
|
|
if (!leafName)
|
|
return;
|
|
|
|
char* lastDot = strrchr(leafName, '.');
|
|
char* suffix = "";
|
|
if (lastDot)
|
|
{
|
|
suffix = nsCRT::strdup(lastDot); // include '.'
|
|
*lastDot = '\0'; // strip suffix and dot.
|
|
}
|
|
const int kMaxRootLength
|
|
= nsFileSpecHelpers::kMaxCoreLeafNameLength - nsCRT::strlen(suffix) - 1;
|
|
if ((int)nsCRT::strlen(leafName) > (int)kMaxRootLength)
|
|
leafName[kMaxRootLength] = '\0';
|
|
for (short indx = 1; indx < 1000 && Exists(); indx++)
|
|
{
|
|
// start with "Picture-1.jpg" after "Picture.jpg" exists
|
|
char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
|
|
sprintf(newName, "%s-%d%s", leafName, indx, suffix);
|
|
SetLeafName(newName);
|
|
}
|
|
if (*suffix)
|
|
nsCRT::free(suffix);
|
|
nsCRT::free(leafName);
|
|
} // nsFileSpec::MakeUnique
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::operator = (const nsFileURL& inURL)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = nsFilePath(inURL); // convert to unix path first
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
|
|
nsSimpleCharString data;
|
|
PRInt32 dataSize;
|
|
inDescriptor.GetData(data, dataSize);
|
|
|
|
#ifdef XP_MAC
|
|
char* decodedData = PL_Base64Decode((const char*)data, (int)dataSize, nsnull);
|
|
// Cast to an alias record and resolve.
|
|
AliasHandle aliasH = nsnull;
|
|
mError = NS_FILE_RESULT(PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4));
|
|
PR_Free(decodedData);
|
|
if (NS_FAILED(mError))
|
|
return; // not enough memory?
|
|
|
|
Boolean changed;
|
|
mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed));
|
|
DisposeHandle((Handle) aliasH);
|
|
mPath.SetToEmpty();
|
|
#else
|
|
mPath = data;
|
|
mError = NS_OK;
|
|
#endif
|
|
}
|
|
|
|
//========================================================================================
|
|
// UNIX & WIN nsFileSpec implementation
|
|
//========================================================================================
|
|
|
|
#if defined XP_UNIX || defined XP_BEOS
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath((const char*)inPath)
|
|
, mError(NS_OK)
|
|
{
|
|
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::operator = (const nsFilePath& inPath)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = (const char*)inPath;
|
|
mError = NS_OK;
|
|
}
|
|
#endif //XP_UNIX
|
|
|
|
#if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS)
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inSpec.mPath)
|
|
, mError(NS_OK)
|
|
{
|
|
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inString)
|
|
, mError(NS_OK)
|
|
{
|
|
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs)
|
|
//----------------------------------------------------------------------------------------
|
|
: mPath(inString)
|
|
, mError(NS_OK)
|
|
{
|
|
// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::operator = (const nsFileSpec& inSpec)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = inSpec.mPath;
|
|
mError = inSpec.Error();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::operator = (const char* inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mPath = inString;
|
|
// Make canonical and absolute.
|
|
nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
|
|
mError = NS_OK;
|
|
}
|
|
#endif //XP_UNIX,PC,XP_BEOS
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
NS_ASSERTION(inRelativePath, "Attempt to append name with a null string");
|
|
|
|
nsFileSpec resultSpec = *this;
|
|
resultSpec += inRelativePath;
|
|
return resultSpec;
|
|
} // nsFileSpec::operator +
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
|
|
#ifdef XP_MAC
|
|
if ( inOther.mSpec.vRefNum == mSpec.vRefNum &&
|
|
inOther.mSpec.parID == mSpec.parID &&
|
|
EqualString(inOther.mSpec.name, mSpec.name, false, true))
|
|
return PR_TRUE;
|
|
#else
|
|
PRBool amEmpty = mPath.IsEmpty();
|
|
PRBool heEmpty = inOther.mPath.IsEmpty();
|
|
if (amEmpty) // we're the same if he's empty...
|
|
return heEmpty;
|
|
if (heEmpty) // ('cuz I'm not...)
|
|
return PR_FALSE;
|
|
|
|
nsSimpleCharString str = mPath;
|
|
nsSimpleCharString inStr = inOther.mPath;
|
|
|
|
// Length() is size of buffer, not length of string
|
|
PRUint32 strLast = str.Length() - 1, inLast = inStr.Length() - 1;
|
|
#if defined(XP_PC)
|
|
#define DIR_SEPARATOR '\\' // XXX doesn't NSPR have this?
|
|
/* 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
|
|
|
|
if(str[strLast] == DIR_SEPARATOR)
|
|
str[strLast] = '\0';
|
|
|
|
if(inStr[inLast] == DIR_SEPARATOR)
|
|
inStr[inLast] = '\0';
|
|
|
|
if (DIR_STRCMP(str, inStr ) == 0)
|
|
return PR_TRUE;
|
|
#undef DIR_SEPARATOR
|
|
#undef DIR_STRCMP
|
|
#endif
|
|
return PR_FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
return (! (*this == inOther) );
|
|
}
|
|
|
|
#ifndef 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?
|
|
PRBool nsFileSpec::IsChildOf(nsFileSpec &possibleParent)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
nsFileSpec iter = *this, parent;
|
|
#ifdef DEBUG
|
|
int depth = 0;
|
|
#endif
|
|
while (1) {
|
|
#ifdef DEBUG
|
|
// sanity
|
|
NS_ASSERTION(depth < 100, "IsChildOf has lost its little mind");
|
|
if (depth > 100)
|
|
return PR_FALSE;
|
|
#endif
|
|
if (iter == possibleParent)
|
|
return PR_TRUE;
|
|
|
|
iter.GetParent(parent); // shouldn't this be an error on parent?
|
|
if (iter.Failed())
|
|
return PR_FALSE;
|
|
|
|
if (iter == parent) // hit bottom
|
|
return PR_FALSE;
|
|
|
|
iter = parent;
|
|
#ifdef DEBUG
|
|
depth++;
|
|
#endif
|
|
}
|
|
|
|
// not reached, but I bet some compiler will whine
|
|
return PR_FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::GetFileSystemCharset(nsString & fileSystemCharset)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
#ifndef XPCOM_STANDALONE
|
|
// From mozilla/widget/src/windows/nsFileWidget.cpp
|
|
|
|
static nsAutoString aCharset;
|
|
nsresult rv;
|
|
|
|
if (aCharset.Length() < 1) {
|
|
nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_PROGID, &rv);
|
|
if (NS_SUCCEEDED(rv))
|
|
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, aCharset);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "error getting platform charset");
|
|
if (NS_FAILED(rv))
|
|
aCharset.AssignWithConversion("ISO-8859-1");
|
|
}
|
|
fileSystemCharset = aCharset;
|
|
#endif /* XPCOM_STANDALONE */
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
PRUnichar * nsFileSpec::ConvertFromFileSystemCharset(const char *inString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
|
|
PRUnichar *outString = nsnull;
|
|
#ifndef XPCOM_STANDALONE
|
|
// From mozilla/widget/src/windows/nsFileWidget.cpp
|
|
|
|
nsIUnicodeDecoder *aUnicodeDecoder = nsnull;
|
|
rv = NS_OK;
|
|
|
|
// get file system charset and create a unicode encoder
|
|
nsAutoString fileSystemCharset;
|
|
GetFileSystemCharset(fileSystemCharset);
|
|
|
|
NS_WITH_SERVICE(nsICharsetConverterManager, ccm, kCharsetConverterManagerCID, &rv);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
rv = ccm->GetUnicodeDecoder(&fileSystemCharset, &aUnicodeDecoder);
|
|
}
|
|
|
|
// converts from the file system charset to unicode
|
|
if (NS_SUCCEEDED(rv)) {
|
|
PRInt32 inLength = nsCRT::strlen(inString);
|
|
PRInt32 outLength;
|
|
rv = aUnicodeDecoder->GetMaxLength(inString, inLength, &outLength);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
outString = new PRUnichar[outLength+1];
|
|
if (nsnull == outString) {
|
|
return nsnull;
|
|
}
|
|
rv = aUnicodeDecoder->Convert(inString, &inLength, outString, &outLength);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
outString[outLength] = 0;
|
|
}
|
|
}
|
|
}
|
|
NS_IF_RELEASE(aUnicodeDecoder);
|
|
#endif /* XPCOM_STANDALONE */
|
|
|
|
return NS_SUCCEEDED(rv) ? outString : nsnull;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::GetNativePathString(nsString &nativePathString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
const char *path = GetCString();
|
|
if (nsnull == path) {
|
|
nativePathString.SetLength(0);
|
|
return;
|
|
}
|
|
else {
|
|
PRUnichar *converted = ConvertFromFileSystemCharset(path);
|
|
if (nsnull != converted) {
|
|
nativePathString.Assign(converted);
|
|
delete [] converted;
|
|
}
|
|
else
|
|
nativePathString.AssignWithConversion(path);
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsFileSpec::GetLeafName(nsString &nativePathString)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
char * path = GetLeafName();
|
|
if (nsnull == path) {
|
|
nativePathString.SetLength(0);
|
|
return;
|
|
} else {
|
|
PRUnichar *converted = ConvertFromFileSystemCharset(path);
|
|
if (nsnull != converted) {
|
|
nativePathString.Assign(converted);
|
|
delete [] converted;
|
|
}
|
|
else
|
|
nativePathString.AssignWithConversion(path);
|
|
|
|
nsCRT::free(path);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef XP_MAC
|
|
#pragma mark -
|
|
#endif
|
|
|
|
//========================================================================================
|
|
// class nsPersistentFileDescriptor
|
|
//========================================================================================
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
|
|
//----------------------------------------------------------------------------------------
|
|
: mDescriptorString(inDesc.mDescriptorString)
|
|
{
|
|
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mDescriptorString = inDesc.mDescriptorString;
|
|
} // nsPersistentFileDescriptor::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
*this = inSpec;
|
|
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
#ifdef XP_MAC
|
|
if (inSpec.Error())
|
|
return;
|
|
AliasHandle aliasH;
|
|
OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH);
|
|
if (err != noErr)
|
|
return;
|
|
|
|
PRUint32 bytes = GetHandleSize((Handle) aliasH);
|
|
HLock((Handle) aliasH);
|
|
char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
|
|
DisposeHandle((Handle) aliasH);
|
|
|
|
mDescriptorString = buf;
|
|
PR_Free(buf);
|
|
#else
|
|
mDescriptorString = inSpec.GetCString();
|
|
#endif // XP_MAC
|
|
} // nsPersistentFileDescriptor::operator =
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
outData = mDescriptorString;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
SetData(inData, inData.Length());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::GetData(nsSimpleCharString& outData, PRInt32& outSize) const
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
outSize = mDescriptorString.Length();
|
|
outData = mDescriptorString;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::SetData(const nsSimpleCharString& inData, PRInt32 inSize)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mDescriptorString.CopyFrom((const char*)inData, inSize);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
void nsPersistentFileDescriptor::SetData(const char* inData, PRInt32 inSize)
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
mDescriptorString.CopyFrom(inData, inSize);
|
|
}
|
|
|
|
//========================================================================================
|
|
// class nsAutoCString
|
|
//========================================================================================
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsAutoCString::~nsAutoCString()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
nsMemory::Free(NS_REINTERPRET_CAST(void*, NS_CONST_CAST(char*, mCString)));
|
|
}
|
|
|
|
//========================================================================================
|
|
// 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.
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
#ifdef XP_PC
|
|
if (!modifiedNSPRPath)
|
|
{
|
|
// If this is the first call, initialize modifiedNSPRPath. Start by cloning
|
|
// mFilePath, but strip the leading separator, if present
|
|
const char* unixPath = (const char*)mFilePath;
|
|
if (!unixPath)
|
|
return nsnull;
|
|
|
|
((nsNSPRPath*)this)->modifiedNSPRPath
|
|
= nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath);
|
|
|
|
// Replace the bar
|
|
if (modifiedNSPRPath[1] == '|')
|
|
modifiedNSPRPath[1] = ':';
|
|
|
|
// Remove the ending separator only if it is not the last separator
|
|
int len = nsCRT::strlen(modifiedNSPRPath);
|
|
if (modifiedNSPRPath[len - 1 ] == '/' && modifiedNSPRPath[len - 2 ] != ':')
|
|
modifiedNSPRPath[len - 1 ] = '\0';
|
|
}
|
|
return modifiedNSPRPath;
|
|
#else
|
|
return (const char*)mFilePath;
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------
|
|
nsNSPRPath::~nsNSPRPath()
|
|
//----------------------------------------------------------------------------------------
|
|
{
|
|
#ifdef XP_PC
|
|
if (modifiedNSPRPath)
|
|
nsCRT::free(modifiedNSPRPath);
|
|
#endif
|
|
}
|
|
|
|
|
|
nsresult
|
|
NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_PROGID));
|
|
|
|
if (!file) return NS_ERROR_FAILURE;
|
|
|
|
#if defined(XP_MAC) || defined(RHAPSODY)
|
|
{
|
|
FSSpec spec = fileSpec->GetFSSpec();
|
|
nsCOMPtr<nsILocalFileMac> psmAppMacFile = do_QueryInterface(file, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
rv = psmAppMacFile->InitWithFSSpec(&spec);
|
|
if (NS_FAILED(rv)) return rv;
|
|
file = do_QueryInterface(psmAppMacFile, &rv);
|
|
}
|
|
#else
|
|
rv = file->InitWithPath(fileSpec->GetNativePathCString());
|
|
#endif
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
*result = file;
|
|
NS_ADDREF(*result);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
|