{ ***************************************************************************** * * * This file is part of the iPhone Laz Extension * * * * See the file COPYING.modifiedLGPL.txt, included in this distribution, * * for details about the copyright. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * ***************************************************************************** } unit iPhoneBundle; {$mode objfpc}{$H+} interface uses Classes, SysUtils; const platform_iPhoneSim = 'iphonesimulator'; sdk_iPhoneSim2_0 = 'iphonesimulator2.0'; sdk_iPhoneSim2_1 = 'iphonesimulator2.1'; sdk_iPhoneSim2_2 = 'iphonesimulator2.2'; sdk_iPhoneSim3_0 = 'iphonesimulator3.0'; sdk_iPhoneSim3_1 = 'iphonesimulator3.1'; type TiPhoneBundleInfo = record DisplayName : WideString; {if DisplayName='' then DisplayName=BundleName} iPlatform : WideString; SDKVersion : WideString; AppID : WideString; MainNib : WideString; end; function GetUserHomeDir: WideString; function GetiPhoneSimUserPath(const UserHomeDir: WideString=''): WideString; procedure MakeSimSpaceStruct(const BundleName: WideString; var BundleAppDir: WideString); procedure MakeSimSpaceStruct(const iPhoneSimUserPath, BundleName: WideString; var BundleAppDir: WideString); procedure MakeSimSpaceStruct(const iPhoneSimUserPath, SpaceName, BundleName: WideString; var BundleAppDir: WideString); function GetBundleExeName(const BundleAppDir, ExeName: WideString): WideString; procedure WritePkgFile(const FileName: WideString); function WriteDefInfoList(const InfoFileName, BundleName, ExeName: WideString; const info: TiPhoneBundleInfo): Boolean; procedure CreateBundle(const BundleName, ExeName: WideString; const Info: TiPhoneBundleInfo; var FullBundlePath, FullExeName: WideString); procedure CreateBundle(const BundleName, SpaceName, ExeName: WideString; const Info: TiPhoneBundleInfo; var RealSpace, FullBundlePath, FullExeName: WideString); function GetBundleFullDir(const BundleName, SpaceName: WideString): WideString; function GetSandBoxDir(const SpaceName: WideString): WideString; function AddPathDelim(const w: WideString): WideString; function RandomSpaceName: WideString; implementation function RandomSpaceName: WideString; var g : TGUID; id : String; begin CreateGUID(g); id:=GUIDToString(g); id:=Copy(id, 2, length(id)-2); Result:=id; end; procedure CreateBundle(const BundleName, SpaceName, ExeName: WideString; const Info: TiPhoneBundleInfo; var RealSpace, FullBundlePath, FullExeName: WideString); var appdir : WideString; begin if SpaceName='' then RealSpace:=RandomSpaceName else RealSpace:=SpaceName; MakeSimSpaceStruct(GetiPhoneSimUserPath, RealSpace, BundleName, appdir); FullBundlePath:=appdir; appdir:=AddPathDelim(appdir); FullExeName:=appdir+ExeName; WritePkgFile(appdir+'PkgInfo'); WriteDefInfoList(appdir+'Info.plist', BundleName, ExeName, Info); end; function GetBundleFullDir(const BundleName, SpaceName: WideString): WideString; var path8 : String; space8 : String; p : string; begin path8:=UTF8Encode(GetiPhoneSimUserPath); space8:=UTF8Encode(SpaceName); p:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(path8)+space8); Result:=UTF8Decode(p+UTF8Encode(BundleName)+'.app'); end; function GetSandBoxDir(const SpaceName: WideString): WideString; var path8 : String; space8 : String; p : string; begin path8:=UTF8Encode(GetiPhoneSimUserPath); space8:=UTF8Encode(SpaceName); p:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(path8)+space8); Result:=UTF8Decode(p); end; procedure CreateBundle(const BundleName, ExeName: WideString; const Info: TiPhoneBundleInfo; var FullBundlePath, FullExeName: WideString); var sp : WideString; begin CreateBundle(BundleName, '', ExeName, Info, sp, FullBundlePath, FullExeName); end; function AddPathDelim(const w: WideString): WideString; begin if w='' then Result:=PathDelim else if w[length(w)]<>PathDelim then Result:=w+PathDelim; end; function GetUserHomeDir: WideString; begin Result:=UTF8Decode(GetUserDir); end; function GetiPhoneSimUserPath(const UserHomeDir: WideString=''): WideString; var nm : WideString; begin if UserHomeDir = '' then nm:=GetUserHomeDir else nm:=UserHomeDir; if nm='' then Exit; if nm[length(nm)]<>'/' then nm:=nm+'/'; Result:=nm+'Library/Application Support/iPhone Simulator/User/Applications/'; end; { ~/Library/Application Support/iPhone Simulator/Users/%SPACENAME% %SPACENAME%/Applications %SPACENAME%/Applications/%AppBundle.app% %SPACENAME%/Documents %SPACENAME%/tmp } procedure MakeSimSpaceStruct(const iPhoneSimUserPath, SpaceName, BundleName: WideString; var BundleAppDir: WideString); var path8 : String; space8 : String; p : string; begin path8:=UTF8Encode(iPhoneSimUserPath); space8:=UTF8Encode(SpaceName); p:=IncludeTrailingPathDelimiter(IncludeTrailingPathDelimiter(path8)+space8); BundleAppDir:=UTF8Decode(p+UTF8Encode(BundleName)+'.app'); ForceDirectories(UTF8Encode(BundleAppDir)); ForceDirectories(p+'Documents'); ForceDirectories(p+'tmp'); end; procedure MakeSimSpaceStruct(const iPhoneSimUserPath, BundleName: WideString; var BundleAppDir: WideString); begin MakeSimSpaceStruct(iPhoneSimUserPath, RandomSpaceName, BundleName, BundleAppDir); end; procedure MakeSimSpaceStruct(const BundleName: WideString; var BundleAppDir: WideString); begin MakeSimSpaceStruct( GetiPhoneSimUserPath, BundleName, BundleAppDir); end; function GetBundleExeName(const BundleAppDir, ExeName: WideString): WideString; begin Result:=AddPathDelim(BundleAppDir)+ExeName; end; procedure WritePkgFile(const FileName: WideString); var fs : TFileStream; s : String; begin fs:=TFileStream.Create( UTF8Encode(FileName), fmCreate); s:='APPL????'; fs.Write(s[1], length(s)); fs.Free; end; function WriteDefInfoList(const InfoFileName, BundleName, ExeName: WideString; const info: TiPhoneBundleInfo): Boolean; const BundleFormat : AnsiString = ''#10+ ''#10+ ''#10+ ''#10+ ' CFBundleDevelopmentRegion'#10+ ' English'#10+ ' CFBundleDisplayName'#10+ ' %s'#10+ {display name} ' CFBundleExecutable'#10+ ' %s'#10+ {exe name} ' CFBundleIdentifier'#10+ ' %s'#10+ {company + bundle name} ' CFBundleInfoDictionaryVersion'#10+ ' 6.0'#10+ ' CFBundleName'#10+ ' %s'#10+ {bundle name} ' CFBundlePackageType'#10+ ' APPL'#10+ ' CFBundleSignature'#10+ ' ????'#10+ ' CFBundleSupportedPlatforms'#10+ ' '#10+' %s'#10+' '#10+ {platform} '%s'+ // optional MainNib name ' CFBundleVersion'#10+ ' 1.0'#10+ ' DTPlatformName'#10+ ' %s'#10+ {platform} ' DTSDKName'#10+ ' %s'#10+ {sdk version} ' LSRequiresIPhoneOS'#10+ ' '#10+ ''#10+ ''; function MainNibString(const NibName: WideString): AnsiString; begin if NibName='' then Result:='' else Result:='NSMainNibFile'+UTF8Encode(NibName)+''#10; end; var dispName : WideString; s : String; fs : TFileStream; begin Result:=false; if BundleName='' then Exit; dispName:=info.DisplayName; if dispName='' then dispName:=BundleName; with info do s:=Format( BundleFormat, [ UTF8Encode(dispName), UTF8Encode(ExeName), UTF8Encode(AppID), UTF8Encode(BundleName), UTF8Encode(iPlatform), MainNibString(info.MainNib), UTF8Encode(iPlatform), UTF8Encode(SDKVersion) ]); if FileExists(InfoFileName) then DeleteFile(InfoFileName); fs:=TFileStream.Create(InfoFileName, fmCreate or fmOpenWrite); try if s<>'' then fs.Write(s[1], length(s)); finally fs.Free; end; end; end.