1 /* curl-shim.c - Implement a small subset of the curl API in terms of
4 * Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6 * This file is part of GnuPG.
8 * GnuPG is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GnuPG is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
32 #include "curl-shim.h"
35 handle_error(CURL
*curl
,CURLcode err
,const char *str
)
39 /* Make sure you never exceed CURL_ERROR_SIZE, currently set to
44 strcpy(curl
->errorbuffer
,"okay");
47 case CURLE_UNSUPPORTED_PROTOCOL
:
48 strcpy(curl
->errorbuffer
,"unsupported protocol");
51 case CURLE_COULDNT_CONNECT
:
52 strcpy(curl
->errorbuffer
,"couldn't connect");
55 case CURLE_WRITE_ERROR
:
56 strcpy(curl
->errorbuffer
,"write error");
59 case CURLE_HTTP_RETURNED_ERROR
:
60 sprintf(curl
->errorbuffer
,"url returned error %u",curl
->status
);
64 strcpy(curl
->errorbuffer
,"generic error");
68 if(str
&& (strlen(curl
->errorbuffer
)+2+strlen(str
)+1)<=CURL_ERROR_SIZE
)
70 strcat(curl
->errorbuffer
,": ");
71 strcat(curl
->errorbuffer
,str
);
79 curl_global_init(long flags
)
86 curl_global_cleanup(void) {}
93 #ifdef HAVE_W32_SYSTEM
97 handle
=calloc(1,sizeof(CURL
));
99 handle
->errors
=stderr
;
105 curl_easy_cleanup(CURL
*curl
)
109 http_close (curl
->hd
, 0);
115 curl_easy_setopt(CURL
*curl
,CURLoption option
,...)
124 curl
->url
=va_arg(ap
,char *);
126 case CURLOPT_USERPWD
:
127 curl
->auth
=va_arg(ap
,char *);
129 case CURLOPT_WRITEFUNCTION
:
130 curl
->writer
=va_arg(ap
,write_func
);
133 curl
->file
=va_arg(ap
,void *);
135 case CURLOPT_ERRORBUFFER
:
136 curl
->errorbuffer
=va_arg(ap
,char *);
139 curl
->proxy
=va_arg(ap
,char *);
142 curl
->flags
.post
=va_arg(ap
,long)?1:0;
144 case CURLOPT_POSTFIELDS
:
145 curl
->postfields
=va_arg(ap
,char *);
147 case CURLOPT_FAILONERROR
:
148 curl
->flags
.failonerror
=va_arg(ap
,long)?1:0;
150 case CURLOPT_VERBOSE
:
151 curl
->flags
.verbose
=va_arg(ap
,long)?1:0;
154 curl
->errors
=va_arg(ap
,FILE *);
157 /* We ignore the huge majority of curl options */
161 return handle_error(curl
,CURLE_OK
,NULL
);
165 curl_easy_perform(CURL
*curl
)
168 CURLcode err
=CURLE_OK
;
169 const char *errstr
=NULL
;
172 /* Emulate the libcurl proxy behavior. If the calling program set a
173 proxy, use it. If it didn't set a proxy or set it to NULL, check
174 for one in the environment. If the calling program explicitly
175 set a null-string proxy the http code doesn't use a proxy at
181 proxy
=getenv(HTTP_PROXY_ENV
);
183 if(curl
->flags
.verbose
)
185 fprintf(curl
->errors
,"* HTTP proxy is \"%s\"\n",proxy
?proxy
:"null");
186 fprintf(curl
->errors
,"* HTTP URL is \"%s\"\n",curl
->url
);
187 fprintf(curl
->errors
,"* HTTP auth is \"%s\"\n",
188 curl
->auth
?curl
->auth
:"null");
189 fprintf(curl
->errors
,"* HTTP method is %s\n",
190 curl
->flags
.post
?"POST":"GET");
195 rc
= http_open (&curl
->hd
, HTTP_REQ_POST
, curl
->url
, curl
->auth
,
199 unsigned int post_len
= strlen(curl
->postfields
);
201 es_fprintf (http_get_write_ptr (curl
->hd
),
202 "Content-Type: application/x-www-form-urlencoded\r\n"
203 "Content-Length: %u\r\n", post_len
);
204 http_start_data (curl
->hd
);
205 es_write (http_get_write_ptr (curl
->hd
),
206 curl
->postfields
, post_len
, NULL
);
208 rc
= http_wait_response (curl
->hd
);
209 curl
->status
= http_get_status_code (curl
->hd
);
210 if (!rc
&& curl
->flags
.failonerror
&& curl
->status
>=300)
211 err
= CURLE_HTTP_RETURNED_ERROR
;
212 http_close (curl
->hd
, 0);
218 rc
= http_open (&curl
->hd
, HTTP_REQ_GET
, curl
->url
, curl
->auth
,
222 rc
= http_wait_response (curl
->hd
);
223 curl
->status
= http_get_status_code (curl
->hd
);
226 if (curl
->flags
.failonerror
&& curl
->status
>=300)
227 err
= CURLE_HTTP_RETURNED_ERROR
;
230 size_t maxlen
= 1024;
235 while ((len
= es_read_line (http_get_read_ptr (curl
->hd
),
236 &line
, &buflen
, &maxlen
)))
242 ret
=(curl
->writer
)(line
,len
,1,curl
->file
);
245 err
=CURLE_WRITE_ERROR
;
251 http_close(curl
->hd
, 0);
257 http_close (curl
->hd
, 0);
263 switch(gpg_err_code (rc
))
268 case GPG_ERR_INV_URI
:
269 err
=CURLE_UNSUPPORTED_PROTOCOL
;
273 errstr
=gpg_strerror (rc
);
274 err
=CURLE_COULDNT_CONNECT
;
278 return handle_error(curl
,err
,errstr
);
281 /* This is not the same exact set that is allowed according to
282 RFC-2396, but it is what the real curl uses. */
283 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
284 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
288 curl_escape(char *str
,int length
)
290 int len
,max
,idx
,enc_idx
=0;
304 for(idx
=0;idx
<len
;idx
++)
312 tmp
=realloc(enc
,max
+1);
322 if(strchr(VALID_URI_CHARS
,str
[idx
]))
323 enc
[enc_idx
++]=str
[idx
];
327 sprintf(numbuf
,"%%%02X",str
[idx
]);
328 strcpy(&enc
[enc_idx
],numbuf
);
338 curl_version_info_data
*
339 curl_version_info(int type
)
341 static curl_version_info_data data
;
342 static const char *protocols
[]={"http",NULL
};
346 data
.protocols
=protocols
;