"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 }