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 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
)
85 curl_global_cleanup(void) {}
92 handle
=calloc(1,sizeof(CURL
));
94 handle
->errors
=stderr
;
100 curl_easy_cleanup(CURL
*curl
)
104 http_close (curl
->hd
, 0);
110 curl_easy_setopt(CURL
*curl
,CURLoption option
,...)
119 curl
->url
=va_arg(ap
,char *);
121 case CURLOPT_USERPWD
:
122 curl
->auth
=va_arg(ap
,char *);
124 case CURLOPT_WRITEFUNCTION
:
125 curl
->writer
=va_arg(ap
,write_func
);
128 curl
->file
=va_arg(ap
,void *);
130 case CURLOPT_ERRORBUFFER
:
131 curl
->errorbuffer
=va_arg(ap
,char *);
134 curl
->proxy
=va_arg(ap
,char *);
137 curl
->flags
.post
=va_arg(ap
,unsigned int);
139 case CURLOPT_POSTFIELDS
:
140 curl
->postfields
=va_arg(ap
,char *);
142 case CURLOPT_FAILONERROR
:
143 curl
->flags
.failonerror
=va_arg(ap
,unsigned int);
145 case CURLOPT_VERBOSE
:
146 curl
->flags
.verbose
=va_arg(ap
,unsigned int);
149 curl
->errors
=va_arg(ap
,FILE *);
152 /* We ignore the huge majority of curl options */
156 return handle_error(curl
,CURLE_OK
,NULL
);
160 curl_easy_perform(CURL
*curl
)
163 CURLcode err
=CURLE_OK
;
164 const char *errstr
=NULL
;
167 /* Emulate the libcurl proxy behavior. If the calling program set a
168 proxy, use it. If it didn't set a proxy or set it to NULL, check
169 for one in the environment. If the calling program explicitly
170 set a null-string proxy the http code doesn't use a proxy at
176 proxy
=getenv(HTTP_PROXY_ENV
);
178 if(curl
->flags
.verbose
)
180 fprintf(curl
->errors
,"* HTTP proxy is \"%s\"\n",proxy
?proxy
:"null");
181 fprintf(curl
->errors
,"* HTTP URL is \"%s\"\n",curl
->url
);
182 fprintf(curl
->errors
,"* HTTP auth is \"%s\"\n",
183 curl
->auth
?curl
->auth
:"null");
184 fprintf(curl
->errors
,"* HTTP method is %s\n",
185 curl
->flags
.post
?"POST":"GET");
190 rc
= http_open (&curl
->hd
, HTTP_REQ_POST
, curl
->url
, curl
->auth
,
194 unsigned int post_len
= strlen(curl
->postfields
);
196 es_fprintf (http_get_write_ptr (curl
->hd
),
197 "Content-Type: application/x-www-form-urlencoded\r\n"
198 "Content-Length: %u\r\n", post_len
);
199 http_start_data (curl
->hd
);
200 es_write (http_get_write_ptr (curl
->hd
),
201 curl
->postfields
, post_len
, NULL
);
203 rc
= http_wait_response (curl
->hd
);
204 curl
->status
= http_get_status_code (curl
->hd
);
205 if (!rc
&& curl
->flags
.failonerror
&& curl
->status
>=300)
206 err
= CURLE_HTTP_RETURNED_ERROR
;
207 http_close (curl
->hd
, 0);
213 rc
= http_open (&curl
->hd
, HTTP_REQ_GET
, curl
->url
, curl
->auth
,
217 rc
= http_wait_response (curl
->hd
);
218 curl
->status
= http_get_status_code (curl
->hd
);
221 if (curl
->flags
.failonerror
&& curl
->status
>=300)
222 err
= CURLE_HTTP_RETURNED_ERROR
;
225 size_t maxlen
= 1024;
230 while ((len
= es_read_line (http_get_read_ptr (curl
->hd
),
231 &line
, &buflen
, &maxlen
)))
237 ret
=(curl
->writer
)(line
,len
,1,curl
->file
);
240 err
=CURLE_WRITE_ERROR
;
246 http_close(curl
->hd
, 0);
252 http_close (curl
->hd
, 0);
258 switch(gpg_err_code (rc
))
263 case GPG_ERR_INV_URI
:
264 err
=CURLE_UNSUPPORTED_PROTOCOL
;
268 errstr
=gpg_strerror (rc
);
269 err
=CURLE_COULDNT_CONNECT
;
273 return handle_error(curl
,err
,errstr
);
276 /* This is not the same exact set that is allowed according to
277 RFC-2396, but it is what the real curl uses. */
278 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
279 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
283 curl_escape(char *str
,int length
)
285 int len
,max
,idx
,enc_idx
=0;
299 for(idx
=0;idx
<len
;idx
++)
307 tmp
=realloc(enc
,max
+1);
317 if(strchr(VALID_URI_CHARS
,str
[idx
]))
318 enc
[enc_idx
++]=str
[idx
];
322 sprintf(numbuf
,"%%%02X",str
[idx
]);
323 strcpy(&enc
[enc_idx
],numbuf
);
333 curl_version_info_data
*
334 curl_version_info(int type
)
336 static curl_version_info_data data
;
337 static const char *protocols
[]={"http",NULL
};
339 data
.protocols
=protocols
;