Aborting in C++

The technique for aborting any time-consuming Chilkat C++ method call follows this recipe:

  1. Declare your own class that derives from the appropriate Chilkat progress monitoring class.  For CkMailMan it is CkMailManProgress (as shown below).  For other Chilkat classes it is CkHttpProgress, CkFtpProgress, CkImapProgress, CkZipProgress, etc.
  2. Create an implementation for the AbortCheck method.  This will override the default implementation from the base class.  (The default implementation simply does nothing.)
  3. The AbortCheck method is called periodically according to the value of the HeartbeatMs property.  The default value of HeartbeatMs is 0, which indicate that no AbortCheck events should be called.  Set HeartbeatMs to a non-zero value (in milliseconds) to enable the AbortCheck callbacks.  Do this by calling put_HeartbeatMs(someValue)  as shown below.
  4. Whenever your application wishes to abort an operation in progress (SMTP, POP3, IMAP, Zip, FTP, etc.), set the abort boolean argument of AbortCheck to true.
  5. Don’t forget to hookup your event monitoring class by calling the SetProgressCallback method.  (See the code example below.)  In some classes, such as for CkImap, the way to hookup the event class is via the put_EventCallbackObject function.  Please review the .h file for details.
#include <CkMailManProgress.h>

class MyMailProgress : public CkMailManProgress
    {
    public:
	MyMailProgress(void) { }
	virtual ~MyMailProgress(void) { }

	// Override the AbortCheck method (which is a virtual method in CkMailProgress)
	// Called periodically according to the value of the HeartbeatMs property.
	void AbortCheck(bool *abort)
	    {
	    printf("AbortCheck!\n");

	    // If your application wishes to abort the email sending/receiving operation,
	    // set the abort boolean like this:
	    *abort = true;
	    }

        // Percentage completion events may also be overridden to abort time-consuming operations.
	void SendPercentDone(long pctDone, bool *abort) 
	    { 
	    printf("SendPercentDone: %d percent\n",pctDone);
	    }
	void ReadPercentDone(long pctDone, bool *abort) 
	    { 
	    printf("ReadPercentDone: %d percent\n",pctDone);
	    }

    };

void AbortCheckDemo(void)
    {
    CkMailMan mailman;
    bool success;
    success = mailman.UnlockComponent("30-day trial");
    if (success != true)
	{
        printf("%s\n",mailman.lastErrorText());
        return;
	}

    // Set the HeartbeatMs property so that AbortCheck is called once every 80 milliseconds.
    mailman.put_HeartbeatMs(80);

    MyMailProgress myProgress;
    mailman.SetProgressCallback(&myProgress);

    CkEmail email;
    // ...
    // ...

    // The AbortCheck event is called periodically while SendEmail is in progress..
    // (Note: In some cases, including here, a percent-done event is also called, and it will have an "abort"
    // boolean argument that may be set to "true" to force an abort.
    // If the percent-done callbacks happen more frequently than the HeartbeatMs setting, then 
    // the AbortCheck events may not be fired at all.)
    success = mailman.SendEmail(email);
    if (success != true)
	{
        printf("%s\n",mailman.lastErrorText());
        return;
	}

    }

Socket SendString (C++) w/ TCHAR

Question:

I need to send a unicode string (e.g TCHAR *ptr) but the API only allows to send char.

Answer:

/*
The _TCHAR data type is defined conditionally in Tchar.h. 
If the symbol _UNICODE is defined for your build, _TCHAR is defined as wchar_t; 
otherwise, for single-byte and MBCS builds, it is defined as char.
*/
bool sendString(CkSocket &sock, TCHAR *str)
    {
    bool success = false;

#ifdef _UNICODE
    success = sock.SendBytes((const unsigned char *)str, _tcslen(str) * 2);
#else
    success = sock.SendString(str);
#endif

    return success;
    }

Is Calling .Dispose() Recommended for C# and VB.NET?

Question:

In your examples online, we have noticed that .Dispose() is never
called after using Chilkat classes (we are writing in C#).

Is calling .Dispose() recommended?  Does your code not need to destroy
any native resources or handles that would normally be cleaned up in
the Dispose method (the IDisposeable interface) ?

Answer:

For objects that manage a TCP/IP socket connection with a server (FTP2, SSH, SFTP, POP3, SMTP, IMAP, HTTP, etc.) then calling Dispose will close the connection.  Aside from memory-usage and socket connections, there are no other resources used by Chilkat classes.  Dispose may also deallocate some internal memory.

The important thing to realize is that once Dispose is called, your code should not use that particular instance of the object again.  I always prefer a more explicit approach.  For example, instead of calling Chilkat.MailMan.Dispose to ensure that a connection to the SMTP server is closed, call Chilkat.MailMan.CloseSmtpConnection.  (If the mailman is not actually connected, calling CloseSmtpConnection does NOT result in an error.  It is harmless.)

Also, when an Chilkat object’s finalizer is called (i.e. when it is garbage-collected), any existing socket connections are closed and internal memory is (of course) deallocated.   You may force garbage collection by doing this (in C#)

 GC.Collect();
 GC.WaitForPendingFinalizers();

Chilkat C++ Libs – Link and Maintain Single EXE?

Question:

I am developing a single EXE in C++ that doesn’t make use of any external libraries and including MFC. Can I add your zip libaries to my application and still maintain the application as a single EXE?

Answer:

Yes, the Chilkat C++ libs may be linked directly into your application.  This results in a single EXE containing the Chilkat library code required to satisfy all direct and indirect references.  (The linker includes only the code needed to resolve all references.)  You may run your EXE on any computer because the licensing is royalty-free.  Internally, Chilkat does not use or reference MFC.   (Note: MFC applications may still use the Chilkat libs.  The point is this: if your application does not use MFC, then linking with Chilkat will not cause MFC to be “pulled-into” your EXE.)

HTTP Progress Monitoring in C++

This blog post shows how to monitor the progress of HTTP uploads and downloads in C++.  The first step is to create a C++ callback class that derives from the CkHttpProgress base class.  You’ll be overriding one or more of the callback methods.  For example:

class MyHttpProgress : public CkHttpProgress
    {
    public:
	MyHttpProgress(void) { }
	virtual ~MyHttpProgress(void) { }

	void PercentDone(int pctDone, bool *abort) 
	    { 
	    printf("PercentDone: %d percent\n",pctDone);

	    // To abort the HTTP operation, set the abort flag equal to true.
	    //if (pctDone > 10)
		//{
		//*abort = true;
		//}
	    }
	void AbortCheck(bool *abort) 
	    { 
	    // To abort the HTTP operation, set the abort flag equal to true.
            // Like this:
            // *abort = true;

            // Note: The AbortCheck event callback is called periodically according to the HeartbeatMs 
            // property setting.

	    printf("AbortCheck!\n");
	    }
	void HttpBeginReceive(void) { printf("HttpBeginReceive!\n"); }
	void HttpEndReceive(bool success) { printf("HttpEndReceive!\n"); }
	void HttpBeginSend(void) { printf("HttpBeginSend!\n"); }
	void HttpEndSend(bool success) { printf("HttpEndSend!\n"); }

    };

In your C++ application, create an instance of your MyHttpProgress class and tell the CkHttp object to use it by calling put_EventCallbackObject. Here’s an example:

void TestDownloadWithEventCallbacks(void)
    {
    MyHttpProgress eventObj;

    CkHttp http;
    bool success = http.UnlockComponent("Anything for 30-day trial");
    
    http.put_EventCallbackObject(&eventObj);

    success = http.Download("http://www.chilkatsoft.com/something/something.zip","something.zip");
    if (!success) 
        {
        printf("%s\n",http.lastErrorText());
        }
    else
        {
        printf("Finished.\n");
        }

    }

Scan/Replace Text in Email Body in C++

This example may help C++ programmers needing to scan email bodies for strings and automatically replace:

void EmailBodyExample(void)
    {
    CkEmail email;

    // Set the plain-text and HTML alternative bodies.
    // Note: Because we're using literal strings, the strings passed
    // to these methods are ANSI strings (i.e. they are 1-byte per char
    // in this case).
    email.AddPlainTextAlternativeBody("á, é, í, ó, ú, abc");
    email.AddHtmlAlternativeBody("<html><body><p>á, é, í, ó, ú, abc</p></body></html>");

    // Suppose we don't know the language or charset of the email?
    // Maybe it's Chinese, perhaps it's Hebrew...
    // You can get the body text in utf-8 (the multibyte encoding of Unicode)
    // for all languages.  Here's how to do it:
    CkString strPlainTextBody;
    CkString strHtmlBody;

    // Get the email bodies into the CkString objects:
    email.GetPlainTextBody(strPlainTextBody);
    email.GetHtmlBody(strHtmlBody);

    // Now get the utf-8 (null-terminated) strings:
    const char *strUtf8PlainTextBody = strPlainTextBody.getUtf8();
    const char *strUtf8HtmlBody = strHtmlBody.getUtf8();

    // Suppose you want to modify the body and replace it?
    // Let's replace "abc" with "123".
    // One way to do it is like this:
    strPlainTextBody.replaceAllOccurances("abc","123");

    // Tell the email object that "const char *" arguments will point to utf-8,
    // not ANSI:
    email.put_Utf8(true);

    // Pass the modified utf-8 string.
    // AddPlainTextAlternativeBody will replace the existing plain-text
    // body if it already exists.
    email.AddPlainTextAlternativeBody(strPlainTextBody.getUtf8());

    // Another way to do it:
    char *tmpBuf = new char[strHtmlBody.getSizeUtf8()+1];   // Add 1 for the terminating null
    strcpy(tmpBuf,strUtf8HtmlBody);
    char *abc = strstr(tmpBuf,"abc");
    if (abc)
	{
	*abc = '1'; abc++;
	*abc = '2'; abc++;
	*abc = '3';
	}
    email.AddHtmlAlternativeBody(tmpBuf);

    delete [] tmpBuf;

    // Save the email and examine it using a text editor or email client..
    email.SaveEml("out.eml");
    }

SFTP Progress Monitoring and Abort (C#)

Here is an example for monitoring the progress of an SFTP file transfer:

        void sftp_OnPercentDone(object sender, Chilkat.PercentDoneEventArgs args)
        {
            progressBar1.Value = args.PercentDone;

            // To abort at any point, you may set args.Abort = true  
            // args.Abort = true;
        }

        void sftp_OnAbortCheck(object sender, Chilkat.AbortCheckEventArgs args)
        {
            // See http://cknotes.com/?p=149  for more information about 
            // using the AbortCheck event...
           
        }

private void button2_Click(object sender, EventArgs e)
{
	// SFTP upload with progress monitoring.
	Chilkat.SFtp sftp = new Chilkat.SFtp();

	// IMPORTANT: Enable event callbacks:
	sftp.EnableEvents = true;

	// Unlock the component.
	bool success = sftp.UnlockComponent("Anything for 30-day trial");
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Connect to the SSH/SFTP server. (use a domain name or IP address)
	success = sftp.Connect("192.168.1.117", 22);
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Authenticate..
	success = sftp.AuthenticatePw("chilkat", "myPassword");
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	success = sftp.InitializeSftp();
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Establish some event handlers:
	sftp.OnAbortCheck += new Chilkat.SFtp.AbortCheckEventHandler(sftp_OnAbortCheck);
	sftp.OnPercentDone += new Chilkat.SFtp.PercentDoneEventHandler(sftp_OnPercentDone);

	// See http://cknotes.com/?p=149  for more information about 
	// using the AbortCheck event...

	// Do an upload.
	// Note: If the file to be uploaded or downloaded is too small, 
	// the PercentDone callback will not be called for each 1%.
	// It's possible if the file is so small relative to the speed
	// of the connection that you may get a single 100% callback if
	// the data transfer happens almost instantaneously.
	string localFilepath = "c:/temp/hamlet.xml";
	string remoteFilepath = "hamlet.xml";
	progressBar1.Value = 0;
	success = sftp.UploadFileByName(remoteFilepath, localFilepath);
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}
	MessageBox.Show("OK!");
}

C++ String Compression: PPMD, Deflate, BZip2, LZW

This C++ example demonstrates string compression using four different compression algorithms: PPMD, Deflate, BZip2, and LZW.

void TestCompression(const char *algorithm)
    {
    CkCompression comp;

    comp.put_Algorithm(algorithm);
    printf ("algorithm: %s\n",algorithm);

    CkByteData compressedData;
    comp.CompressString("abc abc abc abc abc abc abc abc abc abc abc 123 123 abc 123",compressedData);

    // Get the compressed data:
    const unsigned char *pCompressedData = compressedData.getBytes();
    unsigned long numBytes = compressedData.getSize();
    printf("numBytes = %d\n",numBytes);

    // Imagine you've sent the compressed data over a socket connection to some receiver...


    // Decompress:
    CkByteData compressedData2;
    compressedData2.append(pCompressedData,numBytes);
    printf("%s\n",comp.decompressString(compressedData2));
    printf("----\n");
    }

void CompressionExample(void)
    {
    CkCompression comp;
    comp.UnlockComponent("30-day trial");

    TestCompression("deflate");
    TestCompression("ppmd");
    TestCompression("bzip2");
    TestCompression("lzw");

    }

The output is as follows:

algorithm: deflate
numBytes = 15
abc abc abc abc abc abc abc abc abc abc abc 123 123 abc 123
----
algorithm: ppmd
numBytes = 18
abc abc abc abc abc abc abc abc abc abc abc 123 123 abc 123
----
algorithm: bzip2
numBytes = 54
abc abc abc abc abc abc abc abc abc abc abc 123 123 abc 123
----
algorithm: lzw
numBytes = 30
abc abc abc abc abc abc abc abc abc abc abc 123 123 abc 123
----

Inflate from Zip to memory in C++

This example demonstrates how to inflate in-memory from a Zip in C++:

    CkZip zip;

...

    // Assume we have a CkZip object and a .zip has been loaded.
    // It may have been loaded from a file by calling OpenZip, or from an
    // in-memory image of a .zip by calling OpenFromMemory.
    // (or any of the other CkZip.Open* methods)
    CkString strXml;
    CkByteData gifData;

    // Find the file within the zip containing the data we want to access...
    CkZipEntry *entry = zip.FirstMatchingEntry("*hamlet.xml");
    if (entry)
	{
	// Found it.  This is a text file that may be inflated to a null-terminated
	// string.  
	const char *xmlText = entry->inflateToString2();

	// Copy the text to a safe place.  Once the CkZipEntry object is deleted,
	// it is no longer a valid pointer:
	strXml.append(xmlText);

	delete entry;
	}

    // Get the data for a binary file:
    entry = zip.FirstMatchingEntry("*dude.gif");
    if (entry)
	{
	entry->Inflate(gifData);
	delete entry;

	// The binary bytes may be accessed like this:
	const unsigned char *gifBytes = gifData.getData();
	unsigned long numGifBytes = gifData.getSize();
	}

Non-English String Literals in C++ Source Code

When a C++ compiler compiles a C++ source file, it must process the bytes according to a character encoding and that is typically ANSI.  ANSI is not a character encoding, it is simply a keyword that says “Use the default multi-byte character encoding for this computer based on its current locale.”   Therefore, if your program is originally written in Poland and contains string literals (i.e. character string constants in double-quotes) with Polish characters, the same source when compiled on a typical computer in France will not produce the same results.  The bytes for the Polish characters will instead be interpreted as Latin1 characters and the string will be different.  This example demonstrates a technique you may use to embed string literals using quoted-printable so that the C++ source may be compiled on any computer without character encoding issues caused by the locale.   Chilkat provides a free tool to quoted-printable encode a string (which may contain characters in any language):

Quoted-Printable Encoding Tool Download

Here is a screenshot:

Quoted-Printable Encoder

The quoted-printable encoder is a very simple C# program that uses the Chilkat.CkString class.   Here is the complete source code:

        private void button1_Click(object sender, EventArgs e)
        {
            Chilkat.CkString str = new Chilkat.CkString();
            str.append(textBox1.Text);
            str.qpEncode(comboBox1.Text);
            textBox2.Text = str.getString();
        }

Using Quoted-Printable String Literals in C++

Use the tool to convert your string to quoted-printable using the utf-8 character encoding.  (utf-8 is the multi-byte encoding for Unicode, so it is able to mix characters of any language in a single NULL-terminated string.  A “multibyte” encoding is a character encoding such that each character is represented by one or more bytes, and there are no NULL bytes.)

Use the quoted-printable encoded string in your C++ source code like this:
(This example constructs an IMAP mailbox name using Vietnamese characters)

    CkImap imap;
    bool success;
...

    CkString str;
    str.append("C=C3=B4ng c=E1=BB=99ng");
    str.qpDecode("utf-8");
    str.prepend("Inbox.");

    imap.put_Utf8(true);
    success = imap.CreateMailbox(str.getUtf8());
    if (success != true) {
        printf("%s\n",imap.lastErrorText());
        return;
    }