2002-01-13 Marcus Brinkmann <marcus@g10code.de>

* gpgme.c: Various source clean ups, like renaming C to CTX where
	appropriate.
	(gpgme_new): Clear R_CTX before starting the work.
	(my_isdigit): Removed.
	(my_isxdigit): Likewise.

	* data.c: Various source clean ups.
	(gpgme_data_new_from_mem): Check BUFFER after clearing R_DH.
	(gpgme_data_new_with_read_cb): Similar for READ_CB.
	(gpgme_data_new_from_file): Loop over fread while EINTR.
	(gpgme_data_new_from_filepart): Rediddled a bit.  Allow LENGTH to
	be zero.  Loop over fread while EINTR.

	(my_isdigit): Removed.
	(my_isxdigit): Likewise.
This commit is contained in:
Marcus Brinkmann 2002-01-15 19:58:41 +00:00
parent 6d275b5d07
commit d83e746a07
3 changed files with 595 additions and 516 deletions

View File

@ -1,3 +1,21 @@
2002-01-13 Marcus Brinkmann <marcus@g10code.de>
* gpgme.c: Various source clean ups, like renaming C to CTX where
appropriate.
(gpgme_new): Clear R_CTX before starting the work.
(my_isdigit): Removed.
(my_isxdigit): Likewise.
* data.c: Various source clean ups.
(gpgme_data_new_from_mem): Check BUFFER after clearing R_DH.
(gpgme_data_new_with_read_cb): Similar for READ_CB.
(gpgme_data_new_from_file): Loop over fread while EINTR.
(gpgme_data_new_from_filepart): Rediddled a bit. Allow LENGTH to
be zero. Loop over fread while EINTR.
(my_isdigit): Removed.
(my_isxdigit): Likewise.
2001-12-21 Marcus Brinkmann <marcus@g10code.de> 2001-12-21 Marcus Brinkmann <marcus@g10code.de>
* engine-gpgsm.c (_gpgme_gpgsm_new): Replace General_Error with * engine-gpgsm.c (_gpgme_gpgsm_new): Replace General_Error with

View File

@ -1,6 +1,6 @@
/* data.c /* data.c
* Copyright (C) 2000 Werner Koch (dd9jn) * Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 g10 Code GmbH * Copyright (C) 2001, 2002 g10 Code GmbH
* *
* This file is part of GPGME. * This file is part of GPGME.
* *
@ -34,11 +34,9 @@
#include "ops.h" #include "ops.h"
#include "io.h" #include "io.h"
/* When expanding an internal buffer, always extend it by ALLOC_CHUNK
bytes at a time. */
#define ALLOC_CHUNK 1024 #define ALLOC_CHUNK 1024
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
#define my_isxdigit(a) ( my_isdigit((a)) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'f' && (a) <= 'f') )
/** /**
@ -50,17 +48,20 @@
* Return value: An error value or 0 on success * Return value: An error value or 0 on success
**/ **/
GpgmeError GpgmeError
gpgme_data_new ( GpgmeData *r_dh ) gpgme_data_new (GpgmeData *r_dh)
{ {
GpgmeData dh; GpgmeData dh;
if (!r_dh) if (!r_dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
*r_dh = NULL; *r_dh = NULL;
dh = xtrycalloc ( 1, sizeof *dh );
dh = xtrycalloc (1, sizeof *dh);
if (!dh) if (!dh)
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
dh->mode = GPGME_DATA_MODE_INOUT; dh->mode = GPGME_DATA_MODE_INOUT;
*r_dh = dh; *r_dh = dh;
return 0; return 0;
} }
@ -73,43 +74,48 @@ gpgme_data_new ( GpgmeData *r_dh )
* @size: Size of the buffer * @size: Size of the buffer
* @copy: Flag wether a copy of the buffer should be used. * @copy: Flag wether a copy of the buffer should be used.
* *
* Create a new data object and initialize with data * Create a new data object and initialize with data from the memory.
* from the memory. A @copy with value %TRUE creates a copy of the * A @copy with value %TRUE creates a copy of the memory, a value of
* memory, a value of %FALSE uses the original memory of @buffer and the * %FALSE uses the original memory of @buffer and the caller has to
* caller has to make sure that this buffer is valid until gpgme_release_data() * make sure that this buffer is valid until gpgme_data_release() is
* is called. * called.
* *
* Return value: An error value or 0 for success. * Return value: An error value or 0 for success.
**/ **/
GpgmeError GpgmeError
gpgme_data_new_from_mem ( GpgmeData *r_dh, gpgme_data_new_from_mem (GpgmeData *r_dh, const char *buffer, size_t size,
const char *buffer, size_t size, int copy ) int copy)
{ {
GpgmeData dh; GpgmeData dh;
GpgmeError err; GpgmeError err;
if (!r_dh || !buffer) if (!r_dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
*r_dh = NULL; *r_dh = NULL;
err = gpgme_data_new ( &dh ); if (!buffer)
return mk_error (Invalid_Value);
err = gpgme_data_new (&dh);
if (err) if (err)
return err; return err;
dh->type = GPGME_DATA_TYPE_MEM;
dh->len = size; dh->len = size;
if (copy) { if (!copy)
dh->private_buffer = xtrymalloc ( size ); dh->data = buffer;
if ( !dh->private_buffer ) { else
{
dh->private_buffer = xtrymalloc (size);
if (!dh->private_buffer)
{
gpgme_data_release (dh); gpgme_data_release (dh);
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
} }
dh->private_len = size; dh->private_len = size;
memcpy (dh->private_buffer, buffer, size ); memcpy (dh->private_buffer, buffer, size);
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
dh->writepos = size; dh->writepos = size;
} }
else {
dh->data = buffer;
}
dh->type = GPGME_DATA_TYPE_MEM;
*r_dh = dh; *r_dh = dh;
return 0; return 0;
@ -142,19 +148,24 @@ gpgme_data_new_from_mem ( GpgmeData *r_dh,
* Return value: An error value or 0 for success. * Return value: An error value or 0 for success.
**/ **/
GpgmeError GpgmeError
gpgme_data_new_with_read_cb ( GpgmeData *r_dh, gpgme_data_new_with_read_cb (GpgmeData *r_dh,
int (*read_cb)(void*,char *,size_t,size_t*), int (*read_cb) (void *,char *, size_t ,size_t *),
void *read_cb_value ) void *read_cb_value)
{ {
GpgmeData dh; GpgmeData dh;
GpgmeError err; GpgmeError err;
if (!r_dh || !read_cb) if (!r_dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
*r_dh = NULL; *r_dh = NULL;
err = gpgme_data_new ( &dh );
if (!read_cb)
return mk_error (Invalid_Value);
err = gpgme_data_new (&dh);
if (err) if (err)
return err; return err;
dh->type = GPGME_DATA_TYPE_CB; dh->type = GPGME_DATA_TYPE_CB;
dh->mode = GPGME_DATA_MODE_OUT; dh->mode = GPGME_DATA_MODE_OUT;
dh->read_cb = read_cb; dh->read_cb = read_cb;
@ -164,6 +175,7 @@ gpgme_data_new_with_read_cb ( GpgmeData *r_dh,
return 0; return 0;
} }
/** /**
* gpgme_data_new_from_file: * gpgme_data_new_from_file:
* @r_dh: returns the new data object * @r_dh: returns the new data object
@ -178,7 +190,7 @@ gpgme_data_new_with_read_cb ( GpgmeData *r_dh,
* %GPGME_File_Error, the OS error code is held in %errno. * %GPGME_File_Error, the OS error code is held in %errno.
**/ **/
GpgmeError GpgmeError
gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy ) gpgme_data_new_from_file (GpgmeData *r_dh, const char *fname, int copy)
{ {
GpgmeData dh; GpgmeData dh;
GpgmeError err; GpgmeError err;
@ -188,26 +200,29 @@ gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy )
if (!r_dh) if (!r_dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
*r_dh = NULL; *r_dh = NULL;
/* We only support copy for now - in future we might want to honor the
* copy flag and just store a file pointer */
if (!copy)
return mk_error (Not_Implemented);
if (!fname) if (!fname)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
err = gpgme_data_new ( &dh ); /* We only support copy for now. In future we might want to honor
the copy flag and just store a file pointer. */
if (!copy)
return mk_error (Not_Implemented);
err = gpgme_data_new (&dh);
if (err) if (err)
return err; return err;
fp = fopen (fname, "rb"); fp = fopen (fname, "rb");
if (!fp) { if (!fp)
{
int save_errno = errno; int save_errno = errno;
gpgme_data_release (dh); gpgme_data_release (dh);
errno = save_errno; errno = save_errno;
return mk_error (File_Error); return mk_error (File_Error);
} }
if( fstat(fileno(fp), &st) ) { if (fstat(fileno(fp), &st))
{
int save_errno = errno; int save_errno = errno;
fclose (fp); fclose (fp);
gpgme_data_release (dh); gpgme_data_release (dh);
@ -215,17 +230,22 @@ gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy )
return mk_error (File_Error); return mk_error (File_Error);
} }
/* We should check the length of the file and don't allow for to /* We should check the length of the file and don't allow for too
* large files */ large files. */
dh->private_buffer = xtrymalloc ( st.st_size ); dh->private_buffer = xtrymalloc (st.st_size);
if ( !dh->private_buffer ) { if (!dh->private_buffer)
{
fclose (fp); fclose (fp);
gpgme_data_release (dh); gpgme_data_release (dh);
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
} }
dh->private_len = st.st_size; dh->private_len = st.st_size;
if ( fread ( dh->private_buffer, dh->private_len, 1, fp ) != 1 ) { while (fread (dh->private_buffer, dh->private_len, 1, fp) < 1
&& ferror (fp) && errno == EINTR);
if (ferror (fp))
{
int save_errno = errno; int save_errno = errno;
fclose (fp); fclose (fp);
gpgme_data_release (dh); gpgme_data_release (dh);
@ -235,10 +255,10 @@ gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy )
fclose (fp); fclose (fp);
dh->type = GPGME_DATA_TYPE_MEM;
dh->len = dh->private_len; dh->len = dh->private_len;
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
dh->writepos = dh->len; dh->writepos = dh->len;
dh->type = GPGME_DATA_TYPE_MEM;
*r_dh = dh; *r_dh = dh;
return 0; return 0;
@ -257,79 +277,85 @@ gpgme_data_new_from_file ( GpgmeData *r_dh, const char *fname, int copy )
* starting at @offset of @file or @fp. Either a filename or an open * starting at @offset of @file or @fp. Either a filename or an open
* filepointer may be given. * filepointer may be given.
* *
*
* Return value: An error code or 0 on success. If the error code is * Return value: An error code or 0 on success. If the error code is
* %GPGME_File_Error, the OS error code is held in %errno. * %GPGME_File_Error, the OS error code is held in %errno.
**/ **/
GpgmeError GpgmeError
gpgme_data_new_from_filepart ( GpgmeData *r_dh, const char *fname, FILE *fp, gpgme_data_new_from_filepart (GpgmeData *r_dh, const char *fname, FILE *fp,
off_t offset, off_t length ) off_t offset, off_t length)
{ {
GpgmeData dh; GpgmeData dh;
GpgmeError err; GpgmeError err;
int save_errno = 0;
if (!r_dh) if (!r_dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
*r_dh = NULL; *r_dh = NULL;
if ( fname && fp ) /* these are mutual exclusive */
return mk_error (Invalid_Value); if ((fname && fp) || (!fname && !fp))
if (!fname && !fp)
return mk_error (Invalid_Value);
if (!length)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
err = gpgme_data_new ( &dh ); err = gpgme_data_new (&dh);
if (err) if (err)
return err; return err;
if (!fp) { if (!length)
goto out;
if (fname)
{
fp = fopen (fname, "rb"); fp = fopen (fname, "rb");
if (!fp) { if (!fp)
int save_errno = errno; {
gpgme_data_release (dh); err = mk_error (File_Error);
errno = save_errno; goto out;
return mk_error (File_Error);
} }
} }
if ( fseek ( fp, (long)offset, SEEK_SET) ) { if (fseek (fp, (long) offset, SEEK_SET))
int save_errno = errno; {
if (fname) err = mk_error (File_Error);
fclose (fp); goto out;
gpgme_data_release (dh);
errno = save_errno;
return mk_error (File_Error);
} }
dh->private_buffer = xtrymalloc (length);
dh->private_buffer = xtrymalloc ( length ); if (!dh->private_buffer)
if ( !dh->private_buffer ) { {
if (fname) err = mk_error (Out_Of_Core);
fclose (fp); goto out;
gpgme_data_release (dh);
return mk_error (Out_Of_Core);
} }
dh->private_len = length; dh->private_len = length;
if ( fread ( dh->private_buffer, dh->private_len, 1, fp ) != 1 ) { while (fread (dh->private_buffer, dh->private_len, 1, fp) < 1
int save_errno = errno; && ferror (fp) && errno == EINTR);
if (fname)
fclose (fp); if (ferror (fp))
gpgme_data_release (dh); {
errno = save_errno; err = mk_error (File_Error);
return mk_error (File_Error); goto out;
} }
if (fname) dh->type = GPGME_DATA_TYPE_MEM;
fclose (fp);
dh->len = dh->private_len; dh->len = dh->private_len;
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
dh->writepos = dh->len; dh->writepos = dh->len;
dh->type = GPGME_DATA_TYPE_MEM;
out:
if (err)
save_errno = errno;
if (fname && fp)
fclose (fp);
if (err)
{
gpgme_data_release (dh);
errno = save_errno;
}
else
*r_dh = dh; *r_dh = dh;
return 0; return err;
} }
@ -341,14 +367,16 @@ gpgme_data_new_from_filepart ( GpgmeData *r_dh, const char *fname, FILE *fp,
* happens. * happens.
**/ **/
void void
gpgme_data_release ( GpgmeData dh ) gpgme_data_release (GpgmeData dh)
{ {
if (dh) { if (dh)
{
xfree (dh->private_buffer); xfree (dh->private_buffer);
xfree (dh); xfree (dh);
} }
} }
/* /*
* Release the data object @dh. @dh may be NULL in which case nothing * Release the data object @dh. @dh may be NULL in which case nothing
* happens. * happens.
@ -358,19 +386,22 @@ gpgme_data_release ( GpgmeData dh )
* safely be accessed using the string fucntions. * safely be accessed using the string fucntions.
**/ **/
char * char *
_gpgme_data_release_and_return_string ( GpgmeData dh ) _gpgme_data_release_and_return_string (GpgmeData dh)
{ {
char *val = NULL; char *val = NULL;
if (dh) { if (dh)
if ( _gpgme_data_append ( dh, "", 1 ) ) /* append EOS */ {
if (_gpgme_data_append (dh, "", 1)) /* append EOS */
xfree (dh->private_buffer ); xfree (dh->private_buffer );
else { else
{
val = dh->private_buffer; val = dh->private_buffer;
if ( !val && dh->data ) { if (!val && dh->data)
val = xtrymalloc ( dh->len ); {
if ( val ) val = xtrymalloc (dh->len);
memcpy ( val, dh->data, dh->len ); if (val)
memcpy (val, dh->data, dh->len);
} }
} }
xfree (dh); xfree (dh);
@ -378,6 +409,7 @@ _gpgme_data_release_and_return_string ( GpgmeData dh )
return val; return val;
} }
/** /**
* gpgme_data_release_and_get_mem: * gpgme_data_release_and_get_mem:
* @dh: the data object * @dh: the data object
@ -392,22 +424,24 @@ _gpgme_data_release_and_return_string ( GpgmeData dh )
* Return value: a pointer to an allocated buffer of length @r_len. * Return value: a pointer to an allocated buffer of length @r_len.
**/ **/
char * char *
gpgme_data_release_and_get_mem ( GpgmeData dh, size_t *r_len ) gpgme_data_release_and_get_mem (GpgmeData dh, size_t *r_len)
{ {
char *val = NULL; char *val = NULL;
if (r_len) if (r_len)
*r_len = 0; *r_len = 0;
if (dh) { if (dh)
{
size_t len = dh->len; size_t len = dh->len;
val = dh->private_buffer; val = dh->private_buffer;
if ( !val && dh->data ) { if (!val && dh->data)
val = xtrymalloc ( len ); {
if ( val ) val = xtrymalloc (len);
memcpy ( val, dh->data, len ); if (val)
memcpy (val, dh->data, len);
} }
xfree (dh); xfree (dh);
if (val && r_len ) if (val && r_len)
*r_len = len; *r_len = len;
} }
return val; return val;
@ -424,16 +458,17 @@ gpgme_data_release_and_get_mem ( GpgmeData dh, size_t *r_len )
* Return value: the data type * Return value: the data type
**/ **/
GpgmeDataType GpgmeDataType
gpgme_data_get_type ( GpgmeData dh ) gpgme_data_get_type (GpgmeData dh)
{ {
if ( !dh || (!dh->data && !dh->read_cb)) if (!dh || (!dh->data && !dh->read_cb))
return GPGME_DATA_TYPE_NONE; return GPGME_DATA_TYPE_NONE;
return dh->type; return dh->type;
} }
void void
_gpgme_data_set_mode ( GpgmeData dh, GpgmeDataMode mode ) _gpgme_data_set_mode (GpgmeData dh, GpgmeDataMode mode)
{ {
assert (dh); assert (dh);
dh->mode = mode; dh->mode = mode;
@ -441,12 +476,13 @@ _gpgme_data_set_mode ( GpgmeData dh, GpgmeDataMode mode )
GpgmeDataMode GpgmeDataMode
_gpgme_data_get_mode ( GpgmeData dh ) _gpgme_data_get_mode (GpgmeData dh)
{ {
assert (dh); assert (dh);
return dh->mode; return dh->mode;
} }
/** /**
* gpgme_data_rewind: * gpgme_data_rewind:
* @dh: the data object * @dh: the data object
@ -458,24 +494,28 @@ _gpgme_data_get_mode ( GpgmeData dh )
* Return value: An error code or 0 on success * Return value: An error code or 0 on success
**/ **/
GpgmeError GpgmeError
gpgme_data_rewind ( GpgmeData dh ) gpgme_data_rewind (GpgmeData dh)
{ {
if ( !dh ) if (!dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
if ( dh->type == GPGME_DATA_TYPE_NONE switch (dh->type)
|| dh->type == GPGME_DATA_TYPE_MEM ) { {
case GPGME_DATA_TYPE_NONE:
case GPGME_DATA_TYPE_MEM:
dh->readpos = 0; dh->readpos = 0;
} return 0;
else if (dh->type == GPGME_DATA_TYPE_CB) {
case GPGME_DATA_TYPE_CB:
dh->len = dh->readpos = 0; dh->len = dh->readpos = 0;
dh->read_cb_eof = 0; dh->read_cb_eof = 0;
if ( dh->read_cb (dh->read_cb_value, NULL, 0, NULL) ) if (dh->read_cb (dh->read_cb_value, NULL, 0, NULL))
return mk_error (Not_Implemented); return mk_error (Not_Implemented);
}
else
return mk_error (General_Error);
return 0; return 0;
default:
return mk_error (General_Error);
}
} }
/** /**
@ -500,76 +540,90 @@ gpgme_data_rewind ( GpgmeData dh )
* error code GPGME_EOF. * error code GPGME_EOF.
**/ **/
GpgmeError GpgmeError
gpgme_data_read ( GpgmeData dh, char *buffer, size_t length, size_t *nread ) gpgme_data_read (GpgmeData dh, char *buffer, size_t length, size_t *nread)
{ {
size_t nbytes; size_t nbytes;
if ( !dh ) if (!dh)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM ) {
switch (dh->type)
{
case GPGME_DATA_TYPE_MEM:
nbytes = dh->len - dh->readpos; nbytes = dh->len - dh->readpos;
if ( !nbytes ) { if (!nbytes)
{
*nread = 0; *nread = 0;
return mk_error(EOF); return mk_error(EOF);
} }
if (!buffer) {
if (!buffer)
*nread = nbytes; *nread = nbytes;
} else
else { {
if (nbytes > length) if (nbytes > length)
nbytes = length; nbytes = length;
memcpy ( buffer, dh->data + dh->readpos, nbytes ); memcpy (buffer, dh->data + dh->readpos, nbytes);
*nread = nbytes; *nread = nbytes;
dh->readpos += nbytes; dh->readpos += nbytes;
} }
} return 0;
else if (dh->type == GPGME_DATA_TYPE_CB) {
if (!buffer) { case GPGME_DATA_TYPE_CB:
if (!buffer)
{
*nread = 0; *nread = 0;
return mk_error (Invalid_Type); return mk_error (Invalid_Type);
} }
nbytes = dh->len - dh->readpos; nbytes = dh->len - dh->readpos;
if ( nbytes ) { if (nbytes)
/* we have unread data - return this */ {
/* We have unread data - return this. */
if (nbytes > length) if (nbytes > length)
nbytes = length; nbytes = length;
memcpy ( buffer, dh->data + dh->readpos, nbytes ); memcpy (buffer, dh->data + dh->readpos, nbytes);
*nread = nbytes; *nread = nbytes;
dh->readpos += nbytes; dh->readpos += nbytes;
} }
else { /* get the data from the callback */ else
if (!dh->read_cb || dh->read_cb_eof) { {
/* Get the data from the callback. */
if (!dh->read_cb || dh->read_cb_eof)
{
*nread = 0; *nread = 0;
return mk_error (EOF); return mk_error (EOF);
} }
if (dh->read_cb (dh->read_cb_value, buffer, length, nread )) { if (dh->read_cb (dh->read_cb_value, buffer, length, nread))
{
*nread = 0; *nread = 0;
dh->read_cb_eof = 1; dh->read_cb_eof = 1;
return mk_error (EOF); return mk_error (EOF);
} }
} }
return 0;
default:
return mk_error (General_Error);
}
}
GpgmeError
_gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length)
{
if (!dh)
return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM)
{
/* Check that we don't unread more than we have yet read. */
if (dh->readpos < length)
return mk_error (Invalid_Value);
/* No need to use the buffer for this data type. */
dh->readpos -= length;
} }
else else
return mk_error (General_Error); return mk_error (General_Error);
return 0;
}
GpgmeError
_gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length )
{
if ( !dh )
return mk_error (Invalid_Value);
if (dh->type == GPGME_DATA_TYPE_MEM ) {
/* check that we don't unread more than we have yet read */
if ( dh->readpos < length )
return mk_error (Invalid_Value);
/* No need to use the buffer for this data type */
dh->readpos -= length;
}
else {
return mk_error (General_Error);
}
return 0; return 0;
} }
@ -579,14 +633,16 @@ _gpgme_data_unread (GpgmeData dh, const char *buffer, size_t length )
* This function does make sense when we know that it contains no nil chars. * This function does make sense when we know that it contains no nil chars.
*/ */
char * char *
_gpgme_data_get_as_string ( GpgmeData dh ) _gpgme_data_get_as_string (GpgmeData dh)
{ {
char *val = NULL; char *val = NULL;
if (dh) { if (dh)
val = xtrymalloc ( dh->len+1 ); {
if ( val ) { val = xtrymalloc (dh->len+1);
memcpy ( val, dh->data, dh->len ); if (val)
{
memcpy (val, dh->data, dh->len);
val[dh->len] = 0; val[dh->len] = 0;
} }
} }
@ -606,7 +662,7 @@ _gpgme_data_get_as_string ( GpgmeData dh )
* Return value: 0 on success or an error code * Return value: 0 on success or an error code
**/ **/
GpgmeError GpgmeError
gpgme_data_write ( GpgmeData dh, const char *buffer, size_t length ) gpgme_data_write (GpgmeData dh, const char *buffer, size_t length)
{ {
if (!dh || !buffer) if (!dh || !buffer)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
@ -616,108 +672,121 @@ gpgme_data_write ( GpgmeData dh, const char *buffer, size_t length )
GpgmeError GpgmeError
_gpgme_data_append ( GpgmeData dh, const char *buffer, size_t length ) _gpgme_data_append (GpgmeData dh, const char *buffer, size_t length)
{ {
assert (dh); assert (dh);
if ( dh->type == GPGME_DATA_TYPE_NONE ) { if (dh->type == GPGME_DATA_TYPE_NONE)
/* convert it to a mem data type */ {
/* Convert it to a mem data type. */
assert (!dh->private_buffer); assert (!dh->private_buffer);
dh->type = GPGME_DATA_TYPE_MEM; dh->type = GPGME_DATA_TYPE_MEM;
dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length; dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
dh->private_buffer = xtrymalloc ( dh->private_len ); dh->private_buffer = xtrymalloc (dh->private_len);
if (!dh->private_buffer) { if (!dh->private_buffer)
{
dh->private_len = 0; dh->private_len = 0;
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
} }
dh->writepos = 0; dh->writepos = 0;
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
} }
else if ( dh->type != GPGME_DATA_TYPE_MEM ) else if (dh->type != GPGME_DATA_TYPE_MEM)
return mk_error (Invalid_Type); return mk_error (Invalid_Type);
if ( dh->mode != GPGME_DATA_MODE_INOUT if (dh->mode != GPGME_DATA_MODE_INOUT
&& dh->mode != GPGME_DATA_MODE_IN ) && dh->mode != GPGME_DATA_MODE_IN)
return mk_error (Invalid_Mode); return mk_error (Invalid_Mode);
if ( !dh->private_buffer ) { if (!dh->private_buffer)
/* we have to copy it now */ {
/* We have to copy it now. */
assert (dh->data); assert (dh->data);
dh->private_len = dh->len+length; dh->private_len = dh->len+length;
if (dh->private_len < ALLOC_CHUNK) if (dh->private_len < ALLOC_CHUNK)
dh->private_len = ALLOC_CHUNK; dh->private_len = ALLOC_CHUNK;
dh->private_buffer = xtrymalloc ( dh->private_len ); dh->private_buffer = xtrymalloc (dh->private_len);
if (!dh->private_buffer) { if (!dh->private_buffer)
{
dh->private_len = 0; dh->private_len = 0;
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
} }
memcpy ( dh->private_buffer, dh->data, dh->len ); memcpy (dh->private_buffer, dh->data, dh->len);
dh->writepos = dh->len; dh->writepos = dh->len;
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
} }
/* allocate more memory if needed */ /* Allocate more memory if needed. */
if ( dh->writepos + length > dh->private_len ) { if (dh->writepos + length > dh->private_len)
{
char *p; char *p;
size_t newlen = dh->private_len size_t newlen = dh->private_len
+ (length < ALLOC_CHUNK? ALLOC_CHUNK : length); + (length < ALLOC_CHUNK? ALLOC_CHUNK : length);
p = xtryrealloc ( dh->private_buffer, newlen ); p = xtryrealloc (dh->private_buffer, newlen);
if ( !p ) if (!p)
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
dh->private_buffer = p; dh->private_buffer = p;
dh->private_len = newlen; dh->private_len = newlen;
dh->data = dh->private_buffer; dh->data = dh->private_buffer;
assert ( !(dh->writepos + length > dh->private_len) ); assert (!(dh->writepos + length > dh->private_len));
} }
memcpy ( dh->private_buffer + dh->writepos, buffer, length ); memcpy (dh->private_buffer + dh->writepos, buffer, length);
dh->writepos += length; dh->writepos += length;
dh->len += length; dh->len += length;
return 0; return 0;
} }
GpgmeError GpgmeError
_gpgme_data_append_string ( GpgmeData dh, const char *s ) _gpgme_data_append_string (GpgmeData dh, const char *s)
{ {
return _gpgme_data_append ( dh, s, s? strlen(s):0 ); return _gpgme_data_append (dh, s, s ? strlen(s) : 0);
} }
GpgmeError GpgmeError
_gpgme_data_append_for_xml ( GpgmeData dh, _gpgme_data_append_for_xml (GpgmeData dh,
const char *buffer, size_t len ) const char *buffer, size_t len)
{ {
const char *text, *s; const char *text, *s;
size_t n; size_t n;
int rc = 0; int rc = 0;
if ( !dh || !buffer ) if (!dh || !buffer)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
do { do
for (text=NULL, s=buffer, n=len; n && !text; s++, n-- ) { {
if ( *s == '<' ) for (text=NULL, s = buffer, n = len; n && !text; s++, n--)
{
if (*s == '<')
text = "&lt;"; text = "&lt;";
else if ( *s == '>' ) else if (*s == '>')
text = "&gt;"; /* not sure whether this is really needed */ text = "&gt;"; /* Not sure whether this is really needed. */
else if ( *s == '&' ) else if (*s == '&')
text = "&amp;"; text = "&amp;";
else if ( !*s ) else if (!*s)
text = "&#00;"; text = "&#00;";
} }
if (text) { if (text)
s--; n++; {
s--;
n++;
} }
if (s != buffer) if (s != buffer)
rc = _gpgme_data_append ( dh, buffer, s-buffer ); rc = _gpgme_data_append (dh, buffer, s-buffer);
if ( !rc && text) { if (!rc && text)
rc = _gpgme_data_append_string ( dh, text ); {
s++; n--; rc = _gpgme_data_append_string (dh, text);
s++;
n--;
} }
buffer = s; buffer = s;
len = n; len = n;
} while ( !rc && len ); }
while (!rc && len);
return rc; return rc;
} }
@ -727,31 +796,31 @@ _gpgme_data_append_for_xml ( GpgmeData dh,
* valid XML. * valid XML.
*/ */
GpgmeError GpgmeError
_gpgme_data_append_string_for_xml ( GpgmeData dh, const char *string ) _gpgme_data_append_string_for_xml (GpgmeData dh, const char *string)
{ {
return _gpgme_data_append_for_xml ( dh, string, strlen (string) ); return _gpgme_data_append_for_xml (dh, string, strlen (string));
} }
static int static int
hextobyte( const byte *s ) hextobyte(const byte *s)
{ {
int c; int c;
if( *s >= '0' && *s <= '9' ) if (*s >= '0' && *s <= '9')
c = 16 * (*s - '0'); c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' ) else if (*s >= 'A' && *s <= 'F')
c = 16 * (10 + *s - 'A'); c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' ) else if (*s >= 'a' && *s <= 'f')
c = 16 * (10 + *s - 'a'); c = 16 * (10 + *s - 'a');
else else
return -1; return -1;
s++; s++;
if( *s >= '0' && *s <= '9' ) if (*s >= '0' && *s <= '9')
c += *s - '0'; c += *s - '0';
else if( *s >= 'A' && *s <= 'F' ) else if (*s >= 'A' && *s <= 'F')
c += 10 + *s - 'A'; c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' ) else if (*s >= 'a' && *s <= 'f')
c += 10 + *s - 'a'; c += 10 + *s - 'a';
else else
return -1; return -1;
@ -759,19 +828,21 @@ hextobyte( const byte *s )
} }
/* /*
* Append a string with percent style (%XX) escape characters as XML * Append a string with percent style (%XX) escape characters as XML.
*/ */
GpgmeError GpgmeError
_gpgme_data_append_percentstring_for_xml ( GpgmeData dh, const char *string ) _gpgme_data_append_percentstring_for_xml (GpgmeData dh, const char *string)
{ {
const byte *s; const byte *s;
byte *buf, *d; byte *buf, *d;
int val; int val;
GpgmeError err; GpgmeError err;
d = buf = xtrymalloc ( strlen (string) ); d = buf = xtrymalloc (strlen (string));
for (s=string; *s; s++ ) { for (s = string; *s; s++)
if ( *s == '%' && (val=hextobyte (s+1)) != -1 ) { {
if (*s == '%' && (val = hextobyte (s+1)) != -1)
{
*d++ = val; *d++ = val;
s += 2; s += 2;
} }
@ -779,7 +850,7 @@ _gpgme_data_append_percentstring_for_xml ( GpgmeData dh, const char *string )
*d++ = *s; *d++ = *s;
} }
err = _gpgme_data_append_for_xml ( dh, buf, d - buf ); err = _gpgme_data_append_for_xml (dh, buf, d - buf);
xfree (buf); xfree (buf);
return err; return err;
} }

View File

@ -1,6 +1,6 @@
/* gpgme.c - GnuPG Made Easy /* gpgme.c - GnuPG Made Easy
* Copyright (C) 2000 Werner Koch (dd9jn) * Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 g10 Code GmbH * Copyright (C) 2001, 2002 g10 Code GmbH
* *
* This file is part of GPGME. * This file is part of GPGME.
* *
@ -29,11 +29,6 @@
#include "context.h" #include "context.h"
#include "ops.h" #include "ops.h"
#define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
#define my_isxdigit(a) ( my_isdigit((a)) \
|| ((a) >= 'A' && (a) <= 'F') \
|| ((a) >= 'f' && (a) <= 'f') )
/** /**
* gpgme_new: * gpgme_new:
* @r_ctx: Returns the new context * @r_ctx: Returns the new context
@ -46,13 +41,16 @@
GpgmeError GpgmeError
gpgme_new (GpgmeCtx *r_ctx) gpgme_new (GpgmeCtx *r_ctx)
{ {
GpgmeCtx c; GpgmeCtx ctx;
c = xtrycalloc ( 1, sizeof *c ); if (!r_ctx)
if (!c) return mk_error (Invalid_Value);
*r_ctx = 0;
ctx = xtrycalloc (1, sizeof *ctx);
if (!ctx)
return mk_error (Out_Of_Core); return mk_error (Out_Of_Core);
c->verbosity = 1; ctx->verbosity = 1;
*r_ctx = c; *r_ctx = ctx;
return 0; return 0;
} }
@ -64,32 +62,32 @@ gpgme_new (GpgmeCtx *r_ctx)
* Release all resources associated with the given context. * Release all resources associated with the given context.
**/ **/
void void
gpgme_release (GpgmeCtx c) gpgme_release (GpgmeCtx ctx)
{ {
if (!c) if (!ctx)
return; return;
_gpgme_engine_release (c->engine); _gpgme_engine_release (ctx->engine);
_gpgme_release_result (c); _gpgme_release_result (ctx);
gpgme_key_release (c->tmp_key); gpgme_key_release (ctx->tmp_key);
gpgme_data_release (c->help_data_1); gpgme_data_release (ctx->help_data_1);
gpgme_data_release (c->notation); gpgme_data_release (ctx->notation);
gpgme_signers_clear (c); gpgme_signers_clear (ctx);
if (c->signers) if (ctx->signers)
xfree (c->signers); xfree (ctx->signers);
/* FIXME: Release the key_queue. */ /* FIXME: Release the key_queue. */
xfree (c); xfree (ctx);
} }
void void
_gpgme_release_result (GpgmeCtx c) _gpgme_release_result (GpgmeCtx ctx)
{ {
_gpgme_release_verify_result (c->result.verify); _gpgme_release_verify_result (ctx->result.verify);
_gpgme_release_decrypt_result (c->result.decrypt); _gpgme_release_decrypt_result (ctx->result.decrypt);
_gpgme_release_sign_result (c->result.sign); _gpgme_release_sign_result (ctx->result.sign);
_gpgme_release_encrypt_result (c->result.encrypt); _gpgme_release_encrypt_result (ctx->result.encrypt);
_gpgme_release_passphrase_result (c->result.passphrase); _gpgme_release_passphrase_result (ctx->result.passphrase);
memset (&c->result, 0, sizeof (c->result)); memset (&ctx->result, 0, sizeof (ctx->result));
_gpgme_set_op_info (c, NULL); _gpgme_set_op_info (ctx, NULL);
} }
@ -101,13 +99,12 @@ _gpgme_release_result (GpgmeCtx c)
* all kinds of operations. It is especially useful in a passphrase callback * all kinds of operations. It is especially useful in a passphrase callback
* to stop the system from asking another time for the passphrase. * to stop the system from asking another time for the passphrase.
**/ **/
void void
gpgme_cancel (GpgmeCtx c) gpgme_cancel (GpgmeCtx ctx)
{ {
return_if_fail (c); return_if_fail (ctx);
c->cancel = 1; ctx->cancel = 1;
} }
/** /**
@ -122,11 +119,11 @@ gpgme_cancel (GpgmeCtx c)
* Return value: An XML string or NULL if no notation data is available. * Return value: An XML string or NULL if no notation data is available.
**/ **/
char * char *
gpgme_get_notation ( GpgmeCtx c ) gpgme_get_notation (GpgmeCtx ctx)
{ {
if ( !c->notation ) if (!ctx->notation)
return NULL; return NULL;
return _gpgme_data_get_as_string ( c->notation ); return _gpgme_data_get_as_string (ctx->notation);
} }
@ -158,43 +155,45 @@ gpgme_get_notation ( GpgmeCtx c )
* Return value: NULL for no info available or an XML string * Return value: NULL for no info available or an XML string
**/ **/
char * char *
gpgme_get_op_info ( GpgmeCtx c, int reserved ) gpgme_get_op_info (GpgmeCtx ctx, int reserved)
{ {
if (!c || reserved) if (!ctx || reserved)
return NULL; /*invalid value */ return NULL; /* Invalid value. */
return _gpgme_data_get_as_string (c->op_info); return _gpgme_data_get_as_string (ctx->op_info);
} }
/* /*
* Store the data object with the operation info in the * Store the data object with the operation info in the
* context. Caller should not use that object anymore. * context. Caller should not use that object anymore.
*/ */
void void
_gpgme_set_op_info (GpgmeCtx c, GpgmeData info) _gpgme_set_op_info (GpgmeCtx ctx, GpgmeData info)
{ {
assert (c); assert (ctx);
gpgme_data_release (c->op_info); gpgme_data_release (ctx->op_info);
c->op_info = NULL; ctx->op_info = NULL;
if (info) if (info)
c->op_info = info; ctx->op_info = info;
} }
GpgmeError GpgmeError
gpgme_set_protocol (GpgmeCtx c, GpgmeProtocol prot) gpgme_set_protocol (GpgmeCtx ctx, GpgmeProtocol protocol)
{ {
if (!c) if (!ctx)
return mk_error (Invalid_Value); return mk_error (Invalid_Value);
switch (prot) switch (protocol)
{ {
case GPGME_PROTOCOL_OpenPGP: case GPGME_PROTOCOL_OpenPGP:
c->use_cms = 0; ctx->use_cms = 0;
break; break;
case GPGME_PROTOCOL_CMS: case GPGME_PROTOCOL_CMS:
c->use_cms = 1; ctx->use_cms = 1;
break; break;
case GPGME_PROTOCOL_AUTO: case GPGME_PROTOCOL_AUTO:
return mk_error (Not_Implemented); return mk_error (Not_Implemented);
@ -205,25 +204,26 @@ gpgme_set_protocol (GpgmeCtx c, GpgmeProtocol prot)
return 0; return 0;
} }
/** /**
* gpgme_set_armor: * gpgme_set_armor:
* @c: the contect * @ctx: the context
* @yes: boolean value to set or clear that flag * @yes: boolean value to set or clear that flag
* *
* Enable or disable the use of an ascii armor for all output. * Enable or disable the use of an ascii armor for all output.
**/ **/
void void
gpgme_set_armor ( GpgmeCtx c, int yes ) gpgme_set_armor (GpgmeCtx ctx, int yes)
{ {
if ( !c ) if (!ctx)
return; /* oops */ return;
c->use_armor = yes; ctx->use_armor = yes;
} }
/** /**
* gpgme_get_armor: * gpgme_get_armor:
* @c: the context * @ctx: the context
* *
* Return the state of the armor flag which can be changed using * Return the state of the armor flag which can be changed using
* gpgme_set_armor(). * gpgme_set_armor().
@ -231,32 +231,32 @@ gpgme_set_armor ( GpgmeCtx c, int yes )
* Return value: Boolean whether armor mode is to be used. * Return value: Boolean whether armor mode is to be used.
**/ **/
int int
gpgme_get_armor (GpgmeCtx c) gpgme_get_armor (GpgmeCtx ctx)
{ {
return c && c->use_armor; return ctx && ctx->use_armor;
} }
/** /**
* gpgme_set_textmode: * gpgme_set_textmode:
* @c: the context * @ctx: the context
* @yes: boolean flag whether textmode should be enabled * @yes: boolean flag whether textmode should be enabled
* *
* Enable or disable the use of the special textmode. Textmode is for example * Enable or disable the use of the special textmode. Textmode is for example
* used for the RFC2015 signatures; note that the updated RFC 3156 mandates * used for the RFC2015 signatures; note that the updated RFC 3156 mandates
* that the MUA does some preparations so that textmode is not anymore needed. * that the MUA does some preparations so that textmode is not needed anymore.
**/ **/
void void
gpgme_set_textmode ( GpgmeCtx c, int yes ) gpgme_set_textmode (GpgmeCtx ctx, int yes)
{ {
if ( !c ) if (!ctx)
return; /* oops */ return;
c->use_textmode = yes; ctx->use_textmode = yes;
} }
/** /**
* gpgme_get_textmode: * gpgme_get_textmode:
* @c: the context * @ctx: the context
* *
* Return the state of the textmode flag which can be changed using * Return the state of the textmode flag which can be changed using
* gpgme_set_textmode(). * gpgme_set_textmode().
@ -264,16 +264,15 @@ gpgme_set_textmode ( GpgmeCtx c, int yes )
* Return value: Boolean whether textmode is to be used. * Return value: Boolean whether textmode is to be used.
**/ **/
int int
gpgme_get_textmode (GpgmeCtx c) gpgme_get_textmode (GpgmeCtx ctx)
{ {
return c && c->use_textmode; return ctx && ctx->use_textmode;
} }
/** /**
* gpgme_set_keylist_mode: * gpgme_set_keylist_mode:
* @c: the context * @ctx: the context
* @mode: listing mode * @mode: listing mode
* *
* This function changes the default behaviour of the keylisting functions. * This function changes the default behaviour of the keylisting functions.
@ -281,17 +280,17 @@ gpgme_get_textmode (GpgmeCtx c)
* information about key validity. * information about key validity.
**/ **/
void void
gpgme_set_keylist_mode ( GpgmeCtx c, int mode ) gpgme_set_keylist_mode (GpgmeCtx ctx, int mode)
{ {
if (!c) if (!ctx)
return; return;
c->keylist_mode = mode; ctx->keylist_mode = mode;
} }
/** /**
* gpgme_set_passphrase_cb: * gpgme_set_passphrase_cb:
* @c: the context * @ctx: the context
* @cb: A callback function * @cb: A callback function
* @cb_value: The value passed to the callback function * @cb_value: The value passed to the callback function
* *
@ -308,7 +307,7 @@ gpgme_set_keylist_mode ( GpgmeCtx c, int mode )
* </literal> * </literal>
* and called whenever gpgme needs a passphrase. DESC will have a nice * and called whenever gpgme needs a passphrase. DESC will have a nice
* text, to be used to prompt for the passphrase and R_HD is just a parameter * text, to be used to prompt for the passphrase and R_HD is just a parameter
* to be used by the callback it self. Becuase the callback returns a const * to be used by the callback it self. Because the callback returns a const
* string, the callback might want to know when it can release resources * string, the callback might want to know when it can release resources
* assocated with that returned string; gpgme helps here by calling this * assocated with that returned string; gpgme helps here by calling this
* passphrase callback with an DESC of %NULL as soon as it does not need * passphrase callback with an DESC of %NULL as soon as it does not need
@ -317,18 +316,18 @@ gpgme_set_keylist_mode ( GpgmeCtx c, int mode )
* *
**/ **/
void void
gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value ) gpgme_set_passphrase_cb (GpgmeCtx ctx, GpgmePassphraseCb cb, void *cb_value)
{ {
if (c) if (ctx)
{ {
c->passphrase_cb = cb; ctx->passphrase_cb = cb;
c->passphrase_cb_value = cb_value; ctx->passphrase_cb_value = cb_value;
} }
} }
/** /**
* gpgme_set_progress_cb: * gpgme_set_progress_cb:
* @c: the context * @ctx: the context
* @cb: A callback function * @cb: A callback function
* @cb_value: The value passed to the callback function * @cb_value: The value passed to the callback function
* *
@ -336,7 +335,7 @@ gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value )
* *
* The callback function is defined as: * The callback function is defined as:
* <literal> * <literal>
* typedef void (*GpgmeProgressCb) (void*cb_value, * typedef void (*GpgmeProgressCb) (void *cb_value,
* const char *what, int type, * const char *what, int type,
* int curretn, int total); * int curretn, int total);
* </literal> * </literal>
@ -344,20 +343,11 @@ gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value )
* status in the file doc/DETAILS of the GnuPG distribution. * status in the file doc/DETAILS of the GnuPG distribution.
**/ **/
void void
gpgme_set_progress_cb ( GpgmeCtx c, GpgmeProgressCb cb, void *cb_value ) gpgme_set_progress_cb (GpgmeCtx ctx, GpgmeProgressCb cb, void *cb_value)
{ {
if (c) if (ctx)
{ {
c->progress_cb = cb; ctx->progress_cb = cb;
c->progress_cb_value = cb_value; ctx->progress_cb_value = cb_value;
} }
} }