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_SRVTAG_GPG_HACK
:
148 curl
->srvtag
=va_arg(ap
,char *);
150 case CURLOPT_FAILONERROR
:
151 curl
->flags
.failonerror
=va_arg(ap
,long)?1:0;
153 case CURLOPT_VERBOSE
:
154 curl
->flags
.verbose
=va_arg(ap
,long)?1:0;
157 curl
->errors
=va_arg(ap
,FILE *);
160 /* We ignore the huge majority of curl options */
164 return handle_error(curl
,CURLE_OK
,NULL
);
168 curl_easy_perform(CURL
*curl
)
171 CURLcode err
=CURLE_OK
;
172 const char *errstr
=NULL
;
175 /* Emulate the libcurl proxy behavior. If the calling program set a
176 proxy, use it. If it didn't set a proxy or set it to NULL, check
177 for one in the environment. If the calling program explicitly
178 set a null-string proxy the http code doesn't use a proxy at
184 proxy
=getenv(HTTP_PROXY_ENV
);
186 if(curl
->flags
.verbose
)
188 fprintf(curl
->errors
,"* HTTP proxy is \"%s\"\n",proxy
?proxy
:"null");
189 fprintf(curl
->errors
,"* HTTP URL is \"%s\"\n",curl
->url
);
190 fprintf(curl
->errors
,"* HTTP auth is \"%s\"\n",
191 curl
->auth
?curl
->auth
:"null");
192 fprintf(curl
->errors
,"* HTTP method is %s\n",
193 curl
->flags
.post
?"POST":"GET");
198 rc
= http_open (&curl
->hd
, HTTP_REQ_POST
, curl
->url
, curl
->auth
,
199 0, proxy
, NULL
, curl
->srvtag
);
202 unsigned int post_len
= strlen(curl
->postfields
);
204 es_fprintf (http_get_write_ptr (curl
->hd
),
205 "Content-Type: application/x-www-form-urlencoded\r\n"
206 "Content-Length: %u\r\n", post_len
);
207 http_start_data (curl
->hd
);
208 es_write (http_get_write_ptr (curl
->hd
),
209 curl
->postfields
, post_len
, NULL
);
211 rc
= http_wait_response (curl
->hd
);
212 curl
->status
= http_get_status_code (curl
->hd
);
213 if (!rc
&& curl
->flags
.failonerror
&& curl
->status
>=300)
214 err
= CURLE_HTTP_RETURNED_ERROR
;
215 http_close (curl
->hd
, 0);
221 rc
= http_open (&curl
->hd
, HTTP_REQ_GET
, curl
->url
, curl
->auth
,
222 0, proxy
, NULL
, curl
->srvtag
);
225 rc
= http_wait_response (curl
->hd
);
226 curl
->status
= http_get_status_code (curl
->hd
);
229 if (curl
->flags
.failonerror
&& curl
->status
>=300)
230 err
= CURLE_HTTP_RETURNED_ERROR
;
233 size_t maxlen
= 1024;
238 while ((len
= es_read_line (http_get_read_ptr (curl
->hd
),
239 &line
, &buflen
, &maxlen
)))
245 ret
=(curl
->writer
)(line
,len
,1,curl
->file
);
248 err
=CURLE_WRITE_ERROR
;
254 http_close(curl
->hd
, 0);
260 http_close (curl
->hd
, 0);
266 switch(gpg_err_code (rc
))
271 case GPG_ERR_INV_URI
:
272 err
=CURLE_UNSUPPORTED_PROTOCOL
;
276 errstr
=gpg_strerror (rc
);
277 err
=CURLE_COULDNT_CONNECT
;
281 return handle_error(curl
,err
,errstr
);
284 /* This is not the same exact set that is allowed according to
285 RFC-2396, but it is what the real curl uses. */
286 #define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
287 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
291 curl_escape(char *str
,int length
)
293 int len
,max
,idx
,enc_idx
=0;
307 for(idx
=0;idx
<len
;idx
++)
315 tmp
=realloc(enc
,max
+1);
325 if(strchr(VALID_URI_CHARS
,str
[idx
]))
326 enc
[enc_idx
++]=str
[idx
];
330 sprintf(numbuf
,"%%%02X",str
[idx
]);
331 strcpy(&enc
[enc_idx
],numbuf
);
341 curl_version_info_data
*
342 curl_version_info(int type
)
344 static curl_version_info_data data
;
345 static const char *protocols
[]={"http",NULL
};
349 data
.protocols
=protocols
;