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
|
---|
61 | extern unsigned char* _mbsrchr( const unsigned char*, int);
|
---|
62 | #endif
|
---|
63 |
|
---|
64 | // return pointer to last instance of the given separator
|
---|
65 | static 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 | //----------------------------------------------------------------------------------------
|
---|
88 | nsSimpleCharString::nsSimpleCharString()
|
---|
89 | //----------------------------------------------------------------------------------------
|
---|
90 | : mData(nsnull)
|
---|
91 | {
|
---|
92 |
|
---|
93 | } // nsSimpleCharString::nsSimpleCharString
|
---|
94 |
|
---|
95 | //----------------------------------------------------------------------------------------
|
---|
96 | nsSimpleCharString::nsSimpleCharString(const char* inString)
|
---|
97 | //----------------------------------------------------------------------------------------
|
---|
98 | : mData(nsnull)
|
---|
99 | {
|
---|
100 | if (inString)
|
---|
101 | CopyFrom(inString, strlen(inString));
|
---|
102 | } // nsSimpleCharString::nsSimpleCharString
|
---|
103 |
|
---|
104 | //----------------------------------------------------------------------------------------
|
---|
105 | nsSimpleCharString::nsSimpleCharString(const nsString& inString)
|
---|
106 | //----------------------------------------------------------------------------------------
|
---|
107 | : mData(nsnull)
|
---|
108 | {
|
---|
109 | *this = inString;
|
---|
110 | } // nsSimpleCharString::nsSimpleCharString
|
---|
111 |
|
---|
112 | //----------------------------------------------------------------------------------------
|
---|
113 | nsSimpleCharString::nsSimpleCharString(const nsSimpleCharString& inOther)
|
---|
114 | //----------------------------------------------------------------------------------------
|
---|
115 | {
|
---|
116 | mData = inOther.mData;
|
---|
117 | AddRefData();
|
---|
118 | } // nsSimpleCharString::nsSimpleCharString
|
---|
119 |
|
---|
120 | //----------------------------------------------------------------------------------------
|
---|
121 | nsSimpleCharString::nsSimpleCharString(const char* inData, PRUint32 inLength)
|
---|
122 | //----------------------------------------------------------------------------------------
|
---|
123 | : mData(nsnull)
|
---|
124 | {
|
---|
125 | CopyFrom(inData, inLength);
|
---|
126 | } // nsSimpleCharString::nsSimpleCharString
|
---|
127 |
|
---|
128 | //----------------------------------------------------------------------------------------
|
---|
129 | nsSimpleCharString::~nsSimpleCharString()
|
---|
130 | //----------------------------------------------------------------------------------------
|
---|
131 | {
|
---|
132 | ReleaseData();
|
---|
133 | } // nsSimpleCharString::nsSimpleCharString
|
---|
134 |
|
---|
135 | //----------------------------------------------------------------------------------------
|
---|
136 | void nsSimpleCharString::operator = (const char* inString)
|
---|
137 | //----------------------------------------------------------------------------------------
|
---|
138 | {
|
---|
139 | if (inString)
|
---|
140 | CopyFrom(inString, strlen(inString));
|
---|
141 | else
|
---|
142 | SetToEmpty();
|
---|
143 | } // nsSimpleCharString::operator =
|
---|
144 |
|
---|
145 | //----------------------------------------------------------------------------------------
|
---|
146 | void 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 | //----------------------------------------------------------------------------------------
|
---|
157 | void 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 | //----------------------------------------------------------------------------------------
|
---|
168 | void 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 | //----------------------------------------------------------------------------------------
|
---|
179 | nsSimpleCharString nsSimpleCharString::operator + (const char* inOther) const
|
---|
180 | //----------------------------------------------------------------------------------------
|
---|
181 | {
|
---|
182 | nsSimpleCharString result(*this);
|
---|
183 | result += inOther;
|
---|
184 | return result;
|
---|
185 | } // nsSimpleCharString::operator =
|
---|
186 |
|
---|
187 | //----------------------------------------------------------------------------------------
|
---|
188 | void 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 | //----------------------------------------------------------------------------------------
|
---|
203 | void 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 | //----------------------------------------------------------------------------------------
|
---|
218 | void nsSimpleCharString::SetToEmpty()
|
---|
219 | //----------------------------------------------------------------------------------------
|
---|
220 | {
|
---|
221 | ReleaseData();
|
---|
222 | } // nsSimpleCharString::SetToEmpty
|
---|
223 |
|
---|
224 | //----------------------------------------------------------------------------------------
|
---|
225 | void 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 | //----------------------------------------------------------------------------------------
|
---|
239 | void nsSimpleCharString::AddRefData()
|
---|
240 | //----------------------------------------------------------------------------------------
|
---|
241 | {
|
---|
242 | if (mData)
|
---|
243 | ++mData->mRefCount;
|
---|
244 | } // nsSimpleCharString::AddRefData
|
---|
245 |
|
---|
246 | //----------------------------------------------------------------------------------------
|
---|
247 | void 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 | //----------------------------------------------------------------------------------------
|
---|
259 | inline PRUint32 CalculateAllocLength(PRUint32 logicalLength)
|
---|
260 | // Round up to the next multiple of 256.
|
---|
261 | //----------------------------------------------------------------------------------------
|
---|
262 | {
|
---|
263 | return ((1 + (logicalLength >> 8)) << 8);
|
---|
264 | }
|
---|
265 |
|
---|
266 | //----------------------------------------------------------------------------------------
|
---|
267 | void 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 | //========================================================================================
|
---|
309 | NS_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 | //----------------------------------------------------------------------------------------
|
---|
328 | nsresult 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 | //----------------------------------------------------------------------------------------
|
---|
337 | void 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 | //----------------------------------------------------------------------------------------
|
---|
384 | char* 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 | //----------------------------------------------------------------------------------------
|
---|
425 | void 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 | //----------------------------------------------------------------------------------------
|
---|
531 | nsFileURL::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 | //----------------------------------------------------------------------------------------
|
---|
549 | nsFileURL::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 | //----------------------------------------------------------------------------------------
|
---|
568 | nsFileURL::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 | //----------------------------------------------------------------------------------------
|
---|
579 | nsFileURL::nsFileURL(const nsFilePath& inOther)
|
---|
580 | //----------------------------------------------------------------------------------------
|
---|
581 | {
|
---|
582 | *this = inOther;
|
---|
583 | } // nsFileURL::nsFileURL
|
---|
584 | #endif
|
---|
585 |
|
---|
586 | #if !defined(XP_MAC)
|
---|
587 | //----------------------------------------------------------------------------------------
|
---|
588 | nsFileURL::nsFileURL(const nsFileSpec& inOther)
|
---|
589 | //----------------------------------------------------------------------------------------
|
---|
590 | {
|
---|
591 | *this = inOther;
|
---|
592 | } // nsFileURL::nsFileURL
|
---|
593 | #endif
|
---|
594 |
|
---|
595 | //----------------------------------------------------------------------------------------
|
---|
596 | nsFileURL::~nsFileURL()
|
---|
597 | //----------------------------------------------------------------------------------------
|
---|
598 | {
|
---|
599 | }
|
---|
600 |
|
---|
601 | #if !defined(XP_MAC)
|
---|
602 | //----------------------------------------------------------------------------------------
|
---|
603 | void 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 | //----------------------------------------------------------------------------------------
|
---|
615 | void 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 | //----------------------------------------------------------------------------------------
|
---|
627 | nsFileURL nsFileURL::operator +(const char* inRelativeUnixPath) const
|
---|
628 | //----------------------------------------------------------------------------------------
|
---|
629 | {
|
---|
630 | nsFileURL result(*this);
|
---|
631 | result += inRelativeUnixPath;
|
---|
632 | return result;
|
---|
633 | } // nsFileURL::operator +
|
---|
634 |
|
---|
635 | //----------------------------------------------------------------------------------------
|
---|
636 | void 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 | //----------------------------------------------------------------------------------------
|
---|
647 | void 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 | //----------------------------------------------------------------------------------------
|
---|
671 | void 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 | //----------------------------------------------------------------------------------------
|
---|
689 | nsFilePath::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 | //----------------------------------------------------------------------------------------
|
---|
700 | nsFilePath::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 | //----------------------------------------------------------------------------------------
|
---|
727 | nsFilePath::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 | //----------------------------------------------------------------------------------------
|
---|
750 | nsFilePath::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 | //----------------------------------------------------------------------------------------
|
---|
760 | nsFilePath::nsFilePath(const nsFileSpec& inOther)
|
---|
761 | //----------------------------------------------------------------------------------------
|
---|
762 | : mPath(inOther.mPath)
|
---|
763 | {
|
---|
764 | }
|
---|
765 | #endif // XP_UNIX
|
---|
766 |
|
---|
767 | //----------------------------------------------------------------------------------------
|
---|
768 | nsFilePath::~nsFilePath()
|
---|
769 | //----------------------------------------------------------------------------------------
|
---|
770 | {
|
---|
771 | }
|
---|
772 |
|
---|
773 | #if (defined XP_UNIX || defined XP_BEOS)
|
---|
774 | //----------------------------------------------------------------------------------------
|
---|
775 | void 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 | //----------------------------------------------------------------------------------------
|
---|
786 | void 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 | //----------------------------------------------------------------------------------------
|
---|
807 | void nsFilePath::operator = (const nsFileURL& inOther)
|
---|
808 | //----------------------------------------------------------------------------------------
|
---|
809 | {
|
---|
810 | mPath = (const char*)nsFilePath(inOther);
|
---|
811 | }
|
---|
812 | #endif
|
---|
813 |
|
---|
814 | //----------------------------------------------------------------------------------------
|
---|
815 | void 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 | //----------------------------------------------------------------------------------------
|
---|
825 | void 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 | //----------------------------------------------------------------------------------------
|
---|
839 | nsFilePath 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 | //----------------------------------------------------------------------------------------
|
---|
860 | nsFileSpec::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 | //----------------------------------------------------------------------------------------
|
---|
868 | void nsFileSpec::Clear()
|
---|
869 | //----------------------------------------------------------------------------------------
|
---|
870 | {
|
---|
871 | mPath.SetToEmpty();
|
---|
872 | mError = NS_ERROR_NOT_INITIALIZED;
|
---|
873 | }
|
---|
874 |
|
---|
875 | #endif
|
---|
876 |
|
---|
877 | //----------------------------------------------------------------------------------------
|
---|
878 | nsFileSpec::~nsFileSpec()
|
---|
879 | //----------------------------------------------------------------------------------------
|
---|
880 | {
|
---|
881 | // mPath cleans itself up
|
---|
882 | }
|
---|
883 |
|
---|
884 | //----------------------------------------------------------------------------------------
|
---|
885 | nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
|
---|
886 | //----------------------------------------------------------------------------------------
|
---|
887 | {
|
---|
888 | *this = inDescriptor;
|
---|
889 | }
|
---|
890 |
|
---|
891 | //----------------------------------------------------------------------------------------
|
---|
892 | nsFileSpec::nsFileSpec(const nsFileURL& inURL)
|
---|
893 | //----------------------------------------------------------------------------------------
|
---|
894 | {
|
---|
895 | *this = nsFilePath(inURL); // convert to unix path first
|
---|
896 | }
|
---|
897 |
|
---|
898 | //----------------------------------------------------------------------------------------
|
---|
899 | void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
|
---|
900 | //----------------------------------------------------------------------------------------
|
---|
901 | {
|
---|
902 | if (inSuggestedLeafName && *inSuggestedLeafName)
|
---|
903 | SetLeafName(inSuggestedLeafName);
|
---|
904 |
|
---|
905 | MakeUnique();
|
---|
906 | } // nsFileSpec::MakeUnique
|
---|
907 |
|
---|
908 | //----------------------------------------------------------------------------------------
|
---|
909 | void 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 | //----------------------------------------------------------------------------------------
|
---|
943 | void nsFileSpec::operator = (const nsFileURL& inURL)
|
---|
944 | //----------------------------------------------------------------------------------------
|
---|
945 | {
|
---|
946 | *this = nsFilePath(inURL); // convert to unix path first
|
---|
947 | }
|
---|
948 |
|
---|
949 | //----------------------------------------------------------------------------------------
|
---|
950 | void 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 | //----------------------------------------------------------------------------------------
|
---|
995 | nsFileSpec::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 | //----------------------------------------------------------------------------------------
|
---|
1004 | void 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 | //----------------------------------------------------------------------------------------
|
---|
1014 | nsFileSpec::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 | //----------------------------------------------------------------------------------------
|
---|
1023 | nsFileSpec::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 | //----------------------------------------------------------------------------------------
|
---|
1034 | nsFileSpec::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 | //----------------------------------------------------------------------------------------
|
---|
1045 | void nsFileSpec::operator = (const nsFileSpec& inSpec)
|
---|
1046 | //----------------------------------------------------------------------------------------
|
---|
1047 | {
|
---|
1048 | mPath = inSpec.mPath;
|
---|
1049 | mError = inSpec.Error();
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | //----------------------------------------------------------------------------------------
|
---|
1053 | void 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 | //----------------------------------------------------------------------------------------
|
---|
1064 | nsFileSpec 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 | //----------------------------------------------------------------------------------------
|
---|
1075 | PRBool 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 | //----------------------------------------------------------------------------------------
|
---|
1129 | PRBool 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.
|
---|
1143 | const char* nsFileSpec::GetCString() const
|
---|
1144 | //----------------------------------------------------------------------------------------
|
---|
1145 | {
|
---|
1146 | return mPath;
|
---|
1147 | }
|
---|
1148 | #endif
|
---|
1149 |
|
---|
1150 | //----------------------------------------------------------------------------------------
|
---|
1151 | // Is our spec a child of the provided parent?
|
---|
1152 | PRBool 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 | //----------------------------------------------------------------------------------------
|
---|
1195 | nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
|
---|
1196 | //----------------------------------------------------------------------------------------
|
---|
1197 | : mDescriptorString(inDesc.mDescriptorString)
|
---|
1198 | {
|
---|
1199 | } // nsPersistentFileDescriptor::nsPersistentFileDescriptor
|
---|
1200 |
|
---|
1201 | //----------------------------------------------------------------------------------------
|
---|
1202 | void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
|
---|
1203 | //----------------------------------------------------------------------------------------
|
---|
1204 | {
|
---|
1205 | mDescriptorString = inDesc.mDescriptorString;
|
---|
1206 | } // nsPersistentFileDescriptor::operator =
|
---|
1207 |
|
---|
1208 | //----------------------------------------------------------------------------------------
|
---|
1209 | nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
|
---|
1210 | //----------------------------------------------------------------------------------------
|
---|
1211 | {
|
---|
1212 | *this = inSpec;
|
---|
1213 | } // nsPersistentFileDescriptor::nsPersistentFileDescriptor
|
---|
1214 |
|
---|
1215 | //----------------------------------------------------------------------------------------
|
---|
1216 | void 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 | //----------------------------------------------------------------------------------------
|
---|
1262 | nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
|
---|
1263 | //----------------------------------------------------------------------------------------
|
---|
1264 | {
|
---|
1265 | } // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
|
---|
1266 |
|
---|
1267 | //----------------------------------------------------------------------------------------
|
---|
1268 | void nsPersistentFileDescriptor::GetData(nsAFlatCString& outData) const
|
---|
1269 | //----------------------------------------------------------------------------------------
|
---|
1270 | {
|
---|
1271 | outData.Assign(mDescriptorString, mDescriptorString.Length());
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | //----------------------------------------------------------------------------------------
|
---|
1275 | void nsPersistentFileDescriptor::SetData(const nsAFlatCString& inData)
|
---|
1276 | //----------------------------------------------------------------------------------------
|
---|
1277 | {
|
---|
1278 | mDescriptorString.CopyFrom(inData.get(), inData.Length());
|
---|
1279 | }
|
---|
1280 |
|
---|
1281 | //----------------------------------------------------------------------------------------
|
---|
1282 | void nsPersistentFileDescriptor::SetData(const char* inData, PRInt32 inSize)
|
---|
1283 | //----------------------------------------------------------------------------------------
|
---|
1284 | {
|
---|
1285 | mDescriptorString.CopyFrom(inData, inSize);
|
---|
1286 | }
|
---|
1287 |
|
---|
1288 | //========================================================================================
|
---|
1289 | // class nsNSPRPath
|
---|
1290 | //========================================================================================
|
---|
1291 |
|
---|
1292 | //----------------------------------------------------------------------------------------
|
---|
1293 | nsNSPRPath::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 | //----------------------------------------------------------------------------------------
|
---|
1326 | nsNSPRPath::~nsNSPRPath()
|
---|
1327 | //----------------------------------------------------------------------------------------
|
---|
1328 | {
|
---|
1329 | #if defined(XP_WIN) || defined(XP_OS2)
|
---|
1330 | if (modifiedNSPRPath)
|
---|
1331 | nsCRT::free(modifiedNSPRPath);
|
---|
1332 | #endif
|
---|
1333 | }
|
---|
1334 |
|
---|
1335 |
|
---|
1336 | nsresult
|
---|
1337 | NS_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 |
|
---|