B4A Library Chilkat-Bundle

This is a - partially - wrap for the Components of https://www.chilkatsoft.com/

Note that the B4A and B4J wrappers are free but you need a Chilkat License to Unlock the Chilkat Library.
The prices starting at $US 289

Buy a Chilkat License
More information about licensing:
Licensing Explained

Licensing Information:
  • The Bundle provides licenses to all existing Chilkat classes.
  • A 1-Developer license is for a single named developer, 4-Developers allows for up to 4 named developers.
  • A Site-Wide license is for any number of developers at a single company location.
  • A license is valid across all supported operating systems, programming languages, architectures, frameworks, etc.
  • The license covers new versions while maintenance/support has not expired.


The interesting part is "A license is valid across all supported operating systems, programming languages, architectures, frameworks, etc." which means that you only need ONE License to use the Chilkat Library in every programming language you want.

I do use them in the 1st line in Delphi for example. But i also wanted to use them in B4J and B4A so i started doing wrappers for it :)

Chilkat is a cross-language, cross-platform API providing 90+ classes for many Internet protocols, formats, and algorithms.
Some classes need a license: SSH, SFTP, FTP2, HTTP, REST, Socket/TLS, IMAP, ...
Some are free: JSON, XML, Cert, PrivateKey, ...

The Objects wrapped so far are:
  • CkAuthGoogle
  • CkBinData
  • CkCert
  • CkDateTime ' Testedpartially (it is used n the Dropboxtest)
  • CkDtObj ' Testedpartially (it is used n the Dropboxtest)
  • CkEmail
  • CkFileAccess
  • CkFtp2
  • CkFtp2Progress
  • CkGlobal ' Tested. It is needed to Unlock the Chilkat Library
  • CkHttp ' Tested partially (it is used n the Dropboxtest)
  • CkImap ' Tested partially (it is used in the IMAP Test)
  • CkJavaKeyStore
  • CkJsonObject' Tested partially (it is used n the Dropboxtest)
  • CkJwt
  • CkOAuth2
  • CkPem
  • CkPfx
  • CkPrivateKey
  • CkPrng
  • CkPublicKey
  • CkRest' Tested partially (it is used in the Dropboxtest)
  • CkRsa
  • CkScp
  • CkSFtp
  • CkSFtpDir
  • CkSFtpFile
  • CkSFtpProgress
  • CkSocket
  • CkSsh ' Tested partially (it is used in the SSHtest)
  • CkSshKey
  • CkSshTunnel
  • CkStream' Tested partially (it is used n the Dropboxtest)
  • CkString
  • CkStringArray
  • CkStringBuilder
  • CkTask
  • CkUrl
  • CkWebSocket
  • CkZipCrc
But, honestly, only a few of them are tested as of now :D
I spent a lot of time doing the wraps though

Some notes:
- As the Library behind (-so Files) is written to support multiple languages the Methods are somehow "Crypted" looking at them from a B4X perspective.
I did try to change the Methods and Properties available to be "B4X conform" :)

For example:
Java:
  public int get_AnsiCodePage() {
    return chilkatJNI.CkGlobal_get_AnsiCodePage(swigCPtr, this);
  }

  public void put_AnsiCodePage(int newVal) {
    chilkatJNI.CkGlobal_put_AnsiCodePage(swigCPtr, this, newVal);
  }
The 1st is a getter, the second a setter for the Values inside the native code.

Inside the wrapper such code is translated into
Java:
  public int getAnsiCodePage() {
    return this.getObject().get_AnsiCodePage();
  }

  public void setAnsiCodePage(int newVal) {
      this.getObject().put_AnsiCodePage(newVal);
  }
meaning that in B4A and B4J you would use
B4X:
' Set
global1.AnsiCodepage = 1
' Get
dim cp as Int = global1.AnsiCodepage
- Usually the Methods wants to return something "into a special Object". But all methods also has a similar Method/Property which returns a String instead of using CkString-Object.
Java:
  public void getThreadPoolLogPath2(CkString str) {
      this.getObject().get_ThreadPoolLogPath(str);
  }

  public String getThreadPoolLogPath() {
    return this.getObject().threadPoolLogPath();
  }
getThreadPoolLogPath2(CkString str) will return the result into the CkString Object named str.
and getThreadPoolLogPath() will return the String directly.

Library and Example can be downloaded from this Dropbox Link:

The B4J Version is HERE.
 
Last edited:

amidgeha

Active Member
Licensed User
Longtime User
Thank you, this is going to be the most powerful and productive component in B4X
 

JohnC

Expert
Licensed User
Longtime User
Hey Don, this is awesome!

I use nsoftware.com's products/classes in my VB/NET projects which has a lot more "classes", but it is much more expensive (> $1000), and always wished it was wrapped for B4x.

However, Chilkatsoft looks to have many of the classes I need/use - and $249 is a very reasonable price :)

Great job!
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
However, Chilkatsoft looks to have many of the classes I need/use - and $249 is a very reasonable price
For what you get for this money i agree fully. As mentioned above; in first line i do use them in Delphi as all i need to do is to import some pascal-files to my project and directly use them with no need to write a wrapper at all :D

But i also love B4X and, as the Components are compatible with Android and Windows i though it would be nice to have some of them wrapped for B4A/B4J.

I only partially tested the wrapped objects. But, for example, the IMAP i tested successfully with my Google Account.
SSH i tested with my Account.
Dropbox i tested with my account.

A lot of objects wrapped need to get tested though.

Basically everything regarding HTTP, REST, JSON should be possible already.

It is a bit of work for the Chilkat-Java Example code to "translate" to use the wrapped objects. I just can say that all examples i did implement in my Example-project that it all works so far. I Mean Umlocking the Library, Dropbox Up- and Download, SSH-Connection and sending a command, IMAP-Connection, getting 50 emails incl. Attachments-infos.
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User

Krammig

Member
Licensed User
Longtime User
Thank you DonManfred this is a fantastic contribution.

I have been using the Chilkat libraries for "many many" years across my VB6 VB.Net and Delphi Android and iPhone apps and can attest to the quality of that product.

By you adding this to B4X it will enable faster more efficient development where these types of functions are required.

Now, how much Chocolate do I need to send you so you can do one for B4i ? :D :D

Cheers
 

walterf25

Expert
Licensed User
Longtime User
This is a - partially - wrap for the Components of https://www.chilkatsoft.com/

Note that the B4A and B4J wrappers are free but you need a Chilkat License to Unlock the Chilkat Library.
The prices starting at $US 289




The interesting part is "A license is valid across all supported operating systems, programming languages, architectures, frameworks, etc." which means that you only need ONE License to use the Chilkat Library in every programming language you want.

I do use them in the 1st line in Delphi for example. But i also wanted to use them in B4J and B4A so i started doing wrappers for it :)



The Objects wrapped so far are:
  • CkAuthGoogle
  • CkBinData
  • CkCert
  • CkDateTime ' Testedpartially (it is used n the Dropboxtest)
  • CkDtObj ' Testedpartially (it is used n the Dropboxtest)
  • CkEmail
  • CkFileAccess
  • CkFtp2
  • CkFtp2Progress
  • CkGlobal ' Tested. It is needed to Unlock the Chilkat Library
  • CkHttp ' Tested partially (it is used n the Dropboxtest)
  • CkImap ' Tested partially (it is used in the IMAP Test)
  • CkJavaKeyStore
  • CkJsonObject' Tested partially (it is used n the Dropboxtest)
  • CkJwt
  • CkOAuth2
  • CkPem
  • CkPfx
  • CkPrivateKey
  • CkPrng
  • CkPublicKey
  • CkRest' Tested partially (it is used in the Dropboxtest)
  • CkRsa
  • CkScp
  • CkSFtp
  • CkSFtpDir
  • CkSFtpFile
  • CkSFtpProgress
  • CkSocket
  • CkSsh ' Tested partially (it is used in the SSHtest)
  • CkSshKey
  • CkSshTunnel
  • CkStream' Tested partially (it is used n the Dropboxtest)
  • CkString
  • CkStringArray
  • CkStringBuilder
  • CkTask
  • CkUrl
  • CkWebSocket
  • CkZipCrc
But, honestly, only a few of them are tested as of now :D
I spent a lot of time doing the wraps though

Some notes:
- As the Library behind (-so Files) is written to support multiple languages the Methods are somehow "Crypted" looking at them from a B4X perspective.
I did try to change the Methods and Properties available to be "B4X conform" :)

For example:
Java:
  public int get_AnsiCodePage() {
    return chilkatJNI.CkGlobal_get_AnsiCodePage(swigCPtr, this);
  }

  public void put_AnsiCodePage(int newVal) {
    chilkatJNI.CkGlobal_put_AnsiCodePage(swigCPtr, this, newVal);
  }
The 1st is a getter, the second a setter for the Values inside the native code.

Inside the wrapper such code is translated into
Java:
  public int getAnsiCodePage() {
    return this.getObject().get_AnsiCodePage();
  }

  public void setAnsiCodePage(int newVal) {
      this.getObject().put_AnsiCodePage(newVal);
  }
meaning that in B4A and B4J you would use
B4X:
' Set
global1.AnsiCodepage = 1
' Get
dim cp as Int = global1.AnsiCodepage
- Usually the Methods wants to return something "into a special Object". But all methods also has a similar Method/Property which returns a String instead of using CkString-Object.
Java:
  public void getThreadPoolLogPath2(CkString str) {
      this.getObject().get_ThreadPoolLogPath(str);
  }

  public String getThreadPoolLogPath() {
    return this.getObject().threadPoolLogPath();
  }
getThreadPoolLogPath2(CkString str) will return the result into the CkString Object named str.
and getThreadPoolLogPath() will return the String directly.

Library and Example can be downloaded from this Dropbox Link:

The B4J Version is HERE.
Noiiiiice, I have a chilkat license, i only wrapped the Email part, nice to see you have done all the libraries provided by them.
Thanks,
Walter
 

walterf25

Expert
Licensed User
Longtime User

DonManfred

Expert
Licensed User
Longtime User
you haven't wrapped the ckSH library yet
You mean CkSSH?
B4X:
    'CkSsh ssh = new CkSsh();
    Dim ssh As CkSsh
    ssh.Initialize("")
    '// Hostname may be an IP address Or hostname:
    Dim hostname As String = "...
    Dim port As Int = 22
    '
    '// Connect To an SSH server:
    Dim success As Boolean = ssh.Connect(hostname,port)
    If success = False Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Wait a Max of 5 seconds when reading responses..
    'ssh.put_IdleTimeoutMs(5000);
    ssh.IdleTimeoutMs = 5000
    '
    '// Authenticate using login/password:
    success = ssh.AuthenticatePw("ssh-xxxx","yyyyy")
    If success = False Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Open a session channel.  (It Is possible To have multiple
    '// session channels open simultaneously.)
    Dim channelNum As Int
    channelNum = ssh.OpenSessionChannel()
    If channelNum < 0 Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    ' Start a shell on the channel:
    success = ssh.SendReqShell(channelNum)
    If success = False Then
        Log($"SendReqShell(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '    // Start a command in the remote shell.  This example
    '// will send a "ls" command To retrieve the directory listing.
    success = ssh.ChannelSendString(channelNum,"ls\r\n","ansi")
    If success = False Then
        Log($"ChannelSendString(channelNum,"ls","ansi") = FALSE"$)       
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Send an EOF.  This tells the server that no more data will
    '// be sent on this channel.  The channel remains open, And
    '// the SSH client may still receive output on this channel.
    success = ssh.ChannelSendEof(channelNum)
    If success = False Then
        Log($"ChannelSendEof(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Read whatever output may already be available on the
    '// SSH connection.  ChannelReadAndPoll returns the number of bytes
    '// that are available in the channel's internal buffer that
    '// are ready To be "picked up" by calling GetReceivedText
    '// Or GetReceivedData.
    '// A Return value of -1 indicates failure.
    '// A Return value of -2 indicates a failure via timeout.
    '
    '// The ChannelReadAndPoll method waits
    '// For data To arrive on the connection usingi the IdleTimeoutMs
    '// property setting.  Once the first data arrives, it continues
    '// reading but instead uses the pollTimeoutMs passed in the 2nd argument:
    '// A Return value of -2 indicates a timeout where no data Is received.
    Dim n As Int
    Dim pollTimeoutMs As Int = 10000
    n = ssh.ChannelReadAndPoll(channelNum,pollTimeoutMs)
    If n < 0 Then
        Log($"ChannelReadAndPoll(channelNum,pollTimeoutMs) < 0"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Close the channel:
    success = ssh.ChannelSendClose(channelNum)
    If success <> True Then
        Log($"ChannelSendClose(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Perhaps we did Not receive all of the commands output.
    '// To make sure,  call ChannelReceiveToClose To accumulate any remaining
    '// output Until the server's corresponding "channel close" is received.
    success = ssh.ChannelReceiveToClose(channelNum)
    If success <> True Then
        Log($"ChannelReceiveToClose(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Let's pickup the accumulated output of the command:
    Dim cmdOutput As String = ssh.getReceivedText(channelNum,"ansi")
    If ssh.LastMethodSuccess <> True Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Display the remote shell's command output:
    Log(cmdOutput)
    '
    '// Disconnect
    ssh.Disconnect()
 

walterf25

Expert
Licensed User
Longtime User
Yes, you are the man.
You mean CkSSH?
B4X:
    'CkSsh ssh = new CkSsh();
    Dim ssh As CkSsh
    ssh.Initialize("")
    '// Hostname may be an IP address Or hostname:
    Dim hostname As String = "...
    Dim port As Int = 22
    '
    '// Connect To an SSH server:
    Dim success As Boolean = ssh.Connect(hostname,port)
    If success = False Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Wait a Max of 5 seconds when reading responses..
    'ssh.put_IdleTimeoutMs(5000);
    ssh.IdleTimeoutMs = 5000
    '
    '// Authenticate using login/password:
    success = ssh.AuthenticatePw("ssh-xxxx","yyyyy")
    If success = False Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Open a session channel.  (It Is possible To have multiple
    '// session channels open simultaneously.)
    Dim channelNum As Int
    channelNum = ssh.OpenSessionChannel()
    If channelNum < 0 Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    ' Start a shell on the channel:
    success = ssh.SendReqShell(channelNum)
    If success = False Then
        Log($"SendReqShell(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '    // Start a command in the remote shell.  This example
    '// will send a "ls" command To retrieve the directory listing.
    success = ssh.ChannelSendString(channelNum,"ls\r\n","ansi")
    If success = False Then
        Log($"ChannelSendString(channelNum,"ls","ansi") = FALSE"$)       
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Send an EOF.  This tells the server that no more data will
    '// be sent on this channel.  The channel remains open, And
    '// the SSH client may still receive output on this channel.
    success = ssh.ChannelSendEof(channelNum)
    If success = False Then
        Log($"ChannelSendEof(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Read whatever output may already be available on the
    '// SSH connection.  ChannelReadAndPoll returns the number of bytes
    '// that are available in the channel's internal buffer that
    '// are ready To be "picked up" by calling GetReceivedText
    '// Or GetReceivedData.
    '// A Return value of -1 indicates failure.
    '// A Return value of -2 indicates a failure via timeout.
    '
    '// The ChannelReadAndPoll method waits
    '// For data To arrive on the connection usingi the IdleTimeoutMs
    '// property setting.  Once the first data arrives, it continues
    '// reading but instead uses the pollTimeoutMs passed in the 2nd argument:
    '// A Return value of -2 indicates a timeout where no data Is received.
    Dim n As Int
    Dim pollTimeoutMs As Int = 10000
    n = ssh.ChannelReadAndPoll(channelNum,pollTimeoutMs)
    If n < 0 Then
        Log($"ChannelReadAndPoll(channelNum,pollTimeoutMs) < 0"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Close the channel:
    success = ssh.ChannelSendClose(channelNum)
    If success <> True Then
        Log($"ChannelSendClose(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Perhaps we did Not receive all of the commands output.
    '// To make sure,  call ChannelReceiveToClose To accumulate any remaining
    '// output Until the server's corresponding "channel close" is received.
    success = ssh.ChannelReceiveToClose(channelNum)
    If success <> True Then
        Log($"ChannelReceiveToClose(channelNum) = FALSE"$)
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Let's pickup the accumulated output of the command:
    Dim cmdOutput As String = ssh.getReceivedText(channelNum,"ansi")
    If ssh.LastMethodSuccess <> True Then
        Log(ssh.lastErrorText)
        Return
    End If
    '
    '// Display the remote shell's command output:
    Log(cmdOutput)
    '
    '// Disconnect
    ssh.Disconnect()
 

amidgeha

Active Member
Licensed User
Longtime User
Is it possible to use Chilkat bundle to get the TCP/IP Fingerprint such as OS, MTU and Distance?
 

MMORETTI964

Member
Licensed User
Longtime User
Many thanks, Don Manfred!
I've seen a little bug in sample (almost, seems):
Dim responseStr As String = rest.fullRequestNoBody2("POST","/2/files/download")
should be
Dim responseStr As String = rest.fullRequestNoBody("POST","/2/files/download")

Great great job.
 

MMORETTI964

Member
Licensed User
Longtime User
We're rewriting our FTP implementation using Chilkat FTP.
Seems the implementation of the event "PercentDone" was not fired (don't know if caused by boolean return type).
This would be important because there is a way to abort a "longtime" FTP Download/Upload.
We've implemented as "void" or as boolean but nothing changed (used during a GetFileAsync with AutoSetProgress = true).

Also, some events of the CkFtp2Progress (ex: AbortCheck) are not implemented: there is a way to implement them with a reflector (using the rest of library as usual?)
In effect many of that methods in that class seems to be events...

If we can contribute in some way, donation included, let me know.
 
Last edited:

MMORETTI964

Member
Licensed User
Longtime User
Yes, we've registered it with a "progress" class.

Dim ftp_progress As CkFtp2Progress
ftp_progress.Initialize("fprogre")
mftp.EventCallbackObject=ftp_progress


In effect I saw the callback ProgressInfo works like a champ.
PercentDone however doesn't fire.
My doubt is on the return of the event PercentDone, it's a boolean (was not a void-returning function like the ProgressInfo).

Also would be fine having other events, I think I cannot made simply by reflector.

Many thanks in advance for your response and your aid.
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
PercentDone however doesn't fire.
i saw a small problem in the wrapper.

Can you try to change the event from PercentDone to PercentDoner (an additional r at the end).

Does it raise the event then??

The two events are implemented as public subs in the wrapper. The native Chilcat is calling the Methods when working.
Inside these methods i raise the event in B4A. Here i am using the wrong eventname. PercentDoner instead of PercentDone.

You do not need to call this subs/methods manually. Just Ignore them. And even ignore it´s return boolean...
 
Last edited:
Top