unit KaMResourceInput; interface uses Classes; function KaMResourceExists(const aReference: string): Boolean; function KaMOpenResourceStream(const aReference: string): TStream; function KaMResolvePackagedResource(const aRelativeIdentity: string): string; implementation uses CastleUriUtils, CastleDownload; 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; 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.