tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ExtractingFilePath.cpp (5806B)


      1 // ExtractingFilePath.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../Common/Wildcard.h"
      6 
      7 #include "../../../Windows/FileName.h"
      8 
      9 #include "ExtractingFilePath.h"
     10 
     11 bool g_PathTrailReplaceMode =
     12    #ifdef _WIN32
     13      true
     14    #else
     15      false
     16    #endif
     17    ;
     18 
     19 
     20 static void ReplaceIncorrectChars(UString &s)
     21 {
     22  {
     23    for (unsigned i = 0; i < s.Len(); i++)
     24    {
     25      wchar_t c = s[i];
     26      if (
     27          #ifdef _WIN32
     28          c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '"'
     29          || c == '/'
     30          // || c == 0x202E // RLO
     31          ||
     32          #endif
     33          c == WCHAR_PATH_SEPARATOR)
     34        s.ReplaceOneCharAtPos(i, '_');
     35    }
     36  }
     37  
     38  if (g_PathTrailReplaceMode)
     39  {
     40    /*
     41    // if (g_PathTrailReplaceMode == 1)
     42    {
     43      if (!s.IsEmpty())
     44      {
     45        wchar_t c = s.Back();
     46        if (c == '.' || c == ' ')
     47        {
     48          // s += (wchar_t)(0x9c); // STRING TERMINATOR
     49          s += (wchar_t)'_';
     50        }
     51      }
     52    }
     53    else
     54    */
     55    {
     56      unsigned i;
     57      for (i = s.Len(); i != 0;)
     58      {
     59        wchar_t c = s[i - 1];
     60        if (c != '.' && c != ' ')
     61          break;
     62        i--;
     63        s.ReplaceOneCharAtPos(i, '_');
     64        // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));
     65      }
     66      /*
     67      if (g_PathTrailReplaceMode > 1 && i != s.Len())
     68      {
     69        s.DeleteFrom(i);
     70      }
     71      */
     72    }
     73  }
     74 }
     75 
     76 #ifdef _WIN32
     77 
     78 /* WinXP-64 doesn't support ':', '\\' and '/' symbols in name of alt stream.
     79   But colon in postfix ":$DATA" is allowed.
     80   WIN32 functions don't allow empty alt stream name "name:" */
     81 
     82 void Correct_AltStream_Name(UString &s)
     83 {
     84  unsigned len = s.Len();
     85  const unsigned kPostfixSize = 6;
     86  if (s.Len() >= kPostfixSize
     87      && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), ":$DATA"))
     88    len -= kPostfixSize;
     89  for (unsigned i = 0; i < len; i++)
     90  {
     91    wchar_t c = s[i];
     92    if (c == ':' || c == '\\' || c == '/'
     93        || c == 0x202E // RLO
     94        )
     95      s.ReplaceOneCharAtPos(i, '_');
     96  }
     97  if (s.IsEmpty())
     98    s = '_';
     99 }
    100 
    101 static const unsigned g_ReservedWithNum_Index = 4;
    102 
    103 static const char * const g_ReservedNames[] =
    104 {
    105  "CON", "PRN", "AUX", "NUL",
    106  "COM", "LPT"
    107 };
    108 
    109 static bool IsSupportedName(const UString &name)
    110 {
    111  for (unsigned i = 0; i < ARRAY_SIZE(g_ReservedNames); i++)
    112  {
    113    const char *reservedName = g_ReservedNames[i];
    114    unsigned len = MyStringLen(reservedName);
    115    if (name.Len() < len)
    116      continue;
    117    if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))
    118      continue;
    119    if (i >= g_ReservedWithNum_Index)
    120    {
    121      wchar_t c = name[len];
    122      if (c < L'0' || c > L'9')
    123        continue;
    124      len++;
    125    }
    126    for (;;)
    127    {
    128      wchar_t c = name[len++];
    129      if (c == 0 || c == '.')
    130        return false;
    131      if (c != ' ')
    132        break;
    133    }
    134  }
    135  return true;
    136 }
    137 
    138 static void CorrectUnsupportedName(UString &name)
    139 {
    140  if (!IsSupportedName(name))
    141    name.InsertAtFront(L'_');
    142 }
    143 
    144 #endif
    145 
    146 static void Correct_PathPart(UString &s)
    147 {
    148  // "." and ".."
    149  if (s.IsEmpty())
    150    return;
    151 
    152  if (s[0] == '.' && (s[1] == 0 || s[1] == '.' && s[2] == 0))
    153    s.Empty();
    154  #ifdef _WIN32
    155  else
    156    ReplaceIncorrectChars(s);
    157  #endif
    158 }
    159 
    160 // static const char * const k_EmptyReplaceName = "[]";
    161 static const char k_EmptyReplaceName = '_';
    162 
    163 UString Get_Correct_FsFile_Name(const UString &name)
    164 {
    165  UString res = name;
    166  Correct_PathPart(res);
    167  
    168  #ifdef _WIN32
    169  CorrectUnsupportedName(res);
    170  #endif
    171  
    172  if (res.IsEmpty())
    173    res = k_EmptyReplaceName;
    174  return res;
    175 }
    176 
    177 
    178 void Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)
    179 {
    180  unsigned i = 0;
    181 
    182  if (absIsAllowed)
    183  {
    184    #if defined(_WIN32) && !defined(UNDER_CE)
    185    bool isDrive = false;
    186    #endif
    187    
    188    if (parts[0].IsEmpty())
    189    {
    190      i = 1;
    191      #if defined(_WIN32) && !defined(UNDER_CE)
    192      if (parts.Size() > 1 && parts[1].IsEmpty())
    193      {
    194        i = 2;
    195        if (parts.Size() > 2 && parts[2] == L"?")
    196        {
    197          i = 3;
    198          if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))
    199          {
    200            isDrive = true;
    201            i = 4;
    202          }
    203        }
    204      }
    205      #endif
    206    }
    207    #if defined(_WIN32) && !defined(UNDER_CE)
    208    else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))
    209    {
    210      isDrive = true;
    211      i = 1;
    212    }
    213 
    214    if (isDrive)
    215    {
    216      // we convert "c:name" to "c:\name", if absIsAllowed path.
    217      UString &ds = parts[i - 1];
    218      if (ds.Len() > 2)
    219      {
    220        parts.Insert(i, ds.Ptr(2));
    221        ds.DeleteFrom(2);
    222      }
    223    }
    224    #endif
    225  }
    226 
    227  if (i != 0)
    228    keepAndReplaceEmptyPrefixes = false;
    229 
    230  for (; i < parts.Size();)
    231  {
    232    UString &s = parts[i];
    233 
    234    Correct_PathPart(s);
    235 
    236    if (s.IsEmpty())
    237    {
    238      if (!keepAndReplaceEmptyPrefixes)
    239        if (isDir || i != parts.Size() - 1)
    240        {
    241          parts.Delete(i);
    242          continue;
    243        }
    244      s = k_EmptyReplaceName;
    245    }
    246    else
    247    {
    248      keepAndReplaceEmptyPrefixes = false;
    249      #ifdef _WIN32
    250      CorrectUnsupportedName(s);
    251      #endif
    252    }
    253    
    254    i++;
    255  }
    256 
    257  if (!isDir)
    258  {
    259    if (parts.IsEmpty())
    260      parts.Add((UString)k_EmptyReplaceName);
    261    else
    262    {
    263      UString &s = parts.Back();
    264      if (s.IsEmpty())
    265        s = k_EmptyReplaceName;
    266    }
    267  }
    268 }
    269 
    270 UString MakePathFromParts(const UStringVector &parts)
    271 {
    272  UString s;
    273  FOR_VECTOR (i, parts)
    274  {
    275    if (i != 0)
    276      s.Add_PathSepar();
    277    s += parts[i];
    278  }
    279  return s;
    280 }