Quantcast
Channel: Chilkat Tech Notes
Viewing all 415 articles
Browse latest View live

Generated Code for XAdES Signing Certificates

$
0
0

Question:

I am user of your component and I have problem with signing XML files.
I got (invalid) ds:Signature with same not replaced text “TO BE GENERATED BY CHILKAT” in tree node (SigningCertificate|xades:Cert[1] and SigningCertificate|xades:Cert[2])
The SigningCertificate|xades:Cert[0] is valid.

...
CkXml object1;
object1.put_Tag("xades:QualifyingProperties");
object1.AddAttribute("xmlns:xades","http://uri.etsi.org/01903/v1.3.2#");
object1.AddAttribute("xmlns:xades141","http://uri.etsi.org/01903/v1.4.1#");
object1.AddAttribute("Target","#xmldsig-0d264d45-0a6a-4431-8e74-35463a71756c");
object1.UpdateAttrAt("xades:SignedProperties",true,"Id","xmldsig-0d264d45-0a6a-4431-8e74-35463a71756c-signedprops");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime","TO BE GENERATED BY CHILKAT");
object1.UpdateAttrAt("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert|xades:CertDigest|ds:DigestMethod",true,"Algorithm","http://www.w3.org/2000/09/xmldsig#sha1");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert|xades:CertDigest|ds:DigestValue","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert|xades:IssuerSerial|ds:X509IssuerName","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert|xades:IssuerSerial|ds:X509SerialNumber","TO BE GENERATED BY CHILKAT");
object1.UpdateAttrAt("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[1]|xades:CertDigest|ds:DigestMethod",true,"Algorithm","http://www.w3.org/2000/09/xmldsig#sha1");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[1]|xades:CertDigest|ds:DigestValue","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[1]|xades:IssuerSerial|ds:X509IssuerName","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[1]|xades:IssuerSerial|ds:X509SerialNumber","TO BE GENERATED BY CHILKAT");
object1.UpdateAttrAt("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[2]|xades:CertDigest|ds:DigestMethod",true,"Algorithm","http://www.w3.org/2000/09/xmldsig#sha1");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[2]|xades:CertDigest|ds:DigestValue","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[2]|xades:IssuerSerial|ds:X509IssuerName","TO BE GENERATED BY CHILKAT");
object1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificate|xades:Cert[2]|xades:IssuerSerial|ds:X509SerialNumber","TO BE GENERATED BY CHILKAT");
gen.AddObject("",object1.getXml(),"","");
...

Answer:

The online tool at https://tools.chilkat.io/xmlDsigGen.cshtml will generate code for the number of certs it finds in the sample already-signed XML that was provided as input.   The sample code is just generally showing how you would add certs to the SignedSignatureProperties.    The SigningCertificates, as specified at https://www.w3.org/TR/XAdES/#Syntax_for_XAdES_The_SigningCertificate_element    specify that you would potentially include the certificates in the chain of authentication up to the point of trust:   “The certificate used to verify the signature shall be identified in the sequence; the signature policy may mandate other certificates be present, that may include all the certificates up to the point of trust.”   The number of certs in the chain of authentication can vary, depending on the cert.   Also, the server/receivor may or may not require the chain of authentication.  It could be that the receiving service only requires the cert used for signing, without the remainder of the certs in the chain of authentication.

 


Working with Huge (Extremely Large) JSON Files

$
0
0

Question:

I am using the following calls in Visual FoxPro with Chilkat_9_5_0.JsonObject (9.5.0.80) and the resulting JSON is writing only {}

oChilkatJson=Createobject('Chilkat_9_5_0.JsonObject')
oChilkatJson.LoadFile("pathToLargeJSONFile")
oChilkatJson.EmitCompact=1
=STRTOFILE(oChilkatJson.Emit(),pathToOutputFile)

Original Size of JSON: 259 MB (271,982,395 bytes)

New JSON outputs as: {}

I could use the https://www.example-code.com/foxpro/create_complex_json.asp​ to read and write each JSON property/object to memory and perform the one EMIT() a the end, I would think it would be the same result.

It reads it fine and I can loop through the JSON object.

Is there a file size limitation to writing using EMIT()?

What method is the best way to read and write large JSON.  The JSON files we work with could be larger than this, up to 2GB.

Answer:

This is a great question because the answer allows me to describe a general situation that should be avoided.   In some programming languages, it’s generally not a good idea to pass huge amounts of data to a method, or return huge amounts of data from a method.   Programming languages that uses the ActiveX, such as FoxPro, VB6, DataFlex, VBScript, Classic ASP, etc. would qualify.   When an ActiveX method returns a string, it must marshal the string as a BSTR (utf-16) and return it to the application.  This is a more-than-doubling of the memory required because the utf-8 held internally by the JSON object is mostly or entirely 1-byte per char.  The BSTR is 2 bytes per char.  At the point of returning the string, the memory usage will jump to 3 times the size of the JSON.  (If you have 250MB of JSON, returning the BSTR requires another 500MB — and it’s likely that the older programming language (FoxPro, VB6, etc.) cannot even handle a string that size, and there may be limitations within the COM infrastructure itself.

The solution is to NOT pass the JSON string back-and-forth.  This can be accomplished using the “Sb” methods — i.e. methods that pass the string in or out via a StringBuilder object.  This way, you’re just passing a reference to an object, and the string itself stays entirely within native (Chilkat) memory in utf-8 representation.   In this case, you would instead call EmitSb (instead of Emit) to write the JSON into a StringBuilder object, and then call StringBuilder.WriteFile.  However, this is still a doubling of memory usage because you’ll have a complete copy of the JSON within the JsonObject, and also within the StringBuilder (although it’s not as bad as the original case, and whatever limitations imposed by COM or the older programming language won’t exist).  But… if you’re only needing to get the JSON to save it to a file, the best solution is to call JsonObject.WriteFile to just write the JSON file directly using the JsonObject.

GMail “Allow Access for Less Secured Apps”

$
0
0

Question:

I created a Gmail account and I am SendEmailAsync to send email via that Gmail account through a VB6 program. I had to turn on “allow access for less secured apps” for that Gmail account but otherwise, I am able to get everything working. However, after some weeks of inactivity, Google would automatically turn disable access for less secured apps and block access.

Is there a way for me to send emails without having to turn on “allow less secured apps” setting ?

Answer:

The term “less secured apps” means doing SMTP, POP3, or IMAP authentication with anything other than OAuth2.   (i.e. using password or digest authentication methods that have existed in these protocols for many years, and are still widely used.    Chilkat can do OAuth2 authentication with GMail — but as with any OAuth2 authentication, you’ll need to popup a browser to allow the GMail account owner to interactively authorize access.   However, once your app obtains the OAuth2 token, it can save it to persistent storage (file, database, etc.) so that the interactive browser interaction does not need to happen again.  The OAuth2 token can be refreshed as needed without user interaction.   (For example, if you use Mozilla Thunderbird and setup usage with a GMail account, you’ll notice the up-front request for authorization, but it never  has to be re-done.)

There are examples on example-code.com for each of the programming language categories, under the “IMAP”, “SMTP”, and “POP3” categories, showing how to get a GMail OAuth2 token and how to use it.  For example:

https://www.example-code.com/vb6/gmail_imap_oauth2_access_token.asp

and

https://www.example-code.com/vb6/gmail_imap_login_oauth2.asp

and for refreshing an access token:

https://www.example-code.com/vb6/gmail_imap_refresh_oauth2_token.asp

 

Getting OAuth2 Token in Desktop App vs. Web App

$
0
0

Question:

I have done some Dataflex development for the UK ‘Making Tax Digital’ functions that require oAuth2 authorisation. I’ve used your example code for the Windows work but I now need to get this working for a Dataflex Web based version. That communication part will all take place from the Web server. Any pointers on how to get oAuth to work through the Web Server using Dataflex?

Answer:

Chilkat’s OAuth2 class is only for desktop applications.  This is because you don’t really need it for web based apps (where code runs on the web server).  Doing OAuth2 with the typical Authorization Code Flow (see https://medium.com/@darutk/diagrams-and-movies-of-all-the-oauth-2-0-flows-194f3c3ade85)  presents difficulty for desktop apps because a callback URL is part of the flow.  The resource owner must interactively authorize access through a web browser.  This results in a redirect response to the callback URL.  It means your app needs a way to receive that HTTP request.  Chilkat solves the problem by creating a background thread that waits for the callback (i.e. it behaves as a web server for that one request).

This problem no longer exists when your web-based application is running on a web server.  You don’t need Chilkat to get the OAuth2 token.  (You can use Chilkat in both web-based and desktop applications to make REST requests once have the OAuth2 token in hand.)   Implementing the OAuth2 Authorization Code Flow in a web-based app should be fairly easy and straightforward.  Nothing special is needed because OAuth2 requires no cryptographic computations on the client side (in this case, the “client side” is your code running on the web server).  It’s essentially just a matter of passing information back-and-forth.  Chilkat has some (hopefully working) examples online in ASP.NET and Classic ASP at http://tools.chilkat.io/oauth2.cshtml  and http://tools.chilkat.io/oauth2.asp   You can try them out and see the ASP.NET or Classic ASP source code that implements it.

Chilkat PHP Extension on MacOSX Catalina with SIP (System Integrity Protection)

$
0
0

Mac OS X 10.11 El Capitan and later protects system files and processes with a new feature named System Integrity Protection. SIP is a kernel-level feature that limits what the “root” account can do.   It will prevent you from copying the Chilkat PHP shared lib (.so) to the PHP extensions directory.  Also, if you try to move the PHP extension directory elsewhere, you may get an error such as this:

PHP Warning:  PHP Startup: Unable to load dynamic library 'chilkat_9_5_0' 
(tried: /usr/local/lib/php/extensions/chilkat_9_5_0 (dlopen(/usr/local/lib/php/extensions/chilkat_9_5_0, 0x0009): 
dlopen(): file not found: /usr/local/lib/php/extensions/chilkat_9_5_0), 
/usr/local/lib/php/extensions/chilkat_9_5_0.so (dlopen(/usr/local/lib/php/extensions/chilkat_9_5_0.so, 0x0009): 
code signature in (/usr/local/lib/php/extensions/chilkat_9_5_0.so) not valid for use in process: mapped file has no cdhash, completely unsigned? 
Code has to be at least ad-hoc signed.)) in Unknown on line 0

Solution:

You need to codesign the chilkat_9_5_0.so.   Also, if you are trying to copy the chilkat_9_5_0.so to the default PHP extensions directory, you’ll need to temporarily turn off SIP.

How to CodeSign a .so/.dylib on MacOSX

1. First make sure you accept an XCode license.  This is a prerequisite that may not be necessary if you’ve already done it. Open a terminal, and run

sudo xcodebuild -license

Agree to the license..

2. You’ll probably need to know the specific identity names/strings for the command to codesign.  Run this command:

security find-identity -v -p codesigning

The output will be something like this:

  1) 9B8D24EC5FBACDE87E6700C7F03A49734F14DBF1 "Apple Development: username@example.com (4R8P377T9H)"
     1 valid identities found

3) Codesign the chilkat_9_5_0.so. Use the quoted string for one of the identities listed in the previous command.

codesign -f -s "Apple Development: username@example.com (4R8P377T9H)" chilkat_9_5_0.so

How to Temporarily Turn Off System Integrity Protection (SIP) on MacOS

  1. Click the Apple symbol in the Menu bar.
  2. Click Restart…
  3. Hold down Command-R to reboot into Recovery Mode.
  4. Click Utilities.
  5. Select Terminal.
  6. Type csrutil disable.
  7. Press Return or Enter on your keyboard.
  8. Click the Apple symbol in the Menu bar.
  9. Click Restart…

If you later want to start using SIP once again (and you really should), then follow these steps again, except this time you’ll enter csrutil enable in the Terminal instead.

Find the PHP Extensions Directory

The Chilkat PHP extension download provides a showExtDir.php script to show the PHP extensions directory.  Run it to see the directory

php showExtDir.php

Copy the chilkat_9_5_0.php to the PHP Extensions Directory

With SIP temporarily turned off, you may copy the chilkat_9_5_0.so to the PHP extensions directory.

sudo cp chilkat_9_5_0.so /usr/lib/php/extensions/no-debug-non-zts-20180731

 

Delphi DLL PercentDone Callbacks

$
0
0

The Chilkat Delphi DLL (non-ActiveX) supports callbacks starting in version 9.5.0.82, to be released in Feb 2020.   Pre-release Beta builds are available upon request.

Also see:

1) First define a function exactly as shown here.  Make sure to use the “cdecl” calling convention.

Returning a non-zero Result will cause the Chilkat method to abort.  It is important to set Result := 0 to allow the Chilkat method to continue.

function MyPercentDone(pctDone: Integer): Integer; cdecl;
begin
    Form1.ProgressBar1.Position := pctDone;
    Result := 0;
end;

2) Set the percent-done callback by calling the appropriate SetPercentDone function.   For the CkZip object it is  CkZip_SetPercentDone(zip,MyPercentDone);

Note: This example shows PercentDone events using CkZip.  The same technique applies to any Chilkat class having callbacks. 
For example, CkRest_SetPercentDone.

// Create a .zip with PercentDone callbacks.
procedure TForm1.Button1Click(Sender: TObject);
var
zip: HCkZip;
success: Boolean;
recurse: Boolean;

begin
zip := CkZip_Create();
success := CkZip_NewZip(zip,'C:/temp/out.zip');
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

recurse := True;
success := CkZip_AppendFiles(zip,'c:/temp/someDir/*',recurse);
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

// Setup the percent-done callback.
CkZip_SetPercentDone(zip,MyPercentDone);

// The MyPercentDone function will be called from within CkZip_WriteZipAndClose
success := CkZip_WriteZipAndClose(zip);
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

Memo1.Lines.Add('Zip Created!');

CkZip_Dispose(zip);

end;


 

Delphi DLL AbortCheck Callbacks

$
0
0

The Chilkat Delphi DLL (non-ActiveX) supports callbacks starting in version 9.5.0.82, to be released in Feb 2020. Pre-release Beta builds are available upon request.

Also see:

1) First define a function exactly as shown here. Make sure to use the “cdecl” calling convention. Returning a non-zero Result will cause the Chilkat method to abort.

function MyAbortCheck(): Integer; cdecl;
begin
    Form1.Memo1.Lines.Add('AbortCheck!');
    Result := 0;
end;

2) Set the abort check callback by calling the appropriate SetAbortCheck function. For the CkZip object it is CkZip_SetAbortCheck(zip,MyAbortCheck);

Note: This example shows AbortCheck events using CkZip.  The same technique applies to any Chilkat class having callbacks. 
For example, CkRest_SetAbortCheck.

procedure TForm1.Button1Click(Sender: TObject);
var
zip: HCkZip;
success: Boolean;
recurse: Boolean;

begin

zip := CkZip_Create();
success := CkZip_NewZip(zip,'C:/temp/out.zip');
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

recurse := True;
success := CkZip_AppendFiles(zip,'c:/temp/someDir/*',recurse);
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

// Setup the abort check callback.
// The HeartbeatMs property defines the number of milliseconds between AbortCheck callbacks.
CkZip_putHeartbeatMs(zip,25);
CkZip_SetAbortCheck(zip,MyAbortCheck);

// The MyAbortCheck function will be called from within CkZip_WriteZipAndClose
success := CkZip_WriteZipAndClose(zip);
if (success == False) then
  begin
    Memo1.Lines.Add(CkZip__lastErrorText(zip));
    Exit;
  end;

Memo1.Lines.Add('Zip Created!');

CkZip_Dispose(zip);

end;

Delphi DLL ProgressInfo Callbacks

$
0
0

The Chilkat Delphi DLL (non-ActiveX) supports callbacks starting in version 9.5.0.82, to be released in Feb 2020. Pre-release Beta builds are available upon request.

Also see:

1) First define a procedure exactly as shown here. Make sure to use the “cdecl” calling convention.

procedure MyProgressInfo(name: PWideChar; value: PWideChar) cdecl;
begin
  Form1.Memo1.Lines.Add(name + ': ' + value);
end;

2) Set the ProgressInfo callback by calling the appropriate SetProgressInfo function. For the CkSocket object it is CkSocket_SetProgressInfo(sock,MyProgressInfo);

Note: This example shows ProgressInfo callbacks using CkSocket. The same technique applies to any Chilkat class having callbacks.
For example, CkRest_SetProgressInfo.

procedure TForm1.Button1Click(Sender: TObject);
var
  sock: HCkSocket;
  success: Boolean;
begin
    sock := CkSocket_Create();
    CkSocket_SetProgressInfo(sock,MyProgressInfo);

    success := CkSocket_Connect(sock,'google.com',443,True,2000);
    if (success == False) then
      begin
        Memo1.Lines.Add(CkSocket__lastErrorText(sock));
        Exit;
      end;

    Memo1.Lines.Add('Success');
end;

 


Delphi DLL TaskCompleted Callbacks

$
0
0

The Chilkat Delphi DLL (non-ActiveX) supports callbacks starting in version 9.5.0.82, to be released in Feb 2020. Pre-release Beta builds are available upon request.

Also see:

1) First define a procedure exactly as shown here. Make sure to use the “cdecl” calling convention.

// Called from a background thread.
procedure MyTaskCompleted(task: HCkTask) cdecl;
var
    rest: HCkRest;
begin
    // Chilkat v9.5.0.82 introduces a new LoadTaskCaller method to get the instance of the object 
    // that made the async method call.
    // To do it, we first create a new/empty object of the correct type.  In this case, it is a Rest object.
    rest := CkRest_Create();

    // Next, we call LoadTaskCaller to make it reference the object instance that made the async call.
    CkRest_LoadTaskCaller(rest,task);

    // Now that we have the caller object, we can get its properties, such as the ResponseHeader:
    Form1.Memo1.Lines.Add(CkRest__responseHeader(rest));
    Form1.Memo1.Lines.Add('---');

    // The async method's return value is obtained from the Task object.  If the async method returns a string,
    // then we call CkTask__getResultString. 
    // (In the code below, you can see that we called CkRest_FullRequestNoBodyAsync.  
    // The FullRequestNoBody method returns a string, and therefore we can
    // get the string return value by calling CkTask__getResultString.)
    Form1.Memo1.Lines.Add(CkTask__getResultString(task));

end;

2) Set the task completed callback by calling the appropriate SetTaskCompleted function. For the CkRest object it is CkZip_SetTaskCompleted(rest,MyTaskCompleted);

Note: This example shows TaskCompleted callbacks using CkRest. The same technique applies to any Chilkat class having callbacks.
For example, CkHttp_SetTaskCompleted.

procedure TForm1.Button1Click(Sender: TObject);
var
rest: HCkRest;
bTls: Boolean;
port: Integer;
bAutoReconnect: Boolean;
success: Boolean;
task: HCkTask;

begin
rest := CkRest_Create();

// Connect to the REST server.
bTls := True;
port := 443;
bAutoReconnect := True;
success := CkRest_Connect(rest,'www.alphavantage.co',port,bTls,bAutoReconnect);
if (success == False) then
  begin
    Memo1.Lines.Add(CkRest__lastErrorText(rest));
    Exit;
  end;

success := CkRest_AddQueryParam(rest,'function','TIME_SERIES_DAILY');
success := CkRest_AddQueryParam(rest,'symbol','AAPL');
// You can test this code by getting a free API key at www.alphavantage.co
success := CkRest_AddQueryParam(rest,'apikey','my_api_key');

// Setup the TaskCompleted callback.
CkRest_SetTaskCompleted(rest,MyTaskCompleted);

// Create a task to send a GET request to https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&apikey=my_api_key
task := CkRest_FullRequestNoBodyAsync(rest,'GET','/query');
if (CkRest_getLastMethodSuccess(rest) == False) then
  begin
    Memo1.Lines.Add(CkRest__lastErrorText(rest));
    Exit;
  end;

// Schedule the task for running on Chilkat's background thread pool.  This changes the task's state
// from Inert to Live.
success := CkTask_Run(task);
if (success == False) then
  begin
    Memo1.Lines.Add(CkTask__lastErrorText(task));
    CkTask_Dispose(task);
    Exit;
  end;

// The application is now free to do anything else
// while the HTTP request is in progress.  When the task
// is completed, the TaskCompleted callback is called.
CkTask_Dispose(task);

CkRest_Dispose(rest);

end;


 

Accurate Date/Time with Timezone when Downloading Files from FTP?

$
0
0

Question:

Can you please confirm when downloading file(s) from FTP using Chilkat component, the date/time stamp of the file (creation/modified date) is communicated after download?

For example, a PC where the file is being downloaded is at EST while the server where the file was located is on PST timezone. Server time for example, was 4:00 AM, while PC where file is being downloaded is at 2:00 AM. Which date we will get in the “creationDate” property of FileInfoType object? Server date(4:00 AM) or client date (2:00 AM)

If that is still giving server date, is there any way to detect server timezone or if there is a way to convert the date to local date?

Answer:

This is a good question, and the answer depends on the capabilities (make/model) of the FTP server.  If the FTP server supports the MLSD command then Chilkat will automatically know and use the MLSD command to fetch directory listings, and the date/times are provided with timezone information.  Chilkat will download and save the local file with the correct date/time.  If the client-side is EST, and the server is PST, then the adjustment is made.

Many FTP servers are older and do not support MLSD.  In these cases, the server only supports the “LIST” command which provides directory listings in human-readable format, and the listing formats can vary greatly, and the information available can vary greatly.  For example, it may be that for files older than a certain limit, that hour/minute/second information is not provided.  Certainly timezone information is not provided.  In this case, Chilkat assumes that the timezone of the server is the same as the client.  (There is no way to know the timezone of the server.)

.NET Core Async Method Call with TaskCompleted Callback

$
0
0
Here is a complete example showing how to write a call to an asynchronous Chilkat method in .NET Core. (Note: This is .NET Core, not .NET Framework.) This example uses the TaskCompleted callback to get notified when the task completes.
using System;
using System.Collections;

namespace ChilkatTest
{
    class Program
    {
        bool m_taskFinished = false;

        Hashtable m_chilkatTasks = new Hashtable();
        Hashtable m_chilkatSockets = new Hashtable();

        // This callback will occur within the background thread..
        public void Socket_HandleTaskIdCompleted(int taskId)
        {
            // Get the Chilkat task for this callback.
            Chilkat.Task task = (Chilkat.Task) m_chilkatTasks[taskId];
            if (task == null)
            {
                System.Diagnostics.Debug.WriteLine("Task not found.");
                return;
            }

            // Get the Chilkat socket.
            Chilkat.Socket socket = (Chilkat.Socket)m_chilkatSockets[taskId];
            if (socket == null)
            {
                System.Diagnostics.Debug.WriteLine("Socket not found.");
                return;
            }

            // Do whatever we want..

            // For this example, examine the contents of the socket.LastErrorText for both success and failure.
            System.Diagnostics.Debug.WriteLine(socket.LastErrorText);

            // Did the call socket connect successfully?
            if (task.GetResultBool() == true)
            {
                System.Diagnostics.Debug.WriteLine("The TLS connection was successful.");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("The TLS connection failed.");
            }

            m_chilkatTasks.Remove(taskId);
            m_chilkatSockets.Remove(taskId);

            m_taskFinished = true;
        }


        // .NET Core async with TaskFinished callback.
        void TestSocketConnectAsync()
        {
            Chilkat.Socket socket = new Chilkat.Socket();

            // Setup the TaskCompleted callback.
            Chilkat.Socket.TaskIdCompleted taskIdCompleted = new Chilkat.Socket.TaskIdCompleted(Socket_HandleTaskIdCompleted);
            socket.setTaskIdCompletedCb(taskIdCompleted);

            Chilkat.Task task = socket.ConnectAsync("google.com", 443, true, 5000);
            if (socket.LastMethodSuccess == false)
            {
                System.Diagnostics.Debug.WriteLine(socket.LastErrorText);
                return;
            }

            // Save the task to our hashtable so we can access the Chilkat.Task object from within the TaskCompleted callback.
            m_chilkatTasks[task.TaskId] = task;

            // Also save the socket object for access within the TaskCompleted callback.
            m_chilkatSockets[task.TaskId] = socket;


            // Schedule the task for running on the thread pool.  This changes the task's state
            // from Inert to Live.
            bool success = task.Run();
            if (success != true)
            {
                System.Diagnostics.Debug.WriteLine(task.LastErrorText);
                return;
            }

        }

        void WaitUntilFinished()
        {
            while (!m_taskFinished)
            {
                System.Threading.Thread.Sleep(100);
            }
        }

        static bool UnlockChilkat()
        {
            Chilkat.Global glob = new Chilkat.Global();
            bool unlocked = glob.UnlockBundle("trial");
            if (!unlocked)
            {
                System.Diagnostics.Debug.WriteLine(glob.LastErrorText);
            }
            return unlocked;
        }

        static void Main(string[] args)
        {
            if (!UnlockChilkat()) return;

            Program prog = new Program();
            prog.TestSocketConnectAsync();

            // Wait for the async task to finish before exiting the program.
            prog.WaitUntilFinished();

            System.Diagnostics.Debug.WriteLine("Exiting..");
        }
    }
}

Chilkat v9.5.0.82 Pre-Release Notes

$
0
0

The previous version release notes: Chilkat v9.5.0.80 Release Notes

(Chilkat v9.5.0.81 was a hotfix specific to UWP (Universal Windows Platform) on NuGet.)

Chilkat v9.5.0.82 Pre-Release Notes

  • 6-Nov-2019 JsonObject: Type JsonTypeOf method returned -1 for inner nodes rather than the correct value of 3.
  • 6-Nov-2019 Ftp2: Improved internal directory parsing for z/OS FTP servers returning MVS datasets.
  • 10-Nov-2019 Http: Added the TlsNoClientRootCert keyword to the UncommonOptions property.  Prevents the root CA cert from being included in the client certificate chain sent to the server for client-side authentication.
  • 12-Nov-2019 Xml: In attribute values: tabs, newlines, carriage returns are emitted using “	”, “
”, and “
” respectively.
  • 12-Nov-2019: Http: The QuickGetObj and QuickGet methods did not propery set the WasRedirected and FinalRedirectUrl properties when redirects are automatically followed.
  • 12-Nov-2019: Ftp2: Solved problems with some Active mode data transfers (non-passive mode transfers).
  • 17-Nov-2019: StringBuilder: Added the ReplaceNoCase method to do string case-insensitive string replacements.
  • 24-Nov-2019: Csv: GetNumCols(rowIndex) returned a cached row count after a row is deleted by DeleteRow.
  • 29-Nov-2019: SSH/SFTP: Default for EnableCompression is changed to false because some servers fail with compression enabled, and in other cases performance is slower with compression enabled.  (Yet in other cases, it’s possible that performance is better with compression enabled — it entirely has to do with the compressibility of the data being sent/received.)
  • 13-Dec-2019: Delphi DLL: Added event callbacks.  See https://cknotes.com/delphi-dll-progressinfo-callbacks/
  • 17-Dec-2019: Pfx: Added the ability to decode PFX files that are AES256-SHA256 Encrypted
  • 18-Dec-2019: TLS: For the case where a client certificate is needed for authentication (two-way SSL / mutual authentication), if on a Windows system where the private key is installed in the Windows protected store as non-exportable with the security option to force a dialog to be displayed when accessing — in this case Chilkat would fail because the private key was accessed using the “silent flag” (to prevent a Windows dialog).  This is fixed.  The dialog will appear (triggered by the private key access and displayed by the Windows OS), and the TLS handshake will complete.   NOTE: Private key installed in this way cannot be used in non-interactive applications.
  • 19-Dec-2019: Tar: Fixed the UntarFirstMatchingToMemory method.

O365 IMAP Authentication: OAuth and MFA Solution

$
0
0

There is much confusion and worry about Microsoft’s plans to disable standard password authentication for the IMAP, and POP3  protocols. Here is the announcement posted on 20-Sept-2019 on the Office 365 blog: https://developer.microsoft.com/en-us/office/blogs/end-of-support-for-basic-authentication-access-to-exchange-online-apis-for-office-365-customers/

Chilkat already supports OAuth2 for the IMAP, POP3, and SMTP protocols. (Microsoft will continue to support basic auth for SMTP)  In all three protocols, an application can provide an access token and use the “XOAUTH2” authentication method in Chilkat.  The questions to be answered are:

  1. How to get an O365 OAuth2 token with the correct scope to successfully authenticate within the IMAP, POP3, or SMTP protocols?
  2. Does your Microsoft mail server support the XOAUTH2 authentication method?

MFA (Multi-Factor Authentication, or “Modern Authentication”) is another issue altogether, and at this point in time I don’t know how it fits with the email protocols.  You can also interact with O365 via the REST/HTTP protocol.  For example, see https://docs.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/mail-rest-operations    Modifying your application to use REST would be a complete rewrite of the email functionality.

How to Get an OAuth2 Token for O365 for IMAP?

The general procedure and flow is the same for all OAuth2 implementations whether you’re authenticating with Google, Microsoft, Quickbooks, a government service, etc.   There are many possible minor differences that can make it difficult, but Chilkat has the features to accommodate everything encountered so far.    In general, you’ll get an access token for an account once, and then use the access token to authenticate until it expires.  Getting the initial access token requires interactive authorization in a web browser from the O365 account owner.   When the access token expires, it can be refreshed non-interactively.  (Your application can automatically fetch a new access token when the server responds with the error that indicates the token expired.)

Some services also allow for an “OAuth2 Client Credentials Grant Type”.  This is for when an application is accessing its own account rather than a user’s account. This flow type does not require interactive authorization because the application is accessing its own data.   (I do not know if O365 offers the Client Credentials grant type.)

The general procedure for getting an OAuth2 access token is for the case where your application is accessing a user’s account (not  your own) and the O365 account owner will need to interactively authorize the access.  If your application is a desktop application, then you’ll use the Chilkat.OAuth2 class.  If  your application is a web application running on your web server, then you don’t use Chilkat.OAuth2.  Instead, you just implement OAuth2 directly.

Here is a C# example for getting a Microsoft Graph OAuth2 access token in a desktop application:   https://www.example-code.com/csharp/microsoft_graph_oauth2_access_token.asp

The following inputs need to be provided:

Also see:  https://docs.microsoft.com/en-us/graph/auth/

Unfortunately, the Microsoft documentation is a bit confusing and at this point there are no simple straightforward and clear answers to the above questions.   However, if these questions can be answered, it SHOULD be possible to get an OAuth2 access token for O365 IMAP.   Once accomplished, the OAuth2 access token can be used in the same way as with GMail, as shown here:  https://www.example-code.com/csharp/gmail_imap_login_oauth2.asp

 

Note: To obtain an OAuth2 access token in a web app (not a desktop app), you wouldn’t use Chilkat.OAuth2.
Chilkat provides ASP.NET and Classic ASP examples here:  https://tools.chilkat.io/oauth2.cshtml
and here: https://tools.chilkat.io/oauth2.asp

 

 

Chilkat v9.5.0.83 Pre-Release Notes

$
0
0

The previous version release notes: Chilkat v9.5.0.82 Release Notes

Chilkat v9.5.0.83 Pre-Release Notes

    • 25-Mar-2020 SHA3: Added the SHA3 hash algorithms: sha3-224, sha3-256, sha3-384, sha3-512. The SHA3 hash algorithms may generally be used in any property or method of any Chilkat class where a hash algorithm is specified.
    • 25-Mar-2020 MailMan: Added OAuth2 authentication capability (“AUTH XOAUTH2”) for POP3 servers such as pop.gmail.com that support the XOAUTH2 authentication mechanism.
    • 26-Mar-2020 Csv: Added the SortByColumnIndex method.

Python Error: UnicodeEncodeError: ‘charmap’ codec can’t encode character

$
0
0

Question:

I’ve discovered an error on your example ( https://www.example-code.com/chilkat2-python/xml_i.asp ) as follows…

    AccountID: f1f489fb-9267-429e-a1dc-bc63a7c3f71e
    Traceback (most recent call last):
      File "M:\EXPORTIT\PY\CK_xero_accounts.py", line 50, in 
        print("Name: " + xml.GetChildContent("Accounts|Account[i]|Name"))
      File "m:\Python\Python35-32\lib\encodings\cp437.py", line 19, in encode
        return codecs.charmap_encode(input,self.errors,encoding_map)[0]
    UnicodeEncodeError: 'charmap' codec can't encode character '\u2013' in position 20: character maps to 

It’s failing on the this line from the “https://www.chilkatsoft.com/exampleData/xero_accounts.xml”,

          Wages Payable – Payroll

Answer:

The problem is that your Python code is expecting the returned string to be in the cp437 byte representation. “cp437” is code page 437, which is:

Code page 437 is the character set of the original IBM PC (personal computer). 
It is also known as CP437, OEM-US, OEM 437, PC-8, or DOS Latin US. The set includes all 
printable ASCII characters, extended codes for accented letters (diacritics), some Greek letters, 
icons, and line-drawing symbols.

The problematic char is the funky dash char. Chilkat is returning strings using the utf-8 byte representation. The fix in Python is to tell Python that you’re expecting utf-8. See https://stackoverflow.com/questions/2276200/changing-default-encoding-of-python or Google “python use utf-8 by default” to see what other possible solutions exist.


DNS Error: failed to get host address info, gai_error 8

$
0
0

If your MacOSX/iOS Swift application gets this error in the Chilkat LastErrorText:

        smtpSocketConnect:
          socket2Connect:
            connect2:
              connectImplicitSsl:
                connectSocket:
                  connect_ipv6_or_ipv4:
                    getAddressInfo:
                      Failed to get host address info. (4)
                      gai_error: 8
                      hostOrIpAddr: smtp.gmail.com
                      port: 465
                    --getAddressInfo
                    getAddressInfo failed.
                  --connect_ipv6_or_ipv4
                --connectSocket
              --connectImplicitSsl
              ConnectFailReason: DNS lookup failed
            --connect2
          --socket2Connect

The solution is to enable the Outgoing Connections option in your Swift project.

Start Browser from Client-Side PHP Script

$
0
0

Let’s say you have a PHP script (not PHP on a web server, but simply a .php script that you run from a command line), this is one way to start/launch a browser and automatically load/navigate to a URL.

<?php

// Type "start iexplore" and press "Enter" to open Internet Explorer and view its default home screen. 
// Alternatively, type "start firefox," "start opera" or "start chrome" and press "Enter" to open one of those browsers.
	
pclose(popen('start iexplore https://www.chilkatsoft.com &', 'r'));
//pclose(popen('start firefox -url https://www.chilkatsoft.com &', 'r'));
//pclose(popen('start chrome https://www.chilkatsoft.com &', 'r'));

?>

OAuth2 Request Access Token w/ Basic Authentication

$
0
0

Some OAuth2 token endpoints want the Client ID/Client Secret to be included using HTTP Basic Authentication.

For example, we can look at the documentation for the GoToMeeting API at https://goto-developer.logmeininc.com/how-get-access-token-and-organizer-key
You’ll see this under the “2 – Request Access Token”  in the GoTo API documentation linked above:

curl -X POST "https://api.getgo.com/oauth/v2/token" \
  -H "Authorization: Basic {Base64 Encoded consumerKey and consumerSecret}" \
  -H "Accept:application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code={responseKey}"

When the token endpoint desires Basic Authentication, set Chilkat.OAuth2.UseBasicAuth = true.

For example, the QuickBooks API also requires it:  https://www.example-code.com/csharp/quickbooks_oauth2_desktop_app.asp

0x80090016 – Keyset does not exist

$
0
0

This blog post describes one possible cause for the “Keyset does not exist” error when trying to access/use a non-exportable private key via the Microsoft CNG or CryptoAPI.

The situation was that the certificate was installed to the user’s Current User Personal Store, but the corresponding private key was stored in the Local Machine Key Store (machine keyset).  There were additional restrictions in place at the File System level which prevented users, that are not members of the Administrators group, from accessing LM Private Keys; even when access to the keys has been granted within the MMC snap-in.

The solution is to install the private key to the Current User Protected Store.

 

 

Convert VB6 Date to Timestamp used by Amazon?

$
0
0

A VB6 Date is an OLE Date (8-byte value, often represented as a double).  Use the Chilkat CkDateTime’s SetFromOleDate function to load the VB6 date/time into the CkDateTime object, then call GetAsTimestamp to emit in timestamp format.

Viewing all 415 articles
Browse latest View live