~ubuntu-branches/ubuntu/feisty/gnupg2/feisty

« back to all changes in this revision

Viewing changes to keyserver/curl-shim.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-11-24 18:48:23 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20061124184823-17ir9m46tl09n9k4
Tags: 2.0.0-4ubuntu1
* Synchronize to Debian, reapply remaining Ubuntu changes to pristine Debian
  version:
  - Remove libpcsclite-dev, libopensc2-dev build dependencies (they are in
    universe).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* curl-shim.c - Implement a small subset of the curl API in terms of
 
2
 * the iobuf HTTP API
 
3
 *
 
4
 * Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 
5
 *
 
6
 * This file is part of GnuPG.
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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,
 
21
 * USA.
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
#include <stdarg.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
 
 
31
#include "http.h"
 
32
#include "util.h"
 
33
#include "ksutil.h"
 
34
#include "curl-shim.h"
 
35
 
 
36
static CURLcode
 
37
handle_error(CURL *curl,CURLcode err,const char *str)
 
38
{
 
39
  if(curl->errorbuffer)
 
40
    {
 
41
      /* Make sure you never exceed CURL_ERROR_SIZE, currently set to
 
42
         256 in curl-shim.h */
 
43
      switch(err)
 
44
        {
 
45
        case CURLE_OK:
 
46
          strcpy(curl->errorbuffer,"okay");
 
47
          break;
 
48
 
 
49
        case CURLE_UNSUPPORTED_PROTOCOL:
 
50
          strcpy(curl->errorbuffer,"unsupported protocol");
 
51
          break;
 
52
 
 
53
        case CURLE_COULDNT_CONNECT:
 
54
          strcpy(curl->errorbuffer,"couldn't connect");
 
55
          break;
 
56
 
 
57
        case CURLE_WRITE_ERROR:
 
58
          strcpy(curl->errorbuffer,"write error");
 
59
          break;
 
60
 
 
61
        case CURLE_HTTP_RETURNED_ERROR:
 
62
          sprintf(curl->errorbuffer,"url returned error %u",curl->status);
 
63
          break;
 
64
 
 
65
        default:
 
66
          strcpy(curl->errorbuffer,"generic error");
 
67
          break;
 
68
        }
 
69
 
 
70
      if(str && (strlen(curl->errorbuffer)+2+strlen(str)+1)<=CURL_ERROR_SIZE)
 
71
        {
 
72
          strcat(curl->errorbuffer,": ");
 
73
          strcat(curl->errorbuffer,str);
 
74
        }
 
75
    }
 
76
 
 
77
  return err;
 
78
}
 
79
 
 
80
CURLcode
 
81
curl_global_init(long flags)
 
82
{
 
83
  return CURLE_OK;
 
84
}
 
85
 
 
86
void
 
87
curl_global_cleanup(void) {}
 
88
 
 
89
CURL *
 
90
curl_easy_init(void)
 
91
{
 
92
  CURL *handle;
 
93
 
 
94
  handle=calloc(1,sizeof(CURL));
 
95
  if(handle)
 
96
    handle->errors=stderr;
 
97
 
 
98
  return handle;
 
99
}
 
100
 
 
101
void
 
102
curl_easy_cleanup(CURL *curl)
 
103
{
 
104
  if (curl)
 
105
    {
 
106
      http_close (curl->hd, 0);
 
107
      free(curl);
 
108
    }
 
109
}
 
110
 
 
111
CURLcode
 
112
curl_easy_setopt(CURL *curl,CURLoption option,...)
 
113
{
 
114
  va_list ap;
 
115
 
 
116
  va_start(ap,option);
 
117
 
 
118
  switch(option)
 
119
    {
 
120
    case CURLOPT_URL:
 
121
      curl->url=va_arg(ap,char *);
 
122
      break;
 
123
    case CURLOPT_USERPWD:
 
124
      curl->auth=va_arg(ap,char *);
 
125
      break;
 
126
    case CURLOPT_WRITEFUNCTION:
 
127
      curl->writer=va_arg(ap,write_func);
 
128
      break;
 
129
    case CURLOPT_FILE:
 
130
      curl->file=va_arg(ap,void *);
 
131
      break;
 
132
    case CURLOPT_ERRORBUFFER:
 
133
      curl->errorbuffer=va_arg(ap,char *);
 
134
      break;
 
135
    case CURLOPT_PROXY:
 
136
      curl->proxy=va_arg(ap,char *);
 
137
      break;
 
138
    case CURLOPT_POST:
 
139
      curl->flags.post=va_arg(ap,unsigned int);
 
140
      break;
 
141
    case CURLOPT_POSTFIELDS:
 
142
      curl->postfields=va_arg(ap,char *);
 
143
      break;
 
144
    case CURLOPT_FAILONERROR:
 
145
      curl->flags.failonerror=va_arg(ap,unsigned int);
 
146
      break;
 
147
    case CURLOPT_VERBOSE:
 
148
      curl->flags.verbose=va_arg(ap,unsigned int);
 
149
      break;
 
150
    case CURLOPT_STDERR:
 
151
      curl->errors=va_arg(ap,FILE *);
 
152
      break;
 
153
    default:
 
154
      /* We ignore the huge majority of curl options */
 
155
      break;
 
156
    }
 
157
 
 
158
  return handle_error(curl,CURLE_OK,NULL);
 
159
}
 
160
 
 
161
CURLcode
 
162
curl_easy_perform(CURL *curl)
 
163
{
 
164
  int rc;
 
165
  CURLcode err=CURLE_OK;
 
166
  const char *errstr=NULL;
 
167
  char *proxy=NULL;
 
168
 
 
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
 
173
     all. */
 
174
 
 
175
  if(curl->proxy)
 
176
    proxy=curl->proxy;
 
177
  else
 
178
    proxy=getenv(HTTP_PROXY_ENV);
 
179
 
 
180
  if(curl->flags.verbose)
 
181
    fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null");
 
182
 
 
183
  if(curl->flags.post)
 
184
    {
 
185
      rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth,
 
186
                      0, proxy, NULL);
 
187
      if (!rc)
 
188
        {
 
189
          unsigned int post_len = strlen(curl->postfields);
 
190
 
 
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);
 
197
 
 
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);
 
203
          curl->hd = NULL;
 
204
        }
 
205
    }
 
206
  else
 
207
    {
 
208
      rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth,
 
209
                      0, proxy, NULL);
 
210
      if (!rc)
 
211
        {
 
212
          rc = http_wait_response (curl->hd);
 
213
          curl->status = http_get_status_code (curl->hd);
 
214
          if (!rc)
 
215
            {
 
216
              if (curl->flags.failonerror && curl->status>=300)
 
217
                err = CURLE_HTTP_RETURNED_ERROR;
 
218
              else
 
219
                {
 
220
                  unsigned int maxlen = 1024, buflen, len;
 
221
                  char *line = NULL;
 
222
 
 
223
                  while ((len = es_read_line (http_get_read_ptr (curl->hd),
 
224
                                              &line, &buflen, &maxlen)))
 
225
                    {
 
226
                      size_t ret;
 
227
 
 
228
                      maxlen=1024;
 
229
 
 
230
                      ret=(curl->writer)(line,len,1,curl->file);
 
231
                      if(ret!=len)
 
232
                        {
 
233
                          err=CURLE_WRITE_ERROR;
 
234
                          break;
 
235
                        }
 
236
                    }
 
237
 
 
238
                  es_free (line);
 
239
                  http_close(curl->hd, 0);
 
240
                  curl->hd = NULL;
 
241
                }
 
242
            }
 
243
          else
 
244
            {
 
245
              http_close (curl->hd, 0);
 
246
              curl->hd = NULL;
 
247
            }
 
248
        }
 
249
    }
 
250
 
 
251
  switch(gpg_err_code (rc))
 
252
    {
 
253
    case 0:
 
254
      break;
 
255
 
 
256
    case GPG_ERR_INV_URI:
 
257
      err=CURLE_UNSUPPORTED_PROTOCOL;
 
258
      break;
 
259
 
 
260
    default:
 
261
      errstr=gpg_strerror (rc);
 
262
      err=CURLE_COULDNT_CONNECT;
 
263
      break;
 
264
    }
 
265
      
 
266
  return handle_error(curl,err,errstr);
 
267
}
 
268
 
 
269
/* This is not the same exact set that is allowed according to
 
270
   RFC-2396, but it is what the real curl uses. */
 
271
#define VALID_URI_CHARS "abcdefghijklmnopqrstuvwxyz" \
 
272
                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
 
273
                        "0123456789"
 
274
 
 
275
char *
 
276
curl_escape(char *str,int length)
 
277
{
 
278
  int len,max,idx,enc_idx=0;
 
279
  char *enc;
 
280
 
 
281
  if(length)
 
282
    len=length;
 
283
  else
 
284
    len=strlen(str);
 
285
 
 
286
  enc=malloc(len+1);
 
287
  if(!enc)
 
288
    return enc;
 
289
 
 
290
  max=len;
 
291
 
 
292
  for(idx=0;idx<len;idx++)
 
293
    {
 
294
      if(enc_idx+3>max)
 
295
        {
 
296
          char *tmp;
 
297
 
 
298
          max+=100;
 
299
 
 
300
          tmp=realloc(enc,max+1);
 
301
          if(!tmp)
 
302
            {
 
303
              free(enc);
 
304
              return NULL;
 
305
            }
 
306
 
 
307
          enc=tmp;
 
308
        }
 
309
 
 
310
      if(strchr(VALID_URI_CHARS,str[idx]))
 
311
        enc[enc_idx++]=str[idx];
 
312
      else
 
313
        {
 
314
          char numbuf[5];
 
315
          sprintf(numbuf,"%%%02X",str[idx]);
 
316
          strcpy(&enc[enc_idx],numbuf);
 
317
          enc_idx+=3;
 
318
        }
 
319
    }
 
320
 
 
321
  enc[enc_idx]='\0';
 
322
 
 
323
  return enc;
 
324
}
 
325
 
 
326
void
 
327
curl_free(char *ptr)
 
328
{
 
329
  free(ptr);
 
330
}