VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpec.cpp@ 7139

最後變更 在這個檔案從7139是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 48.8 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "nsFileSpec.h"
39
40#include "nsDebug.h"
41#include "nsEscape.h"
42#include "nsMemory.h"
43
44#include "prtypes.h"
45#include "plstr.h"
46#include "plbase64.h"
47#include "prmem.h"
48
49#include "nsCOMPtr.h"
50#include "nsIServiceManager.h"
51#include "nsILocalFile.h"
52
53#include <string.h>
54#include <stdio.h>
55
56#if defined(XP_WIN)
57#include <mbstring.h>
58#endif
59
60#ifdef XP_OS2
61extern unsigned char* _mbsrchr( const unsigned char*, int);
62#endif
63
64// return pointer to last instance of the given separator
65static inline char *GetLastSeparator(const char *str, char sep)
66{
67#if defined(XP_WIN) || defined(XP_OS2)
68 return (char*) _mbsrchr((const unsigned char *) str, sep);
69#else
70 return (char*) strrchr(str, sep);
71#endif
72}
73
74#if defined(XP_MACOSX)
75#include <sys/stat.h>
76#endif
77
78#if defined(XP_MAC) || defined(XP_MACOSX)
79#include <Aliases.h>
80#include <TextUtils.h>
81#endif
82
83//========================================================================================
84// class nsSimpleCharString
85//========================================================================================
86
87//----------------------------------------------------------------------------------------
88nsSimpleCharString::nsSimpleCharString()
89//----------------------------------------------------------------------------------------
90: mData(nsnull)
91{
92
93} // nsSimpleCharString::nsSimpleCharString
94
95//----------------------------------------------------------------------------------------
96nsSimpleCharString::nsSimpleCharString(const char* inString)
97//----------------------------------------------------------------------------------------
98: mData(nsnull)
99{
100 if (inString)
101 CopyFrom(inString, strlen(inString));
102} // nsSimpleCharString::nsSimpleCharString
103
104//----------------------------------------------------------------------------------------
105nsSimpleCharString::nsSimpleCharString(const nsString& inString)
106//----------------------------------------------------------------------------------------
107: mData(nsnull)
108{
109 *this = inString;
110} // nsSimpleCharString::nsSimpleCharString
111
112//----------------------------------------------------------------------------------------
113nsSimpleCharString::nsSimpleCharString(const nsSimpleCharString& inOther)
114//----------------------------------------------------------------------------------------
115{
116 mData = inOther.mData;
117 AddRefData();
118} // nsSimpleCharString::nsSimpleCharString
119
120//----------------------------------------------------------------------------------------
121nsSimpleCharString::nsSimpleCharString(const char* inData, PRUint32 inLength)
122//----------------------------------------------------------------------------------------
123: mData(nsnull)
124{
125 CopyFrom(inData, inLength);
126} // nsSimpleCharString::nsSimpleCharString
127
128//----------------------------------------------------------------------------------------
129nsSimpleCharString::~nsSimpleCharString()
130//----------------------------------------------------------------------------------------
131{
132 ReleaseData();
133} // nsSimpleCharString::nsSimpleCharString
134
135//----------------------------------------------------------------------------------------
136void nsSimpleCharString::operator = (const char* inString)
137//----------------------------------------------------------------------------------------
138{
139 if (inString)
140 CopyFrom(inString, strlen(inString));
141 else
142 SetToEmpty();
143} // nsSimpleCharString::operator =
144
145//----------------------------------------------------------------------------------------
146void nsSimpleCharString::operator = (const nsString& inString)
147//----------------------------------------------------------------------------------------
148{
149 PRUint32 len = inString.Length();
150 ReallocData(len);
151 if (!mData)
152 return;
153 inString.ToCString(mData->mString, len + 1);
154} // nsSimpleCharString::operator =
155
156//----------------------------------------------------------------------------------------
157void nsSimpleCharString::operator = (const nsSimpleCharString& inOther)
158//----------------------------------------------------------------------------------------
159{
160 if (mData == inOther.mData)
161 return;
162 ReleaseData();
163 mData = inOther.mData;
164 AddRefData();
165} // nsSimpleCharString::operator =
166
167//----------------------------------------------------------------------------------------
168void nsSimpleCharString::operator += (const char* inOther)
169//----------------------------------------------------------------------------------------
170{
171 if (!inOther)
172 return;
173 int newLength = Length() + strlen(inOther);
174 ReallocData(newLength);
175 strcat(mData->mString, inOther);
176} // nsSimpleCharString::operator =
177
178//----------------------------------------------------------------------------------------
179nsSimpleCharString nsSimpleCharString::operator + (const char* inOther) const
180//----------------------------------------------------------------------------------------
181{
182 nsSimpleCharString result(*this);
183 result += inOther;
184 return result;
185} // nsSimpleCharString::operator =
186
187//----------------------------------------------------------------------------------------
188void nsSimpleCharString::Catenate(const char* inString1, const char* inString2)
189//----------------------------------------------------------------------------------------
190{
191 if (!inString2)
192 {
193 *this += inString1;
194 return;
195 }
196 int newLength = Length() + strlen(inString1) + strlen(inString2);
197 ReallocData(newLength);
198 strcat(mData->mString, inString1);
199 strcat(mData->mString, inString2);
200} // nsSimpleCharString::operator =
201
202//----------------------------------------------------------------------------------------
203void nsSimpleCharString::CopyFrom(const char* inData, PRUint32 inLength)
204//----------------------------------------------------------------------------------------
205{
206 if (!inData)
207 return;
208 ReallocData(inLength);
209 if (!mData)
210 return;
211 if (inLength != 0) {
212 memcpy(mData->mString, inData, inLength);
213 }
214 mData->mString[inLength] = '\0';
215} // nsSimpleCharString::CopyFrom
216
217//----------------------------------------------------------------------------------------
218void nsSimpleCharString::SetToEmpty()
219//----------------------------------------------------------------------------------------
220{
221 ReleaseData();
222} // nsSimpleCharString::SetToEmpty
223
224//----------------------------------------------------------------------------------------
225void nsSimpleCharString::Unescape()
226//----------------------------------------------------------------------------------------
227{
228 if (!mData)
229 return;
230 ReallocData(mData->mLength);
231 if (!mData)
232 return;
233 nsUnescape(mData->mString);
234 mData->mLength = strlen(mData->mString);
235} // nsSimpleCharString::Unescape
236
237
238//----------------------------------------------------------------------------------------
239void nsSimpleCharString::AddRefData()
240//----------------------------------------------------------------------------------------
241{
242 if (mData)
243 ++mData->mRefCount;
244} // nsSimpleCharString::AddRefData
245
246//----------------------------------------------------------------------------------------
247void nsSimpleCharString::ReleaseData()
248//----------------------------------------------------------------------------------------
249{
250 if (!mData)
251 return;
252 NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
253 if (--mData->mRefCount == 0)
254 PR_Free(mData);
255 mData = nsnull;
256} // nsSimpleCharString::ReleaseData
257
258//----------------------------------------------------------------------------------------
259inline PRUint32 CalculateAllocLength(PRUint32 logicalLength)
260// Round up to the next multiple of 256.
261//----------------------------------------------------------------------------------------
262{
263 return ((1 + (logicalLength >> 8)) << 8);
264}
265
266//----------------------------------------------------------------------------------------
267void nsSimpleCharString::ReallocData(PRUint32 inLength)
268// Reallocate mData to a new length. Since this presumably precedes a change to the string,
269// we want to detach ourselves if the data is shared by another string, even if the length
270// requested would not otherwise require a reallocation.
271//----------------------------------------------------------------------------------------
272{
273 PRUint32 newAllocLength = CalculateAllocLength(inLength);
274 PRUint32 oldAllocLength = CalculateAllocLength(Length());
275 if (mData)
276 {
277 NS_ASSERTION(mData->mRefCount > 0, "String deleted too many times!");
278 if (mData->mRefCount == 1)
279 {
280 // We are the sole owner, so just change its length, if necessary.
281 if (newAllocLength > oldAllocLength)
282 mData = (Data*)PR_Realloc(mData, newAllocLength + sizeof(Data));
283 mData->mLength = inLength;
284 mData->mString[inLength] = '\0'; // we may be truncating
285 return;
286 }
287 }
288 PRUint32 copyLength = Length();
289 if (inLength < copyLength)
290 copyLength = inLength;
291 Data* newData = (Data*)PR_Malloc(newAllocLength + sizeof(Data));
292 // If data was already allocated when we get to here, then we are cloning the data
293 // from a shared pointer.
294 if (mData)
295 {
296 memcpy(newData, mData, sizeof(Data) + copyLength);
297 mData->mRefCount--; // Say goodbye
298 }
299 else
300 newData->mString[0] = '\0';
301
302 mData = newData;
303 mData->mRefCount = 1;
304 mData->mLength = inLength;
305} // nsSimpleCharString::ReleaseData
306
307
308//========================================================================================
309NS_NAMESPACE nsFileSpecHelpers
310//========================================================================================
311{
312 enum
313 { kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
314 , kMaxAltDigitLength = 5
315 , kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
316 };
317#if !defined(XP_MAC)
318 NS_NAMESPACE_PROTOTYPE void Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs);
319 NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
320#endif
321#if defined(XP_WIN) || defined(XP_OS2)
322 NS_NAMESPACE_PROTOTYPE void NativeToUnix(nsSimpleCharString& ioPath);
323 NS_NAMESPACE_PROTOTYPE void UnixToNative(nsSimpleCharString& ioPath);
324#endif
325} NS_NAMESPACE_END
326
327//----------------------------------------------------------------------------------------
328nsresult ns_file_convert_result(PRInt32 nativeErr)
329//----------------------------------------------------------------------------------------
330{
331 return nativeErr ?
332 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
333 : NS_OK;
334}
335
336//----------------------------------------------------------------------------------------
337void nsSimpleCharString::LeafReplace(char inSeparator, const char* inLeafName)
338//----------------------------------------------------------------------------------------
339{
340 // Find the existing leaf name
341 if (IsEmpty())
342 return;
343 if (!inLeafName)
344 {
345 SetToEmpty();
346 return;
347 }
348 char* chars = mData->mString;
349 char* lastSeparator = GetLastSeparator(chars, inSeparator);
350 int oldLength = Length();
351 PRBool trailingSeparator = (lastSeparator + 1 == chars + oldLength);
352 if (trailingSeparator)
353 {
354 char savedCh = *lastSeparator;
355 char *savedLastSeparator = lastSeparator;
356 *lastSeparator = '\0';
357 lastSeparator = GetLastSeparator(chars, inSeparator);
358 *savedLastSeparator = savedCh;
359 }
360 if (lastSeparator)
361 lastSeparator++; // point at the trailing string
362 else
363 lastSeparator = chars; // the full monty
364
365 PRUint32 savedLastSeparatorOffset = (lastSeparator - chars);
366 int newLength =
367 (lastSeparator - chars) + strlen(inLeafName) + (trailingSeparator != 0);
368 ReallocData(newLength);
369
370 chars = mData->mString; // it might have moved.
371 chars[savedLastSeparatorOffset] = '\0'; // strip the current leaf name
372
373 strcat(chars, inLeafName);
374 if (trailingSeparator)
375 {
376 // If the original ended in a slash, then the new one should, too.
377 char sepStr[2] = "/";
378 *sepStr = inSeparator;
379 strcat(chars, sepStr);
380 }
381} // nsSimpleCharString::LeafReplace
382
383//----------------------------------------------------------------------------------------
384char* nsSimpleCharString::GetLeaf(char inSeparator) const
385// Returns a pointer to an allocated string representing the leaf.
386//----------------------------------------------------------------------------------------
387{
388 if (IsEmpty())
389 return nsnull;
390
391 char* chars = mData->mString;
392 const char* lastSeparator = GetLastSeparator(chars, inSeparator);
393 // If there was no separator, then return a copy of our path.
394 if (!lastSeparator)
395 return nsCRT::strdup(*this);
396
397 // So there's at least one separator. What's just after it?
398 // If the separator was not the last character, return the trailing string.
399 const char* leafPointer = lastSeparator + 1;
400 if (*leafPointer)
401 return nsCRT::strdup(leafPointer);
402
403 // So now, separator was the last character. Poke in a null instead.
404 *(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
405 leafPointer = GetLastSeparator(chars, inSeparator);
406 char* result = leafPointer ? nsCRT::strdup(++leafPointer) : nsCRT::strdup(chars);
407 // Restore the poked null before returning.
408 *(char*)lastSeparator = inSeparator;
409#if defined(XP_WIN) || defined(XP_OS2)
410 // If it's a drive letter use the colon notation.
411 if (!leafPointer && result[1] == '|' && result[2] == 0)
412 result[1] = ':';
413#endif
414 return result;
415} // nsSimpleCharString::GetLeaf
416
417
418#if 0
419#pragma mark -
420#endif
421
422#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
423
424//----------------------------------------------------------------------------------------
425void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
426// Make the path a valid one by creating all the intermediate directories. Does NOT
427// make the leaf into a directory. This should be a unix path.
428//----------------------------------------------------------------------------------------
429{
430 if (!inPath)
431 return;
432
433 char* pathCopy = nsCRT::strdup( inPath );
434 if (!pathCopy)
435 return;
436
437 const char kSeparator = '/'; // I repeat: this should be a unix-style path.
438 const int kSkipFirst = 1;
439
440#if defined(XP_WIN) || defined(XP_OS2)
441 // Either this is a relative path, or we ensure that it has
442 // a drive letter specifier.
443 NS_ASSERTION( pathCopy[0] != '/' || (pathCopy[1] && (pathCopy[2] == '|' || pathCopy[2] == '/')),
444 "Not a UNC path and no drive letter!" );
445#endif
446 char* currentStart = pathCopy;
447 char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
448 if (currentEnd)
449 {
450 nsFileSpec spec;
451 *currentEnd = '\0';
452
453#if defined(XP_WIN) || defined(XP_OS2)
454 /*
455 if we have a drive letter path, we must make sure that the inital path has a '/' on it, or
456 Canonify will turn "/c|" into a path relative to the running executable.
457 */
458 if (pathCopy[0] == '/' && pathCopy[1] && pathCopy[2] == '|')
459 {
460 char* startDir = (char*)PR_Malloc(strlen(pathCopy) + 2);
461 strcpy(startDir, pathCopy);
462 strcat(startDir, "/");
463
464 spec = nsFilePath(startDir, PR_FALSE);
465
466 PR_Free(startDir);
467 }
468 else
469 {
470 // move after server name and share name in UNC path
471 if (pathCopy[0] == '/' &&
472 currentEnd == currentStart+kSkipFirst)
473 {
474 *currentEnd = '/';
475 currentStart = strchr(pathCopy+2, kSeparator);
476 currentStart = strchr(currentStart+1, kSeparator);
477 currentEnd = strchr(currentStart+1, kSeparator);
478 if (currentEnd)
479 *currentEnd = '\0';
480 }
481 spec = nsFilePath(pathCopy, PR_FALSE);
482 }
483#else
484 spec = nsFilePath(pathCopy, PR_FALSE);
485#endif
486 do
487 {
488 // If the node doesn't exist, and it is not the initial node in a full path,
489 // then make a directory (We cannot make the initial (volume) node).
490 if (!spec.Exists() && *currentStart != kSeparator)
491 spec.CreateDirectory(mode);
492
493 currentStart = ++currentEnd;
494 currentEnd = strchr(currentStart, kSeparator);
495 if (!currentEnd)
496 break;
497
498 *currentEnd = '\0';
499
500 spec += currentStart; // "lengthen" the path, adding the next node.
501 } while (currentEnd);
502 }
503 nsCRT::free(pathCopy);
504} // nsFileSpecHelpers::MakeAllDirectories
505
506#endif // XP_UNIX || XP_WIN || XP_OS2 || XP_BEOS
507
508#if 0
509#pragma mark -
510#endif
511
512#if defined(XP_WIN)
513#include "nsFileSpecWin.cpp" // Windows-specific implementations
514#elif defined(XP_MAC)
515//#include "nsFileSpecMac.cpp" // Macintosh-specific implementations
516// we include the .cpp file in the project now.
517#elif defined(XP_BEOS)
518#include "nsFileSpecBeOS.cpp" // BeOS-specific implementations
519#elif defined(XP_UNIX) || defined(XP_MACOSX)
520#include "nsFileSpecUnix.cpp" // Unix-specific implementations
521#elif defined(XP_OS2)
522#include "nsFileSpecOS2.cpp" // OS/2-specific implementations
523#endif
524
525//========================================================================================
526// nsFileURL implementation
527//========================================================================================
528
529#if !defined(XP_MAC)
530//----------------------------------------------------------------------------------------
531nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
532//----------------------------------------------------------------------------------------
533{
534 if (!inString)
535 return;
536 NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
537 // Make canonical and absolute. Since it's a parameter to this constructor,
538 // inString is escaped. We want to make an nsFilePath, which requires
539 // an unescaped string.
540 nsSimpleCharString unescapedPath(inString + kFileURLPrefixLength);
541 unescapedPath.Unescape();
542 nsFilePath path(unescapedPath, inCreateDirs);
543 *this = path;
544} // nsFileURL::nsFileURL
545#endif
546
547#if !defined(XP_MAC)
548//----------------------------------------------------------------------------------------
549nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
550//----------------------------------------------------------------------------------------
551{
552 NS_LossyConvertUCS2toASCII cstring(inString);
553 if (!inString.Length())
554 return;
555 NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
556 "Not a URL!");
557 // Make canonical and absolute. Since it's a parameter to this constructor,
558 // inString is escaped. We want to make an nsFilePath, which requires
559 // an unescaped string.
560 nsSimpleCharString unescapedPath(cstring.get() + kFileURLPrefixLength);
561 unescapedPath.Unescape();
562 nsFilePath path(unescapedPath, inCreateDirs);
563 *this = path;
564} // nsFileURL::nsFileURL
565#endif
566
567//----------------------------------------------------------------------------------------
568nsFileURL::nsFileURL(const nsFileURL& inOther)
569//----------------------------------------------------------------------------------------
570: mURL(inOther.mURL)
571#if defined(XP_MAC)
572, mFileSpec(inOther.GetFileSpec())
573#endif
574{
575} // nsFileURL::nsFileURL
576
577#if !defined(XP_MAC)
578//----------------------------------------------------------------------------------------
579nsFileURL::nsFileURL(const nsFilePath& inOther)
580//----------------------------------------------------------------------------------------
581{
582 *this = inOther;
583} // nsFileURL::nsFileURL
584#endif
585
586#if !defined(XP_MAC)
587//----------------------------------------------------------------------------------------
588nsFileURL::nsFileURL(const nsFileSpec& inOther)
589//----------------------------------------------------------------------------------------
590{
591 *this = inOther;
592} // nsFileURL::nsFileURL
593#endif
594
595//----------------------------------------------------------------------------------------
596nsFileURL::~nsFileURL()
597//----------------------------------------------------------------------------------------
598{
599}
600
601#if !defined(XP_MAC)
602//----------------------------------------------------------------------------------------
603void nsFileURL::operator = (const char* inString)
604//----------------------------------------------------------------------------------------
605{
606 // XXX is this called by nsFileSpecImpl.cpp::SetURLString?
607 // if so, there's a bug...
608
609 mURL = inString;
610 NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
611} // nsFileURL::operator =
612#endif
613
614//----------------------------------------------------------------------------------------
615void nsFileURL::operator +=(const char* inRelativeUnixPath)
616//----------------------------------------------------------------------------------------
617{
618 char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
619 mURL += escapedPath;
620 nsCRT::free(escapedPath);
621#if defined(XP_MAC)
622 mFileSpec += inRelativeUnixPath;
623#endif
624} // nsFileURL::operator +=
625
626//----------------------------------------------------------------------------------------
627nsFileURL nsFileURL::operator +(const char* inRelativeUnixPath) const
628//----------------------------------------------------------------------------------------
629{
630 nsFileURL result(*this);
631 result += inRelativeUnixPath;
632 return result;
633} // nsFileURL::operator +
634
635//----------------------------------------------------------------------------------------
636void nsFileURL::operator = (const nsFileURL& inOther)
637//----------------------------------------------------------------------------------------
638{
639 mURL = inOther.mURL;
640#if defined(XP_MAC)
641 mFileSpec = inOther.GetFileSpec();
642#endif
643} // nsFileURL::operator =
644
645#if !defined(XP_MAC)
646//----------------------------------------------------------------------------------------
647void nsFileURL::operator = (const nsFilePath& inOther)
648//----------------------------------------------------------------------------------------
649{
650 mURL = kFileURLPrefix;
651 char* original = (char*)(const char*)inOther; // we shall modify, but restore.
652 if (!original || !*original) return;
653#if defined(XP_WIN) || defined(XP_OS2)
654 // because we don't want to escape the '|' character, change it to a letter.
655 // Note that a UNC path will not have a '|' character.
656 char oldchar = original[2];
657 original[2] = 'x';
658 char* escapedPath = nsEscape(original, url_Path);
659 original[2] = escapedPath[2] = oldchar; // restore it
660#else
661 char* escapedPath = nsEscape(original, url_Path);
662#endif
663 if (escapedPath)
664 mURL += escapedPath;
665 nsCRT::free(escapedPath);
666} // nsFileURL::operator =
667#endif
668
669#if !defined(XP_MAC)
670//----------------------------------------------------------------------------------------
671void nsFileURL::operator = (const nsFileSpec& inOther)
672//----------------------------------------------------------------------------------------
673{
674 *this = nsFilePath(inOther);
675 if (mURL[mURL.Length() - 1] != '/' && inOther.IsDirectory())
676 mURL += "/";
677} // nsFileURL::operator =
678#endif
679
680#if 0
681#pragma mark -
682#endif
683
684//========================================================================================
685// nsFilePath implementation
686//========================================================================================
687
688//----------------------------------------------------------------------------------------
689nsFilePath::nsFilePath(const nsFilePath& inPath)
690//----------------------------------------------------------------------------------------
691 : mPath(inPath.mPath)
692#if defined(XP_MAC)
693 , mFileSpec(inPath.mFileSpec)
694#endif
695{
696}
697
698#if !defined(XP_MAC)
699//----------------------------------------------------------------------------------------
700nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
701//----------------------------------------------------------------------------------------
702: mPath(inString)
703{
704 if (mPath.IsEmpty())
705 return;
706
707 NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
708
709#if defined(XP_WIN) || defined(XP_OS2)
710 nsFileSpecHelpers::UnixToNative(mPath);
711#endif
712 // Make canonical and absolute.
713 nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
714#if defined(XP_WIN) || defined(XP_OS2)
715 // Assert native path is of one of these forms:
716 // - regular: X:\some\path
717 // - UNC: \\some_machine\some\path
718 NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
719 "unexpected canonical path" );
720 nsFileSpecHelpers::NativeToUnix(mPath);
721#endif
722}
723#endif
724
725#if !defined(XP_MAC)
726//----------------------------------------------------------------------------------------
727nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
728//----------------------------------------------------------------------------------------
729: mPath(inString)
730{
731 if (mPath.IsEmpty())
732 return;
733
734 NS_ASSERTION(strstr((const char*)mPath, kFileURLPrefix) != (const char*)mPath, "URL passed as path");
735#if defined(XP_WIN) || defined(XP_OS2)
736 nsFileSpecHelpers::UnixToNative(mPath);
737#endif
738 // Make canonical and absolute.
739 nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
740#if defined(XP_WIN) || defined(XP_OS2)
741 NS_ASSERTION( mPath[1] == ':' || (mPath[0] == '\\' && mPath[1] == '\\'),
742 "unexpected canonical path" );
743 nsFileSpecHelpers::NativeToUnix(mPath);
744#endif
745}
746#endif
747
748#if !defined(XP_MAC)
749//----------------------------------------------------------------------------------------
750nsFilePath::nsFilePath(const nsFileURL& inOther)
751//----------------------------------------------------------------------------------------
752{
753 mPath = (const char*)inOther.mURL + kFileURLPrefixLength;
754 mPath.Unescape();
755}
756#endif
757
758#if (defined XP_UNIX || defined XP_BEOS)
759//----------------------------------------------------------------------------------------
760nsFilePath::nsFilePath(const nsFileSpec& inOther)
761//----------------------------------------------------------------------------------------
762: mPath(inOther.mPath)
763{
764}
765#endif // XP_UNIX
766
767//----------------------------------------------------------------------------------------
768nsFilePath::~nsFilePath()
769//----------------------------------------------------------------------------------------
770{
771}
772
773#if (defined XP_UNIX || defined XP_BEOS)
774//----------------------------------------------------------------------------------------
775void nsFilePath::operator = (const nsFileSpec& inOther)
776//----------------------------------------------------------------------------------------
777{
778 // XXX bug here, again if.
779
780 mPath = inOther.mPath;
781}
782#endif // XP_UNIX
783
784#if !defined(XP_MAC)
785//----------------------------------------------------------------------------------------
786void nsFilePath::operator = (const char* inString)
787//----------------------------------------------------------------------------------------
788{
789
790 NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
791 mPath = inString;
792 if (mPath.IsEmpty())
793 return;
794#if defined(XP_WIN) || defined(XP_OS2)
795 nsFileSpecHelpers::UnixToNative(mPath);
796#endif
797 // Make canonical and absolute.
798 nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
799#if defined(XP_WIN) || defined(XP_OS2)
800 nsFileSpecHelpers::NativeToUnix(mPath);
801#endif
802}
803#endif // XP_MAC
804
805#if !defined(XP_MAC)
806//----------------------------------------------------------------------------------------
807void nsFilePath::operator = (const nsFileURL& inOther)
808//----------------------------------------------------------------------------------------
809{
810 mPath = (const char*)nsFilePath(inOther);
811}
812#endif
813
814//----------------------------------------------------------------------------------------
815void nsFilePath::operator = (const nsFilePath& inOther)
816//----------------------------------------------------------------------------------------
817{
818 mPath = inOther.mPath;
819#if defined(XP_MAC)
820 mFileSpec = inOther.GetFileSpec();
821#endif
822}
823
824//----------------------------------------------------------------------------------------
825void nsFilePath::operator +=(const char* inRelativeUnixPath)
826//----------------------------------------------------------------------------------------
827{
828 NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
829
830 char* escapedPath = nsEscape(inRelativeUnixPath, url_Path);
831 mPath += escapedPath;
832 nsCRT::free(escapedPath);
833#if defined(XP_MAC)
834 mFileSpec += inRelativeUnixPath;
835#endif
836} // nsFilePath::operator +=
837
838//----------------------------------------------------------------------------------------
839nsFilePath nsFilePath::operator +(const char* inRelativeUnixPath) const
840//----------------------------------------------------------------------------------------
841{
842 NS_ASSERTION(inRelativeUnixPath, "Attempt append relative path with null path");
843
844 nsFilePath resultPath(*this);
845 resultPath += inRelativeUnixPath;
846 return resultPath;
847} // nsFilePath::operator +
848
849
850#if 0
851#pragma mark -
852#endif
853
854//========================================================================================
855// nsFileSpec implementation
856//========================================================================================
857
858#if !defined(XP_MAC)
859//----------------------------------------------------------------------------------------
860nsFileSpec::nsFileSpec()
861//----------------------------------------------------------------------------------------
862: mError(NS_OK) // XXX shouldn't this be NS_ERROR_NOT_INITIALIZED?
863{
864// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
865}
866
867//----------------------------------------------------------------------------------------
868void nsFileSpec::Clear()
869//----------------------------------------------------------------------------------------
870{
871 mPath.SetToEmpty();
872 mError = NS_ERROR_NOT_INITIALIZED;
873}
874
875#endif
876
877//----------------------------------------------------------------------------------------
878nsFileSpec::~nsFileSpec()
879//----------------------------------------------------------------------------------------
880{
881 // mPath cleans itself up
882}
883
884//----------------------------------------------------------------------------------------
885nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
886//----------------------------------------------------------------------------------------
887{
888 *this = inDescriptor;
889}
890
891//----------------------------------------------------------------------------------------
892nsFileSpec::nsFileSpec(const nsFileURL& inURL)
893//----------------------------------------------------------------------------------------
894{
895 *this = nsFilePath(inURL); // convert to unix path first
896}
897
898//----------------------------------------------------------------------------------------
899void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
900//----------------------------------------------------------------------------------------
901{
902 if (inSuggestedLeafName && *inSuggestedLeafName)
903 SetLeafName(inSuggestedLeafName);
904
905 MakeUnique();
906} // nsFileSpec::MakeUnique
907
908//----------------------------------------------------------------------------------------
909void nsFileSpec::MakeUnique()
910//----------------------------------------------------------------------------------------
911{
912 if (!Exists())
913 return;
914
915 char* leafName = GetLeafName();
916 if (!leafName)
917 return;
918
919 char* lastDot = strrchr(leafName, '.');
920 char* suffix = "";
921 if (lastDot)
922 {
923 suffix = nsCRT::strdup(lastDot); // include '.'
924 *lastDot = '\0'; // strip suffix and dot.
925 }
926 const int kMaxRootLength
927 = nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
928 if ((int)strlen(leafName) > (int)kMaxRootLength)
929 leafName[kMaxRootLength] = '\0';
930 for (short indx = 1; indx < 1000 && Exists(); indx++)
931 {
932 // start with "Picture-1.jpg" after "Picture.jpg" exists
933 char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
934 sprintf(newName, "%s-%d%s", leafName, indx, suffix);
935 SetLeafName(newName);
936 }
937 if (*suffix)
938 nsCRT::free(suffix);
939 nsCRT::free(leafName);
940} // nsFileSpec::MakeUnique
941
942//----------------------------------------------------------------------------------------
943void nsFileSpec::operator = (const nsFileURL& inURL)
944//----------------------------------------------------------------------------------------
945{
946 *this = nsFilePath(inURL); // convert to unix path first
947}
948
949//----------------------------------------------------------------------------------------
950void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
951//----------------------------------------------------------------------------------------
952{
953
954 nsCAutoString data;
955 inDescriptor.GetData(data);
956
957#if defined (XP_MAC) || defined(XP_MACOSX)
958 // Decode descriptor into a Handle (which is actually an AliasHandle)
959 char* decodedData = PL_Base64Decode(data.get(), data.Length(), nsnull);
960 Handle aliasH = nsnull;
961 mError = NS_FILE_RESULT(::PtrToHand(decodedData, &aliasH, (data.Length() * 3) / 4));
962 PR_Free(decodedData);
963 if (NS_FAILED(mError))
964 return; // not enough memory?
965#endif
966
967#if defined(XP_MAC)
968 Boolean changed;
969 mError = NS_FILE_RESULT(::ResolveAlias(nsnull, (AliasHandle)aliasH, &mSpec, &changed));
970 DisposeHandle((Handle) aliasH);
971 mPath.SetToEmpty();
972#elif defined(XP_MACOSX)
973 Boolean changed;
974 FSRef fileRef;
975 mError = NS_FILE_RESULT(::FSResolveAlias(nsnull, (AliasHandle)aliasH, &fileRef, &changed));
976 ::DisposeHandle(aliasH);
977
978 UInt8 pathBuf[PATH_MAX];
979 mError = NS_FILE_RESULT(::FSRefMakePath(&fileRef, pathBuf, PATH_MAX));
980 if (NS_FAILED(mError))
981 return;
982 mPath = (const char*)pathBuf;
983#else
984 mPath = data.get();
985 mError = NS_OK;
986#endif
987}
988
989//========================================================================================
990// UNIX & WIN nsFileSpec implementation
991//========================================================================================
992
993#if (defined XP_UNIX || defined XP_BEOS)
994//----------------------------------------------------------------------------------------
995nsFileSpec::nsFileSpec(const nsFilePath& inPath)
996//----------------------------------------------------------------------------------------
997: mPath((const char*)inPath)
998, mError(NS_OK)
999{
1000// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
1001}
1002
1003//----------------------------------------------------------------------------------------
1004void nsFileSpec::operator = (const nsFilePath& inPath)
1005//----------------------------------------------------------------------------------------
1006{
1007 mPath = (const char*)inPath;
1008 mError = NS_OK;
1009}
1010#endif //XP_UNIX
1011
1012#if (defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS))
1013//----------------------------------------------------------------------------------------
1014nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
1015//----------------------------------------------------------------------------------------
1016: mPath(inSpec.mPath)
1017, mError(NS_OK)
1018{
1019// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
1020}
1021
1022//----------------------------------------------------------------------------------------
1023nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
1024//----------------------------------------------------------------------------------------
1025: mPath(inString)
1026, mError(NS_OK)
1027{
1028// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
1029 // Make canonical and absolute.
1030 nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
1031}
1032
1033//----------------------------------------------------------------------------------------
1034nsFileSpec::nsFileSpec(const nsString& inString, PRBool inCreateDirs)
1035//----------------------------------------------------------------------------------------
1036: mPath(inString)
1037, mError(NS_OK)
1038{
1039// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
1040 // Make canonical and absolute.
1041 nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
1042}
1043
1044//----------------------------------------------------------------------------------------
1045void nsFileSpec::operator = (const nsFileSpec& inSpec)
1046//----------------------------------------------------------------------------------------
1047{
1048 mPath = inSpec.mPath;
1049 mError = inSpec.Error();
1050}
1051
1052//----------------------------------------------------------------------------------------
1053void nsFileSpec::operator = (const char* inString)
1054//----------------------------------------------------------------------------------------
1055{
1056 mPath = inString;
1057 // Make canonical and absolute.
1058 nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
1059 mError = NS_OK;
1060}
1061#endif //XP_UNIX,XP_WIN,XP_OS2,XP_BEOS
1062
1063//----------------------------------------------------------------------------------------
1064nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
1065//----------------------------------------------------------------------------------------
1066{
1067 NS_ASSERTION(inRelativePath, "Attempt to append name with a null string");
1068
1069 nsFileSpec resultSpec = *this;
1070 resultSpec += inRelativePath;
1071 return resultSpec;
1072} // nsFileSpec::operator +
1073
1074//----------------------------------------------------------------------------------------
1075PRBool nsFileSpec::operator == (const nsFileSpec& inOther) const
1076//----------------------------------------------------------------------------------------
1077{
1078
1079#if defined(XP_MAC)
1080 if ( inOther.mSpec.vRefNum == mSpec.vRefNum &&
1081 inOther.mSpec.parID == mSpec.parID &&
1082 EqualString(inOther.mSpec.name, mSpec.name, false, true))
1083 return PR_TRUE;
1084#else
1085 PRBool amEmpty = mPath.IsEmpty();
1086 PRBool heEmpty = inOther.mPath.IsEmpty();
1087 if (amEmpty) // we're the same if he's empty...
1088 return heEmpty;
1089 if (heEmpty) // ('cuz I'm not...)
1090 return PR_FALSE;
1091
1092 nsSimpleCharString str = mPath;
1093 nsSimpleCharString inStr = inOther.mPath;
1094
1095 // Length() is size of buffer, not length of string
1096 PRUint32 strLast = str.Length() - 1, inLast = inStr.Length() - 1;
1097#if defined(XP_WIN) || defined(XP_OS2)
1098#define DIR_SEPARATOR '\\' // XXX doesn't NSPR have this?
1099 /* windows does not care about case. */
1100#ifdef XP_OS2
1101#define DIR_STRCMP strcmp
1102#else
1103#define DIR_STRCMP _stricmp
1104#endif
1105#else
1106#define DIR_SEPARATOR '/'
1107#if defined(VMS)
1108#define DIR_STRCMP strcasecmp
1109#else
1110#define DIR_STRCMP strcmp
1111#endif
1112#endif
1113
1114 if(str[strLast] == DIR_SEPARATOR)
1115 str[strLast] = '\0';
1116
1117 if(inStr[inLast] == DIR_SEPARATOR)
1118 inStr[inLast] = '\0';
1119
1120 if (DIR_STRCMP(str, inStr ) == 0)
1121 return PR_TRUE;
1122#undef DIR_SEPARATOR
1123#undef DIR_STRCMP
1124#endif
1125 return PR_FALSE;
1126}
1127
1128//----------------------------------------------------------------------------------------
1129PRBool nsFileSpec::operator != (const nsFileSpec& inOther) const
1130//----------------------------------------------------------------------------------------
1131{
1132 return (! (*this == inOther) );
1133}
1134
1135#if !defined(XP_MAC)
1136//----------------------------------------------------------------------------------------
1137// This is the only automatic conversion to const char*
1138// that is provided, and it allows the
1139// path to be "passed" to NSPR file routines. This practice
1140// is VERY EVIL and should only be used to support legacy
1141// code. Using it guarantees bugs on Macintosh. The path is NOT allocated, so do
1142// not even think of deleting (or freeing) it.
1143const char* nsFileSpec::GetCString() const
1144//----------------------------------------------------------------------------------------
1145{
1146 return mPath;
1147}
1148#endif
1149
1150//----------------------------------------------------------------------------------------
1151// Is our spec a child of the provided parent?
1152PRBool nsFileSpec::IsChildOf(nsFileSpec &possibleParent)
1153//----------------------------------------------------------------------------------------
1154{
1155 nsFileSpec iter = *this, parent;
1156#ifdef DEBUG
1157 int depth = 0;
1158#endif
1159 while (1) {
1160#ifdef DEBUG
1161 // sanity
1162 NS_ASSERTION(depth < 100, "IsChildOf has lost its little mind");
1163 if (depth > 100)
1164 return PR_FALSE;
1165#endif
1166 if (iter == possibleParent)
1167 return PR_TRUE;
1168
1169 iter.GetParent(parent); // shouldn't this be an error on parent?
1170 if (iter.Failed())
1171 return PR_FALSE;
1172
1173 if (iter == parent) // hit bottom
1174 return PR_FALSE;
1175
1176 iter = parent;
1177#ifdef DEBUG
1178 depth++;
1179#endif
1180 }
1181
1182 // not reached, but I bet some compiler will whine
1183 return PR_FALSE;
1184}
1185
1186#if 0
1187#pragma mark -
1188#endif
1189
1190//========================================================================================
1191// class nsPersistentFileDescriptor
1192//========================================================================================
1193
1194//----------------------------------------------------------------------------------------
1195nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
1196//----------------------------------------------------------------------------------------
1197 : mDescriptorString(inDesc.mDescriptorString)
1198{
1199} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
1200
1201//----------------------------------------------------------------------------------------
1202void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
1203//----------------------------------------------------------------------------------------
1204{
1205 mDescriptorString = inDesc.mDescriptorString;
1206} // nsPersistentFileDescriptor::operator =
1207
1208//----------------------------------------------------------------------------------------
1209nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
1210//----------------------------------------------------------------------------------------
1211{
1212 *this = inSpec;
1213} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
1214
1215//----------------------------------------------------------------------------------------
1216void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
1217//----------------------------------------------------------------------------------------
1218{
1219#if defined(XP_MAC)
1220 if (inSpec.Error())
1221 return;
1222 AliasHandle aliasH;
1223 OSErr err = NewAlias(nil, inSpec.GetFSSpecPtr(), &aliasH);
1224 if (err != noErr)
1225 return;
1226
1227 PRUint32 bytes = GetHandleSize((Handle) aliasH);
1228 HLock((Handle) aliasH);
1229 char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
1230 DisposeHandle((Handle) aliasH);
1231
1232 mDescriptorString = buf;
1233 PR_Free(buf);
1234#elif defined(XP_MACOSX)
1235 if (inSpec.Error())
1236 return;
1237
1238 FSRef fileRef;
1239 Boolean isDir;
1240 OSErr err = ::FSPathMakeRef((const UInt8*)inSpec.GetCString(), &fileRef, &isDir);
1241 if (err != noErr)
1242 return;
1243
1244 AliasHandle aliasH;
1245 err = ::FSNewAlias(nsnull, &fileRef, &aliasH);
1246 if (err != noErr)
1247 return;
1248
1249 PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
1250 ::HLock((Handle)aliasH);
1251 char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
1252 ::DisposeHandle((Handle) aliasH);
1253
1254 mDescriptorString = buf;
1255 PR_Free(buf);
1256#else
1257 mDescriptorString = inSpec.GetCString();
1258#endif // XP_MAC
1259} // nsPersistentFileDescriptor::operator =
1260
1261//----------------------------------------------------------------------------------------
1262nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
1263//----------------------------------------------------------------------------------------
1264{
1265} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
1266
1267//----------------------------------------------------------------------------------------
1268void nsPersistentFileDescriptor::GetData(nsAFlatCString& outData) const
1269//----------------------------------------------------------------------------------------
1270{
1271 outData.Assign(mDescriptorString, mDescriptorString.Length());
1272}
1273
1274//----------------------------------------------------------------------------------------
1275void nsPersistentFileDescriptor::SetData(const nsAFlatCString& inData)
1276//----------------------------------------------------------------------------------------
1277{
1278 mDescriptorString.CopyFrom(inData.get(), inData.Length());
1279}
1280
1281//----------------------------------------------------------------------------------------
1282void nsPersistentFileDescriptor::SetData(const char* inData, PRInt32 inSize)
1283//----------------------------------------------------------------------------------------
1284{
1285 mDescriptorString.CopyFrom(inData, inSize);
1286}
1287
1288//========================================================================================
1289// class nsNSPRPath
1290//========================================================================================
1291
1292//----------------------------------------------------------------------------------------
1293nsNSPRPath::operator const char*() const
1294// NSPR expects a UNIX path on unix and Macintosh, but a native path on windows. NSPR
1295// cannot be changed, so we have to do the dirty work.
1296//----------------------------------------------------------------------------------------
1297{
1298#if defined(XP_WIN) || defined(XP_OS2)
1299 if (!modifiedNSPRPath)
1300 {
1301 // If this is the first call, initialize modifiedNSPRPath. Start by cloning
1302 // mFilePath, but strip the leading separator, if present
1303 const char* unixPath = (const char*)mFilePath;
1304 if (!unixPath)
1305 return nsnull;
1306
1307 ((nsNSPRPath*)this)->modifiedNSPRPath
1308 = nsCRT::strdup(*unixPath == '/' ? unixPath + 1: unixPath);
1309
1310 // Replace the bar
1311 if (modifiedNSPRPath[1] == '|')
1312 modifiedNSPRPath[1] = ':';
1313
1314 // Remove the ending separator only if it is not the last separator
1315 int len = strlen(modifiedNSPRPath);
1316 if (modifiedNSPRPath[len - 1 ] == '/' && modifiedNSPRPath[len - 2 ] != ':')
1317 modifiedNSPRPath[len - 1 ] = '\0';
1318 }
1319 return modifiedNSPRPath;
1320#else
1321 return (const char*)mFilePath;
1322#endif
1323}
1324
1325//----------------------------------------------------------------------------------------
1326nsNSPRPath::~nsNSPRPath()
1327//----------------------------------------------------------------------------------------
1328{
1329#if defined(XP_WIN) || defined(XP_OS2)
1330 if (modifiedNSPRPath)
1331 nsCRT::free(modifiedNSPRPath);
1332#endif
1333}
1334
1335
1336nsresult
1337NS_FileSpecToIFile(nsFileSpec* fileSpec, nsILocalFile* *result)
1338{
1339 nsresult rv;
1340
1341 nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
1342
1343 if (!file) return NS_ERROR_FAILURE;
1344
1345#if defined(XP_MAC)
1346 {
1347 FSSpec spec = fileSpec->GetFSSpec();
1348 nsCOMPtr<nsILocalFileMac> psmAppMacFile = do_QueryInterface(file, &rv);
1349 if (NS_FAILED(rv)) return rv;
1350 rv = psmAppMacFile->InitWithFSSpec(&spec);
1351 if (NS_FAILED(rv)) return rv;
1352 file = do_QueryInterface(psmAppMacFile, &rv);
1353 }
1354#else
1355 // XP_MACOSX: do this for OS X to preserve long filenames
1356 rv = file->InitWithNativePath(nsDependentCString(fileSpec->GetNativePathCString()));
1357#endif
1358 if (NS_FAILED(rv)) return rv;
1359
1360 *result = file;
1361 NS_ADDREF(*result);
1362 return NS_OK;
1363}
1364
1365
1366
1367
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette