Delphi mORMot. How to make mobile client (android,iOS) - delphi

I'm a new in mORMot.
I made a mormot server and FMX client.
It works on Win mode.
Next I changed destination to Android and get an error.
[DCC Fatal Error] SynCrtSock.pas(253): F2613 Unit 'Contnrs' not found (unit SynCrtSock;).
{$R *.fmx}
{$R *.LgXhdpiTb.fmx ANDROID}
function Client(const SQL: RawUTF8): RawUTF8;
var
Http: THttpClientSocket;
URI: AnsiString;
begin
if ParamCount<>0 then
URI := AnsiString(ParamStr(1))
else
URI := '192.168.1.20';
Http := OpenHttp(URI,'888');
if Http <> nil then
try
Http.Post('root',SQL,TEXT_CONTENT_TYPE);
result := Http.Content;
finally
Http.Free;
end
else
result := '';
end;
procedure TForm3.TMSFMXButton1Click(Sender: TObject);
begin
ds1.DataSet := JSONToClientDataSet(self,Client('select * from Lists'));
end;
It works good for Win but doesn't work for Android.
How to make demo for iOS and Android?

As stated by the documentation, current version of the main framework units target only Win32 / Win64 systems under Delphi, and (in a preliminary state) Windows or Linux under FPC. So you can run a Server on those platforms.
But you can write a Client on all Delphi supported platforms, by using some dedicated cross-platform client units, and generate some code to consume the server ORM and SOA content.
To write an OSX or Mobile client, using FMX for the UI, do not use regular SynCommons.pas mORMot.pas units, but the dedicated units as available in the CrossPlatform sub-folder.
The documentation is pretty detailed about it.
See also this sample and the associated generated client unit.

Related

TidHashSHA512.isavailable is false on Windows 10

I am using that function on Delphi XE2 to hash a string.
I have a bad result if the program is run on Windows 10 — the result is null because TidHashSHA512.isavailable is FALSE.
What do I have to do?
function HashSHA512String(Text: String): String;
var
IdHashSHA512: TIdHashSHA512;
begin
Result := '';
if HashFunctionsOpenSSLLoaded then begin
if TIdHashSHA512.IsAvailable then begin // <-- ADD THIS
IdHashSHA512 := TIdHashSHA512.Create;
try
Result := IdHashSHA512.HashStringAsHex(Text);
finally
FreeAndNil(IdHashSHA512);
end;
end;
end;
end;
Most of Indy's SHA hashes depend on your app hooking up an external hashing library to Indy. Only SHA-1 (amongst a few other non-SHA hashes) is currently implemented natively.
To enable SHA-512, the following callback function pointers in the IdFIPS unit must be assigned at runtime:
IsHashingIntfAvail
UpdateHashInst
FinalHashInst
IsSHA512HashIntfAvail
GetSHA512HashInst
You can use any hashing library you want, as long as the above function pointers are assigned to suitable functions.
Indy provides an implementation that uses hashing functions from OpenSSL. To use it, you can either:
add the IdSSLOpenSSLHeaders unit to your uses clause, and then call its Load() function at runtime.
add the IdSSLOpenSSL unit to your uses clause, and then call its LoadOpenSSLLibrary() function at runtime.
Either way, you will have to distribute the two OpenSSL DLLs with your app (libeay32.dll and ssleay32.dll, which you can download from Indy's Fulgan mirror). Be sure to use builds that have been compiled with SHA-512 enabled.

how to make HTTPS calls on the iOS simulator Delphi seattle

OpenSSL not working for iOS Simulator in Delphi DX
Using info at:
http://blog.marcocantu.com/blog/using_ssl_delphi_ios.html
http://docwiki.embarcadero.com/RADStudio/Seattle/en/OpenSSL
https://plus.google.com/100777187605111792758/posts/SPnHdXvTTNu
I can get it to work on devices, but not on the iOS simulator. Same URL works when I use a TWebbrowser.navigate, but not with INDY of course.. See below, and possibly offer suggestions on how to make HTTPS calls on the iOS simulator ! This worked before in earlier versions of Rad Studio ( XE4, XE5 ) but hasnt since XE7 if my memory has served me right.
I have these files in my usr/lib folder:
libcrypto.0.9.8.dylib
libssl.0.9.8.dylib
Here is my uses
uses
IdSSLOpenSSL,
{$IF Defined(IOS) and Defined(CPUARM)}
IdSSLOpenSSLHeaders_Static,
{$ELSE}
IdSSLOpenSSLHeaders,
{$ENDIF}
...
Here is my onCreate for the main form
procedure TmLoginForm.FormCreate(Sender: TObject);
var
t:string;
begin
IdOpenSSLSetLibPath('/usr/lib/');
...
Here is part of a function that I use, where on the last line an exception is thrown
function ParseGroups(OnlyUserCreated:boolean):integer;
var
IdHTTP :TIdHTTP;
HTML :String;
JSON_Groups :TJSONObject;
Group :uGroup;
begin
result:=0;
HTML:='';
IdHTTP:=TIdHTTP.Create(nil);
IdHTTP.HandleRedirects:=false;
try
HTML:=IdHTTP.Get(URL_Host+ACCESSTOKEN);
Error is: 'Could Not Load SSL Library'
ShowMessage(IdSSLOpenSSLHeaders.WhichFailedToLoad); shows a blank message
Update:
adding
IdSSLOpenSSLHeaders.Load;
after setting the path now causes the whichFailedToLoad say: 'Failed to Load /usr/lib/libcrypto.'
Use System.Net.HttpClient.THTTPClient instead of the Indy components.
var
http : THTTPClient;
html : string;
http := THTTPClient.Create;
try
html := http.Get( url ).ContentAsString();
...
finally
http.Free;
end;
It is a wrapper of the http function from the operating system. If the OS supports https, then this class will do also.
You can also follow this nifty blogpost http://delphiworlds.com/2016/03/building-openssl-dylibs-for-ios-simulator/
It worked just fine for me. I needed it, because my Soap client needs to connect via https, and I did not want to rewrite the soap libs.

How to use Delphi standard confirmation dialog but with checkbox "Don't ask me again"?

In many confirmation dialogs it is usefull to have such option (quick wayt to disable confirmation).
But i can't find how to do that. I don't want to design it myself because i need this dialog to be standard-like and don't wont to redesign with every update of Delphi. Is there simple way to use Delphi standard confirmation dialog with such checkbox ?
UPDATE2. Suggested SynTaskDialog library from Synopse project does great job (all i need and even more), i will use it in my projects. Thanks!
UPDATE. So, thank you guys for ideas. System function MessageBoxCheck is nice solution but seem to be not so stable as it should be. In general i agree that it is good idea to use latest API functions to provide users with best UI experience of modern os and use old-fashioned design for older systems. At moment i stay on simple solution (code is following), but if someone share the code with support of UI for modern OS, it will be nice.
function MsgDlgWithCB(const Msg,Title,CBMsg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: TCheckBox): TForm;
var
i: integer;
b: TButton;
y: integer;
begin
Result := CreateMessageDialog(Msg, DlgType, Buttons, DefaultButton) ;
Result.Position := poScreenCenter;
cbDontAskAnymore := TCheckBox.Create(Result);
cbDontAskAnymore.Caption := CBMsg;
cbDontAskAnymore.Width := 130;
y := -1;
for i := 0 to result.ComponentCount-1 do
if result.Components[i] is TButton then
begin
b := TButton(result.Components[i]);
b.Left := b.Left + cbDontAskAnymore.Width + 16;
Result.ClientWidth := Max(Result.ClientWidth, b.Left+b.Width+16);
y := b.Top+b.Height-cbDontAskAnymore.Height;
end;
if y<0 then
y := Result.ClientHeight - cbDontAskAnymore.height - 16;
Result.Caption := Title;
cbDontAskAnymore.Parent := Result;
cbDontAskAnymore.Top := y;
cbDontAskAnymore.Left := 8;
end;
function MessageDlgCheckbox(const Msg: string; DlgType: TMsgDlgType;
Buttons: TMsgDlgButtons; DefaultButton: TMsgDlgBtn;
var cbDontAskAnymore: Boolean;
const Title: string ='Confirmation';
const CBMsg: string = 'Don''t ask anymore'): integer;
var
f: TForm;
c: TCheckbox;
begin
f := MsgDlgWithCB(Msg,Title,CBMsg,DlgType,Buttons,DefaultButton,c);
try
result := f.ShowModal;
cbDontAskAnymore := c.Checked;
finally
f.free;
end;
end;
You can use our Open Source SynTaskDialog unit.
Windows provides a generic task dialog available since Vista/Seven. But there is none available with previous versions of Windows, i.e. Windows XP or 2K.
This unit (licensed under a MPL/GPL/LGPL tri-license) will use the new TaskDialog API under Vista/Seven, and emulate it with pure Delphi code and standard themed VCL components under XP or 2K. It supports Delphi 6 up to XE4, and is Win32/Win64 Unicode ready.
Here is the result under a Windows Seven 64 bit computer:
And here is the same dialog created from our emulated pure Delphi code:
Since this screenshot was made on a Win 7 machine, the styling is native for that OS. When the emulated version of the dialog runs on XP it displays in a style native to that OS.
You have your "Do not ask for this setting next time" checkbox... and potentially much more!
The system native functionality that offers such facilities is the task dialog API introduced in Vista. This provides means for you to show much more capable dialogs than the older MessageBox API.
Should you need to support XP then you will have to create your own dialog. For example by deriving from TForm and calling ShowModal. If you do this, make the form capable of building itself dynamically. Don't make one form per message that you show!
In my codebase, I have my own wrapper of the task dialog API. This detects at runtime versions of Windows that do not support task dialog and falls back on a custom built Delphi dialog.
Regarding SHMessageBoxCheck I'd be a little wary of taking a dependency on that. According to its documentation it's not supported beyond XP, and you have to import it by ordinal. I'd personally be worried that it might be dropped from a future version of Windows. That said, MS has a strong track record of doing whatever it takes to keep legacy apps working with new OS releases.

Using DwmIsCompositionEnabled (JwaDwmApi) on pre-vista causes error

Been trying to use the following code in order to check if Windows Aero is enabled:
function AeroEnabled: boolean;
var
enabled: bool;
begin
// Function from the JwaDwmapi unit (JEDI Windows Api Library)
DwmIsCompositionEnabled(enabled);
Result := enabled;
end;
...
if (CheckWin32Version(5,4)) and (AeroEnabled) then
CampaignTabs.ColorBackground := clBlack
else begin
GlassFrame.Enabled := False;
CampaignTabs.ColorBackground := clWhite;
end;
However, doing so on a pre-vista machine causes the app to crash because the DWMApi.dll is missing. I've also tried this code however it produces 2 AV's in a row. How can I do this ? I am using Delphi 2010. :)
You've got your versions wrong. Vista/2008 server are version 6.0. Your test should be:
CheckWin32Version(6,0)
I believe that you are using Delphi 2010 or later in which case you should simply call the DwmCompositionEnabled function from the built-in Dwmapi unit. This organises the version check and the delayed binding for you. No need for JEDI.
Edit: Text below was written before the question was edited.
Probably the easiest approach is to check the Windows version. You need Win32MajorVersion>=6 (i.e. Vista or 2008 server) in order to call DwmIsCompositionEnabled.
If you were binding yourself then you would call LoadLibrary with DWMApi.dll and if that succeeded you would then call GetProcAddress to bind. If that succeeded you are good. But, as I said, since you aren't handling the binding yourself then a version check is probably the simplest.
So the function would be:
function AeroEnabled: boolean;
var
enabled: bool;
begin
if Win32MajorVersion>=6 then begin
DwmIsCompositionEnabled(enabled);
Result := enabled;
end else begin
Result := False;
end;
end;
Note, I'm assuming that your library is doing late binding, i.e. explicit linking. If not then you'll need LoadLibrary/GetProcAddress, exactly as is done in #RRUZ's code to which you link.

Help needed coding an IRC client in Delphi 2010 using Indy Components

Im trying to code a basic irc client in Delphi 2010 using Indy components.
Im able to connect to my irc server (unrealircd) using sample A below.
After connecting I have many procedures that should perform actions when it receives a private message, ping, ctcp, channel modes etc. but they never react to any of these incoming events.
Sample A:
This connects to the IRC server when button4 is pressed.
It sucessfully joins the channel with the name specified.
procedure TForm1.Button4Click(Sender: TObject);
begin
IdIRC1.Host := '72.20.53.142';
IdIRC1.Port := 6667;
IdIRC1.Nickname := ssh.frmmain.Edit1.text;//insert your nickname here
try
idIRC1.Connect;
except
if not idIRC1.Connected then
begin
Memo2.Lines.add('Error Connecting to ' + idIRC1.Host);
Exit;
end;
end;
Memo2.Lines.add ('Connected to Auth Server');
idIRC1.Join(channel,key);
Memo2.Lines.add ('Auth Accepted');
end;
These events dont work at all and no errors are generated during a compile.
procedure TForm1.IdIRC1Connected(Sender: TObject);
begin
memo2.Lines.Clear;
memo2.Lines.add ('2Connected');
end;
procedure TForm1.IdIRC1ServerVersion(ASender: TIdContext; Version, Host, Comments: String);
begin
memo2.Lines.Add(Version +'Host '+Host+'Comments '+Comments);
end;
Ive had a few people look at this, and it just seems theres some unicode issues that destroyed my TClientSocket irc setup, and even when I moved to indy and used samples off the official site I was still unable to get anything to fire such as the onconnect event.
A friend had a copy of an application he wrote in Delphi 2010 using the same version of indy and I managed to import his project and it started working.
Not sure why

Resources