xpcom/io/nsLocalFileCommon.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "nsIServiceManager.h"
     7 #include "nsLocalFile.h" // includes platform-specific headers
     9 #include "nsString.h"
    10 #include "nsCOMPtr.h"
    11 #include "nsReadableUtils.h"
    12 #include "nsPrintfCString.h"
    13 #include "nsCRT.h"
    14 #include "nsNativeCharsetUtils.h"
    15 #include "nsUTF8Utils.h"
    17 #ifdef XP_WIN
    18 #include <string.h>
    19 #endif
    22 void NS_StartupLocalFile()
    23 {
    24     nsLocalFile::GlobalInit();
    25 }
    27 void NS_ShutdownLocalFile()
    28 {
    29     nsLocalFile::GlobalShutdown();
    30 }
    32 #if !defined(MOZ_WIDGET_COCOA) && !defined(XP_WIN)
    33 NS_IMETHODIMP
    34 nsLocalFile::InitWithFile(nsIFile *aFile)
    35 {
    36     if (NS_WARN_IF(!aFile))
    37         return NS_ERROR_INVALID_ARG;
    39     nsAutoCString path;
    40     aFile->GetNativePath(path);
    41     if (path.IsEmpty())
    42         return NS_ERROR_INVALID_ARG;
    43     return InitWithNativePath(path); 
    44 }
    45 #endif
    47 #define kMaxFilenameLength 255
    48 #define kMaxExtensionLength 100
    49 #define kMaxSequenceNumberLength 5 // "-9999"
    50 // requirement: kMaxExtensionLength < kMaxFilenameLength - kMaxSequenceNumberLength
    52 NS_IMETHODIMP
    53 nsLocalFile::CreateUnique(uint32_t type, uint32_t attributes)
    54 {
    55     nsresult rv;
    56     bool longName;
    58 #ifdef XP_WIN
    59     nsAutoString pathName, leafName, rootName, suffix;
    60     rv = GetPath(pathName);
    61 #else
    62     nsAutoCString pathName, leafName, rootName, suffix; 
    63     rv = GetNativePath(pathName);
    64 #endif
    65     if (NS_FAILED(rv))
    66         return rv;
    68     longName = (pathName.Length() + kMaxSequenceNumberLength >
    69                 kMaxFilenameLength);
    70     if (!longName)
    71     {
    72         rv = Create(type, attributes);
    73         if (rv != NS_ERROR_FILE_ALREADY_EXISTS)
    74             return rv;
    75     }
    77 #ifdef XP_WIN
    78     rv = GetLeafName(leafName);
    79     if (NS_FAILED(rv))
    80         return rv;
    82     const int32_t lastDot = leafName.RFindChar(char16_t('.'));
    83 #else
    84     rv = GetNativeLeafName(leafName);
    85     if (NS_FAILED(rv))
    86         return rv;
    88     const int32_t lastDot = leafName.RFindChar('.');
    89 #endif
    91     if (lastDot == kNotFound)
    92     {
    93         rootName = leafName;
    94     } 
    95     else
    96     {
    97         suffix = Substring(leafName, lastDot);      // include '.'
    98         rootName = Substring(leafName, 0, lastDot); // strip suffix and dot
    99     }
   101     if (longName)
   102     {
   103         int32_t maxRootLength = (kMaxFilenameLength -
   104                                  (pathName.Length() - leafName.Length()) -
   105                                  suffix.Length() - kMaxSequenceNumberLength);
   107         // We cannot create an item inside a directory whose name is too long.
   108         // Also, ensure that at least one character remains after we truncate
   109         // the root name, as we don't want to end up with an empty leaf name.
   110         if (maxRootLength < 2)
   111             return NS_ERROR_FILE_UNRECOGNIZED_PATH;
   113 #ifdef XP_WIN
   114         // ensure that we don't cut the name in mid-UTF16-character
   115         rootName.SetLength(NS_IS_LOW_SURROGATE(rootName[maxRootLength]) ?
   116                            maxRootLength - 1 : maxRootLength);
   117         SetLeafName(rootName + suffix);
   118 #else
   119         if (NS_IsNativeUTF8())
   120         {
   121             // ensure that we don't cut the name in mid-UTF8-character
   122             // (assume the name is valid UTF8 to begin with)
   123             while (UTF8traits::isInSeq(rootName[maxRootLength]))
   124                 --maxRootLength;
   126             // Another check to avoid ending up with an empty leaf name.
   127             if (maxRootLength == 0 && suffix.IsEmpty())
   128                 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
   129         }
   131         rootName.SetLength(maxRootLength);
   132         SetNativeLeafName(rootName + suffix);
   133 #endif
   134         nsresult rv = Create(type, attributes);
   135         if (rv != NS_ERROR_FILE_ALREADY_EXISTS)
   136             return rv;
   137     }
   139     for (int indx = 1; indx < 10000; indx++)
   140     {
   141         // start with "Picture-1.jpg" after "Picture.jpg" exists
   142 #ifdef XP_WIN
   143         SetLeafName(rootName +
   144                     NS_ConvertASCIItoUTF16(nsPrintfCString("-%d", indx)) +
   145                     suffix);
   146 #else
   147         SetNativeLeafName(rootName + nsPrintfCString("-%d", indx) + suffix);
   148 #endif
   149         rv = Create(type, attributes);
   150         if (NS_SUCCEEDED(rv) || rv != NS_ERROR_FILE_ALREADY_EXISTS) 
   151             return rv;
   152     }
   154     // The disk is full, sort of
   155     return NS_ERROR_FILE_TOO_BIG;
   156 }
   158 #if defined(XP_WIN)
   159 static const char16_t kPathSeparatorChar       = '\\';
   160 #elif defined(XP_UNIX)
   161 static const char16_t kPathSeparatorChar       = '/';
   162 #else
   163 #error Need to define file path separator for your platform
   164 #endif
   166 static int32_t SplitPath(char16_t *path, char16_t **nodeArray, int32_t arrayLen)
   167 {
   168     if (*path == 0)
   169       return 0;
   171     char16_t **nodePtr = nodeArray;
   172     if (*path == kPathSeparatorChar)
   173       path++;    
   174     *nodePtr++ = path;
   176     for (char16_t *cp = path; *cp != 0; cp++) {
   177       if (*cp == kPathSeparatorChar) {
   178         *cp++ = 0;
   179         if (*cp == 0)
   180           break;
   181         if (nodePtr - nodeArray >= arrayLen)
   182           return -1;
   183         *nodePtr++ = cp;
   184       }
   185     }
   186     return nodePtr - nodeArray;
   187 }
   190 NS_IMETHODIMP
   191 nsLocalFile::GetRelativeDescriptor(nsIFile *fromFile, nsACString& _retval)
   192 {
   193     if (NS_WARN_IF(!fromFile))
   194         return NS_ERROR_INVALID_ARG;
   195     const int32_t kMaxNodesInPath = 32;
   197     //
   198     // _retval will be UTF-8 encoded
   199     // 
   201     nsresult rv;
   202     _retval.Truncate(0);
   204     nsAutoString thisPath, fromPath;
   205     char16_t *thisNodes[kMaxNodesInPath], *fromNodes[kMaxNodesInPath];
   206     int32_t  thisNodeCnt, fromNodeCnt, nodeIndex;
   208     rv = GetPath(thisPath);
   209     if (NS_FAILED(rv))
   210         return rv;
   211     rv = fromFile->GetPath(fromPath);
   212     if (NS_FAILED(rv))
   213         return rv;
   215     // get raw pointer to mutable string buffer
   216     char16_t *thisPathPtr; thisPath.BeginWriting(thisPathPtr);
   217     char16_t *fromPathPtr; fromPath.BeginWriting(fromPathPtr);
   219     thisNodeCnt = SplitPath(thisPathPtr, thisNodes, kMaxNodesInPath);
   220     fromNodeCnt = SplitPath(fromPathPtr, fromNodes, kMaxNodesInPath);
   221     if (thisNodeCnt < 0 || fromNodeCnt < 0)
   222       return NS_ERROR_FAILURE;
   224     for (nodeIndex = 0; nodeIndex < thisNodeCnt && nodeIndex < fromNodeCnt; ++nodeIndex) {
   225 #ifdef XP_WIN
   226       if (_wcsicmp(char16ptr_t(thisNodes[nodeIndex]), char16ptr_t(fromNodes[nodeIndex])))
   227         break;
   228 #else
   229       if (nsCRT::strcmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
   230         break;
   231 #endif
   232     }
   234     int32_t branchIndex = nodeIndex;
   235     for (nodeIndex = branchIndex; nodeIndex < fromNodeCnt; nodeIndex++) 
   236       _retval.AppendLiteral("../");
   237     for (nodeIndex = branchIndex; nodeIndex < thisNodeCnt; nodeIndex++) {
   238       NS_ConvertUTF16toUTF8 nodeStr(thisNodes[nodeIndex]);
   239       _retval.Append(nodeStr);
   240       if (nodeIndex + 1 < thisNodeCnt)
   241         _retval.Append('/');
   242     }
   244     return NS_OK;
   245 }
   247 NS_IMETHODIMP
   248 nsLocalFile::SetRelativeDescriptor(nsIFile *fromFile, const nsACString& relativeDesc)
   249 {
   250     NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../");
   252     nsCOMPtr<nsIFile> targetFile;
   253     nsresult rv = fromFile->Clone(getter_AddRefs(targetFile));
   254     if (NS_FAILED(rv))
   255         return rv;
   257     //
   258     // relativeDesc is UTF-8 encoded
   259     // 
   261     nsCString::const_iterator strBegin, strEnd;
   262     relativeDesc.BeginReading(strBegin);
   263     relativeDesc.EndReading(strEnd);
   265     nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd);
   266     nsCString::const_iterator pos(strBegin);
   268     nsCOMPtr<nsIFile> parentDir;
   269     while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) {
   270         rv = targetFile->GetParent(getter_AddRefs(parentDir));
   271         if (NS_FAILED(rv))
   272             return rv;
   273         if (!parentDir)
   274             return NS_ERROR_FILE_UNRECOGNIZED_PATH;
   275         targetFile = parentDir;
   277         nodeBegin = nodeEnd;
   278         pos = nodeEnd;
   279         nodeEnd = strEnd;
   280     }
   282     nodeBegin = nodeEnd = pos;
   283     while (nodeEnd != strEnd) {
   284       FindCharInReadable('/', nodeEnd, strEnd);
   285       targetFile->Append(NS_ConvertUTF8toUTF16(Substring(nodeBegin, nodeEnd)));
   286       if (nodeEnd != strEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
   287         ++nodeEnd;
   288       nodeBegin = nodeEnd;
   289     }
   291     return InitWithFile(targetFile);
   292 }

mercurial