Bug 159987 - Clicking on link with a file:// href where the path to the file contains an extremely long component crashes. Also, fixes initialization of non-extant files on volumes other than the boot volume

git-svn-id: svn://10.0.0.236/branches/CHIMERA_M1_0_BRANCH@126915 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ccarlen%netscape.com
2002-08-09 23:33:32 +00:00
parent 823baf4033
commit b5aba06b3f
2 changed files with 109 additions and 50 deletions

View File

@@ -39,6 +39,7 @@
#include "nsILocalFile.idl"
%{C++
#undef DARWIN
#include <Files.h>
#include <CFURL.h>
%}

View File

@@ -241,6 +241,65 @@ public:
}
};
#pragma mark -
#pragma mark [StBuffer]
template <class T>
class StBuffer
{
public:
StBuffer() :
mBufferPtr(mBuffer),
mCurElemCapacity(kStackBufferNumElems)
{
}
~StBuffer()
{
DeleteBuffer();
}
PRBool EnsureElemCapacity(PRInt32 inElemCapacity)
{
if (inElemCapacity <= mCurElemCapacity)
return PR_TRUE;
if (inElemCapacity > kStackBufferNumElems)
{
DeleteBuffer();
mBufferPtr = (T*)malloc(inElemCapacity * sizeof(T));
mCurElemCapacity = inElemCapacity;
return (mBufferPtr != NULL);
}
mCurElemCapacity = kStackBufferNumElems;
return PR_TRUE;
}
T* get() { return mBufferPtr; }
PRInt32 GetElemCapacity() { return mCurElemCapacity; }
protected:
void DeleteBuffer()
{
if (mBufferPtr != mBuffer)
{
free(mBufferPtr);
mBufferPtr = mBuffer;
}
}
protected:
enum { kStackBufferNumElems = 512 };
T *mBufferPtr;
T mBuffer[kStackBufferNumElems];
PRInt32 mCurElemCapacity;
};
//*****************************************************************************
// nsLocalFile
@@ -1187,61 +1246,60 @@ NS_IMETHODIMP nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **aDirectoryE
/* void initWithPath (in AString filePath); */
NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString& filePath)
{
if (filePath.First() != '/' || filePath.Length() == 0)
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
// First attempt to convert directly to an FSRef.
// This will fail if the all of the path does not exist.
// XXX - Test is it is faster to do the parse and append and possibly just do that in any case.
OSErr err;
FSRef newRef;
err = ::FSPathMakeRef((UInt8 *)(PromiseFlatCString(NS_ConvertUCS2toUTF8(filePath)).get()),
&newRef, nsnull);
if (err == noErr) {
mFSRef = newRef;
mNonExtantNodes.clear();
mIdentityDirty = PR_FALSE;
mFollowLinksDirty = PR_TRUE;
return NS_OK;
}
// Start with the root and append the nodes in the path
mFSRef = kRootFSRef;
mNonExtantNodes.clear();
err = noErr;
nsAString::const_iterator nodeBegin, pathEnd;
filePath.BeginReading(nodeBegin);
++nodeBegin; // Inc over the '/' that we begin with
filePath.EndReading(pathEnd);
nsAString::const_iterator nodeEnd(nodeBegin);
while (nodeEnd != pathEnd) {
FindCharInReadable(kPathSepUnichar, nodeEnd, pathEnd);
const nsAString& nodeName = Substring(nodeBegin, nodeEnd);
if (err == noErr) {
err = ::FSMakeFSRefUnicode(&mFSRef,
nodeName.Length(),
(UniChar*)(PromiseFlatString(nodeName).get()),
kTextEncodingUnknown,
&newRef);
}
if (err == noErr)
mFSRef = newRef;
else
mNonExtantNodes.push_back(nsString(nodeName));
if (nodeEnd != pathEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
++nodeEnd;
nodeBegin = nodeEnd;
}
return NS_OK;
return InitWithNativePath(NS_ConvertUCS2toUTF8(filePath));
}
/* [noscript] void initWithNativePath (in ACString filePath); */
NS_IMETHODIMP nsLocalFile::InitWithNativePath(const nsACString& filePath)
{
return InitWithPath(NS_ConvertUTF8toUCS2(filePath));
if (filePath.First() != '/' || filePath.Length() == 0)
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
mNonExtantNodes.clear();
mIdentityDirty = PR_TRUE;
CFStringRef pathAsCFString;
CFURLRef pathAsCFURL;
pathAsCFString = ::CFStringCreateWithCString(nsnull, PromiseFlatCString(filePath).get(), kCFStringEncodingUTF8);
if (!pathAsCFString)
return NS_ERROR_FAILURE;
pathAsCFURL = ::CFURLCreateWithFileSystemPath(nsnull, pathAsCFString, kCFURLPOSIXPathStyle, PR_FALSE);
if (!pathAsCFURL) {
::CFRelease(pathAsCFString);
return NS_ERROR_FAILURE;
}
CFStringRef leaf = nsnull;
StBuffer<UniChar> buffer;
PRBool success;
while ((success = ::CFURLGetFSRef(pathAsCFURL, &mFSRef)) == PR_FALSE) {
// Extract the last component and push onto the front of mNonExtantNodes
leaf = ::CFURLCopyLastPathComponent(pathAsCFURL);
if (!leaf)
break;
CFIndex leafLen = ::CFStringGetLength(leaf);
if (!buffer.EnsureElemCapacity(leafLen + 1))
break;
::CFStringGetCharacters(leaf, CFRangeMake(0, leafLen), buffer.get());
buffer.get()[leafLen] = '\0';
mNonExtantNodes.push_front(nsString(nsDependentString(buffer.get())));
::CFRelease(leaf);
leaf = nsnull;
// Get the parent of the leaf for the next go round
CFURLRef parent = ::CFURLCreateCopyDeletingLastPathComponent(NULL, pathAsCFURL);
if (!parent)
break;
::CFRelease(pathAsCFURL);
pathAsCFURL = parent;
}
::CFRelease(pathAsCFString);
::CFRelease(pathAsCFURL);
if (leaf)
::CFRelease(leaf);
return success ? NS_OK : NS_ERROR_FAILURE;
}
/* void initWithFile (in nsILocalFile aFile); */