Fix comment.
[gpgme.git] / gpgme / conversion.c
index 32fc954..117df52 100644 (file)
@@ -1,6 +1,6 @@
 /* conversion.c - String conversion helper functions.
    Copyright (C) 2000 Werner Koch (dd9jn)
-   Copyright (C) 2001, 2002 g10 Code GmbH
+   Copyright (C) 2001, 2002, 2003 g10 Code GmbH
  
    This file is part of GPGME.
 
 #include <config.h>
 #endif
 
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/types.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "gpgme.h"
 #include "util.h"
 
-
+\f
+/* Convert two hexadecimal digits from STR to the value they
+   represent.  Returns -1 if one of the characters is not a
+   hexadecimal digit.  */
 int
-_gpgme_hextobyte (const byte *str)
+_gpgme_hextobyte (const unsigned char *str)
 {
   int val = 0;
   int i;
@@ -63,90 +63,168 @@ _gpgme_hextobyte (const byte *str)
    the result.  Currently, LEN is only used to specify if allocation
    is desired or not, the caller is expected to make sure that *DESTP
    is large enough if LEN is not zero.  */
-GpgmeError
+gpgme_error_t
 _gpgme_decode_c_string (const char *src, char **destp, int len)
 {
   char *dest;
 
+  /* Set up the destination buffer.  */
   if (len)
-    dest = *destp;
+    {
+      if (len < strlen (src) + 1)
+       return GPGME_General_Error;
+
+      dest = *destp;
+    }
   else
     {
-      /* We can malloc a buffer of the same length, because the converted
-        string will never be larger.  */
+      /* The converted string will never be larger than the original
+        string.  */
       dest = malloc (strlen (src) + 1);
       if (!dest)
-       return mk_error (Out_Of_Core);
+       return GPGME_Out_Of_Core;
 
       *destp = dest;
     }
 
+  /* Convert the string.  */
   while (*src)
     {
       if (*src != '\\')
-       *(dest++) = *(src++);
-      else if (src[1] == '\\')
-       {
-         src++;
-         *(dest++) = *(src++); 
-        }
-      else if (src[1] == 'n')
-       {
-         src += 2;
-         *(dest++) = '\n'; 
-        }
-      else if (src[1] == 'r')
        {
-         src += 2;
-         *(dest++) = '\r'; 
-        }
-      else if (src[1] == 'v')
-       {
-         src += 2;
-         *(dest++) = '\v'; 
-        }
-      else if (src[1] == 'b')
+         *(dest++) = *(src++);
+         continue;
+       }
+
+      switch (src[1])
        {
-         src += 2;
-         *(dest++) = '\b'; 
-        }
-      else if (src[1] == '0')
+#define DECODE_ONE(match,result)       \
+       case match:                     \
+         src += 2;                     \
+         *(dest++) = result;           \
+         break;
+
+         DECODE_ONE ('\'', '\'');
+         DECODE_ONE ('\"', '\"');
+         DECODE_ONE ('\?', '\?');
+         DECODE_ONE ('\\', '\\');
+         DECODE_ONE ('a', '\a');
+         DECODE_ONE ('b', '\b');
+         DECODE_ONE ('f', '\f');
+         DECODE_ONE ('n', '\n');
+         DECODE_ONE ('r', '\r');
+         DECODE_ONE ('t', '\t');
+         DECODE_ONE ('v', '\v');
+
+       case 'x':
+         {
+           int val = _gpgme_hextobyte (&src[2]);
+
+           if (val == -1)
+             {
+               /* Should not happen.  */
+               *(dest++) = *(src++);
+               *(dest++) = *(src++);
+               if (*src)
+                 *(dest++) = *(src++);
+               if (*src)
+                 *(dest++) = *(src++);
+             }
+           else
+             {
+               if (!val)
+                 {
+                   /* A binary zero is not representable in a C
+                      string.  */
+                   *(dest++) = '\\';
+                   *(dest++) = '0'; 
+                 }
+               else 
+                 *((unsigned char *) dest++) = val;
+               src += 4;
+             }
+         }
+         break;
+
+       default:
+         {
+           /* Should not happen.  */
+           *(dest++) = *(src++);
+           *(dest++) = *(src++);
+         }
+        } 
+    }
+  *(dest++) = 0;
+
+  return 0;
+}
+
+
+/* Decode the percent escaped string SRC and store the result in the
+   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
+   large enough buffer is allocated with malloc and *DESTP is set to
+   the result.  Currently, LEN is only used to specify if allocation
+   is desired or not, the caller is expected to make sure that *DESTP
+   is large enough if LEN is not zero.  */
+gpgme_error_t
+_gpgme_decode_percent_string (const char *src, char **destp, int len)
+{
+  char *dest;
+
+  /* Set up the destination buffer.  */
+  if (len)
+    {
+      if (len < strlen (src) + 1)
+       return GPGME_General_Error;
+
+      dest = *destp;
+    }
+  else
+    {
+      /* The converted string will never be larger than the original
+        string.  */
+      dest = malloc (strlen (src) + 1);
+      if (!dest)
+       return GPGME_Out_Of_Core;
+
+      *destp = dest;
+    }
+
+  /* Convert the string.  */
+  while (*src)
+    {
+      if (*src != '%')
        {
-         /* Hmmm: no way to express this */
-         src += 2;
-         *(dest++) = '\\';
-         *(dest++) = '\0'; 
-        }
-      else if (src[1] == 'x' && isxdigit (src[2]) && isxdigit (src[3]))
+         *(dest++) = *(src++);
+         continue;
+       }
+      else
        {
-         int val = _gpgme_hextobyte (&src[2]);
+         int val = _gpgme_hextobyte (&src[1]);
+         
          if (val == -1)
            {
              /* Should not happen.  */
              *(dest++) = *(src++);
-             *(dest++) = *(src++);
-             *(dest++) = *(src++);
-             *(dest++) = *(src++);
+             if (*src)
+               *(dest++) = *(src++);
+             if (*src)
+               *(dest++) = *(src++);
            }
          else
            {
              if (!val)
                {
+                 /* A binary zero is not representable in a C
+                    string.  */
                  *(dest++) = '\\';
-                 *(dest++) = '\0'; 
+                 *(dest++) = '0'; 
                }
              else 
-               *(byte*)dest++ = val;
-             src += 4;
+               *((unsigned char *) dest++) = val;
+             src += 3;
            }
-        }
-      else
-       {
-         /* should not happen */
-         src++;
-         *(dest++) = '\\'; 
-         *(dest++) = *(src++);
-        } 
+       }
     }
   *(dest++) = 0;
 
@@ -154,115 +232,101 @@ _gpgme_decode_c_string (const char *src, char **destp, int len)
 }
 
 \f
-GpgmeError
-_gpgme_data_append (GpgmeData dh, const char *buffer, size_t length)
+static struct
 {
-  if (!dh || !buffer)
-    return mk_error (Invalid_Value);
-
-  do
-    {
-      ssize_t amt = gpgme_data_write (dh, buffer, length);
-      if (amt == 0 || (amt < 0 && errno != EINTR))
-       return mk_error (File_Error);
-      buffer += amt;
-      length -= amt;
-    }
-  while (length > 0);
+  char *name;
+  gpgme_error_t err;
+} gnupg_errors[] =
+  {
+    { "EOF", GPGME_EOF },
+    { "No_Error", GPGME_No_Error },
+    { "General_Error", GPGME_General_Error },
+    { "Out_Of_Core", GPGME_Out_Of_Core },
+    { "Invalid_Value", GPGME_Invalid_Value },
+    { "IO_Error", GPGME_General_Error },
+    { "Resource_Limit", GPGME_General_Error },
+    { "Internal_Error", GPGME_General_Error },
+    { "Bad_Certificate", GPGME_Invalid_Key },
+    { "Bad_Certificate_Chain", GPGME_General_Error },
+    { "Missing_Certificate", GPGME_No_Public_Key },
+    { "No_Data", GPGME_No_Data },
+    { "Bad_Signature", GPGME_Bad_Signature },
+    { "Not_Implemented", GPGME_Not_Implemented },
+    { "Conflict", GPGME_Conflict },
+    { "Bug", GPGME_General_Error },
+    { "Read_Error", GPGME_General_Error },
+    { "Write_Error", GPGME_General_Error },
+    { "Invalid_Line", GPGME_General_Error },
+    { "Incomplete_Line", GPGME_General_Error },
+    { "Invalid_Response", GPGME_General_Error },
+    { "Agent_Error", GPGME_General_Error },
+    { "No_Public_Key", GPGME_No_Public_Key },
+    { "No_Secret_Key", GPGME_No_Secret_Key },
+    { "File_Open_Error", GPGME_General_Error },
+    { "File_Create_Error", GPGME_General_Error },
+    { "File_Error", GPGME_General_Error },
+    { "Not_Supported", GPGME_General_Error },
+    { "Invalid_Data", GPGME_General_Error },
+    { "Assuan_Server_Fault", GPGME_General_Error },
+    { "Assuan_Error", GPGME_General_Error },
+    { "Invalid_Session_Key", GPGME_General_Error },
+    { "Invalid_Sexp", GPGME_General_Error },
+    { "Unsupported_Algorithm", GPGME_Unsupported_Algorithm },
+    { "No_PIN_Entry", GPGME_Invalid_Engine },
+    { "PIN_Entry_Error", GPGME_Invalid_Engine },
+    { "Bad_PIN", GPGME_Bad_Passphrase },
+    { "Bad_Passphrase", GPGME_Bad_Passphrase },
+    { "Invalid_Name", GPGME_General_Error },
+    { "Bad_Public_Key", GPGME_General_Error },
+    { "Bad_Secret_Key", GPGME_General_Error },
+    { "Bad_Data", GPGME_General_Error },
+    { "Invalid_Parameter", GPGME_General_Error },
+    { "Tribute_to_D_A", GPGME_General_Error },
+    { "No_Dirmngr", GPGME_Invalid_Engine },
+    { "Dirmngr_Error", GPGME_General_Error },
+    { "Certificate_Revoked", GPGME_Key_Revoked },
+    { "No_CRL_Known", GPGME_No_CRL_Known },
+    { "CRL_Too_Old", GPGME_CRL_Too_Old },
+    { "Line_Too_Long", GPGME_General_Error },
+    { "Not_Trusted", GPGME_Key_Not_Trusted },
+    { "Canceled", GPGME_Canceled },
+    { "Bad_CA_Certificate", GPGME_General_Error },
+    { "Certificate_Expired", GPGME_Key_Expired },
+    { "Certificate_Too_Young", GPGME_Invalid_Key },
+    { "Unsupported_Certificate", GPGME_General_Error },
+    { "Unknown_Sexp", GPGME_General_Error },
+    { "Unsupported_Protection", GPGME_General_Error },
+    { "Corrupted_Protection", GPGME_General_Error },
+    { "Ambiguous_Name", GPGME_Ambiguous_Specification },
+    { "Card_Error", GPGME_General_Error },
+    { "Card_Reset", GPGME_General_Error },
+    { "Card_Removed", GPGME_General_Error },
+    { "Invalid_Card", GPGME_General_Error },
+    { "Card_Not_Present", GPGME_General_Error },
+    { "No_PKCS15_App", GPGME_General_Error },
+    { "Not_Confirmed", GPGME_General_Error },
+    { "Configuration_Error", GPGME_General_Error },
+    { "No_Policy_Match", GPGME_Policy_Mismatch },
+    { "Invalid_Index", GPGME_General_Error },
+    { "Invalid_Id", GPGME_General_Error },
+    { "No_Scdaemon", GPGME_Invalid_Engine },
+    { "Scdaemon_Error", GPGME_General_Error },
+    { "Unsupported_Protocol", GPGME_General_Error },
+    { "Bad_PIN_Method", GPGME_General_Error },
+    { "Card_Not_Initialized", GPGME_General_Error },
+    { "Unsupported_Operation", GPGME_General_Error },
+    { "Wrong_Key_Usage", GPGME_Wrong_Key_Usage }
+  };
+    
 
-  return 0;
-}
-
-
-GpgmeError
-_gpgme_data_append_string (GpgmeData dh, const char *str)
+gpgme_error_t
+_gpgme_map_gnupg_error (char *err)
 {
-  if (!str)
-    return 0;
-
-  return _gpgme_data_append (dh, str, strlen (str));
-}
-
-
-GpgmeError
-_gpgme_data_append_for_xml (GpgmeData dh, const char *buffer, size_t len)
-{
-  const char *text, *str;
-  size_t count;
-  int err = 0;
-
-  if (!dh || !buffer)
-    return mk_error (Invalid_Value);
-
-  do
-    {
-      text = NULL;
-      str = buffer;
-      for (count = len; count && !text; str++, count--)
-        {
-          if (*str == '<')
-            text = "&lt;";
-          else if (*str == '>')
-            text = "&gt;";  /* Not sure whether this is really needed.  */
-          else if (*str == '&')
-            text = "&amp;";
-          else if (!*str)
-            text = "&#00;";
-        }
-      if (text)
-        {
-          str--;
-          count++;
-        }
-      if (str != buffer)
-        err = _gpgme_data_append (dh, buffer, str - buffer);
-      if (!err && text)
-        {
-          err = _gpgme_data_append_string (dh, text);
-          str++;
-          count--;
-        }
-      buffer = str;
-      len = count;
-    }
-  while (!err && len);
-  return err;
-}
-
-
-/* Append a string to DATA and convert it so that the result will be
-   valid XML.  */
-GpgmeError
-_gpgme_data_append_string_for_xml (GpgmeData dh, const char *str)
-{
-  return _gpgme_data_append_for_xml (dh, str, strlen (str));
-}
-
-
-/* Append a string with percent style (%XX) escape characters as
-   XML.  */
-GpgmeError
-_gpgme_data_append_percentstring_for_xml (GpgmeData dh, const char *str)
-{
-  const byte *src;
-  byte *buf, *dst;
-  int val;
-  GpgmeError err;
+  int i;
 
-  buf = malloc (strlen (str));
-  dst = buf;
-  for (src = str; *src; src++)
-    {
-      if (*src == '%' && (val = _gpgme_hextobyte (src + 1)) != -1)
-        {
-          *dst++ = val;
-          src += 2;
-        }
-      else
-        *dst++ = *src;
-    }
+  for (i = 0; i < DIM (gnupg_errors); i++)
+    if (!strcmp (gnupg_errors[i].name, err))
+      return gnupg_errors[i].err;
 
-  err = _gpgme_data_append_for_xml (dh, buf, dst - buf);
-  free (buf);
-  return err;
+  return GPGME_General_Error;
 }