Blame src/conversion.c

Packit d7e8d0
/* conversion.c - String conversion helper functions.
Packit Service 30b792
 * Copyright (C) 2000 Werner Koch (dd9jn)
Packit Service 30b792
 * Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
Packit Service 30b792
 *
Packit Service 30b792
 * This file is part of GPGME.
Packit Service 30b792
 *
Packit Service 30b792
 * GPGME is free software; you can redistribute it and/or modify it
Packit Service 30b792
 * under the terms of the GNU Lesser General Public License as
Packit Service 30b792
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 30b792
 * the License, or (at your option) any later version.
Packit Service 30b792
 *
Packit Service 30b792
 * GPGME is distributed in the hope that it will be useful, but
Packit Service 30b792
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 30b792
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 30b792
 * Lesser General Public License for more details.
Packit Service 30b792
 *
Packit Service 30b792
 * You should have received a copy of the GNU Lesser General Public
Packit Service 30b792
 * License along with this program; if not, see <https://gnu.org/licenses/>.
Packit Service 30b792
 * SPDX-License-Identifier: LGPL-2.1-or-later
Packit Service 30b792
 */
Packit d7e8d0
Packit d7e8d0
#if HAVE_CONFIG_H
Packit d7e8d0
#include <config.h>
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include <stdlib.h>
Packit d7e8d0
#include <string.h>
Packit d7e8d0
#ifdef HAVE_SYS_TYPES_H
Packit d7e8d0
  /* Solaris 8 needs sys/types.h before time.h.  */
Packit d7e8d0
# include <sys/types.h>
Packit d7e8d0
#endif
Packit d7e8d0
#include <time.h>
Packit d7e8d0
#include <errno.h>
Packit d7e8d0
#include <stdarg.h>
Packit d7e8d0
Packit d7e8d0
#include "gpgme.h"
Packit d7e8d0
#include "util.h"
Packit d7e8d0
#include "debug.h"
Packit d7e8d0
Packit d7e8d0
#define atoi_1(p)   (*(p) - '0' )
Packit d7e8d0
#define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
Packit d7e8d0
#define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
static char *
Packit d7e8d0
do_strconcat (const char *s1, va_list arg_ptr)
Packit d7e8d0
{
Packit d7e8d0
  const char *argv[16];
Packit d7e8d0
  size_t argc;
Packit d7e8d0
  size_t needed;
Packit d7e8d0
  char *buffer, *p;
Packit d7e8d0
Packit d7e8d0
  argc = 0;
Packit d7e8d0
  argv[argc++] = s1;
Packit d7e8d0
  needed = strlen (s1);
Packit d7e8d0
  while (((argv[argc] = va_arg (arg_ptr, const char *))))
Packit d7e8d0
    {
Packit d7e8d0
      needed += strlen (argv[argc]);
Packit d7e8d0
      if (argc >= DIM (argv)-1)
Packit d7e8d0
        {
Packit d7e8d0
          gpg_err_set_errno (EINVAL);
Packit d7e8d0
          return NULL;
Packit d7e8d0
        }
Packit d7e8d0
      argc++;
Packit d7e8d0
    }
Packit d7e8d0
  needed++;
Packit d7e8d0
  buffer = malloc (needed);
Packit d7e8d0
  if (buffer)
Packit d7e8d0
    {
Packit d7e8d0
      for (p = buffer, argc=0; argv[argc]; argc++)
Packit d7e8d0
        p = stpcpy (p, argv[argc]);
Packit d7e8d0
    }
Packit d7e8d0
  return buffer;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Concatenate the string S1 with all the following strings up to a
Packit d7e8d0
 * NULL.  Returns a malloced buffer with the new string or NULL on a
Packit d7e8d0
   malloc error or if too many arguments are given.  */
Packit d7e8d0
char *
Packit d7e8d0
_gpgme_strconcat (const char *s1, ...)
Packit d7e8d0
{
Packit d7e8d0
  va_list arg_ptr;
Packit d7e8d0
  char *result;
Packit d7e8d0
Packit d7e8d0
  if (!s1)
Packit d7e8d0
    result = strdup ("");
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      va_start (arg_ptr, s1);
Packit d7e8d0
      result = do_strconcat (s1, arg_ptr);
Packit d7e8d0
      va_end (arg_ptr);
Packit d7e8d0
    }
Packit d7e8d0
  return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
/* Convert two hexadecimal digits from STR to the value they
Packit d7e8d0
   represent.  Returns -1 if one of the characters is not a
Packit d7e8d0
   hexadecimal digit.  */
Packit d7e8d0
int
Packit d7e8d0
_gpgme_hextobyte (const char *str)
Packit d7e8d0
{
Packit d7e8d0
  int val = 0;
Packit d7e8d0
  int i;
Packit d7e8d0
Packit d7e8d0
#define NROFHEXDIGITS 2
Packit d7e8d0
  for (i = 0; i < NROFHEXDIGITS; i++)
Packit d7e8d0
    {
Packit d7e8d0
      if (*str >= '0' && *str <= '9')
Packit d7e8d0
	val += *str - '0';
Packit d7e8d0
      else if (*str >= 'A' && *str <= 'F')
Packit d7e8d0
	val += 10 + *str - 'A';
Packit d7e8d0
      else if (*str >= 'a' && *str <= 'f')
Packit d7e8d0
	val += 10 + *str - 'a';
Packit d7e8d0
      else
Packit d7e8d0
	return -1;
Packit d7e8d0
      if (i < NROFHEXDIGITS - 1)
Packit d7e8d0
	val *= 16;
Packit d7e8d0
      str++;
Packit d7e8d0
    }
Packit d7e8d0
  return val;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Decode the C formatted string SRC and store the result in the
Packit d7e8d0
   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
Packit d7e8d0
   large enough buffer is allocated with malloc and *DESTP is set to
Packit d7e8d0
   the result.  Currently, LEN is only used to specify if allocation
Packit d7e8d0
   is desired or not, the caller is expected to make sure that *DESTP
Packit d7e8d0
   is large enough if LEN is not zero.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpgme_decode_c_string (const char *src, char **destp, size_t len)
Packit d7e8d0
{
Packit d7e8d0
  char *dest;
Packit d7e8d0
Packit d7e8d0
  /* Set up the destination buffer.  */
Packit d7e8d0
  if (len)
Packit d7e8d0
    {
Packit d7e8d0
      if (len < strlen (src) + 1)
Packit d7e8d0
	return gpg_error (GPG_ERR_INTERNAL);
Packit d7e8d0
Packit d7e8d0
      dest = *destp;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      /* The converted string will never be larger than the original
Packit d7e8d0
	 string.  */
Packit d7e8d0
      dest = malloc (strlen (src) + 1);
Packit d7e8d0
      if (!dest)
Packit d7e8d0
	return gpg_error_from_syserror ();
Packit d7e8d0
Packit d7e8d0
      *destp = dest;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* Convert the string.  */
Packit d7e8d0
  while (*src)
Packit d7e8d0
    {
Packit d7e8d0
      if (*src != '\\')
Packit d7e8d0
	{
Packit d7e8d0
	  *(dest++) = *(src++);
Packit d7e8d0
	  continue;
Packit d7e8d0
	}
Packit d7e8d0
Packit d7e8d0
      switch (src[1])
Packit d7e8d0
	{
Packit d7e8d0
#define DECODE_ONE(match,result)	\
Packit d7e8d0
	case match:			\
Packit d7e8d0
	  src += 2;			\
Packit d7e8d0
	  *(dest++) = result;		\
Packit d7e8d0
	  break;
Packit d7e8d0
Packit d7e8d0
	  DECODE_ONE ('\'', '\'');
Packit d7e8d0
	  DECODE_ONE ('\"', '\"');
Packit d7e8d0
	  DECODE_ONE ('\?', '\?');
Packit d7e8d0
	  DECODE_ONE ('\\', '\\');
Packit d7e8d0
	  DECODE_ONE ('a', '\a');
Packit d7e8d0
	  DECODE_ONE ('b', '\b');
Packit d7e8d0
	  DECODE_ONE ('f', '\f');
Packit d7e8d0
	  DECODE_ONE ('n', '\n');
Packit d7e8d0
	  DECODE_ONE ('r', '\r');
Packit d7e8d0
	  DECODE_ONE ('t', '\t');
Packit d7e8d0
	  DECODE_ONE ('v', '\v');
Packit d7e8d0
Packit d7e8d0
	case 'x':
Packit d7e8d0
	  {
Packit d7e8d0
	    int val = _gpgme_hextobyte (&src[2]);
Packit d7e8d0
Packit d7e8d0
	    if (val == -1)
Packit d7e8d0
	      {
Packit d7e8d0
		/* Should not happen.  */
Packit d7e8d0
		*(dest++) = *(src++);
Packit d7e8d0
		*(dest++) = *(src++);
Packit d7e8d0
		if (*src)
Packit d7e8d0
		  *(dest++) = *(src++);
Packit d7e8d0
		if (*src)
Packit d7e8d0
		  *(dest++) = *(src++);
Packit d7e8d0
	      }
Packit d7e8d0
	    else
Packit d7e8d0
	      {
Packit d7e8d0
		if (!val)
Packit d7e8d0
		  {
Packit d7e8d0
		    /* A binary zero is not representable in a C
Packit d7e8d0
		       string.  */
Packit d7e8d0
		    *(dest++) = '\\';
Packit d7e8d0
		    *(dest++) = '0';
Packit d7e8d0
		  }
Packit d7e8d0
		else
Packit d7e8d0
		  *((unsigned char *) dest++) = val;
Packit d7e8d0
		src += 4;
Packit d7e8d0
	      }
Packit d7e8d0
	  }
Packit d7e8d0
	  break;
Packit d7e8d0
Packit d7e8d0
	default:
Packit d7e8d0
	  {
Packit d7e8d0
	    /* Should not happen.  */
Packit d7e8d0
	    *(dest++) = *(src++);
Packit d7e8d0
	    *(dest++) = *(src++);
Packit d7e8d0
	  }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
  *(dest++) = 0;
Packit d7e8d0
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Decode the percent escaped string SRC and store the result in the
Packit d7e8d0
   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
Packit d7e8d0
   large enough buffer is allocated with malloc and *DESTP is set to
Packit d7e8d0
   the result.  Currently, LEN is only used to specify if allocation
Packit d7e8d0
   is desired or not, the caller is expected to make sure that *DESTP
Packit d7e8d0
   is large enough if LEN is not zero.  If BINARY is 1, then '\0'
Packit d7e8d0
   characters are allowed in the output.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpgme_decode_percent_string (const char *src, char **destp, size_t len,
Packit d7e8d0
			      int binary)
Packit d7e8d0
{
Packit d7e8d0
  char *dest;
Packit d7e8d0
Packit d7e8d0
  /* Set up the destination buffer.  */
Packit d7e8d0
  if (len)
Packit d7e8d0
    {
Packit d7e8d0
      if (len < strlen (src) + 1)
Packit d7e8d0
	return gpg_error (GPG_ERR_INTERNAL);
Packit d7e8d0
Packit d7e8d0
      dest = *destp;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      /* The converted string will never be larger than the original
Packit d7e8d0
	 string.  */
Packit d7e8d0
      dest = malloc (strlen (src) + 1);
Packit d7e8d0
      if (!dest)
Packit d7e8d0
	return gpg_error_from_syserror ();
Packit d7e8d0
Packit d7e8d0
      *destp = dest;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* Convert the string.  */
Packit d7e8d0
  while (*src)
Packit d7e8d0
    {
Packit d7e8d0
      if (*src != '%')
Packit d7e8d0
	{
Packit d7e8d0
	  *(dest++) = *(src++);
Packit d7e8d0
	  continue;
Packit d7e8d0
	}
Packit d7e8d0
      else
Packit d7e8d0
	{
Packit d7e8d0
	  int val = _gpgme_hextobyte (&src[1]);
Packit d7e8d0
Packit d7e8d0
	  if (val == -1)
Packit d7e8d0
	    {
Packit d7e8d0
	      /* Should not happen.  */
Packit d7e8d0
	      *(dest++) = *(src++);
Packit d7e8d0
	      if (*src)
Packit d7e8d0
		*(dest++) = *(src++);
Packit d7e8d0
	      if (*src)
Packit d7e8d0
		*(dest++) = *(src++);
Packit d7e8d0
	    }
Packit d7e8d0
	  else
Packit d7e8d0
	    {
Packit d7e8d0
	      if (!val && !binary)
Packit d7e8d0
		{
Packit d7e8d0
		  /* A binary zero is not representable in a C
Packit d7e8d0
		     string.  */
Packit d7e8d0
		  *(dest++) = '\\';
Packit d7e8d0
		  *(dest++) = '0';
Packit d7e8d0
		}
Packit d7e8d0
	      else
Packit d7e8d0
		*((unsigned char *) dest++) = val;
Packit d7e8d0
	      src += 3;
Packit d7e8d0
	    }
Packit d7e8d0
	}
Packit d7e8d0
    }
Packit d7e8d0
  *(dest++) = 0;
Packit d7e8d0
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Encode the string SRC with percent escaping and store the result in
Packit d7e8d0
   the buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
Packit d7e8d0
   large enough buffer is allocated with malloc and *DESTP is set to
Packit d7e8d0
   the result.  Currently, LEN is only used to specify if allocation
Packit d7e8d0
   is desired or not, the caller is expected to make sure that *DESTP
Packit d7e8d0
   is large enough if LEN is not zero.  If BINARY is 1, then '\0'
Packit d7e8d0
   characters are allowed in the output.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpgme_encode_percent_string (const char *src, char **destp, size_t len)
Packit d7e8d0
{
Packit d7e8d0
  size_t destlen;
Packit d7e8d0
  char *dest;
Packit d7e8d0
  const char *str;
Packit d7e8d0
Packit d7e8d0
  destlen = 0;
Packit d7e8d0
  str = src;
Packit d7e8d0
  /* We percent-escape the + character because the user might need a
Packit d7e8d0
     "percent plus" escaped string (special gpg format).  But we
Packit d7e8d0
     percent-escape the space character, which works with and without
Packit d7e8d0
     the special plus format.  */
Packit d7e8d0
  while (*str)
Packit d7e8d0
    {
Packit d7e8d0
      if (*str == '+' || *str == '\"' || *str == '%'
Packit d7e8d0
          || *(const unsigned char *)str <= 0x20)
Packit d7e8d0
        destlen += 3;
Packit d7e8d0
      else
Packit d7e8d0
        destlen++;
Packit d7e8d0
      str++;
Packit d7e8d0
    }
Packit d7e8d0
  /* Terminating nul byte.  */
Packit d7e8d0
  destlen++;
Packit d7e8d0
Packit d7e8d0
  /* Set up the destination buffer.  */
Packit d7e8d0
  if (len)
Packit d7e8d0
    {
Packit d7e8d0
      if (len < destlen)
Packit d7e8d0
	return gpg_error (GPG_ERR_INTERNAL);
Packit d7e8d0
Packit d7e8d0
      dest = *destp;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      /* The converted string will never be larger than the original
Packit d7e8d0
	 string.  */
Packit d7e8d0
      dest = malloc (destlen);
Packit d7e8d0
      if (!dest)
Packit d7e8d0
	return gpg_error_from_syserror ();
Packit d7e8d0
Packit d7e8d0
      *destp = dest;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* Convert the string.  */
Packit d7e8d0
  while (*src)
Packit d7e8d0
    {
Packit d7e8d0
      if (*src == '+' || *src == '\"' || *src == '%'
Packit d7e8d0
          || *(const unsigned char *)src <= 0x20)
Packit d7e8d0
        {
Packit d7e8d0
          snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
Packit d7e8d0
	  dest += 3;
Packit d7e8d0
	}
Packit d7e8d0
      else
Packit d7e8d0
	*(dest++) = *src;
Packit d7e8d0
      src++;
Packit d7e8d0
    }
Packit d7e8d0
  *(dest++) = 0;
Packit d7e8d0
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Split a string into space delimited fields and remove leading and
Packit d7e8d0
 * trailing spaces from each field.  A pointer to each field is
Packit d7e8d0
 * stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
Packit d7e8d0
 * modifies STRING.  The number of parsed fields is returned.
Packit d7e8d0
 */
Packit d7e8d0
int
Packit d7e8d0
_gpgme_split_fields (char *string, char **array, int arraysize)
Packit d7e8d0
{
Packit d7e8d0
  int n = 0;
Packit d7e8d0
  char *p, *pend;
Packit d7e8d0
Packit d7e8d0
  for (p = string; *p == ' '; p++)
Packit d7e8d0
    ;
Packit d7e8d0
  do
Packit d7e8d0
    {
Packit d7e8d0
      if (n == arraysize)
Packit d7e8d0
        break;
Packit d7e8d0
      array[n++] = p;
Packit d7e8d0
      pend = strchr (p, ' ');
Packit d7e8d0
      if (!pend)
Packit d7e8d0
        break;
Packit d7e8d0
      *pend++ = 0;
Packit d7e8d0
      for (p = pend; *p == ' '; p++)
Packit d7e8d0
        ;
Packit d7e8d0
    }
Packit d7e8d0
  while (*p);
Packit d7e8d0
Packit d7e8d0
  return n;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Convert the field STRING into an unsigned long value.  Check for
Packit d7e8d0
 * trailing garbage.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpgme_strtoul_field (const char *string, unsigned long *result)
Packit d7e8d0
{
Packit d7e8d0
  char *endp;
Packit d7e8d0
Packit d7e8d0
  gpg_err_set_errno (0);
Packit d7e8d0
  *result = strtoul (string, &endp, 0);
Packit d7e8d0
  if (errno)
Packit d7e8d0
    return gpg_error_from_syserror ();
Packit d7e8d0
  if (endp == string || *endp)
Packit d7e8d0
    return gpg_error (GPG_ERR_INV_VALUE);
Packit d7e8d0
  return 0;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Convert STRING into an offset value.  Note that this functions only
Packit d7e8d0
 * allows for a base-10 length.  This function is similar to atoi()
Packit d7e8d0
 * and thus there is no error checking.  */
Packit d7e8d0
gpgme_off_t
Packit d7e8d0
_gpgme_string_to_off (const char *string)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_off_t value = 0;
Packit d7e8d0
Packit d7e8d0
  while (*string == ' ' || *string == '\t')
Packit d7e8d0
    string++;
Packit d7e8d0
  for (; *string >= '0' && *string <= '9'; string++)
Packit d7e8d0
    {
Packit d7e8d0
      value *= 10;
Packit d7e8d0
      value += atoi_1 (string);
Packit d7e8d0
    }
Packit d7e8d0
  return value;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_W32_SYSTEM
Packit d7e8d0
static time_t
Packit d7e8d0
_gpgme_timegm (struct tm *tm)
Packit d7e8d0
{
Packit d7e8d0
  /* This one is thread safe.  */
Packit d7e8d0
  SYSTEMTIME st;
Packit d7e8d0
  FILETIME ft;
Packit d7e8d0
  unsigned long long cnsecs;
Packit d7e8d0
Packit d7e8d0
  st.wYear   = tm->tm_year + 1900;
Packit d7e8d0
  st.wMonth  = tm->tm_mon  + 1;
Packit d7e8d0
  st.wDay    = tm->tm_mday;
Packit d7e8d0
  st.wHour   = tm->tm_hour;
Packit d7e8d0
  st.wMinute = tm->tm_min;
Packit d7e8d0
  st.wSecond = tm->tm_sec;
Packit d7e8d0
  st.wMilliseconds = 0; /* Not available.  */
Packit d7e8d0
  st.wDayOfWeek = 0;    /* Ignored.  */
Packit d7e8d0
Packit d7e8d0
  /* System time is UTC thus the conversion is pretty easy.  */
Packit d7e8d0
  if (!SystemTimeToFileTime (&st, &ft))
Packit d7e8d0
    {
Packit d7e8d0
      gpg_err_set_errno (EINVAL);
Packit d7e8d0
      return (time_t)(-1);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
Packit d7e8d0
	    | ft.dwLowDateTime);
Packit d7e8d0
  cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
Packit d7e8d0
  return (time_t)(cnsecs / 10000000ULL);
Packit d7e8d0
}
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* Parse the string TIMESTAMP into a time_t.  The string may either be
Packit d7e8d0
   seconds since Epoch or in the ISO 8601 format like
Packit d7e8d0
   "20390815T143012".  Returns 0 for an empty string or seconds since
Packit d7e8d0
   Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
Packit d7e8d0
   point to the next non-parsed character in TIMESTRING. */
Packit d7e8d0
time_t
Packit d7e8d0
_gpgme_parse_timestamp (const char *timestamp, char **endp)
Packit d7e8d0
{
Packit d7e8d0
  /* Need to skip leading spaces, because that is what strtoul does
Packit d7e8d0
     but not our ISO 8601 checking code. */
Packit d7e8d0
  while (*timestamp && *timestamp== ' ')
Packit d7e8d0
    timestamp++;
Packit d7e8d0
  if (!*timestamp)
Packit d7e8d0
    return 0;
Packit d7e8d0
Packit d7e8d0
  if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
Packit d7e8d0
    {
Packit d7e8d0
      struct tm buf;
Packit d7e8d0
      int year;
Packit d7e8d0
Packit d7e8d0
      year = atoi_4 (timestamp);
Packit d7e8d0
      if (year < 1900)
Packit d7e8d0
        return (time_t)(-1);
Packit d7e8d0
Packit d7e8d0
      if (endp)
Packit d7e8d0
        *endp = (char*)(timestamp + 15);
Packit d7e8d0
Packit d7e8d0
      /* Fixme: We would better use a configure test to see whether
Packit d7e8d0
         mktime can handle dates beyond 2038. */
Packit d7e8d0
      if (sizeof (time_t) <= 4 && year >= 2038)
Packit d7e8d0
        return (time_t)2145914603; /* 2037-12-31 23:23:23 */
Packit d7e8d0
Packit d7e8d0
      memset (&buf, 0, sizeof buf);
Packit d7e8d0
      buf.tm_year = year - 1900;
Packit d7e8d0
      buf.tm_mon = atoi_2 (timestamp+4) - 1;
Packit d7e8d0
      buf.tm_mday = atoi_2 (timestamp+6);
Packit d7e8d0
      buf.tm_hour = atoi_2 (timestamp+9);
Packit d7e8d0
      buf.tm_min = atoi_2 (timestamp+11);
Packit d7e8d0
      buf.tm_sec = atoi_2 (timestamp+13);
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_W32_SYSTEM
Packit d7e8d0
      return _gpgme_timegm (&buf;;
Packit d7e8d0
#else
Packit d7e8d0
#ifdef HAVE_TIMEGM
Packit d7e8d0
      return timegm (&buf;;
Packit d7e8d0
#else
Packit d7e8d0
      {
Packit d7e8d0
        time_t tim;
Packit d7e8d0
Packit d7e8d0
        putenv ("TZ=UTC");
Packit d7e8d0
        tim = mktime (&buf;;
Packit d7e8d0
#ifdef __GNUC__
Packit d7e8d0
#warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
Packit d7e8d0
#endif
Packit d7e8d0
        return tim;
Packit d7e8d0
      }
Packit d7e8d0
#endif /* !HAVE_TIMEGM */
Packit d7e8d0
#endif /* !HAVE_W32_SYSTEM */
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    return (time_t)strtoul (timestamp, endp, 10);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* This function is similar to _gpgme_parse_timestamp but returns an
Packit d7e8d0
 * unsigned long and 0 on error.  */
Packit d7e8d0
unsigned long
Packit d7e8d0
_gpgme_parse_timestamp_ul (const char *timestamp)
Packit d7e8d0
{
Packit d7e8d0
  time_t tim;
Packit d7e8d0
  char *tail;
Packit d7e8d0
Packit d7e8d0
  if (!*timestamp)
Packit d7e8d0
    return 0; /* Shortcut empty strings.  */
Packit d7e8d0
Packit d7e8d0
  tim = _gpgme_parse_timestamp (timestamp, &tail);
Packit d7e8d0
  if (tim == -1 || timestamp == tail || (*tail && *tail != ' '))
Packit d7e8d0
    tim = 0; /* No time given or invalid engine.  */
Packit d7e8d0
Packit d7e8d0
  return (unsigned long)tim;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
/* The GPG backend uses OpenPGP algorithm numbers which we need to map
Packit d7e8d0
   to our algorithm numbers.  This function MUST not change ERRNO. */
Packit d7e8d0
int
Packit d7e8d0
_gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
Packit d7e8d0
{
Packit d7e8d0
  if (protocol == GPGME_PROTOCOL_OPENPGP)
Packit d7e8d0
    {
Packit d7e8d0
      switch (algo)
Packit d7e8d0
        {
Packit d7e8d0
        case 1: case 2: case 3: case 16: case 17: break;
Packit d7e8d0
        case 18: algo = GPGME_PK_ECDH; break;
Packit d7e8d0
        case 19: algo = GPGME_PK_ECDSA; break;
Packit d7e8d0
        case 20: break;
Packit d7e8d0
        case 22: algo = GPGME_PK_EDDSA; break;
Packit d7e8d0
        default: algo = 0; break; /* Unknown.  */
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  return algo;
Packit d7e8d0
}
Packit Service 30b792
Packit Service 30b792
Packit Service 30b792
/* Return a string with a cipher algorithm.  */
Packit Service 30b792
const char *
Packit Service 30b792
_gpgme_cipher_algo_name (int algo, gpgme_protocol_t protocol)
Packit Service 30b792
{
Packit Service 30b792
  if (protocol == GPGME_PROTOCOL_OPENPGP)
Packit Service 30b792
    {
Packit Service 30b792
      /* The algo is given according to OpenPGP specs.  */
Packit Service 30b792
      switch (algo)
Packit Service 30b792
        {
Packit Service 30b792
        case 1:  return "IDEA";
Packit Service 30b792
        case 2:	 return "3DES";
Packit Service 30b792
        case 3:	 return "CAST5";
Packit Service 30b792
        case 4:  return "BLOWFISH";
Packit Service 30b792
        case 7:  return "AES";
Packit Service 30b792
        case 8:  return "AES192";
Packit Service 30b792
        case 9:  return "AES256";
Packit Service 30b792
        case 10: return "TWOFISH";
Packit Service 30b792
        case 11: return "CAMELLIA128";
Packit Service 30b792
        case 12: return "CAMELLIA192";
Packit Service 30b792
        case 13: return "CAMELLIA256";
Packit Service 30b792
        }
Packit Service 30b792
    }
Packit Service 30b792
Packit Service 30b792
  return "Unknown";
Packit Service 30b792
}
Packit Service 30b792
Packit Service 30b792
Packit Service 30b792
/* Return a string with the cipher mode.  */
Packit Service 30b792
const char *
Packit Service 30b792
_gpgme_cipher_mode_name (int algo, gpgme_protocol_t protocol)
Packit Service 30b792
{
Packit Service 30b792
  if (protocol == GPGME_PROTOCOL_OPENPGP)
Packit Service 30b792
    {
Packit Service 30b792
      /* The algo is given according to OpenPGP specs.  */
Packit Service 30b792
      switch (algo)
Packit Service 30b792
        {
Packit Service 30b792
        case 0:  return "CFB";
Packit Service 30b792
        case 1:  return "EAX";
Packit Service 30b792
        case 2:	 return "OCB";
Packit Service 30b792
        }
Packit Service 30b792
    }
Packit Service 30b792
Packit Service 30b792
  return "Unknown";
Packit Service 30b792
}