13.03.2015 Views

Using-libcurl-with-SSH-support-in-Visual-Studio-2010

Using-libcurl-with-SSH-support-in-Visual-Studio-2010

Using-libcurl-with-SSH-support-in-Visual-Studio-2010

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong><br />

<strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong><br />

Version 1.3<br />

© Andrei Jakab (andrei.jakab@tut.fi)<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 1


Revision History<br />

Revision Date By Comment<br />

1.0 11 Jul 2011 Andrei Jakab Initial version<br />

1.1 17 Jul 2012 Andrei Jakab Updated the guide to reflect the latest<br />

versions of:<br />

o ActivePerl (5.14.2.1402)<br />

o <strong>libcurl</strong> (7.26.0)<br />

o lib<strong>SSH</strong>2 (1.4.2)<br />

o NASM (2.10.01)<br />

o OpenSSL (1.0.1c)<br />

1.2 22 Sep 2012 Andrei Jakab Appendix A: corrected preprocessor<br />

def<strong>in</strong>itions<br />

1.3 05 Feb 2013 Andrei Jakab Updated the guide to reflect the latest<br />

versions of:<br />

o ActivePerl (5.16.2.1602)<br />

o <strong>libcurl</strong> (7.28.1)<br />

o lib<strong>SSH</strong>2 (1.4.3)<br />

o NASM (2.10.07)<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 2


Acknowledgements<br />

I would like to thank the follow<strong>in</strong>g people for help<strong>in</strong>g me make this guide what it is today by<br />

lett<strong>in</strong>g me know about typos and by suggest<strong>in</strong>g improvements:<br />

<br />

<br />

<br />

<br />

<br />

<br />

Chengwei L<strong>in</strong><br />

Jon Woellhaf<br />

Philipp Leusmann<br />

Re<strong>in</strong>hard Gentz<br />

Jack Schmidt<br />

Huu M<strong>in</strong>h Nguyen<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 3


Table of Contents<br />

REVISION HISTORY 2<br />

ACKNOWLEDGEMENTS 3<br />

CONVENTIONS 5<br />

1. INTRODUCTION 6<br />

2. DOWNLOADING THE LATEST SOFTWARE 7<br />

3. INSTALLATION / COMPILATION 8<br />

3.1 ActivePerl 8<br />

3.2 Netwide Assembler 9<br />

3.3 OpenSSL 9<br />

3.4 lib<strong>SSH</strong>2 11<br />

3.5 <strong>libcurl</strong> 13<br />

4. USING THE LIBCURL LIBRARY IN YOUR VISUAL STUDIO PROJECT 15<br />

4.1 Prepar<strong>in</strong>g the project’s file structure 15<br />

4.2 Creat<strong>in</strong>g the test project 16<br />

4.3 How to use the <strong>libcurl</strong> library 19<br />

4.3.1 Sample source code 19<br />

4.3.2 Add<strong>in</strong>g <strong>libcurl</strong> to the list of libraries 22<br />

4.3.3 The test-drive 24<br />

5. FINAL NOTES 25<br />

APPENDIX A – ADDING OPENSSL SUPPORT DIRECTLY TO LIBCURL 26<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 4


Conventions<br />

The follow<strong>in</strong>g font conventions are used <strong>in</strong> this document:<br />

<br />

<br />

<br />

<br />

italic is used for filenames, directory names, and URLs<br />

constant width is used to <strong>in</strong>dicate commands and code sections<br />

red, bold and underl<strong>in</strong>ed text <strong>in</strong>dicates important items<br />

bold is used to represent GUI items (e.g. menus, menu items, list nodes etc.)<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 5


1. Introduction<br />

Libcurl is a widely-used open-source library for transferr<strong>in</strong>g files. It <strong>support</strong>s many protocols<br />

(e.g. FTP, HTTP, SFTP etc.) and it is very well designed.<br />

One of <strong>libcurl</strong>’s strengths is its portability. You can build it on numerous platforms and you can<br />

be sure that it will work the same way on all of them. This wide <strong>support</strong> also means that the<br />

developers cannot constantly update the readme files for all the <strong>support</strong>ed platforms. Thus, I<br />

have decided to create this document <strong>in</strong> order to share my experiences while compil<strong>in</strong>g a static<br />

version of the curl library <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong>.<br />

This document is based on my previous guide “<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong><br />

2008”, which was <strong>in</strong>spired from Rosso Salmanzadeh's excellent “<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong>”<br />

guide.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 6


2. Download<strong>in</strong>g the latest software<br />

Libcurl requires two additional open-source libraries <strong>in</strong> order to provide the <strong>SSH</strong> functionality:<br />

lib<strong>SSH</strong>2 and OpenSSL. Also, s<strong>in</strong>ce the compilation of OpenSSL makes use of Perl scripts, you<br />

need to have a Perl distribution <strong>in</strong>stalled on your mach<strong>in</strong>e. I have chosen ActivePerl, a free<br />

distribution by ActiveState, for this purpose. OpenSSL also requires the Netwide Assembler to<br />

be present on your computer.<br />

The OpenSSL and lib<strong>SSH</strong>2 libraries are distributed as tarballs compressed us<strong>in</strong>g gzip. Hence,<br />

you will need a utility to uncompress and subsequently open the tar file. I recommend the opensource<br />

archiver 7-Zip.<br />

In order to obta<strong>in</strong> the latest version of the Netwide Assembler, click on the l<strong>in</strong>k <strong>in</strong> the table<br />

below and, on the webpage that appears, follow the l<strong>in</strong>k that takes you to the latest stable version<br />

of NASM. You have the choice between download<strong>in</strong>g the source code or pre-compiled b<strong>in</strong>aries.<br />

I strongly encourage you to download the b<strong>in</strong>ary files s<strong>in</strong>ce I will not cover the compilation of<br />

NASM <strong>in</strong> this guide. The archives that conta<strong>in</strong> the b<strong>in</strong>ary distributions are located <strong>in</strong> folders<br />

named after their <strong>in</strong>tended architecture e.g. w<strong>in</strong>32, dos, os2 etc.<br />

Software URL Current Version<br />

ActivePerl http://www.activestate.com/activeperl/downloads 5.16.2.1602<br />

OpenSSL http://www.openssl.org/source 1.0.1c<br />

lib<strong>SSH</strong>2 http://www.libssh2.org 1.4.3<br />

<strong>libcurl</strong> http://curl.haxx.se/download.html 7.28.1<br />

Netwide Assembler http://www.nasm.us 2.10.07<br />

7-Zip http://www.7-zip.org 9.20<br />

NOTE: This guide assumes that you already have successfully <strong>in</strong>stalled Microsoft <strong>Visual</strong><br />

<strong>Studio</strong> <strong>2010</strong> (VS<strong>2010</strong>). The examples <strong>in</strong> this document were built us<strong>in</strong>g version<br />

10.0.40219.1 SP1 of VS<strong>2010</strong>.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 7


3. Installation / Compilation<br />

3.1 ActivePerl<br />

Install<strong>in</strong>g ActivePerl is fairly straightforward as long as you are logged <strong>in</strong> <strong>with</strong> an Adm<strong>in</strong>istrator<br />

account. Below are screenshots from each step of the <strong>in</strong>stallation process. Please pay particular<br />

attention to Step 4 because choos<strong>in</strong>g the wrong option there will make your life harder later.<br />

Step 1 - Introduction<br />

Step 2 - EULA<br />

Step 3 - Customization 1<br />

Note 1: The “Documentation” and<br />

“Examples” are only useful if you<br />

wish to learn how to use ActivePerl;<br />

for the purposes of this document,<br />

these items are not needed.<br />

Note 2: The default <strong>in</strong>stallation location is not<br />

<strong>in</strong> the Program Files folder. Make sure<br />

to change this if you like to keep your<br />

C: folder tidy.<br />

Step 4 - Customization 2<br />

NOTE: Make sure that there’s a checkmark<br />

besides the “Add Perl to the PATH<br />

environment variable” option.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 8


Step 5 - Installation Confirmation<br />

Step 6 - Installation Complete<br />

3.2 Netwide Assembler<br />

1. Extract the nasm-2.10.07 folder from the zip file and place it <strong>in</strong> the C: root directory<br />

3.3 OpenSSL<br />

Compil<strong>in</strong>g the OpenSSL library is a bit tricky. The follow<strong>in</strong>g step-by-step guide should help you<br />

get through the compilation process as quickly and as pa<strong>in</strong>lessly as possible.<br />

1. Extract the openssl-1.0.1c.tar file from the gzip file to a temporary directory<br />

2. Extract the openssl-1.0.1c folder from the tar file and place it <strong>in</strong> the C: root directory<br />

3. Close the VS<strong>2010</strong> IDE and open a <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> command prompt. If you’ve<br />

<strong>in</strong>stalled VS <strong>2010</strong> <strong>with</strong> the default sett<strong>in</strong>gs, the command prompt shortcut should be<br />

located <strong>in</strong> Start -> All Programs -> Microsoft <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> -> <strong>Visual</strong> <strong>Studio</strong><br />

Tools -> <strong>Visual</strong> <strong>Studio</strong> Command Prompt (<strong>2010</strong>)<br />

4. Add the NASM executable to the PATH environment variable:<br />

path = %PATH%;C:\nasm-2.10.07<br />

5. Create the directory where the output of the compilation process will be stored:<br />

mkdir c:\openssl_lib<br />

6. Change the work<strong>in</strong>g directory to the OpenSSL directory:<br />

cd /D c:\openssl-1.0.1c<br />

7. Configure the OpenSSL <strong>in</strong>stallation <strong>with</strong>:<br />

perl Configure VC-WIN32 --prefix=c:/openssl_lib<br />

where the --prefix argument specifies where OpenSSL header and library files will<br />

be copied at the end of the compilation process.<br />

NOTE: The path that is passed to the --prefix argument must be <strong>in</strong> the UNIX<br />

format i.e. forward slashes are used to separate directories and not backward<br />

slashes like it is customary <strong>in</strong> W<strong>in</strong>dows.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 9


The output of this command should look like this:<br />

8. Create the required assembly files:<br />

ms\do_nasm<br />

Note: <strong>Us<strong>in</strong>g</strong> assembly files makes the execution of library functions much faster. If you<br />

do not wish to use assembly files, use the follow<strong>in</strong>g command <strong>in</strong>stead and jump to<br />

step 8:<br />

ms\do_ms<br />

9. Compile the static library:<br />

nmake -f ms\nt.mak<br />

10. The compilation process takes a while so you can go grab some coffee/tea at this po<strong>in</strong>t.<br />

11. If all is well, at the end of the compilation you will have some libraries and a number of<br />

executables <strong>in</strong> C:\openssl-1.0.1c\out32<br />

12. The library conta<strong>in</strong>s some built <strong>in</strong> tests that allow you to check if everyth<strong>in</strong>g has<br />

compiled properly and if the library is <strong>in</strong> work<strong>in</strong>g order:<br />

nmake -f ms\nt.mak test<br />

If the library has compiled properly, you should obta<strong>in</strong> a “passed all tests” message once<br />

this command f<strong>in</strong>ishes execut<strong>in</strong>g.<br />

13. To <strong>in</strong>stall OpenSSL to the location you specified <strong>in</strong> step 6, run:<br />

nmake -f ms\nt.mak <strong>in</strong>stall<br />

Note: You can f<strong>in</strong>d additional compil<strong>in</strong>g <strong>in</strong>structions <strong>in</strong> C:\openssl-1.0.1c\INSTALL.W32; this<br />

file also conta<strong>in</strong>s a troubleshoot<strong>in</strong>g section that could help you out if someth<strong>in</strong>g goes<br />

wrong dur<strong>in</strong>g the compilation process.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 10


3.4 lib<strong>SSH</strong>2<br />

1. Extract the libssh2-1.4.3.tar file from the gzip file to a temporary directory.<br />

2. Extract the libssh2-1.4.3 directory from the tar file and place it <strong>in</strong> the C: root directory.<br />

3. Open C:\libssh2-1.4.3\w<strong>in</strong>32\libssh2.dsp <strong>in</strong> the <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> IDE. S<strong>in</strong>ce this<br />

project file was created us<strong>in</strong>g an older version of <strong>Visual</strong> <strong>Studio</strong>, the follow<strong>in</strong>g message<br />

box will appear:<br />

Click on “Yes”. Once the conversion is completed, you should see the follow<strong>in</strong>g <strong>in</strong> the<br />

Solution Explorer w<strong>in</strong>dow:<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 11


4. Set the LIB Debug as the active solution configuration. On the Build menu <strong>in</strong> <strong>Visual</strong><br />

<strong>Studio</strong>, click Configuration Manager… and <strong>in</strong> the w<strong>in</strong>dow that appears select LIB<br />

Debug from the Active solution configuration drop-down list. Close the Configuration<br />

Manager.<br />

5. Next, you must tell the compiler and the librarian where the OpenSSL library is located<br />

and how to compile the library:<br />

a. Right-click on the libssh2 project <strong>in</strong> the Solution Explorer w<strong>in</strong>dow and select<br />

Properties from the pop-up menu.<br />

b. Expand the Configuration Properties node, click on the C/C++ node<br />

i. Select General, choose the Additional Include Directories property and<br />

add the follow<strong>in</strong>g:<br />

;C:\openssl_lib\<strong>in</strong>clude<br />

(the semicolon needed s<strong>in</strong>ce other paths are already present)<br />

ii. Next, click on Code Generation and <strong>in</strong> the Runtime Library field, select<br />

the Multi-threaded Debug DLL (/MDd) option.<br />

c. Also <strong>in</strong> the Configuration Properties node, expand the Librarian node, and<br />

select General.<br />

i. Change the Output File property to:<br />

Debug_lib\libssh2.lib<br />

ii. Click on the Additional Dependencies property and set it to:<br />

libeay32.lib;ssleay32.lib<br />

iii. Choose the Additional Library Directories and add the follow<strong>in</strong>g path:<br />

C:\openssl_lib\lib<br />

d. Click on the OK button.<br />

6. Now we are ready to compile. Right-click on the libssh2 project and select Build from<br />

the pop-up menu. VS<strong>2010</strong> will prompt you to save the solution file that was created for<br />

this project. Once you save it, compilation will beg<strong>in</strong>.<br />

7. The compiler might display a couple of security warn<strong>in</strong>gs and/or “possible loss of data”<br />

warn<strong>in</strong>gs. Also the l<strong>in</strong>ker might display a number of LNK4221 warn<strong>in</strong>gs. For our<br />

purposes, both of these types of warn<strong>in</strong>gs can be safely ignored.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 12


3.5 <strong>libcurl</strong><br />

1. Extract the curl-7.28.1 folder from the archive and place it <strong>in</strong> the C: root directory. For<br />

our purposes, we will need the files located <strong>in</strong> the lib and <strong>in</strong>clude directories.<br />

2. Open C:\curl-7.28.1\lib\<strong>libcurl</strong>.vcproj <strong>in</strong> the <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> IDE. S<strong>in</strong>ce this is a<br />

<strong>Visual</strong> <strong>Studio</strong> 2005 project file, the “<strong>Visual</strong> <strong>Studio</strong> Conversion Wizard” will appear. The<br />

wizard should not encounter any problems convert<strong>in</strong>g the project to the VS<strong>2010</strong> format<br />

but will generate a couple of warn<strong>in</strong>gs, which can be safely ignored.<br />

3. Next, you must tell the compiler and the librarian to use the lib<strong>SSH</strong>2 library and where<br />

this library is located:<br />

a. Right-click on the <strong>libcurl</strong> project <strong>in</strong> the Solution Explorer w<strong>in</strong>dow and select<br />

Properties from the pop-up menu.<br />

b. Expand the Configuration Properties node, then the C/C++ node.<br />

i. Click on the General node. Next to Additional Include Directories, add<br />

the follow<strong>in</strong>g:<br />

;C:\libssh2-1.4.3\<strong>in</strong>clude<br />

(the semicolon is needed s<strong>in</strong>ce there are already two additional <strong>in</strong>clude<br />

directories specified)<br />

ii. Select the Preprocessor node and click on the Preprocessor Def<strong>in</strong>itions<br />

property. Add <strong>in</strong> the follow<strong>in</strong>g to the exist<strong>in</strong>g def<strong>in</strong>itions:<br />

;CURL_STATICLIB;USE_LIB<strong>SSH</strong>2;CURL_DISABLE_LDAP;HAVE_<br />

LIB<strong>SSH</strong>2;HAVE_LIB<strong>SSH</strong>2_H;LIB<strong>SSH</strong>2_WIN32 ;LIB<strong>SSH</strong>2_LIBRARY<br />

c. In the Configuration Properties node, expand the Librarian node, and select<br />

General.<br />

i. Select Additional Dependencies and type <strong>in</strong>:<br />

libssh2.lib<br />

ii. Next to Additional Library Directories, type <strong>in</strong> the path:<br />

C:\libssh2-1.4.3\w<strong>in</strong>32\Debug_lib<br />

d. Click on the OK button.<br />

4. After all this work, we are f<strong>in</strong>ally ready to compile the <strong>libcurl</strong> library. Right-click on the<br />

curllib project <strong>in</strong> the Solution Explorer and select Build from the pop-up menu. VS<strong>2010</strong><br />

will prompt you to save the solution file that was created for this project. Once you save<br />

it, compilation will beg<strong>in</strong>:<br />

1>------ Build started: Project: <strong>libcurl</strong>, Configuration: Debug W<strong>in</strong>32 ------<br />

1> wildcard.c<br />

1> warnless.c<br />

1> version.c<br />

1> url.c<br />

1> transfer.c<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 13


1> timeval.c<br />

…<br />

1> curl_darw<strong>in</strong>ssl.c<br />

1> curl_addr<strong>in</strong>fo.c<br />

1> cookie.c<br />

1> content_encod<strong>in</strong>g.c<br />

1> Generat<strong>in</strong>g Code...<br />

1> Compil<strong>in</strong>g...<br />

1> connect.c<br />

1> base64.c<br />

1> axtls.c<br />

1> asyn-thread.c<br />

1> asyn-ares.c<br />

1> amigaos.c<br />

1> Generat<strong>in</strong>g Code...<br />

1>libssh2.lib(ecp_nistputil.obj) : warn<strong>in</strong>g LNK4221: This object file does not def<strong>in</strong>e any<br />

previously undef<strong>in</strong>ed public symbols, so it will not be used by any l<strong>in</strong>k operation that<br />

consumes this library<br />

1>libssh2.lib(ecp_nistp521.obj) : warn<strong>in</strong>g LNK4221: This object file does not def<strong>in</strong>e any<br />

previously undef<strong>in</strong>ed public symbols, so it will not be used by any l<strong>in</strong>k operation that<br />

consumes this library<br />

1>libssh2.lib(ecp_nistp256.obj) : warn<strong>in</strong>g LNK4221: This object file does not def<strong>in</strong>e any<br />

previously undef<strong>in</strong>ed public symbols, so it will not be used by any l<strong>in</strong>k operation that<br />

consumes this library<br />

1>libssh2.lib(ecp_nistp224.obj) : warn<strong>in</strong>g LNK4221: This object file does not def<strong>in</strong>e any<br />

previously undef<strong>in</strong>ed public symbols, so it will not be used by any l<strong>in</strong>k operation that<br />

consumes this library<br />

1>libssh2.lib(fips_ers.obj) : warn<strong>in</strong>g LNK4221: This object file does not def<strong>in</strong>e any<br />

previously undef<strong>in</strong>ed public symbols, so it will not be used by any l<strong>in</strong>k operation that<br />

consumes this library<br />

1> <strong>libcurl</strong>.vcxproj -> C:\curl-7.28.1\lib\.\Debug\<strong>libcurl</strong>.lib<br />

========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========<br />

The LNK4221 warn<strong>in</strong>gs can be safely ignored.<br />

By default, the output directory is C:\curl-7.28.1\lib\Debug. In order to create an<br />

application that uses the <strong>libcurl</strong> library, we only need the <strong>libcurl</strong>.lib file from the output<br />

directory and the C:\curl-7.28.1\<strong>in</strong>clude\curl directory, which conta<strong>in</strong>s the library’s<br />

header files.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 14


4. <strong>Us<strong>in</strong>g</strong> the <strong>libcurl</strong> library <strong>in</strong> your <strong>Visual</strong> <strong>Studio</strong> project<br />

In this section we will create a test project, which will at the same time test the library’s<br />

functionality and demonstrate how to <strong>in</strong>tegrate <strong>libcurl</strong> <strong>in</strong>to one of your projects. I suggest that<br />

you follow the example step by step (i.e. use the same project names, paths etc.) so that you<br />

obta<strong>in</strong> the same figures as the ones shown below. This will make your life easier <strong>in</strong> case you<br />

encounter any problems along the way.<br />

4.1 Prepar<strong>in</strong>g the project’s file structure<br />

Create the follow<strong>in</strong>g folder structure <strong>in</strong> you C: root directory:<br />

Copy the curl folder from the C:\curl-7.28.1\<strong>in</strong>clude directory <strong>in</strong>to the C:\Projects\custom<br />

libraries\<strong>in</strong>clude directory. The curl directory should conta<strong>in</strong> the follow<strong>in</strong>g files:<br />

Notice that there are also 4 make files <strong>in</strong> this directory. We won’t need them so they can be<br />

safely deleted, if you wish.<br />

F<strong>in</strong>ally, you need to copy liburl.lib from C:\curl-7.28.1\lib\Debug to C:\Projects\custom<br />

libraries\lib_dbg.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 15


4.2 Creat<strong>in</strong>g the test project<br />

The <strong>libcurl</strong> library can be used <strong>in</strong> any type of application. In order to keep th<strong>in</strong>gs simple, we will<br />

create a simple W<strong>in</strong>32 console application.<br />

1. Fire up VS<strong>2010</strong> and go to: File -> New -> Project…<br />

2. First expand the <strong>Visual</strong> C++ node, then select the W<strong>in</strong>32 node and click on the W<strong>in</strong>32<br />

Console Application item <strong>in</strong> the middle panel:<br />

3. Type <strong>in</strong> “test_curl” for the project name. The project location should be:<br />

C:\Projects<br />

Make sure that the checkbox Create directory for solution is checked and click on OK.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 16


4. The W<strong>in</strong>32 Application Wizard will appear. In the first w<strong>in</strong>dow click on Next:<br />

5. In the follow<strong>in</strong>g w<strong>in</strong>dow:<br />

a. Make sure that Console application is selected from the Application type: list<br />

b. In Additional options, uncheck the Precompiled header option.<br />

c. Ensure that both ATL and MFC are unchecked <strong>in</strong> the Add common header files<br />

for: list.<br />

Now you can press on the F<strong>in</strong>ish button and wait for VS<strong>2010</strong> to set up your project.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 17


6. In the Solution Explorer w<strong>in</strong>dow you should see the follow<strong>in</strong>g project structure:<br />

Double-click on test_curl.cpp to open it (if VS<strong>2010</strong> didn’t already do so for you). The<br />

source code should look like this:<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 18


4.3 How to use the <strong>libcurl</strong> library<br />

4.3.1 Sample source code<br />

Replace all the code <strong>in</strong> test_curl.cpp <strong>with</strong> this code:<br />

// headers<br />

#<strong>in</strong>clude "stdafx.h"<br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude <br />

// prototypes<br />

<strong>in</strong>t<br />

<strong>libcurl</strong>_progress_callback (void * clientp, double dltotal,<br />

double dlnow, double ultotal,<br />

double ulnow);<br />

size_t <strong>libcurl</strong>_read_callback(void * pBuffer, size_t size, size_t nmemb,<br />

void * hFile);<br />

void <strong>SSH</strong>Upload(char * strFileName, char * strFilePath);<br />

<strong>in</strong>t _tma<strong>in</strong>(<strong>in</strong>t argc, _TCHAR* argv[])<br />

{<br />

<strong>SSH</strong>Upload("test.txt", "C:\\");<br />

pr<strong>in</strong>tf("Press any key to cont<strong>in</strong>ue...");<br />

_getch();<br />

}<br />

return 0;<br />

void <strong>SSH</strong>Upload(char * strFileName, char * strFilePath)<br />

{<br />

char strBuffer[1024];<br />

CURL * hCurl;<br />

CURLcode ccCurlResult = CURL_LAST;<br />

curl_off_t cotFileSize;<br />

HANDLE hFile;<br />

LARGE_INTEGER liFileSize;<br />

// check parameters<br />

if((strFileName == NULL || strlen(strFileName) == 0) ||<br />

(strFilePath == NULL || strlen(strFilePath) == 0))<br />

return;<br />

// parse file path<br />

if(strFilePath[strlen(strFilePath) - 1] == '\\')<br />

spr<strong>in</strong>tf_s(strBuffer, 1024, "%s%s", strFilePath, strFileName);<br />

else<br />

spr<strong>in</strong>tf_s(strBuffer, 1024, "%s\\%s", strFilePath, strFileName);<br />

// create a handle to the file<br />

hFile = CreateFileA(strBuffer,<br />

GENERIC_READ,<br />

FILE_SHARE_READ,<br />

NULL,<br />

OPEN_EXISTING,<br />

FILE_ATTRIBUTE_NORMAL,<br />

NULL);<br />

// file to open<br />

// open for read<strong>in</strong>g<br />

// share for read<strong>in</strong>g<br />

// default security<br />

// exist<strong>in</strong>g file only<br />

// normal file<br />

// no attr. template<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 19


if(hFile != INVALID_HANDLE_VALUE)<br />

{<br />

// global <strong>libcurl</strong> <strong>in</strong>itialisation<br />

ccCurlResult = curl_global_<strong>in</strong>it(CURL_GLOBAL_WIN32);<br />

if(ccCurlResult == 0)<br />

{<br />

// start <strong>libcurl</strong> easy session<br />

hCurl = curl_easy_<strong>in</strong>it();<br />

if(hCurl)<br />

{<br />

// enable verbose operation<br />

curl_easy_setopt(hCurl, CURLOPT_VERBOSE, TRUE);<br />

// enable upload<strong>in</strong>g<br />

curl_easy_setopt(hCurl, CURLOPT_UPLOAD, TRUE);<br />

// <strong>in</strong>form <strong>libcurl</strong> of the file's size<br />

GetFileSizeEx(hFile, &liFileSize);<br />

cotFileSize = liFileSize.QuadPart;<br />

curl_easy_setopt(hCurl,<br />

CURLOPT_INFILESIZE_LARGE,<br />

cotFileSize);<br />

// enable progress report function<br />

curl_easy_setopt(hCurl, CURLOPT_NOPROGRESS, FALSE);<br />

curl_easy_setopt(hCurl,<br />

CURLOPT_PROGRESSFUNCTION,<br />

<strong>libcurl</strong>_progress_callback);<br />

// use custom read function<br />

curl_easy_setopt(hCurl,<br />

CURLOPT_READFUNCTION,<br />

<strong>libcurl</strong>_read_callback);<br />

// specify which file to upload<br />

curl_easy_setopt(hCurl, CURLOPT_READDATA, hFile);<br />

// specify full path of uploaded file (i.e. server<br />

// address plus remote path)<br />

spr<strong>in</strong>tf_s(strBuffer,<br />

1024,<br />

"sftp://123.123.123.123/home/user/%s",<br />

strFileName);<br />

curl_easy_setopt(hCurl, CURLOPT_URL, strBuffer);<br />

// set <strong>SSH</strong> server port<br />

curl_easy_setopt(hCurl, CURLOPT_PORT, 22);<br />

// set <strong>SSH</strong> user name and password <strong>in</strong> <strong>libcurl</strong> <strong>in</strong> this<br />

// format "user:password"<br />

curl_easy_setopt(hCurl,<br />

CURLOPT_USERPWD,<br />

"user:password");<br />

// set <strong>SSH</strong> authentication to user name and password<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 20


}<br />

}<br />

curl_easy_setopt(hCurl,<br />

CURLOPT_<strong>SSH</strong>_AUTH_TYPES,<br />

CURL<strong>SSH</strong>_AUTH_PASSWORD);<br />

// execute command<br />

ccCurlResult = curl_easy_perform(hCurl);<br />

// end <strong>libcurl</strong> easy session<br />

curl_easy_cleanup(hCurl);<br />

}<br />

}<br />

else<br />

// release file handle<br />

CloseHandle(hFile);<br />

// global <strong>libcurl</strong> cleanup<br />

curl_global_cleanup();<br />

if (ccCurlResult == CURLE_OK)<br />

pr<strong>in</strong>tf("File uploaded successfully.\n");<br />

else<br />

pr<strong>in</strong>tf("File upload failed. Curl error: %d\n",<br />

ccCurlResult);<br />

pr<strong>in</strong>tf("File upload failed! Could not open local file");<br />

size_t <strong>libcurl</strong>_read_callback(void * pBuffer, size_t size,<br />

size_t nmemb, void * hFile)<br />

{<br />

DWORD dwNumberOfBytesRead = 0;<br />

BOOL bResult = ReadFile((HANDLE) hFile, pBuffer, size * nmemb,<br />

&dwNumberOfBytesRead, NULL);<br />

}<br />

return dwNumberOfBytesRead;<br />

<strong>in</strong>t <strong>libcurl</strong>_progress_callback (void * clientp, double dltotal, double dlnow,<br />

double ultotal, double ulnow)<br />

{<br />

pr<strong>in</strong>tf("Uploaded: %d / %d\n", (<strong>in</strong>t) ulnow, (<strong>in</strong>t) ultotal);<br />

}<br />

return 0;<br />

NOTE: You must replace some of the <strong>in</strong>formation <strong>in</strong> the sample code:<br />

l<strong>in</strong>e 17: enter a file name to be uploaded and its location on your computer<br />

l<strong>in</strong>e 93: type <strong>in</strong> your server’s IP address and the remote path where the file should<br />

be stored (here I assume that you have access to a computer that is<br />

runn<strong>in</strong>g a <strong>SSH</strong> server)<br />

l<strong>in</strong>e 104: the log<strong>in</strong> credentials for the <strong>SSH</strong> server<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 21


4.3.2 Add<strong>in</strong>g <strong>libcurl</strong> to the list of libraries<br />

Now let’s tell the compiler where to f<strong>in</strong>d the <strong>libcurl</strong> header files and the library itself:<br />

1. In the Solution Explorer w<strong>in</strong>dow, right-click on the test_curl project w<strong>in</strong>dow and select<br />

Properties from the pop-up menu.<br />

2. Expand the Configuration Properties node.<br />

3. Expand the C/C++ node<br />

a. Select the General node, choose the Additional Include Directories property<br />

and add the path:<br />

C:\Projects\custom_libraries\<strong>in</strong>clude<br />

NOTE: While you might be tempted to <strong>in</strong>clude the "C:\Projects\custom<br />

libraries\<strong>in</strong>clude\curl" directory <strong>in</strong>stead, we must add the parent directory<br />

s<strong>in</strong>ce some <strong>libcurl</strong> files use #<strong>in</strong>clude statements like this one: “#<strong>in</strong>clude<br />

”.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 22


. Select the Preprocessor node and click on the Preprocessor Def<strong>in</strong>itions<br />

property. Add <strong>in</strong> the follow<strong>in</strong>g to the exist<strong>in</strong>g def<strong>in</strong>itions:<br />

;CURL_STATICLIB<br />

4. Expand the L<strong>in</strong>ker node.<br />

a. Select the General node, chose the Additional Library Directories property and<br />

add the path:<br />

C:\Projects\custom_libraries\lib_dbg<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 23


. Select the Input node, click on the Additional Dependencies property and add<br />

the follow<strong>in</strong>g to the exist<strong>in</strong>g list of libraries:<br />

;<strong>libcurl</strong>.lib;ws2_32.lib<br />

5. Click on the OK button.<br />

4.3.3 The test-drive<br />

Now we are f<strong>in</strong>ally ready to reap the fruits of our labor: compile and run the program. Depend<strong>in</strong>g<br />

on the size of the file you chose to upload, the output should look similar to the figure on the<br />

next page.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 24


5. F<strong>in</strong>al Notes<br />

Congratulations! You are now ready to use <strong>libcurl</strong> <strong>in</strong> your own projects. If you run <strong>in</strong>to trouble<br />

down the road, don’t hesitate to post a message on <strong>libcurl</strong>’s very active mail<strong>in</strong>g list:<br />

http://cool.haxx.se/mailman/list<strong>in</strong>fo/curl-library. However, please take a moment and read the<br />

mail<strong>in</strong>g list etiquette (http://curl.haxx.se/mail/etiquette.html) before post<strong>in</strong>g.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 25


Appendix A – Add<strong>in</strong>g OpenSSL <strong>support</strong> directly to <strong>libcurl</strong><br />

Some of you might f<strong>in</strong>d it useful to have SSL/TLS <strong>support</strong> directly built <strong>in</strong>to <strong>libcurl</strong>. In this case,<br />

compilation procedure that was presented <strong>in</strong> section 3.5 is identical <strong>with</strong> the exception of step 3,<br />

which must be replaced <strong>with</strong> the follow<strong>in</strong>g:<br />

3. Next, you must tell the compiler and the librarian to use the OpenSSL library and where<br />

this library is located:<br />

a. Right-click on the <strong>libcurl</strong> project <strong>in</strong> the Solution Explorer w<strong>in</strong>dow and select<br />

Properties from the pop-up menu.<br />

b. Expand the Configuration Properties node, then the C/C++ node.<br />

i. Click on the General node. Next to Additional Include Directories, add<br />

the follow<strong>in</strong>g:<br />

;C:\libssh2-1.4.3\<strong>in</strong>clude;c:\openssl_lib\<strong>in</strong>clude\;c:\openssl_lib\<strong>in</strong>clude\openssl<br />

(the semicolon is needed s<strong>in</strong>ce there are already two additional <strong>in</strong>clude<br />

directories specified)<br />

ii. Select the Preprocessor node and click on the Preprocessor Def<strong>in</strong>itions<br />

property. Add <strong>in</strong> the follow<strong>in</strong>g to the exist<strong>in</strong>g def<strong>in</strong>itions:<br />

;CURL_STATICLIB;USE_LIB<strong>SSH</strong>2;CURL_DISABLE_LDAP;HAVE_<br />

LIB<strong>SSH</strong>2;HAVE_LIB<strong>SSH</strong>2_H;LIB<strong>SSH</strong>2_WIN32<br />

;LIB<strong>SSH</strong>2_LIBRARY;USE_SSLEAY;USE_OPENSSL<br />

c. In the Configuration Properties node, expand the Librarian node, and select<br />

General.<br />

i. Select Additional Dependencies and type <strong>in</strong>:<br />

libssh2.lib;libeay32.lib;ssleay32.lib<br />

ii. Next to Additional Library Directories, type <strong>in</strong> the path:<br />

C:\libssh2-1.4.3\w<strong>in</strong>32\Debug_lib;c:\openssl_lib\lib<br />

S<strong>in</strong>ce the OpenSSL library was already <strong>in</strong>cluded as part of the lib<strong>SSH</strong>2 compilation, at the end<br />

of the <strong>libcurl</strong> compilation, the l<strong>in</strong>ker will present a whole bunch of “second def<strong>in</strong>ition ignored”<br />

warn<strong>in</strong>gs, which can be safely ignored.<br />

<strong>Us<strong>in</strong>g</strong> <strong>libcurl</strong> <strong>with</strong> <strong>SSH</strong> <strong>support</strong> <strong>in</strong> <strong>Visual</strong> <strong>Studio</strong> <strong>2010</strong> 26

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!