X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fengine%2Fe_res.pas;h=e48cc32ed5746264150eb419cbf14ee36db99135;hb=refs%2Fheads%2Fmob;hp=e2f888955076063cf022a58d1c3bda40b2be01ce;hpb=c7827dd408b445f025117f2c5df2a3c0f4622298;p=d2df-sdl.git diff --git a/src/engine/e_res.pas b/src/engine/e_res.pas index e2f8889..81f4638 100644 --- a/src/engine/e_res.pas +++ b/src/engine/e_res.pas @@ -48,7 +48,11 @@ interface function e_FindResource (dirs: SSArray; var name: AnsiString; nameIsDir: Boolean = false): Boolean; function e_FindWad (dirs: SSArray; name: AnsiString): AnsiString; - {--- append dirs to 'path.wad:\file'. if disk is void, append defWad ---} + {--- returns relative wad name; never empty string ---} + function e_FindWadRel (dirs: SSArray; name: AnsiString): AnsiString; + + {--- prepend dirs to 'disk.wad:\file'. if empty disk string then prepend defWad ---} + {--- return empty string if error occured or 'path/to/disk.wad:\file' on success ---} function e_GetResourcePath (dirs: SSArray; path: AnsiString; defWad: AnsiString): AnsiString; {--- same as SysUtils.FinFirst ---} @@ -59,6 +63,8 @@ interface {--- creates all necessary subdirs, if it can ---} function e_GetWriteableDir (dirs: SSArray; required: Boolean=true): AnsiString; + function e_CanCreateFilesAt (dir: AnsiString): Boolean; + implementation uses WadReader, e_log, hashtable; @@ -73,48 +79,26 @@ implementation function e_UpperDir (path: AnsiString): AnsiString; var i: Integer; begin - i := High(path); + i := High(path); // consider possible cases: '\a\', '\a', '\abc\' while (i >= 1) and (path[i] <> '/') and (path[i] <> '\') do Dec(i); - result := Copy(path, 1, i) + result := Copy(path, 1, i-1) // exclude the trailing separator end; - function HasRelativeDirs (name: AnsiString): Boolean; - var i: Integer; ch: Char; + function IsRelativePath (name: AnsiString): Boolean; begin - i := 1; - result := false; - while (result = false) and (name[i] <> #0) do - begin - ch := name[i]; - if (ch = '/') or (ch = '\') then - begin - Inc(i); - if name[i] = '.' then - begin - Inc(i); - if name[i] = '.' then - begin - Inc(i); - ch := name[i]; - result := (ch = #0) or (ch = '/') or (ch = '\') - end - end - end - else - begin - Inc(i) - end - end + result := (copy(name, 1, 3) = '../') or (pos('/../', name) <> 0) or (copy(name, Length(name) - 2) = '/..') or + (copy(name, 1, 3) = '..\') or (pos('\..\', name) <> 0) or (copy(name, Length(name) - 2) = '\..') or + (name = '..'); end; - function HasAbsoluteDirs (name: AnsiString): Boolean; + function IsAbsolutePath (name: AnsiString): Boolean; begin - result := (name = '') or (name[1] = '/') or (name[1] = '\') + result := ExpandFileName(name) = name; end; function e_IsValidResourceName (name: AnsiString): Boolean; begin - result := (HasAbsoluteDirs(name) = false) and (HasRelativeDirs(name) = false) + result := (IsAbsolutePath(name) = false) and (IsRelativePath(name) = false) end; function SpawnStream (dirs: SSArray; name: AnsiString; p: SpawnProc; createNewDir: Boolean): TStream; @@ -215,19 +199,44 @@ implementation end end; + function e_FindWadRel (dirs: SSArray; name: AnsiString): AnsiString; + var + s: AnsiString; + maxpfx: AnsiString = ''; + pfx: AnsiString; + begin + result := name; + if not findFileCI(name) then exit; + for s in dirs do + begin + if (length(s) = 0) then continue; + if (length(name) <= length(s)) then continue; + if (length(s) < length(maxpfx)) then continue; + pfx := s; + if not findFileCI(pfx, true) then continue; + if (pfx[length(pfx)] <> '/') and (pfx[length(pfx)] <> '\') then pfx := pfx+'/'; + if (length(pfx)+1 > length(name)) then continue; + if (strEquCI1251(copy(name, 1, length(pfx)), pfx)) then maxpfx := pfx; + end; + if (length(maxpfx) > 0) then + begin + result := name; + Delete(result, 1, length(maxpfx)); + end; + end; + function e_GetResourcePath (dirs: SSArray; path: AnsiString; defWad: AnsiString): AnsiString; var diskName, fileName: AnsiString; begin if debug_e_res then - e_LogWritefln('e_GetResourcePath0 %s (%s)', [path, defWad]); + e_LogWritefln('e_GetResourcePath %s (%s)', [path, defWad]); assert(length(dirs) > 0); assert(path <> ''); assert(defWad <> ''); diskName := g_ExtractWadName(path); fileName := g_ExtractFilePathName(path); if diskName = '' then diskName := defWad else diskName := e_FindWad(dirs, diskName); - assert(diskName <> '', 'oh fuck, wad "' + diskName + '" not founded'); - result := diskName + ':\' + fileName; + if diskName = '' then result := '' else result := diskName + ':\' + fileName; if debug_e_res then e_LogWritefln(' this>>> %s', [result]); end; @@ -251,7 +260,7 @@ implementation end; // k8: sorry. i know that this sux, but checking directory access rights is unreliable (unportable). - function canCreateFiles (dir: AnsiString): Boolean; + function e_CanCreateFilesAt (dir: AnsiString): Boolean; var f: Integer; st: TStream = nil; @@ -308,7 +317,7 @@ implementation result := dirs[f]; if (findFileCI(result, true)) then begin - if canCreateFiles(result) then + if e_CanCreateFilesAt(result) then begin if not assigned(writeableDirs) then writeableDirs := THashStrCIStr.Create(); writeableDirs.put(dirs[f], result);