C++ libcurl static class


This is kind of part 2 on libcurl, part 1 being a simple c++ http get function.

All of class members are static, so it is pretty much a static class, no need to instantiate it, etc. The class also includes the c++ urlencode function to sanitize the post inputs.

main.cpp
#include <iostream>
#include <string>
 
#include "curlit.h"
 
using namespace std;
 
int main(int argc, char *argv[])
{
    cout << curlit::get("http://www.google.com") << endl;
}

curlit.h
#ifndef __CURLIT_HEADER_FILE__
#define __CURLIT_HEADER_FILE__
 
#include <map>
#include <string>
#include <iostream>
 
#include <curl/curl.h>
 
using namespace std;
 
class curlit
{
protected:    // User declarations
    static char errorBuffer[CURL_ERROR_SIZE];
    static string buffer;
    static int writer(char *data, size_t size, size_t nmemb, string *buffer);
    static string easycurl(const string &url, bool post, const string &postparamstring);
    static string urlencode(const string &c);
    static string char2hex(char dec);    
 
public:        // User declarations
    curlit(){};
    ~curlit(){};
    static string post(const string &url, map<string, string> &abbrevs);
    static string get(const string &url, map<string, string> &abbrevs);
    static string get(const string &url);
 
};
#endif

curlit.cpp
#include "curlit.h"
 
//have to re-declare static members at file level
char curlit::errorBuffer[CURL_ERROR_SIZE];
string curlit::buffer;
 
//---------------------------------------------------------------------------
string curlit::get(const string &url)
{
    bool   usepost=false;
    string params ="";
    return easycurl(url, usepost, params);
}
//---------------------------------------------------------------------------
string curlit::get(const string &url, map<string, string> &m)
{
    bool usepost=false;
    string poststring="";
 
    map<string, string>::iterator curr,end;
    for(curr = m.begin(), end = m.end(); curr != end; curr++)
    {
        poststring+= curr->first + "=" + curlit::urlencode(curr->second)+ "&";
    }
 
    return easycurl(url, usepost, poststring);
}
//---------------------------------------------------------------------------
string curlit::post(const string &url, map<string, string> &m)
{
    bool usepost=true;
    string poststring="";
 
    map<string, string>::iterator curr,end;
    for(curr = m.begin(), end = m.end(); curr != end; curr++)
    {
        poststring+= curr->first + "=" + curlit::urlencode(curr->second)+ "&";
    }
 
    return easycurl(url, usepost, poststring);
}
//---------------------------------------------------------------------------
string curlit::easycurl(const string &url, bool post, const string &postparamstring)
{
 
    // Our curl objects
    buffer="";
    errorBuffer[0]=0;
 
    CURL *curl;
    CURLcode result;
 
    // Create our curl handle
    curl = curl_easy_init();
 
    if (curl)
    {
      // Now set up all of the curl options
      curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
      curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
      curl_easy_setopt(curl, CURLOPT_HEADER, 0);
      curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
      if (post)
      {
          curl_easy_setopt(curl, CURLOPT_POST,1);
          curl_easy_setopt(curl, CURLOPT_POSTFIELDS,postparamstring.c_str());
      }
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST,  2);
      curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);  // this line makes it work under https
      curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt");//read from
      curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt"); //write to
 
      // Attempt to retrieve the remote page
      result = curl_easy_perform(curl);
 
      // Always cleanup
      curl_easy_cleanup(curl);
 
      // Did we succeed?
      if (result == CURLE_OK)
      {
          return buffer;
      }
      else
      {
          cerr << "error:" << errorBuffer <<endl;
          return "";
      }
    }
 
    return "";
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
int curlit::writer(char *data, size_t size, size_t nmemb, string *buffer)
{
  int result = 0;
  if (buffer != NULL)
  {
    buffer->append(data, size * nmemb);
    result = size * nmemb;
  }
  return result;
}
//---------------------------------------------------------------------------
string curlit::urlencode(const string &c)
{
 
    string escaped="";
    int max = c.length();
    for(int i=0; i<max; i++)
    {
        if ( (48 <= c[i] && c[i] <= 57) ||//0-9
             (65 <= c[i] && c[i] <= 90) ||//abc...xyz
             (97 <= c[i] && c[i] <= 122) || //ABC...XYZ
             (c[i]=='~' || c[i]=='!' || c[i]=='*' || c[i]=='(' || c[i]==')' || c[i]=='\'') //~!*()'
        )
        {
            escaped.append( &c[i], 1);
        }
        else
        {
            escaped.append("%");
            escaped.append( char2hex(c[i]) );//converts char 255 to string "ff"
        }
    }
    return escaped;
}
//-----------------------------------------------------------------------------
string curlit::char2hex( char dec )
{
    char dig1 = (dec&0xF0)>>4;
    char dig2 = (dec&0x0F);
    if ( 0<= dig1 && dig1<= 9) dig1+=48;    //0,48inascii
    if (10<= dig1 && dig1<=15) dig1+=97-10; //a,97inascii
    if ( 0<= dig2 && dig2<= 9) dig2+=48;
    if (10<= dig2 && dig2<=15) dig2+=97-10;
 
    string r;
    r.append( &dig1, 1);
    r.append( &dig2, 1);
    return r;
}
//-----------------------------------------------------------------------------


Troubleshooting with libcurl in windows:
I tried the lastest version of libcurl (as of this writing): libcurl-7.18.0-win32-msvc.zip, included the includes, linked in the lib files, and it still required libcurl.dll. When I went to run the application libcurl.dll said it required zlib.dll. Then when I popped a zlib.dll I got the error message: the ordinal 55 could not be located in the dynamic link library zlib1.dll. So I tried different versions of zlib1.dll and didn't get anywhere. Then I tried different versions of libcurl.dll and found one, libcurl-7.14.0-win32-msvc.zip which required zlibwapi.dll instead of zlib1.dll. I googled around to a dll site (not necessarily safe I know) and was able to get it to compile and run. What a headache.

Compile for linux
In linux, you will need to install the package curl-devel. This includes the header and library files, as well as the curl-config utility for compiling. Though it is better to use a makefile, it is possible to compile the following program in one line:
g++ `curl-config --libs` curlit.cpp main.cpp -o curltest


code snippets are licensed under Creative Commons CC-By-SA 3.0 (unless otherwise specified)

M M on 2008-12-29 07:32:01
I had a similar problem with one of the libcurl distributions. However, the .ddl files included in this one worked:

http://my.guardpuppy.com/libcurl-7.15.1-msvc-win32-ssl-0.9.8a-zlib-1.2.3.zip

Robert on 2009-11-19 03:31:18
I had the same problem, also with libcurl version 7.18.0 among others. I tried the version of zlib1.dll that M M suggested but it had the same problem (ordinal 55 not located). I followed the original author's guidance of using libcurl 7.14.0 and I also googled to get zlibwapi.dll (I got mine from www.dll-files.com). On the road again. Many thanks to the original poster!!

Jen on 2010-02-04 00:53:19
http://sourceforge.net/projects/gnuwin32/files/zlib/1.2.3/zlib-1.2.3-bin.zip/download

Harry on 2010-04-16 00:56:26
Hi, i've been trying to create a standalone dll which uses libcurl. Currently my dll is dependant on a couple of other dll's - libcurl.dll is one of them. This is not good. By using the version discussed here. Would this resolve my problem?