doc: Fix documentation of struct data types
[gpgme.git] / src / conversion.c
index 45513f6..b47d6de 100644 (file)
@@ -1,19 +1,19 @@
 /* conversion.c - String conversion helper functions.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2007 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 Lesser General Public License as
    published by the Free Software Foundation; either version 2.1 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
    Lesser General Public License for more details.
-   
+
    You should have received a copy of the GNU Lesser General Public
    License along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 #include <stdlib.h>
 #include <string.h>
-/* Solaris 8 needs sys/types.h before time.h.  */
-#include <sys/types.h>
+#ifdef HAVE_SYS_TYPES_H
+  /* Solaris 8 needs sys/types.h before time.h.  */
+# include <sys/types.h>
+#endif
 #include <time.h>
 #include <errno.h>
 
@@ -93,7 +95,7 @@ _gpgme_decode_c_string (const char *src, char **destp, size_t len)
         string.  */
       dest = malloc (strlen (src) + 1);
       if (!dest)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
 
       *destp = dest;
     }
@@ -148,9 +150,9 @@ _gpgme_decode_c_string (const char *src, char **destp, size_t len)
                    /* A binary zero is not representable in a C
                       string.  */
                    *(dest++) = '\\';
-                   *(dest++) = '0'; 
+                   *(dest++) = '0';
                  }
-               else 
+               else
                  *((unsigned char *) dest++) = val;
                src += 4;
              }
@@ -163,7 +165,7 @@ _gpgme_decode_c_string (const char *src, char **destp, size_t len)
            *(dest++) = *(src++);
            *(dest++) = *(src++);
          }
-        } 
+        }
     }
   *(dest++) = 0;
 
@@ -198,7 +200,7 @@ _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
         string.  */
       dest = malloc (strlen (src) + 1);
       if (!dest)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
 
       *destp = dest;
     }
@@ -214,7 +216,7 @@ _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
       else
        {
          int val = _gpgme_hextobyte (&src[1]);
-         
+
          if (val == -1)
            {
              /* Should not happen.  */
@@ -231,9 +233,9 @@ _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
                  /* A binary zero is not representable in a C
                     string.  */
                  *(dest++) = '\\';
-                 *(dest++) = '0'; 
+                 *(dest++) = '0';
                }
-             else 
+             else
                *((unsigned char *) dest++) = val;
              src += 3;
            }
@@ -267,11 +269,12 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
      the special plus format.  */
   while (*str)
     {
-      if (*str == '+' || *str == '\"' || *str == '%' 
+      if (*str == '+' || *str == '\"' || *str == '%'
           || *(const unsigned char *)str <= 0x20)
         destlen += 3;
       else
         destlen++;
+      str++;
     }
   /* Terminating nul byte.  */
   destlen++;
@@ -279,7 +282,7 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
   /* Set up the destination buffer.  */
   if (len)
     {
-      if (len < destlen);
+      if (len < destlen)
        return gpg_error (GPG_ERR_INTERNAL);
 
       dest = *destp;
@@ -290,7 +293,7 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
         string.  */
       dest = malloc (destlen);
       if (!dest)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
 
       *destp = dest;
     }
@@ -298,7 +301,7 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
   /* Convert the string.  */
   while (*src)
     {
-      if (*src == '+' || *src == '\"' || *src == '%' 
+      if (*src == '+' || *src == '\"' || *src == '%'
           || *(const unsigned char *)src <= 0x20)
         {
           snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
@@ -314,6 +317,39 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
 }
 
 
+#ifdef HAVE_W32_SYSTEM
+static time_t
+_gpgme_timegm (struct tm *tm)
+{
+  /* This one is thread safe.  */
+  SYSTEMTIME st;
+  FILETIME ft;
+  unsigned long long cnsecs;
+
+  st.wYear   = tm->tm_year + 1900;
+  st.wMonth  = tm->tm_mon  + 1;
+  st.wDay    = tm->tm_mday;
+  st.wHour   = tm->tm_hour;
+  st.wMinute = tm->tm_min;
+  st.wSecond = tm->tm_sec;
+  st.wMilliseconds = 0; /* Not available.  */
+  st.wDayOfWeek = 0;    /* Ignored.  */
+
+  /* System time is UTC thus the conversion is pretty easy.  */
+  if (!SystemTimeToFileTime (&st, &ft))
+    {
+      gpg_err_set_errno (EINVAL);
+      return (time_t)(-1);
+    }
+
+  cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
+           | ft.dwLowDateTime);
+  cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
+  return (time_t)(cnsecs / 10000000ULL);
+}
+#endif
+
+
 /* Parse the string TIMESTAMP into a time_t.  The string may either be
    seconds since Epoch or in the ISO 8601 format like
    "20390815T143012".  Returns 0 for an empty string or seconds since
@@ -338,6 +374,9 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp)
       if (year < 1900)
         return (time_t)(-1);
 
+      if (endp)
+        *endp = (char*)(timestamp + 15);
+
       /* Fixme: We would better use a configure test to see whether
          mktime can handle dates beyond 2038. */
       if (sizeof (time_t) <= 4 && year >= 2038)
@@ -345,20 +384,21 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp)
 
       memset (&buf, 0, sizeof buf);
       buf.tm_year = year - 1900;
-      buf.tm_mon = atoi_2 (timestamp+4) - 1; 
+      buf.tm_mon = atoi_2 (timestamp+4) - 1;
       buf.tm_mday = atoi_2 (timestamp+6);
       buf.tm_hour = atoi_2 (timestamp+9);
       buf.tm_min = atoi_2 (timestamp+11);
       buf.tm_sec = atoi_2 (timestamp+13);
 
-      if (endp)
-        *endp = (char*)(timestamp + 15);
+#ifdef HAVE_W32_SYSTEM
+      return _gpgme_timegm (&buf);
+#else
 #ifdef HAVE_TIMEGM
       return timegm (&buf);
 #else
       {
         time_t tim;
-        
+
         putenv ("TZ=UTC");
         tim = mktime (&buf);
 #ifdef __GNUC__
@@ -367,6 +407,7 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp)
         return tim;
       }
 #endif /* !HAVE_TIMEGM */
+#endif /* !HAVE_W32_SYSTEM */
     }
   else
     return (time_t)strtoul (timestamp, endp, 10);