Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36623960
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
10 KB
Subscribers
None
View Options
diff --git a/src/conversion.c b/src/conversion.c
index 356200ce..b47d6deb 100644
--- a/src/conversion.c
+++ b/src/conversion.c
@@ -1,414 +1,414 @@
/* 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
02111-1307, USA. */
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.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>
#include "gpgme.h"
#include "util.h"
#include "debug.h"
#define atoi_1(p) (*(p) - '0' )
#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
/* 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 char *str)
{
int val = 0;
int i;
#define NROFHEXDIGITS 2
for (i = 0; i < NROFHEXDIGITS; i++)
{
if (*str >= '0' && *str <= '9')
val += *str - '0';
else if (*str >= 'A' && *str <= 'F')
val += 10 + *str - 'A';
else if (*str >= 'a' && *str <= 'f')
val += 10 + *str - 'a';
else
return -1;
if (i < NROFHEXDIGITS - 1)
val *= 16;
str++;
}
return val;
}
/* Decode the C formatted 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_c_string (const char *src, char **destp, size_t len)
{
char *dest;
/* Set up the destination buffer. */
if (len)
{
if (len < strlen (src) + 1)
return gpg_error (GPG_ERR_INTERNAL);
dest = *destp;
}
else
{
/* The converted string will never be larger than the original
string. */
dest = malloc (strlen (src) + 1);
if (!dest)
return gpg_error_from_syserror ();
*destp = dest;
}
/* Convert the string. */
while (*src)
{
if (*src != '\\')
{
*(dest++) = *(src++);
continue;
}
switch (src[1])
{
#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. If BINARY is 1, then '\0'
characters are allowed in the output. */
gpgme_error_t
_gpgme_decode_percent_string (const char *src, char **destp, size_t len,
int binary)
{
char *dest;
/* Set up the destination buffer. */
if (len)
{
if (len < strlen (src) + 1)
return gpg_error (GPG_ERR_INTERNAL);
dest = *destp;
}
else
{
/* The converted string will never be larger than the original
string. */
dest = malloc (strlen (src) + 1);
if (!dest)
return gpg_error_from_syserror ();
*destp = dest;
}
/* Convert the string. */
while (*src)
{
if (*src != '%')
{
*(dest++) = *(src++);
continue;
}
else
{
int val = _gpgme_hextobyte (&src[1]);
if (val == -1)
{
/* Should not happen. */
*(dest++) = *(src++);
if (*src)
*(dest++) = *(src++);
if (*src)
*(dest++) = *(src++);
}
else
{
if (!val && !binary)
{
/* A binary zero is not representable in a C
string. */
*(dest++) = '\\';
*(dest++) = '0';
}
else
*((unsigned char *) dest++) = val;
src += 3;
}
}
}
*(dest++) = 0;
return 0;
}
/* Encode the string SRC with percent escaping 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. If BINARY is 1, then '\0'
characters are allowed in the output. */
gpgme_error_t
_gpgme_encode_percent_string (const char *src, char **destp, size_t len)
{
size_t destlen;
char *dest;
const char *str;
destlen = 0;
str = src;
/* We percent-escape the + character because the user might need a
"percent plus" escaped string (special gpg format). But we
percent-escape the space character, which works with and without
the special plus format. */
while (*str)
{
if (*str == '+' || *str == '\"' || *str == '%'
|| *(const unsigned char *)str <= 0x20)
destlen += 3;
else
destlen++;
str++;
}
/* Terminating nul byte. */
destlen++;
/* Set up the destination buffer. */
if (len)
{
- if (len < destlen);
+ if (len < destlen)
return gpg_error (GPG_ERR_INTERNAL);
dest = *destp;
}
else
{
/* The converted string will never be larger than the original
string. */
dest = malloc (destlen);
if (!dest)
return gpg_error_from_syserror ();
*destp = dest;
}
/* Convert the string. */
while (*src)
{
if (*src == '+' || *src == '\"' || *src == '%'
|| *(const unsigned char *)src <= 0x20)
{
snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
dest += 3;
}
else
*(dest++) = *src;
src++;
}
*(dest++) = 0;
return 0;
}
#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
Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
point to the next non-parsed character in TIMESTRING. */
time_t
_gpgme_parse_timestamp (const char *timestamp, char **endp)
{
/* Need to skip leading spaces, because that is what strtoul does
but not our ISO 8601 checking code. */
while (*timestamp && *timestamp== ' ')
timestamp++;
if (!*timestamp)
return 0;
if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
{
struct tm buf;
int year;
year = atoi_4 (timestamp);
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)
return (time_t)2145914603; /* 2037-12-31 23:23:23 */
memset (&buf, 0, sizeof buf);
buf.tm_year = year - 1900;
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);
#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__
#warning fixme: we must somehow reset TZ here. It is not threadsafe anyway.
#endif
return tim;
}
#endif /* !HAVE_TIMEGM */
#endif /* !HAVE_W32_SYSTEM */
}
else
return (time_t)strtoul (timestamp, endp, 10);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Feb 26, 7:04 PM (1 d, 8 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
aa/88/b5fd8471933f27714a628a293c10
Attached To
rM GPGME
Event Timeline
Log In to Comment