See ChangeLog: Mon Mar 13 19:22:46 CET 2000 Werner Koch
authorWerner Koch <wk@gnupg.org>
Mon, 13 Mar 2000 18:19:12 +0000 (18:19 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 13 Mar 2000 18:19:12 +0000 (18:19 +0000)
19 files changed:
ChangeLog
acinclude.m4
cipher/ChangeLog
cipher/md.c
configure.in
doc/Makefile.am
doc/gcryptref.sgml
doc/version.sgml.in [new file with mode: 0644]
g10/ChangeLog
g10/Makefile.am
g10/build-packet.c
g10/kbx.h
g10/kbxblob.c
g10/kbxfile.c [new file with mode: 0644]
g10/keydb.h
g10/packet.h
g10/ringedit.c
scripts/db2html.in [new file with mode: 0755]
tools/Makefile.am

index 4e84473..e0091e2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Mon Mar 13 19:22:46 CET 2000  Werner Koch  <wk@openit.de>
+
+       * configure.in: Now uses the Docbook M$s from GPH.
+
 Mon Jan 31 17:46:35 CET 2000  Werner Koch  <wk@>
 
        * Makefile.am: Re-added tools. By RĂ©mi.
index 4a8f0a2..20c92be 100644 (file)
@@ -663,4 +663,116 @@ if test $gnupg_cv_mkdir_takes_one_arg = yes ; then
 fi
 ])
 
+
+dnl GPH_PROG_DOCBOOK()
+dnl Check whether we have the needed Docbook environment
+dnl and issue a warning if this is not the case.
+dnl
+dnl This test defines these variables for substitution:
+dnl    DB2HTML - command used to convert Docbook to HTML
+dnl    DB2TEX  - command used to convert Docbook to TeX
+dnl    DB2MAN  - command used to convert Docbook to man pages
+dnl    JADE    - command to invoke jade
+dnl    JADETEX - command to invoke jadetex
+dnl    DSL_FOR_HTML - the stylesheet used to for the Docbook->HTML conversion
+dnl The following make conditionals are defined
+dnl    HAVE_DB2MAN  - defined when db2man is available
+dnl    HAVE_DB2TEX  - defined when db2tex is available
+dnl    HAVE_DB2HTML - defined when db2html is available
+dnl    HAVE_DOCBOOK - defined when the entire Docbook environment is present
+dnl    HAVE_JADE    - defined when jade is installed
+dnl    HAVE_JADETEX - defined when jadetex is installed
+dnl
+dnl (wk 2000-02-17)
+dnl
+AC_DEFUN(GPH_PROG_DOCBOOK,
+  [  AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+     all=yes
+     AC_PATH_PROG(DB2MAN, docbook-to-man, no)
+     test "$DB2MAN" = no && all=no
+     AM_CONDITIONAL(HAVE_DB2MAN, test "$DB2MAN" != no )
+
+     AC_PATH_PROG(JADE, jade, no)
+     test "$JADE" = no && all=no
+     AM_CONDITIONAL(HAVE_JADE, test "$JADE" != no )
+
+     AC_PATH_PROG(JADETEX, jadetex, no)
+     test "$JADETEX" = no && all=no
+     AM_CONDITIONAL(HAVE_JADETEX, test "$JADETEX" != no )
+
+     stylesheet_dirs='
+/usr/local/lib/dsssl/stylesheets/docbook
+/usr/local/share/dsssl/stylesheets/docbook
+/usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/local/share/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/lib/dsssl/stylesheets/docbook
+/usr/share/dsssl/stylesheets/docbook
+/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/share/sgml/stylesheet/dsssl/docbook/nwalsh
+'
+
+    AC_MSG_CHECKING(for TeX stylesheet)
+    dsl=none
+    for d in ${stylesheet_dirs}; do
+        file=${d}/print/docbook.dsl
+        if test -f $file; then
+            dsl=$file
+            break
+        fi
+    done
+    AC_MSG_RESULT([$dsl])
+    okay=no
+    if test $dsl = none ; then
+       DB2TEX="$missing_dir/missing db2tex"
+       all=no
+    else
+       DB2TEX="$JADE -t tex -i tex -d $dsl"
+       okay=yes
+    fi
+    AC_SUBST(DB2TEX)
+    AM_CONDITIONAL(HAVE_DB2TEX, test $okay = yes )
+
+    if ( $ac_aux_dir/db2html.in --version) < /dev/null > /dev/null 2>&1; then
+        :
+    else
+        AC_ERROR([needed $ac_aux_dir/db2html.in not found])
+    fi
+
+    AC_MSG_CHECKING(for HTML stylesheet)
+    DSL_FOR_HTML="none"
+    for d in ${stylesheet_dirs}; do
+        file=${d}/html/docbook.dsl
+        if test -f $file; then
+            DSL_FOR_HTML=$file
+            break
+        fi
+    done
+    AC_MSG_RESULT([$DSL_FOR_HTML])
+    okay=no
+    if test $DSL_FOR_HTML = none ; then
+       DB2HTML="$missing_dir/missing db2html"
+       all=no
+    else
+       DB2HTML="`cd $ac_aux_dir && pwd`/db2html --copyfiles"
+       okay=yes
+    fi
+    AC_SUBST(DB2HTML)
+    AC_SUBST(DSL_FOR_HTML)
+    AM_CONDITIONAL(HAVE_DB2HTML, test $okay = yes )
+
+    AM_CONDITIONAL(HAVE_DOCBOOK, test "$all" != yes )
+    if test $all = no ; then
+        AC_MSG_WARN([[
+***
+*** It seems that the Docbook environment is not installed as required.
+*** We will try to build everything,  but if you either touch some files
+*** or use a bogus make tool, you may run into problems.
+*** Docbook is normally only needed to build the documentation.
+***]])
+    fi
+  ])
+
+
+
+
 dnl *-*wedit:notab*-*  Please keep this as the last line.
index c0657d7..a811897 100644 (file)
@@ -1,3 +1,7 @@
+Mon Mar 13 19:22:46 CET 2000  Werner Koch  <wk@openit.de>
+
+       * md.c (gcry_md_hash_buffer): Add support for the other algorithms.
+
 Mon Jan 31 16:37:34 CET 2000  Werner Koch  <wk@gnupg.de>
 
        * genprime.c (generate_elg_prime): Fixed returned factors which never
index bc0a6c3..680558d 100644 (file)
@@ -596,15 +596,22 @@ gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen )
  * Shortcut function to hash a buffer with a given algo. The only supported
  * algorithm is RIPE-MD. The supplied digest buffer must be large enough
  * to store the resulting hash.  No error is returned, the function will
- * abort on an invalite algo.  DISABLED_ALGOS are ignored here.
+ * abort on an invalid algo.  DISABLED_ALGOS are ignored here.
  */
 void
 gcry_md_hash_buffer( int algo, char *digest, const char *buffer, size_t length)
 {
     if( algo == GCRY_MD_RMD160 )
        rmd160_hash_buffer( digest, buffer, length );
-    else
-       BUG();
+    else { /* for the others we do not have a fast function, so
+           * we use the normal functions to do it */
+       GCRY_MD_HD h = md_open( algo, 0 );
+       if( !h )
+           BUG(); /* algo not available */
+       md_write( h, (byte*)buffer, length );
+       md_final( h );
+       memcpy( digest, md_read( h, algo ), md_digest_length( algo ) );
+    }
 }
 
 static int
index ac926d6..fddb93d 100644 (file)
@@ -164,8 +164,7 @@ AC_PROG_CPP
 AC_ISC_POSIX
 AC_PROG_INSTALL
 AC_PROG_AWK
-AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no)
-AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes)
+GPH_PROG_DOCBOOK
 
 
 dnl
@@ -687,6 +686,7 @@ GNUPG_FIX_HDR_VERSION(gcrypt/gcrypt.h, GCRYPT_VERSION)
 
 
 AC_OUTPUT_COMMANDS([
+chmod +x scripts/db2html
 chmod +x gcrypt/gcrypt-config
 cat >gnupg-defs.tmp <<G10EOF
 /* Generated automatically by configure */
@@ -719,6 +719,7 @@ DATADIRNAME=$DATADIRNAME
 
 AC_OUTPUT([
 Makefile
+scripts/db2html
 intl/Makefile
 po/Makefile.in
 jnlib/Makefile
@@ -727,7 +728,7 @@ mpi/Makefile
 cipher/Makefile
 g10/Makefile
 doc/Makefile
-doc/gph/Makefile
+doc/version.sgml
 tools/Makefile
 zlib/Makefile
 checks/Makefile
index 04ad0a4..995b0b3 100644 (file)
@@ -1,33 +1,40 @@
 ## Process this file with automake to create Makefile.in
 
-EXTRA_DIST = DETAILS gpg.sgml gpg.1 FAQ HACKING OpenPGP
+EXTRA_DIST = DETAILS gpg.sgml gpg.1 FAQ HACKING OpenPGP \
+            version.sgml.in
 
 man_MANS = gpg.1
 
+pkgdata_DATA = gcryptref.html gcryptref.ps
 
-gcryptref.dvi : gcryptref.sgml
+BUILT_SOURCES = version.sgml gcryptref.html gcryptref.ps
 
-gcryptref.texi : gcryptref.sgml
-gcryptref.xml  : gcryptref.sgml
+CLEANFILES = gcryptref.aux gcryptref.log gcryptref.tex gcryptref.dvi
 
 
-%.ps: %.dvi
-       dvips -o $@ $<
-
+gcryptref.sgml : version.sgml
 
-if MAINTAINER_MODE
 
+if HAVE_DB2MAN
 %.1 : %.sgml
-       docbook-to-man $<  >$@
+       $(DB2MAN) $<  >$@
+endif
 
-%.texi : %.xml
-       docbook2texi $< >$@
+if HAVE_DB2TEX
+%.ps : %.dvi
+       dvips -o $@ $<
 
-%.xml  : %.sgml
-       sgml2xml -x lower $< >$@
+%.tex : %.sgml
+       $(DB2TEX) -V generate-book-toc $< > $@
 
+%.dvi : %.tex
+       $(JADETEX) $<
 endif
 
+if HAVE_DB2HTML
+%.html : %.sgml
+       $(DB2HTML) --nosplit $<
+endif
 
 
 
index abc3efb..bf9d509 100644 (file)
@@ -18,7 +18,9 @@
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 -->
 
-<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
+<!--entity genindex system "gcryptref.toc-idx"-->
+<!entity packageversion system "version.sgml">
 <!entity libgcrypt "Libgcrypt">
 <!entity sexp     "S-Exp">
 <!entity cipherref system "gcryptref-cipher.sgml">
 <!entity miscref   system "gcryptref-misc.sgml">
 ]>
 
+<book>
+<bookinfo>
+<title>The &libgcrypt; Reference Manual</title>
+<subtitle>Version &packageversion;</subtitle>
+<date>
+2000-03-13
+</date>
+<copyright>
+<year>2000</year>
+<holder>Free Software Foundation, Inc.</holder>
+</copyright>
+<abstract>
+<para>
+Please direct questions, bug reports, or suggestions concerning
+this manual to the mailing list <email>gnupg-doc@gnupg.org</email>.
+</para>
+
+<para>
+This manual may be redistributed under the terms of the
+<ulink url="http://www.gnu.org/copyleft/gpl.html"><phrase>GNU
+General Public License</phrase></ulink>.
+</para>
+</abstract>
+</bookinfo>
+
+
+
 
 <reference>
 <title>&libgcrypt; Reference Pages</title>
@@ -37,7 +66,7 @@
 <!-- Hash Functions -->
 &digestref;
 
-<!-- ublic Key Functions -->
+<!-- Public Key Functions -->
 &pubkeyref;
 
 <!-- Miscellaneous Functions  -->
diff --git a/doc/version.sgml.in b/doc/version.sgml.in
new file mode 100644 (file)
index 0000000..d78bda9
--- /dev/null
@@ -0,0 +1 @@
+@VERSION@
index 21b2488..6cd97d6 100644 (file)
@@ -1,3 +1,11 @@
+Mon Mar 13 19:22:46 CET 2000  Werner Koch  <wk@openit.de>
+
+       * build-paket.c (do_user_id): Save offset where name has been stored.
+
+       * ringedit.c : Add new access method KBXF
+
+       * kbxfile.c: New.
+
 Mon Feb 21 22:43:01 CET 2000  Werner Koch  <wk@>
 
        * kbx.h: New.
index bc83ad9..9018c14 100644 (file)
@@ -4,7 +4,9 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
 EXTRA_DIST = OPTIONS  pubring.asc  options.skel
 OMIT_DEPENDENCIES = zlib.h zconf.h
 LDFLAGS = -static @LDFLAGS@ @DYNLINK_LDFLAGS@
-needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la
+# we need to add libutil.la a second time because we have to resolve
+# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon.
+needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la ../util/libutil.la
 
 #noinst_PROGRAMS = gpgd
 bin_PROGRAMS = gpg
@@ -22,6 +24,9 @@ common_source =  \
              skclist.c         \
              ringedit.c        \
              kbnode.c          \
+             kbx.h             \
+             kbxblob.c         \
+             kbxfile.c         \
              main.h            \
              mainproc.c        \
              armor.c           \
index 2f3eebe..5772b13 100644 (file)
@@ -196,6 +196,7 @@ static int
 do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
 {
     write_header(out, ctb, uid->len);
+    uid->stored_at = iobuf_tell( out ); /* what a hack */
     if( iobuf_write( out, uid->name, uid->len ) )
        return GPGERR_WRITE_FILE;
     return 0;
index 9e61ebb..6508d3e 100644 (file)
--- a/g10/kbx.h
+++ b/g10/kbx.h
 #ifndef GPG_KBX_H
 #define GPG_KBX_H 1
 
+#include "keydb.h"
+
+typedef struct kbxblob *KBXBLOB;
+
+int  kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock );
+void kbx_release_blob ( KBXBLOB blob );
 
 
 #endif /*GPG_KBX_H*/
index cf3bb7a..c780487 100644 (file)
  * 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
- *
- ***********************************************
- * adler_cksum() is based on the zlib code with these conditions:
- *
- *     Copyright (C) 1995-1998 Mark Adler
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
  */
 
 
@@ -51,9 +30,11 @@ the beginning of the Blob.
 The first record of a plain KBX file has a special format:
 
  u32  length of the first record
- u32  magic 'KBXf'
+ byte Blob type (1)
  byte version number (1)
- b[3] reserved
+ byte reserved
+ byte reserved
+ u32  magic 'KBXf'
  byte marginals  used for validity calculation of this file
  byte completes  ditto.
  byte cert_depth ditto.
@@ -61,8 +42,8 @@ The first record of a plain KBX file has a special format:
 The standard KBX Blob looks like this:
 
  u32  length of this blob (including these 4 bytes)
- byte version number (1)
- byte reserved
+ byte Blob type (2)
+ byte version number of this blob type (1)
  u16  Blob flags
        bit 0 = contains secret key material
 
@@ -98,6 +79,8 @@ The standard KBX Blob looks like this:
  u8    all_validity
  u16   reserved
  u32   recheck_after
+ u32   Newest timestamp in the keyblock (useful for KS syncronsiation?)
+ u32   Blob created at
  u32   size of reserved space (not including this field)
       reserved space
 
@@ -107,7 +90,7 @@ The standard KBX Blob looks like this:
 
     maybe we put a sigture here later.
 
- u32   adler checksum
+ b16   MD5 checksum  (useful for KS syncronsiation)
  *
  */
 
@@ -120,6 +103,8 @@ The standard KBX Blob looks like this:
 #include <assert.h>
 #include <gcrypt.h>
 
+#include "iobuf.h"
+#include "util.h"
 #include "kbx.h"
 
 /* special values of the signature status */
@@ -135,22 +120,21 @@ The standard KBX Blob looks like this:
 struct kbxblob_key {
     char   fpr[20];
     u32    off_kid;
-    ulong  off_kid_addr; /* where it is stored in the datablock */
+    ulong  off_kid_addr;
     u16    flags;
 };
 struct kbxblob_uid {
-    u32    off;
-    ulong  off_addr; /* where it is stored in the datablock */
+    ulong  off_addr;
     u32    len;
     u16    flags;
-    byte   validity
+    byte   validity;
 };
 
 struct keyid_list {
     struct keyid_list *next;
     int seqno;
-    char kid[8];
-}
+    byte kid[8];
+};
 
 struct kbxblob {
     int nkeys;
@@ -161,49 +145,10 @@ struct kbxblob {
     u32  *sigs;
 
     struct keyid_list *temp_kids;
-} *KBXBLOB;
+    IOBUF buf; /* the KBX is stored here */
+};
 
 
-static u32
-adler_cksum ( const byte *buf, size_t len )
-{
-    unsigned long s1 = 1;
-    unsigned long s2 = 0;
-
-  #define X_BASE 65521L /* largest prime smaller than 65536 */
-  #define X_NMAX 5552  /* largest n such that                   */
-                           /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-  #define X_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
-  #define X_DO2(buf,i) X_DO1(buf,i); X_DO1(buf,i+1);
-  #define X_DO4(buf,i) X_DO2(buf,i); X_DO2(buf,i+2);
-  #define X_DO8(buf,i) X_DO4(buf,i); X_DO4(buf,i+4);
-  #define X_DO16(buf)  X_DO8(buf,0); X_DO8(buf,8);
-    while ( len  ) {
-       int k = len < NMAX ? len : NMAX;
-       len -= k;
-       while ( k >= 16 ) {
-           DO16(buf);
-           buf += 16;
-           k -= 16;
-       }
-       if ( k ) {
-             do {
-               s1 += *buf++;
-               s2 += s1;
-           } while ( --k );
-       }
-       s1 %= BASE;
-       s2 %= BASE;
-    }
-  #undef X_BASE
-  #undef X_NMAX
-  #undef X_DO1
-  #undef X_DO2
-  #undef X_DO4
-  #undef X_DO8
-  #undef X_DO16
-    return ( s2 << 16 ) | s1;
-}
 
 
 /* Note: this functions are only used for temportay iobufs and therefore
@@ -211,14 +156,14 @@ adler_cksum ( const byte *buf, size_t len )
 static void
 put8 ( IOBUF out, byte a )
 {
-    iobuf_put ( out, a )
+    iobuf_put ( out, a );
 }
 
 static void
 put16 ( IOBUF out, u16 a )
 {
     iobuf_put ( out, a>>8 );
-    iobuf_put ( out, a )
+    iobuf_put ( out, a );
 }
 
 static void
@@ -227,7 +172,7 @@ put32 ( IOBUF out, u32 a )
     iobuf_put (out, a>> 24);
     iobuf_put (out, a>> 16);
     iobuf_put (out, a>> 8);
-    iobuf_put (out, a) )
+    iobuf_put (out, a );
 }
 
 static void
@@ -245,7 +190,7 @@ static void
 put32at ( IOBUF out, u32 a, size_t pos )
 {
     size_t n;
-    byte *p,
+    byte *p;
 
     iobuf_flush_temp ( out );
     p = iobuf_get_temp_buffer( out );
@@ -269,37 +214,44 @@ temp_store_kid ( KBXBLOB blob, PKT_public_key *pk )
     struct keyid_list *k, *r;
 
     k = gcry_xmalloc ( sizeof *k );
-    k->kid = pk->keyid;
+    k->kid[0] = pk->keyid[0] >> 24 ;
+    k->kid[1] = pk->keyid[0] >> 16 ;
+    k->kid[2] = pk->keyid[0] >>  8 ;
+    k->kid[3] = pk->keyid[0]      ;
+    k->kid[4] = pk->keyid[0] >> 24 ;
+    k->kid[5] = pk->keyid[0] >> 16 ;
+    k->kid[6] = pk->keyid[0] >>  8 ;
+    k->kid[7] = pk->keyid[0]      ;
     k->seqno = 0;
     k->next = blob->temp_kids;
     blob->temp_kids = k;
     for ( r=k; r; r = r->next ) {
-       k->seqno++
+       k->seqno++;
     }
 
     return k->seqno;
 }
 
 static void
-put_stored_kid( IOBUF a, KBXBLOB blob, int seqno )
+put_stored_kid( KBXBLOB blob, int seqno )
 {
     struct keyid_list *r;
 
     for ( r = blob->temp_kids; r; r = r->next ) {
        if( r->seqno == seqno ) {
-           putn ( a, r->kid, 8 );
+           putn ( blob->buf, r->kid, 8 );
            return;
        }
     }
     BUG();
 }
 
-static int
+static void
 release_kid_list ( struct keyid_list *kl )
 {
     struct keyid_list *r, *r2;
 
-    for ( r = blob->temp_kids; r; r = r2 ) {
+    for ( r = kl; r; r = r2 ) {
        r2 = r->next;
        gcry_free( r );
     }
@@ -310,19 +262,18 @@ static int
 create_key_part( KBXBLOB blob, KBNODE keyblock )
 {
     KBNODE node;
-    byte fpr[MAX_FINGERPRINT_LEN];
     size_t fprlen;
     int n;
 
     for ( n=0, node = keyblock; node; node = node->next ) {
-       if ( node->pkt->pkttype == PKT_PUBLIC_KEY:
+       if ( node->pkt->pkttype == PKT_PUBLIC_KEY
             || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
            PKT_public_key *pk = node->pkt->pkt.public_key;
 
            fingerprint_from_pk( pk, blob->keys[n].fpr, &fprlen );
            if ( fprlen != 20 ) { /*v3 fpr - shift right and fill with zeroes*/
                assert( fprlen == 16 );
-               memmove( blob->keys[n]+4, blob->keys[n].fpr, 16);
+               memmove( blob->keys[n].fpr+4, blob->keys[n].fpr, 16);
                memset( blob->keys[n].fpr, 0, 4 );
                blob->keys[n].off_kid = temp_store_kid( blob, pk );
            }
@@ -351,7 +302,6 @@ create_uid_part( KBXBLOB blob, KBNODE keyblock )
        if ( node->pkt->pkttype == PKT_USER_ID ) {
            PKT_user_id *u = node->pkt->pkt.user_id;
 
-           blob->uids[n].off   = 0;  /* must calculate this later */
            blob->uids[n].len   = u->len;
            blob->uids[n].flags = 0;
            blob->uids[n].validity = 0;
@@ -382,13 +332,14 @@ create_sig_part( KBXBLOB blob, KBNODE keyblock )
 
 
 static int
-create_blob_header( IOBUF a, KBXBLOB blob )
+create_blob_header( KBXBLOB blob )
 {
+    IOBUF a = blob->buf;
     int i;
 
     put32 ( a, 0 ); /* blob length, needs fixup */
-    put8 ( a, 1 );  /* version number */
-    put8 ( a, 0 );  /* reserved */
+    put8 ( a, 2 );  /* blob type */
+    put8 ( a, 1 );  /* blob type version */
     put16 ( a, 0 ); /* blob flags */
 
     put32 ( a, 0 ); /* offset to the keyblock, needs fixup */
@@ -398,7 +349,7 @@ create_blob_header( IOBUF a, KBXBLOB blob )
     put16 ( a, 20 + 8 + 2 + 2 );  /* size of key info */
     for ( i=0; i < blob->nkeys; i++ ) {
        putn ( a, blob->keys[i].fpr, 20 );
-       blob->keys[i].off_kid_addr = iobuf_tell ( out );
+       blob->keys[i].off_kid_addr = iobuf_tell ( a );
        put32 ( a, 0 ); /* offset to keyid, fixed up later */
        put16 ( a, blob->keys[i].flags );
        put16 ( a, 0 ); /* reserved */
@@ -407,7 +358,7 @@ create_blob_header( IOBUF a, KBXBLOB blob )
     put16 ( a, blob->nuids );
     put16 ( a, 4 + 4 + 2 + 1 + 1 );  /* size of uid info */
     for ( i=0; i < blob->nuids; i++ ) {
-       blob->uids[i].off_addr = iobuf_tell ( out );
+       blob->uids[i].off_addr = iobuf_tell ( a );
        put32 ( a, 0 ); /* offset to userid, fixed up later */
        put32 ( a, blob->uids[i].len );
        put16 ( a, blob->uids[i].flags );
@@ -425,16 +376,18 @@ create_blob_header( IOBUF a, KBXBLOB blob )
     put8 ( a, 0 );  /* validity of all user IDs */
     put16 ( a, 0 );  /* reserved */
     put32 ( a, 0 );  /* time of next recheck */
+    put32 ( a, 0 );  /* newest timestamp (none) */
+    put32 ( a, make_timestamp() );  /* creation time */
     put32 ( a, 0 );  /* size of reserved space */
-       /* reserved space (which is currently 0) */
+       /* reserved space (which is currently of size 0) */
 
     /* We need to store the keyids for all v3 keys because those key IDs are
      * not part of the fingerprint.  While we are doing that, we fixup all
      * the keyID offsets */
     for ( i=0; i < blob->nkeys; i++ ) {
        if ( blob->keys[i].off_kid ) { /* this is a v3 one */
-           put32at ( a, iobuf_tell(), blob->keys[i].off_kid_addr );
-           put_stored_kid ( a, blob, blob->keys[i].off_kid );
+           put32at ( a, iobuf_tell(a), blob->keys[i].off_kid_addr );
+           put_stored_kid ( blob, blob->keys[i].off_kid );
        }
        else { /* the better v4 key IDs - just store an offset 8 bytes back */
            put32at ( a, blob->keys[i].off_kid_addr-8,
@@ -447,38 +400,60 @@ create_blob_header( IOBUF a, KBXBLOB blob )
 }
 
 static int
-create_blob_keyblock( IOBUF a, KBXBLOB blob, KBNODE keyblock )
+create_blob_keyblock( KBXBLOB blob, KBNODE keyblock )
 {
+    IOBUF a = blob->buf;
     KBNODE node;
     int rc;
+    int nsig;
 
-    for ( node = keyblock; node; node = node->next ) {
-       /* we must get some offset into thge keyblock and do some
-        * fixups */
-       rc = build_packet ( fp, node->pkt );
+    for ( nsig = 0, node = keyblock; node; node = node->next ) {
+       rc = build_packet ( a, node->pkt );
        if ( rc ) {
-           log_error("build_packet(%d) for kbxblob failed: %s\n",
+           gpg_log_error("build_packet(%d) for kbxblob failed: %s\n",
                        node->pkt->pkttype, gpg_errstr(rc) );
            return GPGERR_WRITE_FILE;
        }
+       if ( node->pkt->pkttype == PKT_USER_ID ) {
+           PKT_user_id *u = node->pkt->pkt.user_id;
+           /* build_packet has set the offset of the name into u ;
+            * now we can do the fixup */
+           put32at ( a, u->stored_at, blob->uids[nsig].off_addr );
+           nsig++;
+       }
     }
+    assert( nsig == blob->nsigs );
     return 0;
 }
 
 static int
-create_blob_trailer( IOBUF a, KBXBLOB blob )
+create_blob_trailer( KBXBLOB blob )
 {
+    IOBUF a = blob->buf;
     return 0;
 }
 
 static int
-create_blob_finish( IOBUF a, KBXBLOB blob )
+create_blob_finish( KBXBLOB blob )
 {
+    IOBUF a = blob->buf;
+    byte *p;
+    size_t n;
 
+    /* write a placeholder for the checksum */
+    put32( a, 0 ); put32( a, 0 ); put32( a, 0 ); put32( a, 0 );
+    /* get the memory area */
+    iobuf_flush_temp ( a );
+    p = iobuf_get_temp_buffer ( a );
+    n = iobuf_get_temp_length ( a );
+    assert( n >= 20 );
 
     /* fixup the length */
-    /* optionally we could sign the whole stuff at this point */
-    /* write the checksum */
+    put32at ( a, 0, n );
+
+    /* calculate and store the MD5 checksum */
+    gcry_md_hash_buffer( GCRY_MD_MD5, p + n - 16, p, n - 16 );
+
     return 0;
 }
 
@@ -488,9 +463,7 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock )
 {
     int rc = 0;
     KBNODE node;
-    struct kbxblob *blob;
-    int nkey, nuid, nsig;
-    IOBUF a = NULL;
+    KBXBLOB blob;
 
     *retkbx = NULL;
     blob = gcry_calloc (1, sizeof *blob );
@@ -507,56 +480,63 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock )
          case PKT_PUBLIC_SUBKEY:
          case PKT_SECRET_SUBKEY: blob->nkeys++; break;
          case PKT_USER_ID:  blob->nuids++; break;
-         case PKT_SIGNATURE: blob->nsigs++, break;
+         case PKT_SIGNATURE: blob->nsigs++; break;
+         default: break;
        }
     }
-    blob->nkeys = gcry_calloc ( blob->nkeys, sizeof ( blob->keys ) );
-    blob->nuids = gcry_calloc ( blob->nuids, sizeof ( blob->uids ) );
-    blob->nsigs = gcry_calloc ( blob->nsigs, sizeof ( blob->sigs ) );
-    if ( !blob->nkeys || !blob->nuids || !blob->nsigs ) {
+    blob->keys = gcry_calloc ( blob->nkeys, sizeof ( blob->keys ) );
+    blob->uids = gcry_calloc ( blob->nuids, sizeof ( blob->uids ) );
+    blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( blob->sigs ) );
+    if ( !blob->keys || !blob->uids || !blob->sigs ) {
        rc = GCRYERR_NO_MEM;
        goto leave;
     }
 
-    rc = create_key_part ( blob, keyblock ),
+    rc = create_key_part ( blob, keyblock );
     if( rc )
        goto leave;
-    rc = create_uid_part ( blob, keyblock ),
+    rc = create_uid_part ( blob, keyblock );
     if( rc )
        goto leave;
-    rc = create_sig_part ( blob, keyblock ),
+    rc = create_sig_part ( blob, keyblock );
     if( rc )
        goto leave;
 
-    a = iobuf_temp();
-    rc = create_blob_header ( a, blob );
+    blob->buf = iobuf_temp();
+    rc = create_blob_header ( blob );
     if( rc )
        goto leave;
-    rc = create_blob_keyblock ( a, blob, keyblock );
+    rc = create_blob_keyblock ( blob, keyblock );
     if( rc )
        goto leave;
-    rc = create_blob_trailer ( a, blob );
+    rc = create_blob_trailer ( blob );
     if( rc )
        goto leave;
-    rc = create_blob_finish ( a, blob );
+    rc = create_blob_finish ( blob );
     if( rc )
        goto leave;
 
-    /* now we take the iobuf and copy it to the output */
-
     *retkbx = blob;
 
-  failure:
-    if( a )
-       iobuf_cancel( a );
+  leave:
     release_kid_list( blob->temp_kids );
+    blob->temp_kids = NULL;
     if ( rc ) {
-       gcry_free( blob->nkeys );
-       gcry_free( blob->nuids );
-       gcry_free( blob->nsigs );
-       gcry_free( blob );
+       kbx_release_blob ( blob );
     }
     return rc;
 }
 
+void
+kbx_release_blob ( KBXBLOB blob )
+{
+    if( !blob )
+       return;
+    if( blob->buf )
+       iobuf_cancel( blob->buf );
+    gcry_free( blob->keys );
+    gcry_free( blob->uids );
+    gcry_free( blob->sigs );
+    gcry_free( blob );
+}
 
diff --git a/g10/kbxfile.c b/g10/kbxfile.c
new file mode 100644 (file)
index 0000000..215259e
--- /dev/null
@@ -0,0 +1,45 @@
+/* kbxfile.c - KBX file handling
+ *     Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ */
+
+/****************
+ * We will change the whole system to use only KBX.  This file here
+ * will implements the methods needed to operate on plain KBXfiles.
+ * Most stuff from getkey and ringedit will be replaced by stuff here.
+ * To make things even mor easier we will only allow one updateable kbxfile
+ * and optionally some read-only files.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <gcrypt.h>
+
+#include "kbx.h"
+
+
+int
+kbxfile_search_by_fpr( void )
+{
+    return -1;
+}
+
index 221c01c..05aac77 100644 (file)
@@ -57,7 +57,8 @@ struct kbnode_struct {
 enum resource_type {
     rt_UNKNOWN = 0,
     rt_RING = 1,
-    rt_GDBM = 2
+    rt_GDBM = 2,
+    rt_KBXF = 3
 };
 
 
index 495871c..02f7017 100644 (file)
@@ -162,6 +162,8 @@ typedef struct {
 } PKT_comment;
 
 typedef struct {
+    ulong stored_at;     /* the stream offset where it was stored
+                          * by build-packet */
     int  len;            /* length of the name */
     char name[1];
 } PKT_user_id;
index df51be6..2fa79fd 100644 (file)
@@ -60,6 +60,7 @@
 #include "options.h"
 #include "main.h"
 #include "i18n.h"
+#include "kbx.h"
 
 
 #ifdef MKDIR_TAKES_ONE_ARG
@@ -96,6 +97,12 @@ static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
 static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
 static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
 
+static int do_kbxf_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
+                                               const char *fname );
+static int do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root );
+static int do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
+static int do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root );
+
 #ifdef HAVE_LIBGDBM
 static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
 static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
@@ -206,6 +213,7 @@ add_keyblock_resource( const char *url, int force, int secret )
 
     /* Do we have an URL?
      * gnupg-gdbm:filename  := this is a GDBM resource
+     * gnupg-kbxf:filename  := this is a KBX file resource
      * gnupg-ring:filename  := this is a plain keyring
      * filename := See what is is, but create as plain keyring.
      */
@@ -214,6 +222,10 @@ add_keyblock_resource( const char *url, int force, int secret )
            rt = rt_RING;
            resname += 11;
        }
+       else if( !strncmp( resname, "gnupg-kbxf:", 11 ) ) {
+           rt = rt_KBXF;
+           resname += 11;
+       }
        else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
            rt = rt_GDBM;
            resname += 11;
@@ -259,8 +271,17 @@ add_keyblock_resource( const char *url, int force, int secret )
                    rt = rt_GDBM;
                else if( magic == 0xce9a5713 )
                    log_error("%s: endianess does not match\n", url );
-               else
+               else {
+                   char buf[8];
+
                    rt = rt_RING;
+                   if( fread( buf, 8, 1, fp) == 1 ) {
+                       if( !memcmp( buf+4, "KBXf", 4 )
+                           && buf[0] == 1 && buf[1] == 1 ) {
+                           rt = rt_KBXF;
+                       }
+                   }
+               }
            }
            else /* maybe empty: assume ring */
                rt = rt_RING;
@@ -277,6 +298,7 @@ add_keyblock_resource( const char *url, int force, int secret )
        goto leave;
 
       case rt_RING:
+      case rt_KBXF:
        iobuf = iobuf_open( filename );
        if( !iobuf && !force ) {
            rc = GPGERR_OPEN_FILE;
@@ -341,6 +363,7 @@ add_keyblock_resource( const char *url, int force, int secret )
       #endif
        break;
 
+
     #ifdef HAVE_LIBGDBM
       case rt_GDBM:
        resource_table[i].dbf = gdbm_open( filename, 0,
@@ -458,6 +481,10 @@ search( PACKET *pkt, KBPOS *kbpos, int secret )
                rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
                                                 resource_table[i].fname );
                break;
+             case rt_KBXF:
+               rc = do_kbxf_search( pkt, kbpos, resource_table[i].iobuf,
+                                                resource_table[i].fname );
+               break;
             #ifdef HAVE_LIBGDBM
              case rt_GDBM: {
                    PKT_public_key *req_pk = pkt->pkt.public_key;
@@ -706,6 +733,8 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
     switch( kbpos->rt ) {
       case rt_RING:
        return keyring_read( kbpos, ret_root );
+      case rt_KBXF:
+       return do_kbxf_read( kbpos, ret_root );
      #ifdef HAVE_LIBGDBM
       case rt_GDBM:
        return do_gdbm_read( kbpos, ret_root );
@@ -762,6 +791,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
        kbpos->valid = 0;
        switch( kbpos->rt ) {
          case rt_RING:
+         case rt_KBXF:
            kbpos->fp = iobuf_open( rentry->fname );
            if( !kbpos->fp ) {
                log_error("can't open `%s'\n", rentry->fname );
@@ -788,6 +818,11 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
                    return GPGERR_GENERAL;
                rc = keyring_enum( kbpos, ret_root, mode == 11 );
                break;
+             case rt_KBXF:
+               if( !kbpos->fp )
+                   return GPGERR_GENERAL;
+               rc = do_kbxf_enum( kbpos, ret_root, mode == 11 );
+               break;
             #ifdef HAVE_LIBGDBM
              case rt_GDBM:
                rc = do_gdbm_enum( kbpos, ret_root );
@@ -812,6 +847,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
     else {
        switch( kbpos->rt ) {
          case rt_RING:
+         case rt_KBXF:
            if( kbpos->fp ) {
                iobuf_close( kbpos->fp );
                kbpos->fp = NULL;
@@ -852,6 +888,9 @@ insert_keyblock( KBPOS *kbpos, KBNODE root )
       case rt_RING:
        rc = keyring_copy( kbpos, 1, root );
        break;
+      case rt_KBXF:
+       rc = do_kbxf_copy( kbpos, 1, root );
+       break;
      #ifdef HAVE_LIBGDBM
       case rt_GDBM:
        rc = do_gdbm_store( kbpos, root, 0 );
@@ -881,6 +920,9 @@ delete_keyblock( KBPOS *kbpos )
       case rt_RING:
        rc = keyring_copy( kbpos, 2, NULL );
        break;
+      case rt_KBXF:
+       rc = do_kbxf_copy( kbpos, 2, NULL );
+       break;
      #ifdef HAVE_LIBGDBM
       case rt_GDBM:
        log_debug("deleting gdbm keyblock is not yet implemented\n");
@@ -909,6 +951,9 @@ update_keyblock( KBPOS *kbpos, KBNODE root )
       case rt_RING:
        rc = keyring_copy( kbpos, 3, root );
        break;
+      case rt_KBXF:
+       rc = do_kbxf_copy( kbpos, 3, root );
+       break;
      #ifdef HAVE_LIBGDBM
       case rt_GDBM:
        rc = do_gdbm_store( kbpos, root, 1 );
@@ -1544,6 +1589,478 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
 }
 
 \f
+/****************************************************************
+ ********** Functions which operate on KBX files ****************
+ ****************************************************************/
+
+/****************
+ * search a KBX file return 0 if found, -1 if not found or an errorcode.
+ */
+static int
+do_kbxf_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
+{
+    int rc;
+    PACKET pkt;
+    int save_mode;
+    ulong offset;
+    int pkttype = req->pkttype;
+    PKT_public_key *req_pk = req->pkt.public_key;
+    PKT_secret_key *req_sk = req->pkt.secret_key;
+
+    init_packet(&pkt);
+    save_mode = set_packet_list_mode(0);
+    kbpos->rt = rt_RING;
+    kbpos->valid = 0;
+
+  #if HAVE_DOSISH_SYSTEM || 1
+    assert(!iobuf);
+    iobuf = iobuf_open( fname );
+    if( !iobuf ) {
+       log_error("%s: can't open keyring file\n", fname);
+       rc = GPGERR_KEYRING_OPEN;
+       goto leave;
+    }
+  #else
+    if( iobuf_seek( iobuf, 0 ) ) {
+       log_error("can't rewind keyring file\n");
+       rc = GPGERR_KEYRING_OPEN;
+       goto leave;
+    }
+  #endif
+
+    while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
+       if( pkt.pkttype == PKT_SECRET_KEY ) {
+           PKT_secret_key *sk = pkt.pkt.secret_key;
+
+           if(   req_sk->timestamp == sk->timestamp
+              && req_sk->pubkey_algo == sk->pubkey_algo
+              && !cmp_seckey( req_sk, sk) )
+               break; /* found */
+       }
+       else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
+           PKT_public_key *pk = pkt.pkt.public_key;
+
+           if(   req_pk->timestamp == pk->timestamp
+              && req_pk->pubkey_algo == pk->pubkey_algo
+              && !cmp_pubkey( req_pk, pk ) )
+               break; /* found */
+       }
+       else
+           BUG();
+       free_packet(&pkt);
+    }
+    if( !rc ) {
+       kbpos->offset = offset;
+       kbpos->valid = 1;
+    }
+
+  leave:
+    free_packet(&pkt);
+    set_packet_list_mode(save_mode);
+  #if HAVE_DOSISH_SYSTEM || 1
+    iobuf_close(iobuf);
+  #endif
+    return rc;
+}
+
+
+static int
+do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root )
+{
+    PACKET *pkt;
+    int rc;
+    RESTBL *rentry;
+    KBNODE root = NULL;
+    IOBUF a;
+    int in_cert = 0;
+
+    if( !(rentry=check_pos(kbpos)) )
+       return GPGERR_GENERAL;
+
+    a = iobuf_open( rentry->fname );
+    if( !a ) {
+       log_error("can't open `%s'\n", rentry->fname );
+       return GPGERR_OPEN_FILE;
+    }
+
+    if( !kbpos->valid )
+       log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
+    if( iobuf_seek( a, kbpos->offset ) ) {
+       log_error("can't seek to %lu\n", kbpos->offset);
+       iobuf_close(a);
+       return GPGERR_KEYRING_OPEN;
+    }
+
+    pkt = gcry_xmalloc( sizeof *pkt );
+    init_packet(pkt);
+    kbpos->count=0;
+    while( (rc=parse_packet(a, pkt)) != -1 ) {
+       if( rc ) {  /* ignore errors */
+           if( rc != GPGERR_UNKNOWN_PACKET ) {
+               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+               rc = GPGERR_INV_KEYRING;
+               goto ready;
+           }
+           kbpos->count++;
+           free_packet( pkt );
+           init_packet( pkt );
+           continue;
+       }
+       /* make a linked list of all packets */
+       switch( pkt->pkttype ) {
+         case PKT_COMPRESSED:
+           log_error("skipped compressed packet in keyring\n" );
+           free_packet(pkt);
+           init_packet(pkt);
+           break;
+
+         case PKT_PUBLIC_KEY:
+         case PKT_SECRET_KEY:
+           if( in_cert )
+               goto ready;
+           in_cert = 1;
+         default:
+           kbpos->count++;
+           if( !root )
+               root = new_kbnode( pkt );
+           else
+               add_kbnode( root, new_kbnode( pkt ) );
+           pkt = gcry_xmalloc( sizeof *pkt );
+           init_packet(pkt);
+           break;
+       }
+    }
+  ready:
+    kbpos->valid = 0;
+    if( rc == -1 && root )
+       rc = 0;
+
+    if( rc )
+       release_kbnode( root );
+    else
+       *ret_root = root;
+    free_packet( pkt );
+    gcry_free( pkt );
+    iobuf_close(a);
+    return rc;
+}
+
+
+static int
+do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
+{
+    PACKET *pkt;
+    int rc;
+    RESTBL *rentry;
+    KBNODE root = NULL;
+
+    if( !(rentry=check_pos(kbpos)) )
+       return GPGERR_GENERAL;
+
+    if( kbpos->pkt ) {
+       root = new_kbnode( kbpos->pkt );
+       kbpos->pkt = NULL;
+    }
+
+    pkt = gcry_xmalloc( sizeof *pkt );
+    init_packet(pkt);
+    while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
+       if( rc ) {  /* ignore errors */
+           if( rc != GPGERR_UNKNOWN_PACKET ) {
+               log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) );
+               rc = GPGERR_INV_KEYRING;
+               goto ready;
+           }
+           free_packet( pkt );
+           init_packet( pkt );
+           continue;
+       }
+       /* make a linked list of all packets */
+       switch( pkt->pkttype ) {
+         case PKT_COMPRESSED:
+           log_error("skipped compressed packet in keyring\n" );
+           free_packet(pkt);
+           init_packet(pkt);
+           break;
+
+         case PKT_PUBLIC_KEY:
+         case PKT_SECRET_KEY:
+           if( root ) { /* store this packet */
+               kbpos->pkt = pkt;
+               pkt = NULL;
+               goto ready;
+           }
+           root = new_kbnode( pkt );
+           pkt = gcry_xmalloc( sizeof *pkt );
+           init_packet(pkt);
+           break;
+
+         default:
+           /* skip pakets at the beginning of a keyring, until we find
+            * a start packet; issue a warning if it is not a comment */
+           if( !root && pkt->pkttype != PKT_COMMENT
+                     && pkt->pkttype != PKT_OLD_COMMENT ) {
+               break;
+           }
+           if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
+                                     ||pkt->pkttype == PKT_COMMENT
+                                     ||pkt->pkttype == PKT_OLD_COMMENT )) ) {
+               init_packet(pkt);
+               break;
+           }
+           add_kbnode( root, new_kbnode( pkt ) );
+           pkt = gcry_xmalloc( sizeof *pkt );
+           init_packet(pkt);
+           break;
+       }
+    }
+  ready:
+    if( rc == -1 && root )
+       rc = 0;
+
+    if( rc )
+       release_kbnode( root );
+    else
+       *ret_root = root;
+    free_packet( pkt );
+    gcry_free( pkt );
+
+    return rc;
+}
+
+
+/****************
+ * Perform insert/delete/update operation.
+ * mode 1 = insert
+ *     2 = delete
+ *     3 = update
+ */
+static int
+do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root )
+{
+    RESTBL *rentry;
+    IOBUF fp, newfp;
+    int rc=0;
+    char *bakfname = NULL;
+    char *tmpfname = NULL;
+
+    if( !(rentry = check_pos( kbpos )) )
+       return GPGERR_GENERAL;
+    if( kbpos->fp )
+       BUG(); /* not allowed with such a handle */
+
+    if( opt.dry_run )
+       return 0;
+
+    lock_rentry( rentry );
+
+    /* open the source file */
+    fp = iobuf_open( rentry->fname );
+    if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
+       KBNODE kbctx, node;
+
+       /* insert: create a new file */
+       newfp = iobuf_create( rentry->fname );
+       if( !newfp ) {
+           log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno));
+           unlock_rentry( rentry );
+           return GPGERR_OPEN_FILE;
+       }
+       else if( !opt.quiet )
+           log_info(_("%s: keyring created\n"), rentry->fname );
+
+       kbctx=NULL;
+       while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
+           if( (rc = build_packet( newfp, node->pkt )) ) {
+               log_error("build_packet(%d) failed: %s\n",
+                           node->pkt->pkttype, gpg_errstr(rc) );
+               iobuf_cancel(newfp);
+               unlock_rentry( rentry );
+               return GPGERR_WRITE_FILE;
+           }
+       }
+       if( iobuf_close(newfp) ) {
+           log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
+           unlock_rentry( rentry );
+           return GPGERR_CLOSE_FILE;
+       }
+       if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
+           log_error("%s: chmod failed: %s\n",
+                                   rentry->fname, strerror(errno) );
+           unlock_rentry( rentry );
+           return GPGERR_WRITE_FILE;
+       }
+       return 0;
+    }
+    if( !fp ) {
+       log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
+       rc = GPGERR_OPEN_FILE;
+       goto leave;
+    }
+
+    /* create the new file */
+  #ifdef USE_ONLY_8DOT3
+    /* Here is another Windoze bug?:
+     * you cant rename("pubring.gpg.tmp", "pubring.gpg");
+     * but     rename("pubring.gpg.tmp", "pubring.aaa");
+     * works.  So we replace .gpg by .bak or .tmp
+     */
+    if( strlen(rentry->fname) > 4
+       && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) {
+       bakfname = gcry_xmalloc( strlen( rentry->fname ) + 1 );
+       strcpy(bakfname,rentry->fname);
+       strcpy(bakfname+strlen(rentry->fname)-4, ".bak");
+       tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 1 );
+       strcpy(tmpfname,rentry->fname);
+       strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp");
+    }
+    else { /* file does not end with gpg; hmmm */
+       bakfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
+       strcpy(stpcpy(bakfname,rentry->fname),".bak");
+       tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
+       strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
+    }
+  #else
+    bakfname = gcry_xmalloc( strlen( rentry->fname ) + 2 );
+    strcpy(stpcpy(bakfname,rentry->fname),"~");
+    tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 );
+    strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
+  #endif
+    newfp = iobuf_create( tmpfname );
+    if( !newfp ) {
+       log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
+       iobuf_close(fp);
+       rc = GPGERR_OPEN_FILE;
+       goto leave;
+    }
+
+    if( mode == 1 ) { /* insert */
+       /* copy everything to the new file */
+       rc = copy_all_packets( fp, newfp );
+       if( rc != -1 ) {
+           log_error("%s: copy to %s failed: %s\n",
+                     rentry->fname, tmpfname, gpg_errstr(rc) );
+           iobuf_close(fp);
+           iobuf_cancel(newfp);
+           goto leave;
+       }
+       rc = 0;
+    }
+
+    if( mode == 2 || mode == 3 ) { /* delete or update */
+       /* copy first part to the new file */
+       rc = copy_some_packets( fp, newfp, kbpos->offset );
+       if( rc ) { /* should never get EOF here */
+           log_error("%s: copy to %s failed: %s\n",
+                     rentry->fname, tmpfname, gpg_errstr(rc) );
+           iobuf_close(fp);
+           iobuf_cancel(newfp);
+           goto leave;
+       }
+       /* skip this keyblock */
+       assert( kbpos->count );
+       rc = skip_some_packets( fp, kbpos->count );
+       if( rc ) {
+           log_error("%s: skipping %u packets failed: %s\n",
+                           rentry->fname, kbpos->count, gpg_errstr(rc));
+           iobuf_close(fp);
+           iobuf_cancel(newfp);
+           goto leave;
+       }
+    }
+
+    if( mode == 1 || mode == 3 ) { /* insert or update */
+       KBNODE kbctx, node;
+
+       /* append the new data */
+       kbctx=NULL;
+       while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
+           if( (rc = build_packet( newfp, node->pkt )) ) {
+               log_error("build_packet(%d) failed: %s\n",
+                           node->pkt->pkttype, gpg_errstr(rc) );
+               iobuf_close(fp);
+               iobuf_cancel(newfp);
+               rc = GPGERR_WRITE_FILE;
+               goto leave;
+           }
+       }
+       kbpos->valid = 0;
+    }
+
+    if( mode == 2 || mode == 3 ) { /* delete or update */
+       /* copy the rest */
+       rc = copy_all_packets( fp, newfp );
+       if( rc != -1 ) {
+           log_error("%s: copy to %s failed: %s\n",
+                     rentry->fname, tmpfname, gpg_errstr(rc) );
+           iobuf_close(fp);
+           iobuf_cancel(newfp);
+           goto leave;
+       }
+       rc = 0;
+    }
+
+    /* close both files */
+    if( iobuf_close(fp) ) {
+       log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) );
+       rc = GPGERR_CLOSE_FILE;
+       goto leave;
+    }
+    if( iobuf_close(newfp) ) {
+       log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
+       rc = GPGERR_CLOSE_FILE;
+       goto leave;
+    }
+    /* if the new file is a secring, restrict the permissions */
+  #ifndef HAVE_DOSISH_SYSTEM
+    if( rentry->secret ) {
+       if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
+           log_error("%s: chmod failed: %s\n",
+                                   tmpfname, strerror(errno) );
+           rc = GPGERR_WRITE_FILE;
+           goto leave;
+       }
+    }
+  #endif
+
+    /* rename and make backup file */
+    if( !rentry->secret ) {  /* but not for secret keyrings */
+      #ifdef HAVE_DOSISH_SYSTEM
+       remove( bakfname );
+      #endif
+       if( rename( rentry->fname, bakfname ) ) {
+           log_error("%s: rename to %s failed: %s\n",
+                                   rentry->fname, bakfname, strerror(errno) );
+           rc = GPGERR_RENAME_FILE;
+           goto leave;
+       }
+    }
+  #ifdef HAVE_DOSISH_SYSTEM
+    remove( rentry->fname );
+  #endif
+    if( rename( tmpfname, rentry->fname ) ) {
+       log_error("%s: rename to %s failed: %s\n",
+                           tmpfname, rentry->fname,strerror(errno) );
+       rc = GPGERR_RENAME_FILE;
+       if( rentry->secret ) {
+           log_info(_(
+               "WARNING: 2 files with confidential information exists.\n"));
+           log_info(_("%s is the unchanged one\n"), rentry->fname );
+           log_info(_("%s is the new one\n"), tmpfname );
+           log_info(_("Please fix this possible security flaw\n"));
+       }
+       goto leave;
+    }
+
+  leave:
+    unlock_rentry( rentry );
+    gcry_free(bakfname);
+    gcry_free(tmpfname);
+    return rc;
+}
+
+
+\f
 #ifdef HAVE_LIBGDBM
 /****************************************************************
  ********** Functions which operates on GDM files ***************
diff --git a/scripts/db2html.in b/scripts/db2html.in
new file mode 100755 (executable)
index 0000000..ba35afb
--- /dev/null
@@ -0,0 +1,151 @@
+#!/bin/sh
+# db2html.in - Docbook to HTML rendering (wk 2000-02-15)
+#
+#      Copyright (C) 2000 Free Software Foundation
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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
+
+nosplit=no
+copyfiles=no
+stylesheet=@DSL_FOR_HTML@
+JADE=@JADE@
+
+usage () {
+    echo 'usage: db2html [--nosplit] [--copyfiles] filename' >&2
+    exit 1
+}
+
+
+while test "`echo $1 | head -c1`" = "-"; do
+    case $1 in
+      --version)
+       cat <<EOF
+db2html 0.5
+Copyright (C) 2000 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+stylesteet: $stylesheet
+EOF
+       exit 0
+       ;;
+      --help|-h|-help)
+       usage
+       ;;
+      --nosplit)
+       nosplit=yes
+       ;;
+      --copyfiles)
+       copyfiles=yes
+       ;;
+      --)
+       shift
+       break
+       ;;
+      *)
+       echo "invalid option $1" >&2
+       exit 1
+       ;;
+    esac
+    shift
+done
+
+if test $# = 1; then
+   input="$1"
+else
+   usage
+fi
+
+# grep the document type
+doctype=`grep -i '\<doctype' $input|awk 'NR==1 {print $2}'| tr '[A-Z]' '[a-z]'`
+if test -z $doctype; then
+    doctype=book
+    echo "no DOCTYPE found - assuming '$doctype'" >&2
+else
+    echo "DOCTYPE is '$doctype'" >&2
+fi
+
+output="`basename $input| sed 's/\.sgml$//'`.html"
+
+
+if test $nosplit = yes; then
+    echo "running jade on '$input' ..." >&2
+    $JADE -d $stylesheet -t sgml -i html -V nochunks $input > $output
+    echo "$output created"
+    exit 0
+fi
+
+if test -d html ; then
+    :
+else
+    if mkdir html; then
+       echo "'html' directory created" >&2
+    else
+       echo "failed to create 'html' directory" >&2
+       exit 1
+    fi
+fi
+
+outputdir="html/`basename $input| sed 's/\.sgml$//'`"
+
+if test -d $outputdir ; then
+    :
+else
+    if mkdir $outputdir; then
+       echo "'$outputdir' created" >&2
+    else
+       echo "failed to create '$outputdir'" >&2
+       exit 1
+    fi
+fi
+echo "creating html pages in '$outputdir' ..." >&2
+if test "$input" = "`basename $input`"; then
+    inp="../../$input"
+else
+    inp="$input"
+fi
+echo "running jade on '$inp' ..." >&2
+(cd $outputdir && $JADE -t sgml -i html -d $stylesheet $inp )
+echo "html version in '$outputdir' created" >&2
+
+# break out all filerefs and copy them to the outputdirectory
+# fixme: handling of path components is wrong
+if test $copyfiles = yes; then
+    echo "looking for filerefs ..." >&2
+    for file in `nsgmls -i html $input \
+                   | awk '/^AFILEREF[ \t]+CDATA/ {print $3}'`; do
+       d=$outputdir/`basename $file`
+       if cat $file > $outputdir/`basename $file` ; then
+           echo "  $file -> $d" >&2
+       fi
+    done
+fi
+
+mainfile=`ls $outputdir/${doctype}* | head -1`
+
+cat > $output <<EOF
+<html><title>$output</title>
+<body>
+
+<a href="$mainfile">$mainfile</a>
+
+</body>
+</html>
+EOF
+
+echo "$output created with link to '$mainfile'" >&2
+
+exit 0
+
index 92e008d..057f883 100644 (file)
@@ -2,8 +2,10 @@
 
 EXTRA_DIST = lspgpot
 INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
-needed_libs = ../gcrypt/libgcrypt.la \
-             ../util/libutil.la ../jnlib/libjnlib.la @INTLLIBS@
+# we need to add libutil.la a second time because we have to resolve
+# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon.
+needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la \
+             ../jnlib/libjnlib.la ../util/libutil.la @INTLLIBS@
 
 
 noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest