Home | History | Annotate | Download | only in fileapi
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "DOMFilePath.h"
     33 
     34 #if ENABLE(FILE_SYSTEM)
     35 
     36 #include "RegularExpression.h"
     37 #include <wtf/Vector.h>
     38 #include <wtf/text/CString.h>
     39 
     40 namespace WebCore {
     41 
     42 const char DOMFilePath::separator = '/';
     43 const char DOMFilePath::root[] = "/";
     44 
     45 String DOMFilePath::append(const String& base, const String& components)
     46 {
     47     return ensureDirectoryPath(base) + components;
     48 }
     49 
     50 String DOMFilePath::ensureDirectoryPath(const String& path)
     51 {
     52     if (!DOMFilePath::endsWithSeparator(path)) {
     53         String newPath = path;
     54         newPath.append(DOMFilePath::separator);
     55         return newPath;
     56     }
     57     return path;
     58 }
     59 
     60 String DOMFilePath::getName(const String& path)
     61 {
     62     int index = path.reverseFind(DOMFilePath::separator);
     63     if (index != -1)
     64         return path.substring(index + 1);
     65     return path;
     66 }
     67 
     68 String DOMFilePath::getDirectory(const String& path)
     69 {
     70     int index = path.reverseFind(DOMFilePath::separator);
     71     if (index == 0)
     72         return DOMFilePath::root;
     73     if (index != -1)
     74         return path.substring(0, index);
     75     return ".";
     76 }
     77 
     78 bool DOMFilePath::isParentOf(const String& parent, const String& mayBeChild)
     79 {
     80     ASSERT(DOMFilePath::isAbsolute(parent));
     81     ASSERT(DOMFilePath::isAbsolute(mayBeChild));
     82     if (parent == DOMFilePath::root && mayBeChild != DOMFilePath::root)
     83         return true;
     84     if (parent.length() >= mayBeChild.length() || !mayBeChild.startsWith(parent, false))
     85         return false;
     86     if (mayBeChild[parent.length()] != DOMFilePath::separator)
     87         return false;
     88     return true;
     89 }
     90 
     91 String DOMFilePath::removeExtraParentReferences(const String& path)
     92 {
     93     ASSERT(DOMFilePath::isAbsolute(path));
     94     Vector<String> components;
     95     Vector<String> canonicalized;
     96     path.split(DOMFilePath::separator, components);
     97     for (size_t i = 0; i < components.size(); ++i) {
     98         if (components[i] == ".")
     99             continue;
    100         if (components[i] == "..") {
    101             if (canonicalized.size() > 0)
    102                 canonicalized.removeLast();
    103             continue;
    104         }
    105         canonicalized.append(components[i]);
    106     }
    107     if (canonicalized.isEmpty())
    108         return DOMFilePath::root;
    109     String result;
    110     for (size_t i = 0; i < canonicalized.size(); ++i) {
    111         result.append(DOMFilePath::separator);
    112         result.append(canonicalized[i]);
    113     }
    114     return result;
    115 }
    116 
    117 // Check the naming restrictions defined in FileSystem API 8.3.
    118 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
    119 bool DOMFilePath::isValidPath(const String& path)
    120 {
    121     if (path.isEmpty() || path == DOMFilePath::root)
    122         return true;
    123 
    124     // Chars 0-31 in UTF-8 prepresentation are not allowed.
    125     for (size_t i = 0; i < path.length(); ++i)
    126         if (path[i] < 32)
    127             return false;
    128 
    129     // Unallowed names.
    130     DEFINE_STATIC_LOCAL(RegularExpression, unallowedNamesRegExp1, ("(/|^)(CON|PRN|AUX|NUL)([\\./]|$)", TextCaseInsensitive));
    131     DEFINE_STATIC_LOCAL(RegularExpression, unallowedNamesRegExp2, ("(/|^)(COM|LPT)[1-9]([\\./]|$)", TextCaseInsensitive));
    132 
    133     if (unallowedNamesRegExp1.match(path) >= 0)
    134         return false;
    135     if (unallowedNamesRegExp2.match(path) >= 0)
    136         return false;
    137 
    138     // Names must not end with period or whitespace.
    139     DEFINE_STATIC_LOCAL(RegularExpression, endingRegExp, ("[\\.\\s](/|$)", TextCaseInsensitive));
    140 
    141     if (endingRegExp.match(path) >= 0)
    142         return false;
    143 
    144     // Unallowed chars: '\', '<', '>', ':', '?', '*', '"', '|'
    145     // (We don't check '/' here as this method takes paths as its argument.)
    146     DEFINE_STATIC_LOCAL(RegularExpression, unallowedCharsRegExp, ("[\\\\<>:\\?\\*\"|]", TextCaseInsensitive));
    147 
    148     if (unallowedCharsRegExp.match(path) >= 0)
    149         return false;
    150 
    151     return true;
    152 }
    153 
    154 bool DOMFilePath::isValidName(const String& name)
    155 {
    156     if (name.isEmpty())
    157         return true;
    158     // '/' is not allowed in name.
    159     if (name.contains('/'))
    160         return false;
    161     return isValidPath(name);
    162 }
    163 
    164 } // namespace WebCore
    165 
    166 #endif // ENABLE(FILE_SYSTEM)
    167