* curl-shim.h, curl-shim.c: New. This is code to fake the curl API in
[gnupg.git] / keyserver / curl-shim.c
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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21  */
22
23 #include <config.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include "http.h"
30 #include "util.h"
31 #include "curl-shim.h"
32
33 static CURLcode handle_error(CURL *curl,CURLcode err,const char *str)
34 {
35   if(curl->errorbuffer)
36     {
37       switch(err)
38         {
39         case CURLE_OK:
40           strcpy(curl->errorbuffer,"okay");
41           break;
42
43         case CURLE_COULDNT_CONNECT:
44           strcpy(curl->errorbuffer,"couldn't connect");
45           break;
46
47         case CURLE_WRITE_ERROR:
48           strcpy(curl->errorbuffer,"write error");
49           break;
50
51         default:
52           strcpy(curl->errorbuffer,"generic error");
53           break;
54         }
55
56       if(str && (strlen(curl->errorbuffer)+2+strlen(str)+1)<=CURL_ERROR_SIZE)
57         {
58           strcat(curl->errorbuffer,": ");
59           strcat(curl->errorbuffer,str);
60         }
61     }
62
63   return err;
64 }
65
66 CURLcode curl_global_init(long flags)
67 {
68   return CURLE_OK;
69 }
70
71 void curl_global_cleanup(void) {}
72
73 CURL *curl_easy_init(void)
74 {
75   return calloc(1,sizeof(CURL));
76 }
77
78 void curl_easy_cleanup(CURL *curl)
79 {
80   free(curl);
81 }
82
83 CURLcode curl_easy_setopt(CURL *curl,CURLoption option,...)
84 {
85   va_list ap;
86
87   va_start(ap,option);
88
89   switch(option)
90     {
91     case CURLOPT_URL:
92       curl->url=va_arg(ap,char *);
93       break;
94     case CURLOPT_WRITEFUNCTION:
95       curl->writer=va_arg(ap,write_func);
96       break;
97     case CURLOPT_FILE:
98       curl->file=va_arg(ap,void *);
99       break;
100     case CURLOPT_ERRORBUFFER:
101       curl->errorbuffer=va_arg(ap,char *);
102       break;
103     case CURLOPT_PROXY:
104       curl->proxy=va_arg(ap,char *);
105       break;
106     default:
107       /* We ignore the huge majority of curl options */
108       break;
109     }
110
111   return handle_error(curl,CURLE_OK,NULL);
112 }
113
114 CURLcode curl_easy_perform(CURL *curl)
115 {
116   int rc;
117   CURLcode err=CURLE_OK;
118   const char *errstr=NULL;
119
120   rc=http_open_document(&curl->hd,curl->url,0,curl->proxy);
121   if(rc!=0)
122     {
123       if(rc==G10ERR_NETWORK)
124         errstr=strerror(errno);
125       else
126         errstr=g10_errstr(rc);
127
128       err=CURLE_COULDNT_CONNECT;
129     }
130   else
131     {
132       size_t maxlen=1024,buflen,len;
133       byte *line=NULL;
134
135       while((len=iobuf_read_line(curl->hd.fp_read,&line,&buflen,&maxlen)))
136         {
137           maxlen=1024;
138           size_t ret;
139
140           ret=(curl->writer)(line,len,1,curl->file);
141           if(ret!=len)
142             {
143               err=CURLE_WRITE_ERROR;
144               break;
145             }
146         }
147
148       m_free(line);
149       http_close(&curl->hd);
150     }
151
152   return handle_error(curl,err,errstr);
153 }