"Fossies" - the Fresh Open Source Software Archive

Member "unrar/extinfo.cpp" (4 May 2022, 4965 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "extinfo.cpp" see the Fossies "Dox" file reference documentation.

    1 #include "rar.hpp"
    2 
    3 #include "hardlinks.cpp"
    4 #include "win32stm.cpp"
    5 
    6 #ifdef _WIN_ALL
    7 #include "win32acl.cpp"
    8 #include "win32lnk.cpp"
    9 #endif
   10 
   11 #ifdef _UNIX
   12 #include "uowners.cpp"
   13 #ifdef SAVE_LINKS
   14 #include "ulinks.cpp"
   15 #endif
   16 #endif
   17 
   18 
   19 
   20 // RAR2 service header extra records.
   21 #ifndef SFX_MODULE
   22 void SetExtraInfo20(CommandData *Cmd,Archive &Arc,wchar *Name)
   23 {
   24   if (Cmd->Test)
   25     return;
   26   switch(Arc.SubBlockHead.SubType)
   27   {
   28 #ifdef _UNIX
   29     case UO_HEAD:
   30       if (Cmd->ProcessOwners)
   31         ExtractUnixOwner20(Arc,Name);
   32       break;
   33 #endif
   34 #ifdef _WIN_ALL
   35     case NTACL_HEAD:
   36       if (Cmd->ProcessOwners)
   37         ExtractACL20(Arc,Name);
   38       break;
   39     case STREAM_HEAD:
   40       ExtractStreams20(Arc,Name);
   41       break;
   42 #endif
   43   }
   44 }
   45 #endif
   46 
   47 
   48 // RAR3 and RAR5 service header extra records.
   49 void SetExtraInfo(CommandData *Cmd,Archive &Arc,wchar *Name)
   50 {
   51 #ifdef _UNIX
   52   if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
   53       Arc.SubHead.CmpName(SUBHEAD_TYPE_UOWNER))
   54     ExtractUnixOwner30(Arc,Name);
   55 #endif
   56 #ifdef _WIN_ALL
   57   if (!Cmd->Test && Cmd->ProcessOwners && Arc.SubHead.CmpName(SUBHEAD_TYPE_ACL))
   58     ExtractACL(Arc,Name);
   59   if (Arc.SubHead.CmpName(SUBHEAD_TYPE_STREAM))
   60     ExtractStreams(Arc,Name,Cmd->Test);
   61 #endif
   62 }
   63 
   64 
   65 // Extra data stored directly in file header.
   66 void SetFileHeaderExtra(CommandData *Cmd,Archive &Arc,wchar *Name)
   67 {
   68 #ifdef _UNIX
   69    if (Cmd->ProcessOwners && Arc.Format==RARFMT50 && Arc.FileHead.UnixOwnerSet)
   70      SetUnixOwner(Arc,Name);
   71 #endif
   72 }
   73 
   74 
   75 
   76 
   77 // Calculate a number of path components except \. and \..
   78 static int CalcAllowedDepth(const wchar *Name)
   79 {
   80   int AllowedDepth=0;
   81   while (*Name!=0)
   82   {
   83     if (IsPathDiv(Name[0]) && Name[1]!=0 && !IsPathDiv(Name[1]))
   84     {
   85       bool Dot=Name[1]=='.' && (IsPathDiv(Name[2]) || Name[2]==0);
   86       bool Dot2=Name[1]=='.' && Name[2]=='.' && (IsPathDiv(Name[3]) || Name[3]==0);
   87       if (!Dot && !Dot2)
   88         AllowedDepth++;
   89     }
   90     Name++;
   91   }
   92   return AllowedDepth;
   93 }
   94 
   95 
   96 // Check if all existing path components are directories and not links.
   97 static bool LinkInPath(const wchar *Name)
   98 {
   99   wchar Path[NM];
  100   if (wcslen(Name)>=ASIZE(Path))
  101     return true;  // It should not be that long, skip.
  102   wcsncpyz(Path,Name,ASIZE(Path));
  103   for (wchar *s=Path+wcslen(Path)-1;s>Path;s--)
  104     if (IsPathDiv(*s))
  105     {
  106       *s=0;
  107       FindData FD;
  108       if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir))
  109         return true;
  110     }
  111   return false;
  112 }
  113 
  114 
  115 bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName)
  116 {
  117   // Catch root dir based /path/file paths also as stuff like \\?\.
  118   // Do not check PrepSrcName here, it can be root based if destination path
  119   // is a root based.
  120   if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName))
  121     return false;
  122 
  123   // Number of ".." in link target.
  124   int UpLevels=0;
  125   for (int Pos=0;*TargetName!=0;Pos++)
  126   {
  127     bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && 
  128               (IsPathDiv(TargetName[2]) || TargetName[2]==0) &&
  129               (Pos==0 || IsPathDiv(*(TargetName-1)));
  130     if (Dot2)
  131       UpLevels++;
  132     TargetName++;
  133   }
  134   // If link target includes "..", it must not have another links
  135   // in the path, because they can bypass our safety check. For example,
  136   // suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next
  137   // or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next.
  138   if (UpLevels>0 && LinkInPath(PrepSrcName))
  139     return false;
  140     
  141   // We could check just prepared src name, but for extra safety
  142   // we check both original (as from archive header) and prepared
  143   // (after applying the destination path and -ep switches) names.
  144 
  145   int AllowedDepth=CalcAllowedDepth(SrcName); // Original name depth.
  146 
  147   // Remove the destination path from prepared name if any. We should not
  148   // count the destination path depth, because the link target must point
  149   // inside of this path, not outside of it.
  150   size_t ExtrPathLength=wcslen(Cmd->ExtrPath);
  151   if (ExtrPathLength>0 && wcsncmp(PrepSrcName,Cmd->ExtrPath,ExtrPathLength)==0)
  152   {
  153     PrepSrcName+=ExtrPathLength;
  154     while (IsPathDiv(*PrepSrcName))
  155       PrepSrcName++;
  156   }
  157   int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName);
  158 
  159   return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels;
  160 }
  161 
  162 
  163 bool ExtractSymlink(CommandData *Cmd,ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName)
  164 {
  165 #if defined(SAVE_LINKS) && defined(_UNIX)
  166   // For RAR 3.x archives we process links even in test mode to skip link data.
  167   if (Arc.Format==RARFMT15)
  168     return ExtractUnixLink30(Cmd,DataIO,Arc,LinkName);
  169   if (Arc.Format==RARFMT50)
  170     return ExtractUnixLink50(Cmd,LinkName,&Arc.FileHead);
  171 #elif defined _WIN_ALL
  172   // RAR 5.0 archives store link information in file header, so there is
  173   // no need to additionally test it if we do not create a file.
  174   if (Arc.Format==RARFMT50)
  175     return CreateReparsePoint(Cmd,LinkName,&Arc.FileHead);
  176 #endif
  177   return false;
  178 }