2026-09-15 10:16:31 +05:00
|
|
|
unit KaMResourceInput;
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
Classes;
|
|
|
|
|
|
|
|
|
|
function KaMResourceExists(const aReference: string): Boolean;
|
|
|
|
|
function KaMOpenResourceStream(const aReference: string): TStream;
|
2026-09-17 13:18:03 +05:00
|
|
|
function KaMResolvePackagedResource(const aRelativeIdentity: string): string;
|
2026-09-15 10:16:31 +05:00
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
CastleUriUtils, CastleDownload;
|
|
|
|
|
|
2026-09-17 13:18:03 +05:00
|
|
|
procedure ValidatePackagedRelativeIdentity(const aRelativeIdentity: string);
|
|
|
|
|
var
|
|
|
|
|
I, ComponentStart: Integer;
|
|
|
|
|
begin
|
|
|
|
|
if (aRelativeIdentity = '') or (aRelativeIdentity[1] = '/') then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: invalid packaged resource identity');
|
|
|
|
|
|
|
|
|
|
ComponentStart := 1;
|
|
|
|
|
for I := 1 to Length(aRelativeIdentity) do
|
|
|
|
|
begin
|
|
|
|
|
if (aRelativeIdentity[I] = '\') or (aRelativeIdentity[I] = ':')
|
|
|
|
|
or (Ord(aRelativeIdentity[I]) < 32) then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: invalid packaged resource identity');
|
|
|
|
|
if aRelativeIdentity[I] = '/' then
|
|
|
|
|
begin
|
|
|
|
|
if (I = ComponentStart)
|
|
|
|
|
or ((I = ComponentStart + 1) and (aRelativeIdentity[ComponentStart] = '.'))
|
|
|
|
|
or ((I = ComponentStart + 2) and (aRelativeIdentity[ComponentStart] = '.')
|
|
|
|
|
and (aRelativeIdentity[ComponentStart + 1] = '.')) then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: invalid packaged resource identity');
|
|
|
|
|
ComponentStart := I + 1;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
if (ComponentStart > Length(aRelativeIdentity))
|
|
|
|
|
or ((Length(aRelativeIdentity) = ComponentStart) and (aRelativeIdentity[ComponentStart] = '.'))
|
|
|
|
|
or ((Length(aRelativeIdentity) = ComponentStart + 1) and (aRelativeIdentity[ComponentStart] = '.')
|
|
|
|
|
and (aRelativeIdentity[ComponentStart + 1] = '.')) then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: invalid packaged resource identity');
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function KaMResolvePackagedResource(const aRelativeIdentity: string): string;
|
|
|
|
|
begin
|
|
|
|
|
ValidatePackagedRelativeIdentity(aRelativeIdentity);
|
|
|
|
|
Result := 'castle-data:/game/' + InternalUriEscape(aRelativeIdentity);
|
|
|
|
|
end;
|
|
|
|
|
|
2026-09-15 10:16:31 +05:00
|
|
|
function ResourceProtocol(const aReference: string): string;
|
|
|
|
|
begin
|
|
|
|
|
if aReference = '' then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: empty resource reference');
|
|
|
|
|
|
|
|
|
|
Result := UriProtocol(aReference);
|
|
|
|
|
if (Result <> '') and (Result <> 'file') and (Result <> 'castle-data') then
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: unsupported resource protocol: ' + Result);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function KaMResourceExists(const aReference: string): Boolean;
|
|
|
|
|
begin
|
|
|
|
|
ResourceProtocol(aReference);
|
|
|
|
|
case UriExists(aReference) of
|
|
|
|
|
ueFile: Result := True;
|
|
|
|
|
ueNotExists, ueDirectory: Result := False;
|
|
|
|
|
ueUnknown:
|
|
|
|
|
raise EDownloadError.Create('KaMResourceInput: resource existence is unknown: ' + aReference);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function KaMOpenResourceStream(const aReference: string): TStream;
|
|
|
|
|
begin
|
|
|
|
|
if ResourceProtocol(aReference) = '' then
|
|
|
|
|
Result := TFileStream.Create(aReference, fmOpenRead)
|
|
|
|
|
else
|
|
|
|
|
Result := Download(aReference, [soForceMemoryStream]);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end.
|