unit Curl;
{
******* NOTE ************ NOTE ************ NOTE *************
This file is a modified version of curl_h.pp
curl_h.pp was a part of the CurlPas project
Curlpas offers two possible licenses MIT X or MPL
The one choosed for this modified version is the MPL.
More infos at http://www.tekool.com/opcurl
See below for infos about copyright and licensing
******* NOTE ************ NOTE ************ NOTE *************
}
{
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is curl_h.pp, a file from Curlpas, a Free Pascal wrapper for Curl.
 *
 * More infos about CurlPas at http://curl.haxx.se
 * Contact Jeffrey Pohlmeyer <yetanothergeek@yahoo.com>
 *
 * The Initial Developer of the Original Code is Jeffrey Pohlmeyer
 * Portions created by Jeffrey Pohlmeyer are Copyright (C) 2001-2002 Jeffrey Pohlmeyer
 *
 * Contributors:
 * Christophe Espern - cespern@free.fr
 *
 * History :
 *
 * 27/03/02 : Christophe Espern
 * - First public release of of this file in OP Curl - Version 0.3
 *
 * 24/03/02 : Christophe Espern
 * - This file has been renamed Curl.pas
 * - Add a note to indicate the fact that this file is a modified version
 * - Add the header for the MPL license
 *
 * 20/03/02 : Christophe Espern
 * - Reorganize the whole file in sections
 * - Remove the link to the C libray in order to allow multi-platforms compilation
 * - Remove all the overloaded easy_cur_opt functions.
 * - Remove the $OBJFPC directive - This will allow to switch with Delphi
 * - Add curl_global_init and curl_global_cleanup declarations from curl.h
 * - Add flags constants from curl.h. They are used in global_init
}
 
interface
 const
  {$IFDEF LINUX}
  LIB_CURL = 'libcurl.so';
  {$ENDIF}
  {$IFDEF WIN32}
  LIB_CURL='libcurl.dll';
  {$ENDIF}
 
  {Global_init flags constants}
  CURL_GLOBAL_SSL= (1 shl 0);
  CURL_GLOBAL_WIN32= (1 shl 1);
  CURL_GLOBAL_ALL =(CURL_GLOBAL_SSL or CURL_GLOBAL_WIN32);
  CURL_GLOBAL_NOTHING=0;
  CURL_GLOBAL_DEFAULT= CURL_GLOBAL_ALL;
  
 {Return codes for curl_easy_ functions}
 type TCurlCode = (
   CURLE_OK, CURLE_UNSUPPORTED_PROTOCOL, CURLE_FAILED_INIT, CURLE_URL_MALFORMAT, CURLE_URL_MALFORMAT_USER,
   CURLE_COULDNT_RESOLVE_PROXY, CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_FTP_WEIRD_SERVER_REPLY,
   CURLE_FTP_ACCESS_DENIED, CURLE_FTP_USER_PASSWORD_INCORRECT, CURLE_FTP_WEIRD_PASS_REPLY, CURLE_FTP_WEIRD_USER_REPLY,
   CURLE_FTP_WEIRD_PASV_REPLY, CURLE_FTP_WEIRD_227_FORMAT, CURLE_FTP_CANT_GET_HOST, CURLE_FTP_CANT_RECONNECT,
   CURLE_FTP_COULDNT_SET_BINARY, CURLE_PARTIAL_FILE, CURLE_FTP_COULDNT_RETR_FILE, CURLE_FTP_WRITE_ERROR,
   CURLE_FTP_QUOTE_ERROR, CURLE_HTTP_NOT_FOUND, CURLE_WRITE_ERROR, CURLE_MALFORMAT_USER, CURLE_FTP_COULDNT_STOR_FILE,
   CURLE_READ_ERROR, CURLE_OUT_OF_MEMORY, CURLE_OPERATION_TIMEOUTED, CURLE_FTP_COULDNT_SET_ASCII, CURLE_FTP_PORT_FAILED,
   CURLE_FTP_COULDNT_USE_REST, CURLE_FTP_COULDNT_GET_SIZE, CURLE_HTTP_RANGE_ERROR, CURLE_HTTP_POST_ERROR,
   CURLE_SSL_CONNECT_ERROR, CURLE_FTP_BAD_DOWNLOAD_RESUME, CURLE_FILE_COULDNT_READ_FILE, CURLE_LDAP_CANNOT_BIND,
   CURLE_LDAP_SEARCH_FAILED, CURLE_LIBRARY_NOT_FOUND, CURLE_FUNCTION_NOT_FOUND, CURLE_ABORTED_BY_CALLBACK,
   CURLE_BAD_FUNCTION_ARGUMENT, CURLE_BAD_CALLING_ORDER, CURLE_HTTP_PORT_FAILED, CURLE_BAD_PASSWORD_ENTERED,
   CURLE_TOO_MANY_REDIRECTS, CURLE_UNKNOWN_TELNET_OPTION, CURLE_TELNET_OPTION_SYNTAX, CURLE_OBSOLETE,
   CURLE_SSL_PEER_CERTIFICATE, CURLE_GOT_NOTHING, CURLE_SSL_ENGINE_NOTFOUND, CURLE_SSL_ENGINE_SETFAILED, CURL_LAST
 );
 
 { CurlCODE's as strings ... }
 const CurlCodeStrings : array[CURLE_OK..CURL_LAST] of string[33] = (
   'CURLE_OK', 'CURLE_UNSUPPORTED_PROTOCOL', 'CURLE_FAILED_INIT', 'CURLE_URL_MALFORMAT', 'CURLE_URL_MALFORMAT_USER',
   'CURLE_COULDNT_RESOLVE_PROXY', 'CURLE_COULDNT_RESOLVE_HOST', 'CURLE_COULDNT_CONNECT', 'CURLE_FTP_WEIRD_SERVER_REPLY',
   'CURLE_FTP_ACCESS_DENIED', 'CURLE_FTP_USER_PASSWORD_INCORRECT', 'CURLE_FTP_WEIRD_PASS_REPLY', 'CURLE_FTP_WEIRD_USER_REPLY',
   'CURLE_FTP_WEIRD_PASV_REPLY', 'CURLE_FTP_WEIRD_227_FORMAT', 'CURLE_FTP_CANT_GET_HOST', 'CURLE_FTP_CANT_RECONNECT',
   'CURLE_FTP_COULDNT_SET_BINARY', 'CURLE_PARTIAL_FILE', 'CURLE_FTP_COULDNT_RETR_FILE', 'CURLE_FTP_WRITE_ERROR',
   'CURLE_FTP_QUOTE_ERROR', 'CURLE_HTTP_NOT_FOUND', 'CURLE_WRITE_ERROR', 'CURLE_MALFORMAT_USER', 'CURLE_FTP_COULDNT_STOR_FILE',
   'CURLE_READ_ERROR', 'CURLE_OUT_OF_MEMORY', 'CURLE_OPERATION_TIMEOUTED', 'CURLE_FTP_COULDNT_SET_ASCII', 'CURLE_FTP_PORT_FAILED',
   'CURLE_FTP_COULDNT_USE_REST', 'CURLE_FTP_COULDNT_GET_SIZE', 'CURLE_HTTP_RANGE_ERROR', 'CURLE_HTTP_POST_ERROR',
   'CURLE_SSL_CONNECT_ERROR', 'CURLE_FTP_BAD_DOWNLOAD_RESUME', 'CURLE_FILE_COULDNT_READ_FILE', 'CURLE_LDAP_CANNOT_BIND',
   'CURLE_LDAP_SEARCH_FAILED', 'CURLE_LIBRARY_NOT_FOUND', 'CURLE_FUNCTION_NOT_FOUND', 'CURLE_ABORTED_BY_CALLBACK',
   'CURLE_BAD_FUNCTION_ARGUMENT', 'CURLE_BAD_CALLING_ORDER', 'CURLE_HTTP_PORT_FAILED', 'CURLE_BAD_PASSWORD_ENTERED',
   'CURLE_TOO_MANY_REDIRECTS', 'CURLE_UNKNOWN_TELNET_OPTION', 'CURLE_TELNET_OPTION_SYNTAX', 'CURLE_OBSOLETE',
   'CURLE_SSL_PEER_CERTIFICATE', 'CURLE_GOT_NOTHING', 'CURLE_SSL_ENGINE_NOTFOUND', 'CURLE_SSL_ENGINE_SETFAILED', 'CURL_LAST'
 );
 
 type
 { List type used by some curl functions ... }
  pcurl_slist = ^tcurl_slist;
  tcurl_slist = record
    data : PChar;
    next : pcurl_slist;
 end;
 
{Curl Base Functions}
 function curl_version: PChar; cdecl; external LIB_CURL;
 procedure curl_global_cleanup;stdcall; cdecl; external LIB_CURL name 'curl_global_cleanup';
 procedure curl_global_init(flag:longint);stdcall; cdecl; external LIB_CURL name 'curl_global_init';
{Curl Easy Functions}
 function curl_easy_init:LongInt; cdecl; external LIB_CURL;
 procedure curl_easy_cleanup(handle:LongInt);cdecl; external LIB_CURL;
 function curl_easy_perform(handle:LongInt):TCurlCode;stdcall; cdecl; external LIB_CURL;
 function curl_easy_getinfo(handle:LongInt; request:LongInt; return:pointer):TCurlCode;stdcall; cdecl; external LIB_CURL;
 function curl_easy_set_integer(handle:LongInt; option:integer; value:LongInt):TCurlCode;stdcall; cdecl; external LIB_CURL name 'curl_easy_setopt';
 function curl_easy_set_pointer(handle:LongInt; option:integer; value:pointer):TCurlCode;stdcall; cdecl; external LIB_CURL name 'curl_easy_setopt';
 function curl_easy_set_pchar(handle:LongInt; option:integer; value:PChar):TCurlCode;stdcall; cdecl; external LIB_CURL name 'curl_easy_setopt';
 {Curl List Functions}
 function curl_slist_append(aList:pcurl_slist; aData:PChar):pcurl_slist; cdecl; external LIB_CURL;
 procedure curl_slist_free_all(aList:pcurl_slist); cdecl; external LIB_CURL;
 
const
 
 CURL_ERROR_SIZE = 256; { -- Maximum size of error strings returned by libcurl }
 
 CURLCLOSEPOLICY_OLDEST = 1;
 CURLCLOSEPOLICY_LEAST_RECENTLY_USED = 2;
 CURL_HTTP_VERSION_NONE = 0;
 CURL_HTTP_VERSION_1_0 = 1;
 CURL_HTTP_VERSION_1_1 = 2;
 
{Curl Options}
 {boolean options}
 CURLOPT_NOTHING = 0;
 CURLOPT_CRLF = 27;
 CURLOPT_VERBOSE = 41;
 CURLOPT_HEADER = 42;
 CURLOPT_NOPROGRESS = 43;
 CURLOPT_NOBODY = 44;
 CURLOPT_FAILONERROR = 45;
 CURLOPT_UPLOAD = 46;
 CURLOPT_POST = 47;
 CURLOPT_FTPLISTONLY = 48;
 CURLOPT_FTPAPPEND = 50;
 CURLOPT_NETRC = 51;
 CURLOPT_FOLLOWLOCATION = 52;
 CURLOPT_TRANSFERTEXT = 53;
 CURLOPT_PUT = 54;
 CURLOPT_HTTPPROXYTUNNEL = 61;
 CURLOPT_SSL_VERIFYPEER = 64;
 CURLOPT_FRESH_CONNECT = 74;
 CURLOPT_FORBID_REUSE = 75;
 CURLOPT_HTTPGET = 80;
 CURLOPT_FTP_USE_EPSV = 85;
 CURLOPT_AUTOREFERER = 58;
 
 { integer Options }
 CURLOPT_PORT = 3;
 CURLOPT_TIMEOUT =13;
 CURLOPT_LOW_SPEED_LIMIT = 19;
 CURLOPT_LOW_SPEED_TIME = 20;
 CURLOPT_RESUME_FROM = 21;
 CURLOPT_SSLVERSION = 32;
 CURLOPT_TIMECONDITION = 33;
 CURLOPT_TIMEVALUE = 34;
 CURLOPT_PROXYPORT = 59;
 CURLOPT_POSTFIELDSIZE = 60;
 CURLOPT_MAXREDIRS = 68;
 CURLOPT_MAXCONNECTS = 71;
 CURLOPT_CONNECTTIMEOUT = 78;
 
 { integer constants ... }
 CURLOPT_CLOSEPOLICY = 72; { CURLCLOSEPOLICY_LEAST_RECENTLY_USED; CURLCLOSEPOLICY_OLDEST }
 CURLOPT_SSL_VERIFYHOST = 81; { 1:check existence; 2:ensure match }
 CURLOPT_HTTP_VERSION = 84; { CURL_HTTP_VERSION_NONE; CURL_HTTP_VERSION_1_0; CURL_HTTP_VERSION_1_1 }
 
 { PChar parameters ... }
 CURLOPT_URL = 10002;
 CURLOPT_PROXY = 10004;
 CURLOPT_USERPWD = 10005;
 CURLOPT_PROXYUSERPWD = 10006;
 CURLOPT_RANGE = 10007;
 CURLOPT_ERRORBUFFER = 10010;
 CURLOPT_POSTFIELDS = 10015;
 CURLOPT_REFERER = 10016;
 CURLOPT_FTPPORT = 10017;
 CURLOPT_USERAGENT = 10018;
 CURLOPT_COOKIE = 10022;
 CURLOPT_SSLCERT = 10025;
 CURLOPT_SSLCERTPASSWD = 10026;
 CURLOPT_COOKIEFILE = 10031;
 CURLOPT_CUSTOMREQUEST = 10036;
 CURLOPT_INTERFACE = 10062;
 CURLOPT_KRB4LEVEL = 10063;
 CURLOPT_CAINFO = 10065;
 CURLOPT_RANDOM_FILE = 10076;
 CURLOPT_EGDSOCKET = 10077;
 CURLOPT_COOKIEJAR = 10082;
 CURLOPT_SSL_CIPHER_LIST = 10083;
 
 { linked-lists ... }
 CURLOPT_HTTPHEADER = 10023;
 CURLOPT_QUOTE = 10028;
 CURLOPT_POSTQUOTE = 10039;
 CURLOPT_TELNETOPTIONS = 10070;
 CURLOPT_HTTPPOST = 10024; {linked-list of tHttpPost records}
 
 CURLOPT_HTTPREQUEST = 10035; { -- Obsolete}
 
 { Files (100nn) and callbacks (200nn) ... }
 CURLOPT_FILE = 10001;
 CURLOPT_WRITEFUNCTION = 20011;
 
 CURLOPT_INFILE = 10009;
 CURLOPT_INFILESIZE = 14; { -- this one is actually a LongInt, but it wants to be here }
 CURLOPT_READFUNCTION = 20012;
 
 CURLOPT_WRITEHEADER = 10029;
 CURLOPT_HEADERFUNCTION = 20079;
 
 CURLOPT_PROGRESSDATA = 10057;
 CURLOPT_PROGRESSFUNCTION = 20056;
 
 CURLOPT_PASSWDDATA = 10067;
 CURLOPT_PASSWDFUNCTION = 20066;
 
 CURLOPT_CLOSEFUNCTION = 20073;
 
{
 These are documented on the curl website, but not defined in my copy of curl.h:
 - Maybe because I do not have an ssl engine installed ?
    CURLOPT_SSLCERT
    CURLOPT_SSLCERTTYPE
    CURLOPT_SSLCERTPASSWD
    CURLOPT_SSLKEY
    CURLOPT_SSLKEYTYPE
    CURLOPT_SSLKEYASSWD
    CURLOPT_SSL_ENGINE
    CURLOPT_SSL_ENGINEDEFAULT
}
 
 
 
{ "var" style parameters - these get modified}
 
{ CURLOPT_STDERR: Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
  bytes big. If this is not used, error messages go to stderr instead: }
CURLOPT_STDERR = 10037;
 
{ CURLOPT_FILETIME: Pass a pointer to a time_t to get a possible date of the requested
document! Pass a NULL to shut it off. }
CURLOPT_FILETIME = 10069;
 
 
{Other strange things...}
 
{ CURLOPT_FTPASCII: same value as CURLOPT_TRANSFERTEXT - is this one obsolete? }
CURLOPT_FTPASCII = 53;
 
{ CURLOPT_MUTE: obsolete option, removed in 7.8  }
CURLOPT_MUTE = 55;
 
 
{ CURLOPT_WRITEINFO:
curl.h says: "Pass a pointer to string of the output using full variable-replacement as described elsewhere."
jeff.p says:   "huh?"  :-}
CURLOPT_WRITEINFO = 10040;
 
 
{ constants passed to curl_easy_getinfo }
CURLINFO_EFFECTIVE_URL = 1048577;
CURLINFO_CONTENT_TYPE = 1048594; { - added in 7.9.4, bug-fixed in 7.9.5 }
 
CURLINFO_HTTP_CODE = 2097154;
CURLINFO_HEADER_SIZE = 2097163;
CURLINFO_REQUEST_SIZE = 2097164;
CURLINFO_SSL_VERIFYRESULT = 2097165;
CURLINFO_FILETIME = 2097166;
 
CURLINFO_TOTAL_TIME = 3145731;
CURLINFO_NAMELOOKUP_TIME = 3145732;
CURLINFO_CONNECT_TIME = 3145733;
CURLINFO_PRETRANSFER_TIME = 3145734;
CURLINFO_SIZE_UPLOAD = 3145735;
CURLINFO_SIZE_DOWNLOAD = 3145736;
CURLINFO_SPEED_DOWNLOAD = 3145737;
CURLINFO_SPEED_UPLOAD = 3145738;
CURLINFO_CONTENT_LENGTH_DOWNLOAD = 3145743;
CURLINFO_CONTENT_LENGTH_UPLOAD = 3145744;
CURLINFO_STARTTRANSFER_TIME = 3145745;
 
CURLINFO_LASTONE = 18;
 
{ curl.h defines "true" and "false" as integers, so I renamed them ( for obvious reasons ) }
CURL_TRUE = 1;
CURL_FALSE = 0;
 
 
 
 
 
{ Http post data structure and constants ...  }
 
type
  ppHttpPost = ^pHttpPost;
  pHttpPost = ^tHttpPost;
  THttpPost = record
    next : pHttpPost;  { next entry in the list  }
    name : PChar; { pointer to allocated name  }
    namelength : LongInt;  { length of name length  }
    contents : PChar;  { pointer to allocated data contents  }
    contentslength : LongInt;  { length of contents field  }
    contenttype : PChar;  { Content-Type  }
    contentheader : pcurl_slist;   { list of extra headers for this form  }
    more : pHttpPost;   { if one field name has more than one file, this should link to following files }
    flags : LongInt;   { as defined below }
end;
 
const
  HTTPPOST_FILENAME     =  1;  { specified content is a file name, sent as an "attachment" }
  HTTPPOST_READFILE     =  2;  { specified content is a file name, sent as raw data }
  HTTPPOST_PTRNAME      =  4;  { name is only stored pointer do not free in formfree }
  HTTPPOST_PTRCONTENTS  =  8;  { contents is only stored pointer do not free in formfree }
 
 
type tCURLformoption = (
  CURLFORM_NOTHING,
  CURLFORM_COPYNAME,
  CURLFORM_PTRNAME,
  CURLFORM_NAMELENGTH,
  CURLFORM_COPYCONTENTS,
  CURLFORM_PTRCONTENTS,
  CURLFORM_CONTENTSLENGTH,
  CURLFORM_FILECONTENT,
  CURLFORM_ARRAY,
  CURLFORM_ARRAY_START,
  CURLFORM_FILE,
  CURLFORM_CONTENTTYPE,
  CURLFORM_CONTENTHEADER,
  CURLFORM_END,
  CURLFORM_ARRAY_END,
  CURLFORM_LASTENTRY
);
 
 
 
 
procedure curl_formfree( form: pHttpPost ); cdecl; external LIB_CURL;
{
  "curl_formadd" wants a "va_list" as its third parameter,
  but FPC does not support this type of function call.
  It appears that *usually* the number of arguments is an odd number between 5 and 13.
  So this VERY_UGLY workaround should work in most cases ...
}
 
function curl_formadd_5( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1:  tCURLformoption;  Val1:   LongInt;
   Option_End: tCURLformoption
): LongInt; cdecl; external LIB_CURL name 'curl_formadd';
 
 
function curl_formadd_7( httppost: ppHttpPost; last_post:ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   OptN: tCURLformoption
): LongInt; cdecl; external LIB_CURL name 'curl_formadd';
 
 
function curl_formadd_9( httppost: ppHttpPost; last_post:  ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   OptN: tCURLformoption
): LongInt; cdecl; external LIB_CURL name 'curl_formadd';
 
 
function curl_formadd_11( httppost: ppHttpPost; last_post:  ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   Opt4: tCURLformoption;  Val4: LongInt;
   Option_End: tCURLformoption
): LongInt; cdecl; external LIB_CURL name 'curl_formadd';
 
function curl_formadd_13( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   Opt4: tCURLformoption;  Val4: LongInt;
   Opt5: tCURLformoption;  Val5: LongInt;
   Option_End: tCURLformoption
): LongInt; cdecl; external LIB_CURL name 'curl_formadd';
 
 
 
{ Now we can declare overloaded "aliases" for the "real" curl_formadd ... }
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Option_End: tCURLformoption
): LongInt;overload; {5}
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Option_End: tCURLformoption
): LongInt;overload; {7}
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   Option_End: tCURLformoption
): LongInt;overload; {9}
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   Opt4: tCURLformoption;  Val4: LongInt;
   Option_End: tCURLformoption
): LongInt;overload; {11}
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption;  Val1: LongInt;
   Opt2: tCURLformoption;  Val2: LongInt;
   Opt3: tCURLformoption;  Val3: LongInt;
   Opt4: tCURLformoption;  Val4: LongInt;
   Opt5: tCURLformoption;  Val5: LongInt;
   Option_End: tCURLformoption
): LongInt;overload; {13}
 
 
implementation
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption; Val1: LongInt;
   Option_End: tCURLformoption
): LongInt;
begin
  curl_formadd:=curl_formadd_5(httppost, last_post, Opt1, Val1, Option_End);
end;
 
function curl_formadd( httppost: ppHttpPost; last_post: ppHttpPost;
   Opt1: tCURLformoption; Val1: LongInt;
   Opt2: tCURLformoption; Val2: LongInt;
   Option_End: tCURLformoption
): LongInt;
begin
  curl_formadd:=curl_formadd_7( httppost, last_post, Opt1, Val1, Opt2, Val2, Option_End );
end;
 
function curl_formadd( httppost: ppHttpPost; last_post:  ppHttpPost;
   Opt1: tCURLformoption; Val1: LongInt;
   Opt2: tCURLformoption; Val2: LongInt;
   Opt3: tCURLformoption; Val3: LongInt;
   Option_End: tCURLformoption
): LongInt;
begin
  curl_formadd:=curl_formadd_9( httppost, last_post, Opt1, Val1, Opt2, Val2, Opt3, Val3, Option_End );
end;
 
function curl_formadd( httppost: ppHttpPost; last_post:  ppHttpPost;
   Opt1: tCURLformoption; Val1: LongInt;
   Opt2: tCURLformoption; Val2: LongInt;
   Opt3: tCURLformoption; Val3: LongInt;
   Opt4: tCURLformoption; Val4: LongInt;
   Option_End: tCURLformoption
): LongInt;
begin
  curl_formadd:=curl_formadd_11(
    httppost, last_post, Opt1, Val1, Opt2, Val2, Opt3, Val3, Opt4, Val4, Option_End );
end;
 
function curl_formadd( httppost: ppHttpPost; last_post:  ppHttpPost;
   Opt1: tCURLformoption; Val1: LongInt;
   Opt2: tCURLformoption; Val2: LongInt;
   Opt3: tCURLformoption; Val3: LongInt;
   Opt4: tCURLformoption; Val4: LongInt;
   Opt5: tCURLformoption; Val5: LongInt;
   Option_End: tCURLformoption
): LongInt;
begin
  curl_formadd:=curl_formadd_13(
    httppost, last_post, Opt1, Val1, Opt2, Val2, Opt3, Val3, Opt4, Val4, Opt5, Val5, Option_End );
end;
 
end.
unit curlengine;
{/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is the OP-Curl : an Object-Pascal wrapper for Curl.
 *
 * More infos at http://www.tekool.com/opcurl - Contact : cespern@free.fr
 *
 * The Initial Developer of the Original Code is Christophe ESPERN
 * Portions created by Christophe ESPERN are Copyright (C) 2001-2002 Christophe
 * ESPERN. All Rights Reserved.
 *
 * Contributor(s): None
 *
 * Known bugs : None
 *
 
}
 
interface
 
 
uses SysUtils,Curl,Classes;
 
type
 
 TCurlEngine = class (TComponent)
 private
  FStream:TStream;
  FUserName: string;
  FLastError: string;
  FPassword: string;
  FResultString: string;
 protected
  function DoDownload(Url,OutputFile:string): boolean;virtual;
  function DoUpload(URL:string): boolean;virtual;
 public
  constructor Create(Aowner:TComponent);override;
  destructor Destroy;override;
  function UploadFile(InputFile,URL:string):boolean;
  function UploadString(Data,URL:string):boolean;
  function Download(Url,OutputFile:string):boolean;
  procedure FreeResultString;
  property LastError:string read FLastError;
  property ResultString:string read FResultString;
 published
  property UserName:string read FUserName write FUserName;
  property Password:string read FPassword write FPassword;
 end;
 
procedure Register;
 
 
implementation
 
procedure Register;
begin
  RegisterComponents('Tekool', [TCurlEngine]);
end;
 
function WriteFunc(ptr:pointer;size,nmemb:longint;stream:TStream):longint; cdecl;
begin
  try
    Result:=stream.Write(ptr^,size*nmemb)
  except
     raise Exception.create('TCurlEngine : WriteFunc error');
  end;
end;
 
function ReadFunc(ptr:pointer;size,nmemb:longint;stream:TStream):longint; cdecl;
begin
  try
  if size*nmemb>stream.size then
   Result:=stream.Read(ptr^,stream.size)
  else
   Result:=stream.Read(ptr^,size*nmemb);
  except
   raise Exception.create('TCurlEngine : ReadFunc error');
  end;
end;
 
{ TCurlEngine }
 
constructor TCurlEngine.Create(Aowner: TComponent);
begin
  inherited;
 
end;
 
destructor TCurlEngine.Destroy;
begin
  inherited;
end;
 
function TCurlEngine.DoDownload(Url,OutputFile:string): boolean;
var
 HCurl:longint;
 rc:TCurlCode;
 s:string;
begin
 FResultString:='';
 Result:=false;
 try
 if OutputFile<>'' then
  FStream:=TFileStream.Create(OutputFile,fmCreate)
 else
 {$IFDEF FPC}
  FStream:=TFileStream.Create(inttostr(integer(self)),fmCreate) ;
 {$ELSE}
   FStream:=TStringStream.Create('');
 {$ENDIF}
  hCurl:= curl_easy_init;
  if UserName<>'' then
    curl_easy_set_pchar(hCurl, CURLOPT_USERPWD,Pchar(UserName+':'+PassWord));
  curl_easy_set_integer(HCurl,CURLOPT_TIMEOUT,1);
  curl_easy_set_pchar(HCurl, CURLOPT_URL, Pchar(URL));
  curl_easy_set_integer(HCurl,CURLOPT_FILE,integer(FStream));
  curl_easy_set_pointer(HCurl,CURLOPT_WRITEFUNCTION,@WriteFunc);
  rc:= curl_easy_perform(HCurl);
  if rc<>CURLE_OK then
   FLastError:=CurlCodeStrings[rc]
  else begin
   FLastError:='';
   Result:=true;
  end;
  curl_easy_cleanup(HCurl);
  if OutPutFile='' then begin
   FStream.Position := 0;
   SetLength(FResultString, FStream.size);
   FStream.ReadBuffer(Pointer(FResultString)^, FStream.size);
   DeleteFile(inttostr(integer(self)));
  end;
 finally
   DeleteFile(inttostr(integer(self)));
   FStream.free;
 end;
end;
 
function TCurlEngine.DoUpload(URL:string): boolean;
var
 HCurl:LongInt;
begin
 Result:=false;
 try
  if FStream=nil then
    raise EXception.create('TCurlEngine.DoUpload : FStream = nil !');
  hCurl:= curl_easy_init;
  if UserName<>'' then
    curl_easy_set_pchar(hCurl, CURLOPT_USERPWD,Pchar(UserName+':'+PassWord));
  if hCurl <> 0 then begin
    curl_easy_set_pchar(hCurl, CURLOPT_URL, PChar(URL));
    curl_easy_set_integer(hCurl,CURLOPT_UPLOAD, 1);
    curl_easy_set_pointer(hCurl,CURLOPT_READFUNCTION,@ReadFunc);
    curl_easy_set_pointer(hCurl, CURLOPT_INFILE, FStream);
    curl_easy_set_integer(hCurl, CURLOPT_INFILESIZE, longint(FStream.size));
    curl_easy_perform(hCurl);
    curl_easy_cleanup(hCurl);
  end;
 except
  raise;
 end;
end;
 
 
function TCurlEngine.UploadString(Data, URL: string): boolean;
begin
 FStream:= TStringStream. create(data);
 Result:=DoUpload(URL);
 FStream.Free;
end;
 
 
function TCurlEngine.Download(Url, OutputFile: string): boolean;
begin
 Result:=DoDownload(URL,OutputFile);
end;
 
procedure TCurlEngine.FreeResultString;
begin
 FResultString:='';
end;
 
function TCurlEngine.UploadFile(InputFile, URL: string): boolean;
begin
 FStream:=TFileStream.Create(InputFile,fmOpenWrite);
 Result:=DoUpload(URL);
 FStream.free;
end;
 
 
initialization
 curl_global_init(CURL_GLOBAL_ALL);
finalization
 curl_global_cleanup;
end.