1 /* curl-shim.c - Implement a small subset of the curl API in terms of
4 * Copyright (C) 2005, 2006 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 2 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, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
34 #include "curl-shim.h"
37 handle_error(CURL
*curl
,CURLcode err
,const char *str
)
41 /* Make sure you never exceed CURL_ERROR_SIZE, currently set to
46 strcpy(curl
->errorbuffer
,"okay");
49 case CURLE_UNSUPPORTED_PROTOCOL
:
50 strcpy(curl
->errorbuffer
,"unsupported protocol");
53 case CURLE_COULDNT_CONNECT
:
54 strcpy(curl
->errorbuffer
,"couldn't connect");
57 case CURLE_WRITE_ERROR
:
58 strcpy(curl
->errorbuffer
,"write error");
61 case CURLE_HTTP_RETURNED_ERROR
:
62 sprintf(curl
->errorbuffer
,"url returned error %u",curl
->status
);
66 strcpy(curl
->errorbuffer
,"generic error");
70 if(str
&& (strlen(curl
->errorbuffer
)+2+strlen(str
)+1)<=CURL_ERROR_SIZE
)
72 strcat(curl
->errorbuffer
,": ");
73 strcat(curl
->errorbuffer
,str
);
81 curl_global_init(long flags
)
87 curl_global_cleanup(void) {}
94 handle
=calloc(1,sizeof(CURL
));
96 handle
->errors
=stderr
;
102 curl_easy_cleanup(CURL
*curl
)
106 http_close (curl
->hd
, 0);
112 curl_easy_setopt(CURL
*curl
,CURLoption option
,...)
121 curl
->url
=va_arg(ap
,char *);
123 case CURLOPT_USERPWD
:
124 curl
->auth
=va_arg(ap
,char *);
126 case CURLOPT_WRITEFUNCTION
:
127 curl
->writer
=va_arg(ap
,write_func
);
130 curl
->file
=va_arg(ap
,void *);
132 case CURLOPT_ERRORBUFFER
:
133 curl
->errorbuffer
=va_arg(ap
,char *);
136 curl
->proxy
=va_arg(ap
,char *);
139 curl
->flags
.post
=va_arg(ap
,unsigned int);
141 case CURLOPT_POSTFIELDS
:
142 curl
->postfields
=va_arg(ap
,char *);
144 case CURLOPT_FAILONERROR
:
145 curl
->flags
.failonerror
=va_arg(ap
,unsigned int);
147 case CURLOPT_VERBOSE
:
148 curl
->flags
.verbose
=va_arg(ap
,unsigned int);
151 curl
->errors
=va_arg(ap
,FILE *);
154 /* We ignore the huge majority of curl options */
158 return handle_error(curl
,CURLE_OK
,NULL
);
162 curl_easy_perform(CURL
*curl
)
165 CURLcode err
=CURLE_OK
;
166 const char *errstr
=NULL
;
169 /* Emulate the libcurl proxy behavior. If the calling program set a
170 proxy, use it. If it didn't set a proxy or set it to NULL, check
171 for one in the environment. If the calling program explicitly
172 set a null-string proxy the http code doesn't use a proxy at
178 proxy
=getenv(HTTP_PROXY_ENV
);
180 if(curl
->flags
.verbose
)
181 fprintf(curl
->errors
,"* HTTP proxy is \"%s\"\n",proxy
?proxy
:"null");
185 rc
= http_open (&curl
->hd
, HTTP_REQ_POST
, curl
->url
, curl
->auth
,
189 unsigned int post_len
= strlen(curl
->postfields
);
191 es_fprintf (http_get_write_ptr (curl
->hd
),
192 "Content-Type: application/x-www-form-urlencoded\r\n"
193 "Content-Length: %u\r\n", post_len
);
194 http_start_data (curl
->hd
);
195 es_write (http_get_write_ptr (curl
->hd
),
196 curl
->postfields
, post_len
, NULL
);
198 rc
= http_wait_response (curl
->hd
);
199 curl
->status
= http_get_status_code (curl
->hd
);
200 if (!rc
&& curl
->flags
.failonerror
&& curl
->status
>=300)
201 err
= CURLE_HTTP_RETURNED_ERROR
;
202 http_close (curl
->hd
, 0);
208 rc
= http_open (&curl
->hd
, HTTP_REQ_GET
, curl
->url
, curl
->auth
,
212 rc
= http_wait_response (curl
->hd
);
213 curl
->status
= http_get_status_code (curl
->hd
);
216 if (curl
->flags
.failonerror
&& curl
->status
>=300)
217 err
= CURLE_HTTP_RETURNED_ERROR
;
220 size_t maxlen
= 1024;
225 while ((len
= es_read_line (http_get_read_ptr (curl
->hd
),
226 &line
, &buflen
, &maxlen
)))
232 ret
=(curl
->writer
)(line
,len
,1,curl
->file
);
235 err
=CURLE_WRITE_ERROR
;
241 http_close(curl
->hd
, 0);
247 http_close (curl
->hd
, 0);
253 switch(gpg_err_code (rc
))
258 case GPG_ERR_INV_URI
:
259 err
=CURLE_UNSUPPORTED_PROTOCOL
;
263 errstr
=gpg_strerror (rc
);
264 err
=CURLE_COULDNT_CONNECT
;
268 return handle_error(curl
,err
,errstr
);
271 /* This is not the same exact set that is allowed according to
272 RFC-2396, but it is what the real curl uses. */
273 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
274 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
278 curl_escape(char *str
,int length
)
280 int len
,max
,idx
,enc_idx
=0;
294 for(idx
=0;idx
<len
;idx
++)
302 tmp
=realloc(enc
,max
+1);
312 if(strchr(VALID_URI_CHARS
,str
[idx
]))
313 enc
[enc_idx
++]=str
[idx
];
317 sprintf(numbuf
,"%%%02X",str
[idx
]);
318 strcpy(&enc
[enc_idx
],numbuf
);