* keyserver.c (parse_keyserver_uri): If there is a path present, set the
[gnupg.git] / keyserver / gpgkeys_curl.c
index bccfeaf..bd26d78 100644 (file)
@@ -15,7 +15,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
 extern char *optarg;
 extern int optind;
 
-static char proxy[MAX_PROXY+1];
 static FILE *input,*output,*console;
 static CURL *curl;
 static struct ks_options *opt;
 
 static int
-curl_err_to_gpg_err(CURLcode error)
-{
-  switch(error)
-    {
-    case CURLE_FTP_COULDNT_RETR_FILE: return KEYSERVER_KEY_NOT_FOUND;
-    default: return KEYSERVER_INTERNAL_ERROR;
-    }
-}
-
-static size_t
-writer(const void *ptr,size_t size,size_t nmemb,void *stream)
-{
-  const char *buf=ptr;
-  size_t i;
-  static int markeridx=0,begun=0,done=0;
-  static const char *marker=BEGIN;
-
-  /* scan the incoming data for our marker */
-  for(i=0;!done && i<(size*nmemb);i++)
-    {
-      if(buf[i]==marker[markeridx])
-       {
-         markeridx++;
-         if(marker[markeridx]=='\0')
-           {
-             if(begun)
-               done=1;
-             else
-               {
-                 /* We've found the BEGIN marker, so now we're looking
-                    for the END marker. */
-                 begun=1;
-                 marker=END;
-                 markeridx=0;
-                 fprintf(output,BEGIN);
-                 continue;
-               }
-           }
-       }
-      else
-       markeridx=0;
-
-      if(begun)
-       {
-         /* Canonicalize CRLF to just LF by stripping CRs.  This
-            actually makes sense, since on Unix-like machines LF is
-            correct, and on win32-like machines, our output buffer is
-            opened in textmode and will re-canonicalize line endings
-            back to CRLF.  Since we only need to handle armored keys,
-            we don't have to worry about odd cases like CRCRCR and
-            the like. */
-
-         if(buf[i]!='\r')
-           fputc(buf[i],output);
-       }
-    }
-
-  return size*nmemb;
-}
-
-static int
 get_key(char *getkey)
 {
   CURLcode res;
   char errorbuffer[CURL_ERROR_SIZE];
   char request[MAX_URL];
+  struct curl_writer_ctx ctx;
+
+  memset(&ctx,0,sizeof(ctx));
 
   if(strncmp(getkey,"0x",2)==0)
     getkey+=2;
 
   fprintf(output,"KEY 0x%s BEGIN\n",getkey);
 
-  sprintf(request,"%s://%s%s%s%s%s%s",opt->scheme,
-         opt->auth?opt->auth:"",
-         opt->auth?"@":"",opt->host,
-         opt->port?":":"",opt->port?opt->port:"",
-         opt->path?opt->path:"/");
+  sprintf(request,"%s://%s%s%s%s",opt->scheme,opt->host,
+         opt->port?":":"",opt->port?opt->port:"",opt->path?opt->path:"/");
 
   curl_easy_setopt(curl,CURLOPT_URL,request);
-  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,writer);
-  curl_easy_setopt(curl,CURLOPT_FILE,output);
+  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
+  ctx.stream=output;
+  curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
   curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
 
   res=curl_easy_perform(curl);
-  if(res!=0)
+  if(res!=CURLE_OK)
     {
       fprintf(console,"gpgkeys: %s fetch error %d: %s\n",opt->scheme,
              res,errorbuffer);
       fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
     }
   else
-    fprintf(output,"\nKEY 0x%s END\n",getkey);
+    {
+      curl_writer_finalize(&ctx);
+      if(!ctx.flags.done)
+       {
+         fprintf(console,"gpgkeys: no key data found for %s\n",request);
+         fprintf(output,"\nKEY 0x%s FAILED %d\n",
+                 getkey,KEYSERVER_KEY_NOT_FOUND);
+       }
+      else
+       fprintf(output,"\nKEY 0x%s END\n",getkey);
+    }
 
-  return KEYSERVER_OK;
+  return curl_err_to_gpg_err(res);
 }
 
 static void 
@@ -155,6 +105,7 @@ main(int argc,char *argv[])
   char line[MAX_LINE];
   char *thekey=NULL;
   long follow_redirects=5;
+  char *proxy=NULL;
 
   console=stderr;
 
@@ -249,12 +200,20 @@ main(int argc,char *argv[])
 
          if(strncasecmp(start,"http-proxy",10)==0)
            {
+             /* Safe to not check the return code of strdup() here.
+                If it fails, we simply won't use a proxy. */
              if(no)
-               proxy[0]='\0';
+               {
+                 free(proxy);
+                 proxy=strdup("");
+               }
              else if(start[10]=='=')
                {
-                 strncpy(proxy,&start[11],MAX_PROXY);
-                 proxy[MAX_PROXY]='\0';
+                 if(strlen(&start[11])<MAX_PROXY)
+                   {
+                     free(proxy);
+                     proxy=strdup(&start[11]);
+                   }
                }
            }
          else if(strncasecmp(start,"follow-redirects",16)==0)
@@ -277,27 +236,6 @@ main(int argc,char *argv[])
       ret=KEYSERVER_SCHEME_NOT_FOUND;
       goto fail;
     }
-#ifdef HTTP_VIA_LIBCURL
-  else if(strcasecmp(opt->scheme,"http")==0)
-    ;
-#endif /* HTTP_VIA_LIBCURL */
-#ifdef HTTPS_VIA_LIBCURL
-  else if(strcasecmp(opt->scheme,"https")==0)
-    ;
-#endif /* HTTP_VIA_LIBCURL */
-#ifdef FTP_VIA_LIBCURL
-  else if(strcasecmp(opt->scheme,"ftp")==0)
-    ;
-#endif /* FTP_VIA_LIBCURL */
-#ifdef FTPS_VIA_LIBCURL
-  else if(strcasecmp(opt->scheme,"ftps")==0)
-    ;
-#endif /* FTPS_VIA_LIBCURL */
-  else
-    {
-      fprintf(console,"gpgkeys: scheme `%s' not supported\n",opt->scheme);
-      return KEYSERVER_SCHEME_NOT_FOUND;
-    }
 
   if(!opt->host)
     {
@@ -327,8 +265,12 @@ main(int argc,char *argv[])
        curl_easy_setopt(curl,CURLOPT_MAXREDIRS,follow_redirects);
     }
 
+  if(opt->auth)
+    curl_easy_setopt(curl,CURLOPT_USERPWD,opt->auth);
+
   if(opt->debug)
     {
+      fprintf(console,"gpgkeys: curl version = %s\n",curl_version());
       curl_easy_setopt(curl,CURLOPT_STDERR,console);
       curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
     }
@@ -336,7 +278,7 @@ main(int argc,char *argv[])
   curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,opt->flags.check_cert);
   curl_easy_setopt(curl,CURLOPT_CAINFO,opt->ca_cert_file);
 
-  if(proxy[0])
+  if(proxy)
     curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
 
   /* If it's a GET or a SEARCH, the next thing to come in is the
@@ -419,6 +361,8 @@ main(int argc,char *argv[])
   if(curl)
     curl_easy_cleanup(curl);
 
+  free(proxy);
+
   curl_global_cleanup();
 
   return ret;