gpgme/
authorMarcus Brinkmann <mb@g10code.com>
Fri, 14 Dec 2001 00:49:38 +0000 (00:49 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Fri, 14 Dec 2001 00:49:38 +0000 (00:49 +0000)
2001-12-14  Marcus Brinkmann  <marcus@g10code.de>

* engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic.
(_gpgme_gpgsm_new): Initialize some more members.
(_gpgme_gpgsm_release): Free the colon line handler's attic line.
(gpgsm_status_handler): Rework the inline-data processing.

tests/
2001-12-14  Marcus Brinkmann  <marcus@g10code.de>

* gpgsm/t-keylist.c: New file.
* gpgsm/Makefile.am (TESTS): Add t-keylist.

gpgme/ChangeLog
gpgme/engine-gpgsm.c
tests/ChangeLog
tests/gpgsm/Makefile.am
tests/gpgsm/t-keylist.c [new file with mode: 0644]

index 569005f..00449dc 100644 (file)
@@ -1,3 +1,10 @@
+2001-12-14  Marcus Brinkmann  <marcus@g10code.de>
+
+       * engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic.
+       (_gpgme_gpgsm_new): Initialize some more members.
+       (_gpgme_gpgsm_release): Free the colon line handler's attic line.
+       (gpgsm_status_handler): Rework the inline-data processing.
+
 2001-12-13  Marcus Brinkmann  <marcus@g10code.de>
 
        * rungpg.c (_gpgme_gpg_spawn): Do not add the fds to the child
        * engine-gpgsm.c (_gpgme_gpgsm_op_decrypt): New function.
        (_gpgme_gpgsm_op_import): Likewise.
 
-2001-11-22  Marcus Brinkmann  <marcus@gnu.org>
+2001-11-22  Marcus Brinkmann  <marcus@g10code.de>
 
        * engine-gpgsm.c: Shuffle around header inclusion a bit, to still
        keep them seperate.
index 887e9ef..456de4f 100644 (file)
@@ -83,8 +83,13 @@ struct gpgsm_object_s
   {
     GpgColonLineHandler fnc;
     void *fnc_value;
-  } colon;
-  
+    struct
+    {
+      unsigned char *line;
+      int linesize;
+      int linelen;
+    } attic;
+  } colon; 
 };
 
 const char *
@@ -144,6 +149,12 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
   gpgsm->message_fd = -1;
   gpgsm->message_fd_server = -1;
 
+  gpgsm->status.fnc = 0;
+  gpgsm->colon.fnc = 0;
+  gpgsm->colon.attic.line = 0;
+  gpgsm->colon.attic.linesize = 0;
+  gpgsm->colon.attic.linelen = 0;
+
   if (_gpgme_io_pipe (fds, 0) < 0)
     {
       err = mk_error (General_Error);
@@ -222,6 +233,7 @@ _gpgme_gpgsm_release (GpgsmObject gpgsm)
 
   assuan_pipe_disconnect (gpgsm->assuan_ctx);
 
+  xfree (gpgsm->colon.attic.line);
   xfree (gpgsm->command);
   xfree (gpgsm);
 }
@@ -529,36 +541,66 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
 
       if (linelen > 2
          && line[0] == 'D' && line[1] == ' '
-          && gpgsm->colon.fnc )
+          && gpgsm->colon.fnc)
         {
-          unsigned char *s, *d;
-
-          line += 2;
-          linelen -= 2;
-          /* Hmmm, we are using the colon handler even for plain
-             inline data - strange name for that fucntion but for
-             historic reasons we keep it */
-          for (s=d=line; linelen; linelen--)
+         /* We are using the colon handler even for plain inline data
+             - strange name for that function but for historic reasons
+             we keep it.  */
+          /* FIXME We can't use this for binary data because we
+             assume this is a string.  For the current usage of colon
+             output it is correct.  */
+          unsigned char *src = line + 2;
+         unsigned char *end = line + linelen;
+         unsigned char *dst;
+          unsigned char **aline = &gpgsm->colon.attic.line;
+         int *alinelen = &gpgsm->colon.attic.linelen;
+
+         if (gpgsm->colon.attic.linesize
+             < *alinelen + linelen + 1)
+           {
+             unsigned char *newline = xtryrealloc (*aline,
+                                                   *alinelen + linelen + 1);
+             if (!newline)
+               return mk_error (Out_Of_Core);
+             *aline = newline;
+             gpgsm->colon.attic.linesize += linelen + 1;
+           }
+
+         dst = *aline + *alinelen;
+
+          while (src < end)
             {
-              if (*s == '%' && linelen > 2)
-                { /* handle escaping */
-                  s++;
-                  *d++ = xtoi_2 (s);
-                  s += 2;
-                  linelen -= 2;
+              if (*src == '%' && src + 2 < end)
+                {
+                 /* Handle escaped characters.  */
+                 ++src;
+                  *dst = xtoi_2 (src);
+                 (*alinelen)++;
+                  src += 2;
                 }
               else
-                *d++ = *s++;
+               {
+                 *dst = *src++;
+                 (*alinelen)++;
+               }
+
+             if (*dst == '\n')
+               {
+                 /* Terminate the pending line, pass it to the colon
+                    handler and reset it.  */
+
+                 if (*alinelen > 1 && *(dst - 1) == '\r')
+                   dst--;
+                 *dst = '\0';
+
+                 /* FIXME How should we handle the return code? */
+                 gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
+                 dst = *aline;
+                 *alinelen = 0;
+               }
+             else
+               dst++;
             }
-          *d = 0; /* add a hidden string terminator */
-
-          /* fixme: should we handle the return code? */
-          /* fixme: Hmmm: we can't use this for binary data because we
-             assume this is a string.  For the current usage of colon
-             output it is correct */
-          /* FIXME: we need extra bufferring to pass colon lines line
-             by line */
-          gpgsm->colon.fnc (gpgsm->colon.fnc_value, line);
         }
       else if (linelen > 2
          && line[0] == 'S' && line[1] == ' ')
index 897885a..fa8712a 100644 (file)
@@ -1,3 +1,8 @@
+2001-12-14  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgsm/t-keylist.c: New file.
+       * gpgsm/Makefile.am (TESTS): Add t-keylist.
+
 2001-12-13  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgsm/cert_dfn_pca01.der: New file.
index 89d5467..bf724fb 100644 (file)
@@ -22,7 +22,7 @@
 
 TESTS_ENVIRONMENT = GNUPGHOME=.
 
-TESTS = t-import
+TESTS = t-import t-keylist
 
 EXTRA_DIST = cert_dfn_pca01.der cert_dfn_pca15.der cert_g10code_test1.der
 
diff --git a/tests/gpgsm/t-keylist.c b/tests/gpgsm/t-keylist.c
new file mode 100644 (file)
index 0000000..9ead110
--- /dev/null
@@ -0,0 +1,160 @@
+/* t-keylist.c  - regression test
+ *     Copyright (C) 2000 Werner Koch (dd9jn)
+ *      Copyright (C) 2001 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME 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.
+ *
+ * GPGME 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gpgme.h>
+
+#define fail_if_err(a) do { if(a) {                                       \
+                               fprintf (stderr, "%s:%d: GpgmeError %s\n", \
+                                __FILE__, __LINE__, gpgme_strerror(a));   \
+                                exit (1); }                               \
+                             } while(0)
+
+static void
+doit ( GpgmeCtx ctx, const char *pattern )
+{
+    GpgmeError err;
+    GpgmeKey key;
+
+    err = gpgme_op_keylist_start (ctx, pattern, 0 );
+    fail_if_err (err);
+    
+    while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
+        char *p;
+        const char *s;
+        int i;
+
+        printf ("<!-- Begin key object (%p) -->\n", key );
+        p = gpgme_key_get_as_xml ( key );
+        if ( p ) {
+            fputs ( p, stdout );
+            free (p);
+        }
+        else
+            fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout );
+
+        
+        for (i=0; ; i++ ) {
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i );
+            if (!s)
+                break;
+            printf ("<!-- keyid.%d=%s -->\n", i, s );
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i );
+            printf ("<!-- algo.%d=%s -->\n", i, s );
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i );
+            printf ("<!-- caps.%d=%s -->\n", i, s );
+        }
+        for (i=0; ; i++ ) {
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i );
+            if (!s)
+                break;
+            printf ("<!-- name.%d=%s -->\n", i, s );
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i );
+            printf ("<!-- email.%d=%s -->\n", i, s );
+            s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i );
+            printf ("<!-- comment.%d=%s -->\n", i, s );
+        }
+        
+        fputs ("<!-- usable for:", stdout );
+        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_ENCRYPT, NULL, 0 ))
+            fputs (" encryption", stdout);
+        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_SIGN, NULL, 0 ))
+            fputs (" signing", stdout);
+        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_CERTIFY, NULL, 0 ))
+            fputs (" certification", stdout);
+        fputs (" -->\n", stdout );
+
+        printf ("<!-- End key object (%p) -->\n", key );
+        gpgme_key_release (key);
+    }
+    if ( err != GPGME_EOF )
+        fail_if_err (err);
+}
+
+
+/* 
+ * Check that there are no problems when we are using two context for
+ * listing keys. 
+ */
+static void
+check_two_contexts (void)
+{
+    GpgmeError err;
+    GpgmeCtx ctx1, ctx2;
+    GpgmeKey key;
+       
+    err = gpgme_new(&ctx1); fail_if_err (err);
+    err = gpgme_op_keylist_start(ctx1, "", 1); fail_if_err (err);
+    err = gpgme_new(&ctx2); fail_if_err (err);
+    err = gpgme_op_keylist_start(ctx2, "", 1); fail_if_err (err);
+
+    while ( (err=gpgme_op_keylist_next(ctx2, &key)) != GPGME_EOF) {
+        gpgme_key_release (key);
+    }
+    if (err != GPGME_EOF)
+        fail_if_err (err);
+    while ( (err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF) {
+        gpgme_key_release (key);
+    }
+    if (err != GPGME_EOF)
+        fail_if_err (err);
+}
+
+int 
+main (int argc, char **argv )
+{
+    GpgmeCtx ctx;
+    GpgmeError err;
+    int loop = 0;
+    const char *pattern;
+    
+    if( argc ) {
+        argc--; argv++;
+    }
+    
+    if (argc && !strcmp( *argv, "--loop" ) ) {
+        loop = 1;
+        argc--; argv++;
+    }
+    pattern = argc? *argv : NULL;
+
+    err = gpgme_check_engine();
+    fail_if_err (err);
+
+    err = gpgme_new (&ctx);
+    fail_if_err (err);
+    gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+
+    gpgme_set_keylist_mode (ctx, 1); /* no validity calculation */
+    do {
+        fprintf (stderr, "** pattern=`%s'\n", pattern );
+        doit ( ctx, pattern );
+    } while ( loop );
+    gpgme_release (ctx);
+
+    check_two_contexts ();
+
+    return 0;
+}