See ChangeLog: Tue Jan 19 19:34:58 CET 1999 Werner Koch
authorWerner Koch <wk@gnupg.org>
Tue, 19 Jan 1999 18:37:41 +0000 (18:37 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 19 Jan 1999 18:37:41 +0000 (18:37 +0000)
19 files changed:
NEWS
TODO
configure.in
doc/gpg.1pod
g10/ChangeLog
g10/compress.c
g10/export.c
g10/filter.h
g10/g10.c
g10/hkp.c
g10/hkp.h
g10/keygen.c
g10/main.h
g10/signal.c
include/http.h
include/util.h
util/ChangeLog
util/http.c
util/iobuf.c

diff --git a/NEWS b/NEWS
index 1ba5807..eec5c8f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,11 @@
 
     * add some additional time warp checks.
 
-    * Some HKP support
+    * Option --keyserver and command --send-keys to utilize HKP servers
 
     * Upgraded to zlib 1.1.3
 
+
 Noteworthy changes in version 0.9.1
 -----------------------------------
 
diff --git a/TODO b/TODO
index 55380b5..d5bca4f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -22,16 +22,12 @@ Important
 > 0.9.1: I get some occasional segfaults during 'make check' unless I use
 > --with-included-zlib. It's strange, I have zlib-1.1.2 on one machine, and
 > zlib-1.1.3 on another, and both of them fail on occasion (maybe half of the
+[ I hope this is fixed ]
 
 > gpg: /home/jam/.gnupg/pubring.gpg: can't open gdbm file: Can't be writer
 > gpg: keyblock resource `/home/jam/.gnupg/pubring.gpg': file open error
 > gpg: OOPS in close enum_keyblocks - ignored
 
-    > Indeed, comparing zero to 0xfe returns 2, not -something, and this is
-> the problem. This seems to fix it, but I don't know how you want to
-> handle this.
->
-  I'll better write a autoconf test as memcmp is used all over the place.
 
 Needed
 ------
@@ -48,8 +44,6 @@ Needed
       -Wl,-export-dynamic flag from my Makefile and it linked and seems to
       be working OK so far.
 
-    * text_filter.c: use iobuf_readline for cleartext signatures.
-
 
 Minor Bugs
 ----------
index b7de3d7..d26b1bc 100644 (file)
@@ -84,7 +84,7 @@ AC_PROG_CPP
 AC_ISC_POSIX
 AC_PROG_RANLIB
 AC_PROG_INSTALL
-AM_CYGWIN32
+dnl AC_CYGWIN32
 
 
 if test "$GCC" = yes; then
index dcd107e..1e9cdcf 100644 (file)
@@ -184,6 +184,13 @@ B<--export> [I<names>]
     the file given with option "output".  Use together
     with B<-a> to mail those keys.
 
+B<--send-keys> [I<names>]
+    Same as B<--export> but sends the keys to a keyserver.
+    Option B<--keyserver> must be used to give the name
+    of this keyserver. Don't send your complete keyring
+    to a keyserver - select only those keys which are new
+    or changed by you.
+
 B<--export-all> [I<names>]
     Same as B<--export> but does also export keys which
     are not compatible to OpenPGP.
@@ -288,6 +295,20 @@ B<--yes>
 B<--no>
     Assume "no" on most questions.
 
+B<--keyserver> I<name>
+    Use I<name> to lookup keys which are not yet in
+    your keyring; this is only done while verifying
+    messages with signatures.  The option is also
+    required for the command B<--send-keys> to
+    specify the keyserver to where the keys should
+    be send.  All keyservers synchronize with each
+    other - so there is no need to send keys to more
+    than one server.  Using the command
+    "host -l pgp.net | grep wwwkeys" gives you a
+    list of keyservers.  Because there is load
+    balancing using round-robin-dns you may notice
+    that you get different key servers.
+
 B<--keyring> I<file>
     Add I<file> to the list of keyrings.
     If I<file> begins with a tilde and a slash, these
@@ -301,7 +322,6 @@ B<--keyring> I<file>
 B<--secret-keyring> I<file>
     Same as B<--keyring> but for secret keyrings.
 
-
 B<--homedir> I<dir>
     Set the name of the home directory to I<dir>. If this
     option is not used it defaults to F<~/.gnupg>. It does
index f5a694a..c9137ed 100644 (file)
@@ -1,3 +1,12 @@
+Tue Jan 19 19:34:58 CET 1999  Werner Koch  <wk@isil.d.shuttle.de>
+
+       * export.c (export_pubkeys_stream): New.
+       (do_export_stream): New.
+       * g10.c (aSendKeys): New command.
+       * hkp.c (hkp_export): New.
+
+       * compress.c (do_uncompress): Hack for algo 1 and 1.1.3
+
 Sun Jan 17 11:04:33 CET 1999  Werner Koch  <wk@isil.d.shuttle.de>
 
        * textfilter.c (text_filter): Now uses iobuf_read_line().
index 5aad678..accca02 100644 (file)
@@ -146,8 +146,14 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
            if( !n )
                zs->next_in = zfx->inbuf;
            for( p=zfx->inbuf+n; n < zfx->inbufsize; n++, p++ ) {
-               if( (c=iobuf_get(a)) == -1 )
-                   break;
+               if( (c=iobuf_get(a)) == -1 ) {
+                   /* If we use the undocumented feature to suppress
+                    * the zlib header, we have to give inflate an
+                    * extra dummy byte to read */
+                   if( zfx->algo != 1 || zfx->algo1hack )
+                       break;
+                   zfx->algo1hack = 1;
+               }
                *p = c & 0xff;
            }
            zs->avail_in = n;
index 6b4b41c..3cd297f 100644 (file)
@@ -35,6 +35,8 @@
 #include "i18n.h"
 
 static int do_export( STRLIST users, int secret, int onlyrfc );
+static int do_export_stream( IOBUF out, STRLIST users,
+                            int secret, int onlyrfc, int *any );
 
 /****************
  * Export the public keys (to standard out or --output).
@@ -48,6 +50,21 @@ export_pubkeys( STRLIST users, int onlyrfc )
     return do_export( users, 0, onlyrfc );
 }
 
+/****************
+ * Export to an already opened stream; return -1 if no keys have
+ * been exported
+ */
+int
+export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc )
+{
+    int any, rc;
+
+    rc = do_export_stream( out, users, 0, onlyrfc, &any );
+    if( !rc && !any )
+       rc = -1;
+    return rc;
+}
+
 int
 export_seckeys( STRLIST users )
 {
@@ -57,30 +74,46 @@ export_seckeys( STRLIST users )
 static int
 do_export( STRLIST users, int secret, int onlyrfc )
 {
-    int rc = 0;
+    IOBUF out = NULL;
+    int any, rc;
     armor_filter_context_t afx;
+
+    memset( &afx, 0, sizeof afx);
+
+    rc = open_outfile( NULL, 0, &out );
+    if( rc )
+       return rc;
+
+    if( opt.armor ) {
+       afx.what = secret?5:1;
+       iobuf_push_filter( out, armor_filter, &afx );
+    }
+    rc = do_export_stream( out, users, secret, onlyrfc, &any );
+
+    if( rc || !any )
+       iobuf_cancel(out);
+    else
+       iobuf_close(out);
+    return rc;
+}
+
+
+static int
+do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any )
+{
+    int rc = 0;
     compress_filter_context_t zfx;
-    IOBUF out = NULL;
     PACKET pkt;
     KBNODE keyblock = NULL;
     KBNODE kbctx, node;
     KBPOS kbpos;
     STRLIST sl;
     int all = !users;
-    int any=0;
 
-    memset( &afx, 0, sizeof afx);
+    *any = 0;
     memset( &zfx, 0, sizeof zfx);
     init_packet( &pkt );
 
-    if( (rc = open_outfile( NULL, 0, &out )) )
-       goto leave;
-
-
-    if( opt.armor ) {
-       afx.what = secret?5:1;
-       iobuf_push_filter( out, armor_filter, &afx );
-    }
     if( opt.compress_keys && opt.compress )
        iobuf_push_filter( out, compress_filter, &zfx );
 
@@ -157,7 +190,7 @@ do_export( STRLIST users, int secret, int onlyrfc )
                goto leave;
            }
        }
-       any++;
+       ++*any;
     }
     if( rc == -1 )
        rc = 0;
@@ -166,11 +199,7 @@ do_export( STRLIST users, int secret, int onlyrfc )
     if( all == 2 )
        enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
     release_kbnode( keyblock );
-    if( rc || !any )
-       iobuf_cancel(out);
-    else
-       iobuf_close(out);
-    if( !any )
+    if( !*any )
        log_info(_("WARNING: nothing exported\n"));
     return rc;
 }
index ebd58e3..df436be 100644 (file)
@@ -67,6 +67,7 @@ typedef struct {
     byte *outbuf;
     unsigned outbufsize;
     int algo;   /* compress algo */
+    int algo1hack;
 } compress_filter_context_t;
 
 
index 7e71426..8727498 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -43,6 +43,7 @@
 #include "i18n.h"
 #include "status.h"
 #include "g10defs.h"
+#include "hkp.h"
 
 #ifndef IS_G10MAINT
   #define IS_G10 1
@@ -83,6 +84,7 @@ enum cmd_and_opt_values { aNull = 0,
     aListKeys,
     aListSigs,
     aListSecretKeys,
+    aSendKeys,
     aExport,
     aExportAll,
     aExportSecret,
@@ -184,6 +186,7 @@ static ARGPARSE_OPTS opts[] = {
     { aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
   #endif
     { aExport, "export"           , 256, N_("export keys") },
+    { aSendKeys, "send-keys"     , 256, N_("export keys to a key server") },
     { aExportAll, "export-all"    , 256, "@" },
     { aExportSecret, "export-secret-keys" , 256, "@" },
     { aImport, "import",      256     , N_("import/merge keys")},
@@ -639,6 +642,7 @@ main( int argc, char **argv )
          case aListPackets: set_cmd( &cmd, aListPackets); break;
          case aImport: set_cmd( &cmd, aImport); break;
          case aFastImport: set_cmd( &cmd, aFastImport); break;
+         case aSendKeys: set_cmd( &cmd, aSendKeys); break;
          case aExport: set_cmd( &cmd, aExport); break;
          case aExportAll: set_cmd( &cmd, aExportAll); break;
          case aListKeys: set_cmd( &cmd, aListKeys); break;
@@ -1098,10 +1102,14 @@ main( int argc, char **argv )
 
       case aExport:
       case aExportAll:
+      case aSendKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist( &sl, *argv );
-       export_pubkeys( sl, (cmd == aExport) );
+       if( cmd == aSendKeys )
+           hkp_export( sl );
+       else
+           export_pubkeys( sl, (cmd == aExport) );
        free_strlist(sl);
        break;
 
index 79632d7..11f7011 100644 (file)
--- a/g10/hkp.c
+++ b/g10/hkp.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <errno.h>
 #include <assert.h>
 
 #include "ttyio.h"
 #include "i18n.h"
 #include "options.h"
+#include "filter.h"
 #include "http.h"
 #include "main.h"
 
+static int urlencode_filter( void *opaque, int control,
+                            IOBUF a, byte *buf, size_t *ret_len);
 
 /****************
  * Try to import the key with KEYID from a keyserver but ask the user
@@ -58,17 +62,119 @@ hkp_ask_import( u32 *keyid )
      * nicer one */
     sprintf( request, "x-hkp://%s:11371/pks/lookup?op=get&search=0x%08lX",
                        opt.keyserver_name, (ulong)keyid[1] );
-    rc = open_http_document( &hd, request, 0 );
+    rc = http_open_document( &hd, request, 0 );
     if( rc ) {
        log_info("can't get key from keyserver: %s\n", g10_errstr(rc) );
-       goto leave;
     }
-    rc = import_keys_stream( hd.fp_read , 0 );
-    close_http_document( &hd );
+    else {
+       rc = import_keys_stream( hd.fp_read , 0 );
+       http_close( &hd );
+    }
+
+    m_free( request );
+    return rc;
+}
+
+
+int
+hkp_export( STRLIST users )
+{
+    int rc;
+    armor_filter_context_t afx;
+    IOBUF temp = iobuf_temp();
+    struct http_context hd;
+    char *request;
+    unsigned int status;
+
+    if( !opt.keyserver_name ) {
+       log_error("no keyserver known (use option --keyserver)\n");
+       return -1;
+    }
+
+    iobuf_push_filter( temp, urlencode_filter, NULL );
+
+    memset( &afx, 0, sizeof afx);
+    afx.what = 1;
+    iobuf_push_filter( temp, armor_filter, &afx );
 
-  leave:
+    rc = export_pubkeys_stream( temp, users, 1 );
+    if( rc == -1 ) {
+       iobuf_close(temp);
+       return 0;
+    }
+
+    iobuf_flush_temp( temp );
+
+    request = m_alloc( strlen( opt.keyserver_name ) + 100 );
+    sprintf( request, "x-hkp://%s:11371/pks/add", opt.keyserver_name );
+    rc = http_open( &hd, HTTP_REQ_POST, request , 0 );
+    if( rc ) {
+       log_error("can't connect to `%s': %s\n",
+                  opt.keyserver_name, g10_errstr(rc) );
+       iobuf_close(temp);
+       m_free( request );
+       return rc;
+    }
+
+    sprintf( request, "Content-Length: %u\n",
+                     (unsigned)iobuf_get_temp_length(temp) + 9 );
+    iobuf_writestr( hd.fp_write, request );
     m_free( request );
+    http_start_data( &hd );
+
+    iobuf_writestr( hd.fp_write, "keytext=" );
+    iobuf_write( hd.fp_write, iobuf_get_temp_buffer(temp),
+                             iobuf_get_temp_length(temp) );
+    iobuf_put( hd.fp_write, '\n' );
+    iobuf_close(temp);
+
+    rc = http_wait_response( &hd, &status );
+    if( rc ) {
+       log_error("error sending to `%s': %s\n",
+                  opt.keyserver_name, g10_errstr(rc) );
+    }
+    else {
+      #if 1
+       if( opt.verbose ) {
+           int c;
+           while( (c=iobuf_get(hd.fp_read)) != EOF )
+               putchar( c );
+       }
+      #endif
+       if( (status/100) == 2 )
+           log_info("success sending to `%s' (status=%u)\n",
+                                       opt.keyserver_name, status  );
+       else
+           log_error("failed sending to `%s': status=%u\n",
+                                       opt.keyserver_name, status  );
+    }
+    http_close( &hd );
     return rc;
 }
 
+static int
+urlencode_filter( void *opaque, int control,
+                 IOBUF a, byte *buf, size_t *ret_len)
+{
+    size_t size = *ret_len;
+    int rc=0;
+
+    if( control == IOBUFCTRL_FLUSH ) {
+       const byte *p;
+       for(p=buf; size; p++, size-- ) {
+           if( isalnum(*p) || *p == '-' )
+               iobuf_put( a, *p );
+           else if( *p == ' ' )
+               iobuf_put( a, '+' );
+           else {
+               char numbuf[5];
+               sprintf(numbuf, "%%%02X", *p );
+               iobuf_writestr(a, numbuf );
+           }
+       }
+    }
+    else if( control == IOBUFCTRL_DESC )
+       *(char**)buf = "urlencode_filter";
+    return rc;
+}
 
index 6ea5552..b062cfa 100644 (file)
--- a/g10/hkp.h
+++ b/g10/hkp.h
@@ -23,6 +23,7 @@
 
 
 int hkp_ask_import( u32 *keyid );
+int hkp_export( STRLIST users );
 
 
 #endif /*G10_HKP_H*/
index 2b5d34d..7431d8c 100644 (file)
@@ -930,7 +930,7 @@ generate_keypair()
            if( algo == PUBKEY_ALGO_DSA )
                tty_printf(_("Note that this key cannot be used for "
                             "encryption.  You may want to use\n"
-                            "the command \"--add-key\" to generate a "
+                            "the command \"--edit-key\" to generate a "
                             "secondary key for this purpose.\n") );
        }
 
index 94ace8e..2aa946b 100644 (file)
@@ -110,8 +110,10 @@ KBNODE make_mpi_comment_node( const char *s, MPI a );
 /*-- import.c --*/
 int import_keys( const char *filename, int fast );
 int import_keys_stream( IOBUF inp, int fast );
+
 /*-- export.c --*/
 int export_pubkeys( STRLIST users, int onlyrfc );
+int export_pubkeys_stream( IOBUF out, STRLIST users, int onlyrfc );
 int export_seckeys( STRLIST users );
 
 /* dearmor.c --*/
index 1f599d9..364fb47 100644 (file)
@@ -99,6 +99,8 @@ init_signals()
     do_sigaction( SIGSEGV, &nact );
     nact.sa_handler = got_usr_signal;
     sigaction( SIGUSR1, &nact, NULL );
+    nact.sa_handler = SIG_IGN;
+    sigaction( SIGPIPE, &nact, NULL ); 
   #endif
 }
 
index a439b4b..d55213e 100644 (file)
@@ -43,20 +43,33 @@ struct parsed_uri {
 };
 typedef struct parsed_uri *PARSED_URI;
 
+typedef enum {
+    HTTP_REQ_GET  = 1,
+    HTTP_REQ_HEAD = 2,
+    HTTP_REQ_POST = 3
+} HTTP_REQ_TYPE;
+
 struct http_context {
     int initialized;
     unsigned int status_code;
     int socket;
+    int in_data;
     IOBUF fp_read;
     IOBUF fp_write;
     int is_http_0_9;
     PARSED_URI uri;
+    HTTP_REQ_TYPE req_type;
     byte *buffer;         /* line buffer */
     unsigned buffer_size;
 };
 typedef struct http_context *HTTP_HD;
 
-int open_http_document( HTTP_HD hd, const char *document, unsigned int flags );
-void close_http_document( HTTP_HD hd );
+int http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
+                                                 unsigned int flags );
+void http_start_data( HTTP_HD hd );
+int  http_wait_response( HTTP_HD hd, unsigned int *ret_status );
+void http_close( HTTP_HD hd );
+
+int http_open_document( HTTP_HD hd, const char *document, unsigned int flags );
 
 #endif /*G10_HTTP_H*/
index 8b8df37..892d508 100644 (file)
@@ -161,7 +161,6 @@ STRLIST strlist_last( STRLIST node );
 const char *memistr( const char *buf, size_t buflen, const char *sub );
 char *mem2str( char *, const void *, size_t);
 char *trim_spaces( char *string );
-unsigned trim_trailing_ws( byte *line, unsigned len );
 int string_count_chr( const char *string, int c );
 int set_native_charset( const char *newset );
 char *native_to_utf8( const char *string );
index 1f3a87a..356e6df 100644 (file)
@@ -1,3 +1,18 @@
+Tue Jan 19 19:34:58 CET 1999  Werner Koch  <wk@isil.d.shuttle.de>
+
+       * * iobuf.c (iobuf_push_filter): Allow filters for temp streams
+
+       (iobuf_write_temp): Ditto.
+       (iobuf_flush_temp): New.
+       (iobuf_unget_and_close_temp): Removed.
+
+       * http.c (close_http_document): Renamed to http_close().
+       (open_http_document): Renamed to http_open_document().
+       (http_open): New.
+       (http_start_data): New.
+       (http_wait_response): New.
+
+
 Sun Jan 17 11:04:33 CET 1999  Werner Koch  <wk@isil.d.shuttle.de>
 
        * strgutil.c (trim_trailing_ws): New.
index 949cdb3..22c5699 100644 (file)
@@ -64,57 +64,105 @@ static int connect_server( const char *server, ushort port );
 static int write_server( int socket, const char *data, size_t length );
 
 
-
 int
-open_http_document( HTTP_HD hd, const char *document, unsigned int flags )
+http_open( HTTP_HD hd, HTTP_REQ_TYPE reqtype, const char *url,
+                                             unsigned int flags )
 {
     int rc;
 
-    if( flags )
+    if( flags || !(reqtype == HTTP_REQ_GET || reqtype == HTTP_REQ_POST) )
        return G10ERR_INV_ARG;
 
     /* initialize the handle */
     memset( hd, 0, sizeof *hd );
     hd->socket = -1;
+    hd->initialized = 1;
+    hd->req_type = reqtype;
+
+    rc = parse_uri( &hd->uri, url );
+    if( !rc ) {
+       rc = send_request( hd );
+       if( !rc ) {
+           hd->fp_write = iobuf_fdopen( hd->socket , "w" );
+           if( hd->fp_write )
+               return 0;
+           rc = G10ERR_GENERAL;
+       }
+    }
 
-    rc = parse_uri( &hd->uri, document );
-    if( rc )
-       goto failure;
+    if( !hd->fp_read && !hd->fp_write )
+       close( hd->socket );
+    iobuf_close( hd->fp_read );
+    iobuf_close( hd->fp_write);
+    release_parsed_uri( hd->uri );
+    hd->initialized = 0;
 
-    rc = send_request( hd );
-    if( rc )
-       goto failure;
+    return rc;
+}
+
+
+void
+ttp_start_data( HTTP_HD hd )
+{
+    if( !hd->in_data ) {
+       iobuf_put( hd->fp_write, '\n' );
+       hd->in_data = 1;
+    }
+}
+
+
+int
+http_wait_response( HTTP_HD hd, unsigned int *ret_status )
+{
+    int rc;
+
+    http_start_data( hd ); /* make sure that we are in the data */
+    iobuf_flush( hd->fp_write );
+    shutdown( hd->socket, 1 );
+    hd->in_data = 0;
+
+    hd->socket = dup( hd->socket );
+    if( hd->socket == -1 )
+       return G10ERR_GENERAL;
+    iobuf_close( hd->fp_write );
+    hd->fp_write = NULL;
 
     hd->fp_read = iobuf_fdopen( hd->socket , "r" );
     if( !hd->fp_read )
-       goto failure;
+       return G10ERR_GENERAL;
 
     rc = parse_response( hd );
-    if( rc == -1 ) { /* no response from server */
-       /* Hmmm, should we set some errro variable or map errors */
-       goto failure;
-    }
+    if( !rc && ret_status )
+       *ret_status = hd->status_code;
 
-    if( !rc )
-       hd->is_http_0_9 = 1;
-    else
-       hd->status_code = rc ;
+    return rc;
+}
 
-    hd->initialized = 1;
-    return 0;
 
-  failure:
-    if( !hd->fp_read && !hd->fp_write )
-       close( hd->socket );
-    iobuf_close( hd->fp_read );
-    iobuf_close( hd->fp_write);
-    release_parsed_uri( hd->uri );
+int
+http_open_document( HTTP_HD hd, const char *document, unsigned int flags )
+{
+    int rc;
+
+    if( flags )
+       return G10ERR_INV_ARG;
+
+    rc = http_open( hd, HTTP_REQ_GET, document, 0 );
+    if( rc )
+       return rc;
+
+    rc = http_wait_response( hd, NULL );
+    if( rc )
+       http_close( hd );
 
     return rc;
 }
 
+
+
+
 void
-close_http_document( HTTP_HD hd )
+http_close( HTTP_HD hd )
 {
     if( !hd || !hd->initialized )
        return;
@@ -385,12 +433,15 @@ send_request( HTTP_HD hd )
 
     p = build_rel_path( hd->uri );
     request = m_alloc( strlen(p) + 20 );
-    sprintf( request, "GET %s%s HTTP/1.0\r\n\r\n", *p == '/'? "":"/", p );
+    sprintf( request, "%s %s%s HTTP/1.0\r\n\r\n",
+                         hd->req_type == HTTP_REQ_GET ? "GET" :
+                         hd->req_type == HTTP_REQ_HEAD? "HEAD":
+                         hd->req_type == HTTP_REQ_POST? "POST": "OOPS",
+                                                 *p == '/'? "":"/", p );
     m_free(p);
 
     rc = write_server( hd->socket, request, strlen(request) );
     m_free( request );
-    shutdown( hd->socket, 1 );
 
     return rc;
 }
@@ -442,15 +493,12 @@ build_rel_path( PARSED_URI uri )
 
 /***********************
  * Parse the response from a server.
- * Returns: -1 for no response or error
- *          0  for a http 0.9 response
- *        nnn  http 1.0 status code
+ * Returns: errorcode and sets some fileds in the handle
  */
 static int
 parse_response( HTTP_HD hd )
 {
     byte *line, *p, *p2;
-    int status;
     unsigned maxlen, len;
 
     /* Wait for the status line */
@@ -480,9 +528,13 @@ parse_response( HTTP_HD hd )
     /* fixme: add HTTP version number check here */
     if( (p2 = strpbrk( p, " \t" ) ) )
        *p2++ = 0;
-    if( !isdigit(p[0]) || !isdigit(p[1]) || !isdigit(p[2]) || p[3] )
-       return 0; /* malformed HTTP statuscode - assume HTTP 0.9 */
-    status = atoi( p );
+    if( !isdigit(p[0]) || !isdigit(p[1]) || !isdigit(p[2]) || p[3] ) {
+        /* malformed HTTP statuscode - assume HTTP 0.9 */
+       hd->is_http_0_9 = 1;
+       hd->status_code = 200;
+       return 0;
+    }
+    hd->status_code = atoi( p );
 
     /* skip all the header lines and wait for the empty line */
     do {
@@ -498,7 +550,7 @@ parse_response( HTTP_HD hd )
            *line = 0;
     } while( len && *line  );
 
-    return status;
+    return 0;
 }
 
 
index b62da6d..9fba1fc 100644 (file)
@@ -38,6 +38,7 @@ typedef struct {
     char fname[1]; /* name of the file */
 } file_filter_ctx_t ;
 
+
 /* The first partial length header block must be of size 512
  * to make it easier (and efficienter) we use a min. block size of 512
  * for all chznks (but the last one) */
@@ -95,7 +96,7 @@ file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
        assert( size ); /* need a buffer */
        for(; size; size-- ) {
            if( (c=getc(fp)) == EOF ) {
-               if( ferror(fp) ) {
+               if( ferror(fp) && errno != EPIPE  ) {
                    log_error("%s: read error: %s\n",
                                        a->fname, strerror(errno));
                    rc = G10ERR_READ_FILE;
@@ -561,12 +562,9 @@ iobuf_fdopen( int fd, const char *mode )
     file_filter_ctx_t *fcx;
     size_t len;
 
-    if( strchr( mode, 'w' ) )
-       log_bug("iobuf_fdopen: mode `%s' is not supported", mode);
-
     if( !(fp = fdopen(fd, mode)) )
        return NULL;
-    a = iobuf_alloc(1, 8192 );
+    a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 );
     fcx = m_alloc( sizeof *fcx + 20 );
     fcx->fp = fp;
     fcx->print_only_name = 1;
@@ -703,7 +701,6 @@ iobuf_fopen( const char *fname, const char *mode )
 
 
 
-
 /****************
  * Register an i/o filter.
  */
@@ -732,6 +729,9 @@ iobuf_push_filter( IOBUF a,
     a->filter = NULL;
     a->filter_ov = NULL;
     a->filter_eof = 0;
+    if( a->usage == 3 )
+       a->usage = 2;  /* make a write stream from a temp stream */
+
     if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
        b->d.buf = m_alloc( a->d.size );
        b->d.len = 0;
@@ -961,7 +961,7 @@ iobuf_flush(IOBUF a)
        return 0;
 
     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
-    if( a->usage == 3 ) { /* must increase the size of the temp buffer */
+    if( a->usage == 3 ) { /* increase the temp buffer */
        char *newbuf;
        size_t newsize = a->d.size + 8192;
 
@@ -1141,6 +1141,8 @@ iobuf_writestr(IOBUF a, const char *buf )
 int
 iobuf_write_temp( IOBUF a, IOBUF temp )
 {
+    while( temp->chain )
+       pop_filter( temp, temp->filter, NULL );
     return iobuf_write(a, temp->d.buf, temp->d.len );
 }
 
@@ -1158,28 +1160,18 @@ iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
     return n;
 }
 
+
 /****************
- * unget the contents of the temp io stream to A and close temp
- * Could be optimized!!
+ * Call this function to terminate processing of the temp stream
+ * without closing it. This removes all filters from the stream
+ * makes sure that iobuf_get_temp_{buffer,length}() returns correct
+ * values.
  */
 void
-iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
+iobuf_flush_temp( IOBUF temp )
 {
-    if( a->unget.buf ) {
-       if( a->unget.start < a->unget.len )
-           log_fatal("cannot do any more ungets on this buffer\n");
-       /* not yet cleaned up; do it now */
-       m_free(a->unget.buf);
-       a->unget.buf = NULL;
-       a->nofast &= ~2;
-    }
-    a->unget.size = temp->d.len;
-    a->unget.buf = m_alloc( a->unget.size );
-    a->nofast |= 2;
-    a->unget.len = temp->d.len;
-    a->unget.start = 0;
-    memcpy( a->unget.buf, temp->d.buf, a->unget.len );
-    iobuf_close(temp);
+    while( temp->chain )
+       pop_filter( temp, temp->filter, NULL );
 }
 
 
@@ -1285,7 +1277,7 @@ iobuf_seek( IOBUF a, ulong newpos )
     if( a->chain )
        log_debug("pop_filter called in iobuf_seek - please report\n");
     while( a->chain )
-       pop_filter( a, a->filter, NULL );
+       pop_filter( a, a->filter, NULL );
 
     return 0;
 }
@@ -1310,6 +1302,7 @@ get_real_fname( IOBUF a )
     return NULL;
 }
 
+
 /****************
  * Retrieve the filename
  */