unrarsrc  6.1.7
About: unrar extracts, views and tests the contents of archives created with the RAR archiver.
  Fossies Dox: unrarsrc-6.1.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

extinfo.cpp
Go to the documentation of this file.
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
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.
50{
51#ifdef _UNIX
52 if (!Cmd->Test && Cmd->ProcessOwners && Arc.Format==RARFMT15 &&
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);
60 ExtractStreams(Arc,Name,Cmd->Test);
61#endif
62}
63
64
65// Extra data stored directly in file header.
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 \..
78static 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.
97static 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
115bool 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
163bool 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}
@ RARFMT50
Definition: archive.hpp:13
@ RARFMT15
Definition: archive.hpp:13
FileHeader FileHead
Definition: archive.hpp:104
RARFORMAT Format
Definition: archive.hpp:117
FileHeader SubHead
Definition: archive.hpp:107
SubBlockHeader SubBlockHead
Definition: archive.hpp:106
static bool FastFind(const wchar *FindMask, FindData *fd, bool GetSymLink=false)
Definition: find.cpp:108
wchar ExtrPath[NM]
Definition: options.hpp:112
bool ProcessOwners
Definition: options.hpp:157
bool Test
Definition: options.hpp:189
bool ExtractSymlink(CommandData *Cmd, ComprDataIO &DataIO, Archive &Arc, const wchar *LinkName)
Definition: extinfo.cpp:163
void SetExtraInfo(CommandData *Cmd, Archive &Arc, wchar *Name)
Definition: extinfo.cpp:49
void SetExtraInfo20(CommandData *Cmd, Archive &Arc, wchar *Name)
Definition: extinfo.cpp:22
bool IsRelativeSymlinkSafe(CommandData *Cmd, const wchar *SrcName, const wchar *PrepSrcName, const wchar *TargetName)
Definition: extinfo.cpp:115
void SetFileHeaderExtra(CommandData *Cmd, Archive &Arc, wchar *Name)
Definition: extinfo.cpp:66
static int CalcAllowedDepth(const wchar *Name)
Definition: extinfo.cpp:78
static bool LinkInPath(const wchar *Name)
Definition: extinfo.cpp:97
#define SUBHEAD_TYPE_ACL
Definition: headers.hpp:116
#define SUBHEAD_TYPE_STREAM
Definition: headers.hpp:117
@ STREAM_HEAD
Definition: headers.hpp:88
@ NTACL_HEAD
Definition: headers.hpp:88
@ UO_HEAD
Definition: headers.hpp:87
#define SUBHEAD_TYPE_UOWNER
Definition: headers.hpp:118
bool IsPathDiv(int Ch)
Definition: pathfn.cpp:134
bool IsFullRootPath(const wchar *Path)
Definition: pathfn.cpp:585
#define ASIZE(x)
Definition: rardefs.hpp:10
wchar_t wchar
Definition: rartypes.hpp:13
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
Definition: strfn.cpp:275
bool UnixOwnerSet
Definition: headers.hpp:242
bool CmpName(const wchar *Name)
Definition: headers.hpp:254
Definition: find.hpp:9
bool IsLink
Definition: find.hpp:14
bool IsDir
Definition: find.hpp:13
ushort SubType
Definition: headers.hpp:301
void SetUnixOwner(Archive &Arc, const wchar *FileName)
Definition: uowners.cpp:93
void ExtractUnixOwner20(Archive &Arc, const wchar *FileName)
Definition: uowners.cpp:3
void ExtractUnixOwner30(Archive &Arc, const wchar *FileName)
Definition: uowners.cpp:50
void ExtractACL20(Archive &Arc, const wchar *FileName)
Definition: win32acl.cpp:8
void ExtractACL(Archive &Arc, const wchar *FileName)
Definition: win32acl.cpp:67
bool CreateReparsePoint(CommandData *Cmd, const wchar *Name, FileHeader *hd)
Definition: win32lnk.cpp:32