summaryrefslogtreecommitdiffstats
path: root/libtdenetwork/libgpgme-copy
diff options
context:
space:
mode:
Diffstat (limited to 'libtdenetwork/libgpgme-copy')
-rw-r--r--libtdenetwork/libgpgme-copy/Makefile.am1
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/ChangeLog829
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/Makefile.am58
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-buffer.c550
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-client.c234
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-connect.c79
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-defs.h323
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-handler.c774
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-inquire.c241
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-io.c87
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-listen.c157
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-logging.c241
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-pipe-connect.c889
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-pipe-server.c187
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-socket-connect.c184
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-socket-server.c187
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-socket.c148
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-uds.c311
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan-util.c171
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/assuan.h565
-rw-r--r--libtdenetwork/libgpgme-copy/assuan/funopen.c64
-rwxr-xr-xlibtdenetwork/libgpgme-copy/assuan/mkerrors228
-rw-r--r--libtdenetwork/libgpgme-copy/configure.in.in364
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ChangeLog5312
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/Makefile.am50
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath-pth-compat.c123
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath-pth.c178
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath-pthread-compat.c104
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath-pthread.c175
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath.c169
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ath.h89
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/context.h118
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/conversion.c414
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data-compat.c209
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data-fd.c78
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data-mem.c251
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data-stream.c101
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data-user.c89
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data.c293
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/data.h132
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/debug.c221
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/debug.h127
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/decrypt-verify.c103
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/decrypt.c340
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/delete.c109
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/edit.c177
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/encrypt-sign.c110
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/encrypt.c222
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/engine-backend.h110
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/engine-gpgsm.c1750
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/engine.c744
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/engine.h133
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/error.c92
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/export.c117
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/fakes.c24
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/funopen.c43
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/genkey.c206
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/get-env.c59
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/gpgme.c582
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/gpgme.h1706
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/import.c273
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/io.h65
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/isascii.c28
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/key.c722
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/keylist.c980
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/libgpgme.vers167
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/memrchr.c210
-rwxr-xr-xlibtdenetwork/libgpgme-copy/gpgme/mkstatus52
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/op-support.c280
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/ops.h169
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/passphrase.c153
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/posix-io.c497
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/posix-sema.c62
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/posix-util.c57
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/priv-io.h67
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/progress.c81
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/putc_unlocked.c31
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/rungpg.c2111
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/sema.h67
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/sig-notation.c260
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/sign.c328
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/signers.c95
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/status-table.h94
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/stpcpy.c55
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/trust-item.c171
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/trustlist.c248
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/util.h106
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/vasprintf.c192
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/verify.c992
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/version.c231
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/w32-io.c1152
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/w32-sema.c115
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/w32-util.c317
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/wait-global.c384
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/wait-private.c147
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/wait-user.c122
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/wait.c204
-rw-r--r--libtdenetwork/libgpgme-copy/gpgme/wait.h82
98 files changed, 33099 insertions, 0 deletions
diff --git a/libtdenetwork/libgpgme-copy/Makefile.am b/libtdenetwork/libgpgme-copy/Makefile.am
new file mode 100644
index 000000000..34527396a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = assuan gpgme
diff --git a/libtdenetwork/libgpgme-copy/assuan/ChangeLog b/libtdenetwork/libgpgme-copy/assuan/ChangeLog
new file mode 100644
index 000000000..b53ac7fd3
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/ChangeLog
@@ -0,0 +1,829 @@
+2006-11-22 Werner Koch <wk@g10code.com>
+
+ * assuan-handler.c (fun1_cookie_write, fun2_cookie_write): New.
+ (assuan_get_data_fp) [HAVE_FUNOPEN]: Use it.
+
+2006-11-21 Werner Koch <wk@g10code.com>
+
+ * Makefile.am (libassuan_pth_a_CFLAGS): New.
+
+ * assuan-pipe-server.c (_assuan_release_context): Free CMDTBL.
+
+2006-11-14 Werner Koch <wk@g10code.com>
+
+ * libassuan.m4 (AM_CHECK_LIBASSUAN): New.
+
+ * assuan-handler.c (assuan_register_post_cmd_notify)
+ (assuan_register_post_cmd_notify): New.
+ * assuan-util.c (assuan_set_io_monitor): New.
+ * assuan-buffer.c (_assuan_read_line): Use it.
+ (_assuan_write_line): Ditto.
+ (_assuan_cookie_write_data): Ditto.
+ (_assuan_cookie_write_flush): Ditto.
+
+2006-10-18 Werner Koch <wk@g10code.com>
+
+ * libassuan.m4: Pass "pthread" to the common macro. Reported by
+ Rex Dieter.
+
+2006-10-16 Werner Koch <wk@g10code.com>
+
+ * mkerrors: Map ASSUAN_Not_Confirmed.
+
+2006-10-10 Werner Koch <wk@g10code.com>
+
+ * libassuan.m4 (AM_PATH_LIBASSUAN_PTH)
+ (AM_PATH_LIBASSUAN_PTHREAD): Fixed.
+
+ * assuan-buffer.c (assuan_sendfd): Implement a runtime detection
+ of implemented descripotr passing.
+
+ * assuan-uds.c: Take care of USE_DESCRIPTOR_PASSING.
+
+ * assuan-defs.h: Add missing semicolon.
+
+2006-10-09 Werner Koch <wk@g10code.com>
+
+ * assuan-handler.c (process_request): Use weak pragma for the sake
+ of old gcc's. Reported by Alain Guibert.
+
+ * assuan-io.c: Removed Pth support.
+ * assuan-io-pth.c: New. Based on assuan-io.c
+
+2006-10-06 Werner Koch <wk@g10code.com>
+
+ * libassuan-config.in: New options --api-version and --thread.
+
+2006-10-04 Werner Koch <wk@g10code.com>
+
+ * assuan-client.c (assuan_transact): Need to map old assuan status
+ codes so that for example CANCELED is correctly mapped.
+
+2006-09-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-client.c (assuan_transact): Do not convert error on
+ status line, it is already a gpg-error. Do convert
+ ASSUAN_Server_Fault.
+
+2006-09-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan.h (assuan_init_socket_server_ext)
+ [_ASSUAN_EXT_SYM_PREFIX]: Fix typo in macro.
+
+2006-09-19 Werner Koch <wk@g10code.com>
+
+ * assuan-defs.h (putc_unlocked): Add prototype.
+
+ * assuan-socket-server.c (accept_connection): Made LEN a socklen_t.
+
+ * assuan.h: Replaced assuan error code enum by simple defines and
+ made assuan_error_t an int.
+ * mkerrors: Changed parser accordingly.
+
+2006-09-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-pipe-connect.c: Add hacks for Slowaris.
+ * assuan-socket.c: Likewise here.
+
+ * assuan.h (enum): Avoid trailing comma in enumerator list. Ugh.
+
+ * mkerrors (_assuan_error): Change return type to assuan_error_t.
+ * assuan-buffer.c (_assuan_read_line): Change return type to
+ assuan_error_t. Map returned value of -1.
+ (_assuan_write_line): Change type of RC to assuan_error_t.
+ * assuan-defs.h (_assuan_read_line, _assuan_error): Likewise for
+ prototypes.
+
+ * assuan-defs.h (unsetenv): Define correctly.
+
+2006-09-14 Werner Koch <wk@g10code.com>
+
+ * assuan-io.c (_assuan_waitpid): New. Changed all waitpid calls
+ to this.
+
+ * assuan.h (_ASSUAN_DEPRECATED): New internal macro.
+ (assuan_pipe_connect2): Declare deprecated.
+ (assuan_init_connected_socket_server): Declare deprecated.
+
+ * assuan-connect.c (assuan_get_peercred): New.
+ * assuan-socket-server.c (accept_connection_bottom): Save uid and gid.
+
+2006-09-13 Werner Koch <wk@g10code.com>
+
+ * assuan-client.c (assuan_transact): Need to map the error code.
+ * mkerrors: Need to map ASSUAN_No_Secret_Key.
+
+ * assuan-pipe-server.c (is_valid_socket): New.
+ (assuan_init_pipe_server): Use UDS with the environmet variable is
+ set and a valid descriptor is given. Ignore FILEDES in this case.
+
+ * assuan-socket-server.c (assuan_init_socket_server_ext): New.
+ Changed other init fucntions to make use of it.
+
+ * assuan-handler.c (assuan_command_parse_fd): Allow for lowercase
+ "fd".
+ (std_handler_reset): Close pending fds.
+ * assuan-uds.c (uds_receivefd): Fixed.
+ (_assuan_uds_close_fds): New.
+
+ * assuan-socket-connect.c (assuan_socket_connect_ext): New. Takes
+ all code of assuan_socket_connect plus an option to use sendmsg.
+ * assuan-pipe-connect.c (assuan_pipe_connect_ext): New arg FLAGS.
+
+2006-09-12 Werner Koch <wk@g10code.com>
+
+ * assuan-buffer.c (_assuan_write_line): Also log the prefix.
+
+ * assuan-defs.h (DIM, DIMof): New.
+
+ * assuan-domain-server.c: Removed.
+ * assuan-domain-connect.c: Renamed to ..
+ * assuan-uds.c: this.
+ (domain_reader, domain_writer, domain_sendfd, domain_receivefd)
+ (assuan_domain_connect, _assuan_domain_init): Removed.
+ (uds_reader, uds_writer, uds_sendfd, uds_receivefd)
+ (_assuan_init_uds_io): New.
+ (_assuan_uds_deinit): New.
+
+ * assuan-io.c (_assuan_simple_sendmsg, _assuan_simple_recvmsg): New.
+ (my_pth_fdmode, my_pth_select): New.
+
+2006-09-11 Werner Koch <wk@g10code.com>
+
+ * assuan-pipe-server.c (assuan_init_pipe_server): Allow for
+ FILEDES to be NULL and try to start as a socketpair server in this
+ case.
+
+ * assuan-pipe-connect.c (assuan_pipe_connect2): Split up into two
+ functions (unix and w32) for clarity.
+ (pipe_connect_unix): This is the new fucntion. Add USE_CMSG flag.
+ (pipe_connect_w32): Ditto.
+ (initial_handshake): Factored out code.
+ (socketpair_connect): New.
+ (assuan_pipe_connect_ext): New.
+ (do_finish): Handle case if outbound and inbound fd are the same.
+ This is to support socketpairs.
+
+2006-09-10 Werner Koch <wk@g10code.com>
+
+ * assuan-util.c (_assuan_log_print_buffer)
+ (_assuan_log_sanitized_string,assuan_set_log_stream): Moved to ..
+ * assuan-logging.c: .. here.
+ (_assuan_log_print_buffer): Only print the leading bytes in hex
+ log mode unless the new env variable ASSUAN_FULL_LOGGING has been
+ set.
+ (_assuan_set_default_log_stream): Test this env variable.
+
+2006-09-06 Werner Koch <wk@g10code.com>
+
+ * assuan.h (_ASSUAN_ONLY_GPG_ERRORS): New.
+
+ * assuan-handler.c (dispatch_command): Use Syntax_Error instead of
+ Invalid_Command.
+
+ * assuan-domain-connect.c: Changed alloc malloc/free/realloc to
+ xtrymalloc et al.
+ (read_int, write_int): Make args void pointers.
+ (domain_receivefd): Take care of realloc shrinking failure.
+
+ * assuan-buffer.c (_assuan_read_line, _assuan_write_line)
+ (assuan_write_line, _assuan_cookie_write_data)
+ (_assuan_cookie_write_flush): Print the inbound fd instead of the
+ address of the context when logging I/0. This makes it more
+ readable.
+
+2006-09-05 Werner Koch <wk@g10code.com>
+
+ * assuan-defs.h (err_code, err_is_eof): New.
+
+ * mkerrors (_assuan_error): New. Wrapped all error code
+ assignments in a call to this.
+ (assuan_strerror): Map gpg-style error codes back. Also print a
+ string for the old EOF code.
+ (assuan_set_assuan_err_source): New.
+
+ * assuan-logging.c (_assuan_log_printf): Do not change ERRNO and
+ print the pid.
+
+ * assuan-domain-connect.c (domain_reader): Replaced plain printf
+ by assuan_log function.
+
+2005-10-24 Werner Koch <wk@g10code.com>
+
+ * putc_unlocked.c, memrchr.c, isascii.c, funopen.c: Changed
+ distribution terms to LGPL. This are small and trivial files so
+ there are no obstacles of doing so.
+ * assuan-socket.c: Likewise, the stated GPL was not intended.
+
+2005-10-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-defs.h (setenv, unsetenv, clearenv) [!HAVE_SETENV]:
+ Define to _assuan_*.
+ * setenv.c: Include "assuan-defs.h".
+ (__add_to_environ): Make static.
+
+2005-10-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-defs.h (memrchr) [!HAVE_MEMRCHR]: New prototype.
+ (stpcpy) [!HAVE_STPCPY]: Likewise.
+ * stpcpy.c: New LGPL'ed file from the GNU C Library.
+ * setenv.c: New file.
+ * assuan-domain-connect.c (read_int): New function.
+ (write_int): New function.
+ (domain_reader): Use read_int.
+ (domain_sendfd): Use write_int.
+
+2005-10-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan.h (assuan_pipe_connect, assuan_pipe_connect2): Make type
+ of ARGV parameter const in prototype.
+ * assuan-pipe-connect.c (assuan_pipe_connect,
+ assuan_pipe_connect2): Likewise in declaration.
+ (assuan_pipe_connect2): Add braindead cast to make execv happy.
+
+ * assuan-client.c (assuan_transact): Change LINE, S and D from
+ unsigned char * to char * to silence gcc warning.
+ * assuan-util.c (_assuan_log_sanitized_string): Add explicit cast
+ to silence gcc warning.
+ * assuan-inquire.c (assuan_inquire): Likewise.
+
+2005-08-19 Werner Koch <wk@g10code.com>
+
+ * funopen.c, assuan-socket.c: Copied from libassuan CVS.
+ * assuan-pipe-connect.c (assuan_pipe_connect2): Add missing
+ declaration of PID.
+
+2005-08-09 Werner Koch <wk@g10code.com>
+
+ * README.1st: Adjusted to cope with changes done in upstream Assuan.
+
+ Merged changes for W32 support from libassuan.
+
+ * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: New.
+ * assuan-io.c [_ASSUAN_NO_PTH]: New.
+ * assuan-pipe-connect.c (fix_Q_SIGNALS) [_ASSUAN_NO_FIXED_SIGNALS]: New.
+ (assuan_pipe_connect2) [_ASSUAN_USE_DOUBLE_FORK]: Use double fork.
+ (fix_Q_SIGNALS) [_ASSUAN_USE_DOUBLE_FORK]: Do not wait..
+ * assuan-logging.c, assuan-io.c: Include config.h
+ Replaced all usages of _WIN32 by the new HAVE_W32_SYSTEM because
+ there is nothing winning in this API.
+ * assuan-pipe-connect.c (assuan_pipe_connect2) [_WIN32]: Return
+ error Not Imlemented.
+ * assuan-logging.c (_assuan_w32_strerror): New.
+ * assuan-defs.h (w32_strerror): new.
+ * assuan-pipe-connect.c (assuan_pipe_connect2, fix_Q_SIGNALS):
+ Factored signal code out to new function.
+ (build_w32_commandline, create_inheritable_pipe): New. Taken
+ from gnupg 1.9.
+ (assuan_pipe_connect2) [W32]: Implemented for W32.
+ * assuan-pipe-server.c (assuan_init_pipe_server) [W32]: Map file
+ descriptors using _get_osfhandle.
+ * assuan-socket-connect.c (assuan_socket_connect) [W32]: Allow for
+ a drive letter in the path.
+ * assuan-client.c (assuan_transact): Handle empty and comment
+ commands correctly.
+ * assuan-util.c (_assuan_calloc): Avoid integer overflow.
+ * assuan-util.c (assuan_set_flag, assuan_get_flag): New.
+ * assuan-defs.h (struct assuan_context_s): New field flags.
+ * assuan.h (assuan_flag_t): New with one flag value
+ ASSUAN_NO_WAITPID for now.
+ * assuan-pipe-connect.c (do_finish): Take care of the no_waitpid
+ flag.
+ * mkerrors: Include config.h into assuan-errors.c. This is
+ required so that assuan.h knows about the W32 macro.
+
+2005-08-09 Timo Schulz <twoaday@g10code.com> (ported from libassuan by wk)
+
+ * assuan-io.c (_assuan_simple_read, _assuan_simple_write): W32
+ support.
+ * assuan-socket.c (_assuan_close): New.
+ (_assuan_sock_new): New.
+ (_assuan_sock_bind): New.
+
+2005-03-22 Werner Koch <wk@g10code.com>
+
+ * assuan-defs.h (struct assuan_io): Renamed elements READ and
+ WRITE to READFNC and WRITEFNC to avoid problems with read defined
+ as macro. Changed callers. Noted by Ville Skyttä.
+
+2004-12-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-pipe-connect.c (do_finish): Do not wait for child to finish.
+ (assuan_pipe_connect): Use double-fork approach.
+ * assuan-connect.c (assuan_disconnect): Do not write BYE to the
+ status line.
+
+2004-12-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * README.1st: Add copyright notice.
+
+2004-06-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-domain-connect.c [HAVE_SYS_UIO_H]: Include <sys/uio.h>.
+
+ * assuan-handler.c: Include <errno.h>.
+
+2004-06-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-buffer.c (assuan_write_line): If the line is longer than
+ the maximum line length, bail out early.
+
+2004-04-19 Werner Koch <wk@gnupg.org>
+
+ * assuan-socket-connect.c: Include sys/types.h
+ * assuan-socket-server.c: Ditto
+ * assuan-domain-connect.c: Ditto.
+
+2004-02-18 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (assuan_get_data_fp): Fail with ENOSYS if we
+ can't implement this.
+
+2004-02-13 Werner Koch <wk@gnupg.org>
+
+ * assuan-domain-connect.c: Removed the unneeded alloca.h
+
+2003-08-13 Werner Koch <wk@gnupg.org>
+
+ * assuan-inquire.c (assuan_inquire): Increase length of cmdbuf to
+ the Assuan limit.
+
+2003-06-24 Werner Koch <wk@gnupg.org>
+
+ * mkerrors: Kludge to print libgpg-error values in an easier
+ readable way.
+
+2003-04-29 Werner Koch <wk@gnupg.org>
+
+ * libassuan.m4: New. Based on libgrypt.m4.
+ * Makefile.am (m4data_DATA): New.
+
+ * assuan.h (AssuanCommand): Removed.
+
+ * assuan-handler.c: Remove the cmd_id element,
+ (assuan_register_command): Likewise. Note that semantics changed.
+ (_assuan_register_std_commands): Adjusted.
+
+2003-02-22 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (bin_SCRIPTS): Renamed from bin_PROGRAMS.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (libassuan_a_LIBADD): New variable.
+ * funopen.c: Move from ../common.
+ * isascii.c: Likewise.
+ * memrchr.c: Likewise.
+ * putc_unlocked.c: Likewise.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-handler.c (_IO_cookie_io_functions_t): Remove.
+ (cookie_io_functions_t): Remove.
+ (fopencookie): Remove prototype.
+ (assuan_get_data_fp): Use funopen, not fopencookie.
+
+2003-02-18 Neal H. Walfield <neal@g10code.de>
+
+ * libassuan-config.in: New file.
+ * Makefile.am (bin_PROGRAMS): New variable.
+
+2003-02-17 Neal H. Walfield <neal@g10code.de>
+
+ * .cvsignore: New file.
+
+2003-02-17 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (lib_LIBRARIES): Use this instead of . . .
+ (noinst_LIBRARIES): . . . this.
+ (include_HEADERS): New variable.
+ (libassuan_a_SOURCES): Remove assuan.h, add assuan-logging.c.
+
+ * assuan.h (assuan_set_assuan_log_stream): New prototype.
+ (assuan_get_assuan_log_stream): Likewise.
+ (assuan_get_assuan_log_prefix): Likewise.
+ * assuan-logging.c: New file.
+
+ * assuan-buffer.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (my_log_prefix): Remove function.
+ (_assuan_read_line): Use assuan_get_assuan_log_prefix in lieu of
+ my_log_prefix.
+ (assuan_write_line): Likewise.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ * assuan-domain-connect.c (LOGERROR, LOGERROR1, LOGERROR2,
+ LOGERRORX): Remove.
+ (LOG): New macro.
+ (domain_reader): Use it.
+ (domain_writer): Likewise.
+ (domain_sendfd): Likewise.
+ (domain_receivefd): Likewise.
+ (_assuan_domain_init): Likewise.
+ (assuan_domain_connect): Likewise.
+ * assuan-pipe-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_pipe_connect): Use it.
+ * assuan-socket-connect.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (LOGERROR, LOGERROR1, LOGERROR2, LOGERRORX): Remove.
+ (LOG): New macro.
+ (assuan_socket_connect): Use it.
+ (socket_reader): Remove dead code.
+ (socket_writer): Likewise.
+ * assuan-util.c [HAVE_JNLIB_LOGGIN]: Do not include
+ "../jnlib/logging.h".
+ (_assuan_log_sanitized_string): Use assuan_get_assuan_log_stream,
+ not jnlib.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h (assuan_command_parse_fd): New prototype.
+ * assuan-handler.c (assuan_command_parse_fd): Rename from
+ parse_cmd_input_output. Export.
+ (std_handler_input): Update to use assuan_command_parse_fd.
+ (std_handler_output): Likewise.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h (assuan_sendfd): New prototype.
+ (assuan_receivefd): New prototype.
+ * assuan-buffer.c (assuan_sendfd): New function.
+ (assuan_receivefd): New function.
+ * assuan-handler.c (parse_cmd_input_output): Recognize incoming
+ file descriptors and act appropriately.
+ * assuan-defs.h (struct assuan_io): Add fields sendfd and
+ receivefd.
+ (struct assuan_context_s): Add fields pendingfds and
+ pendingfdscount.
+ * assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
+ new features.
+ * assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
+ descriptors.
+ (domain_reader): Receive file descriptors.
+ (domain_sendfd): New function.
+ (domain_receivefd): New function.
+ (_assuan_domain_init): Update initialization code to reflect new
+ features.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-domain-connect.c (do_finish): Remove.
+ (_assuan_domain_init): Use default handlers where possible.
+ Add an assert and update comments.
+ * assuan-domain-server.c (accept_connection): Remove.
+ (assuan_init_domain_server): Use default handlers where possible.
+ Put the server in pipe mode: it can only be used by a single
+ client.
+
+2002-11-24 Neal H. Walfield <neal@g10code.de>
+
+ * assuan.h: Add prototype for assuan_domain_connect and
+ assuan_init_domain_server.
+ * assuan-defs.h: Include <unistd.h>.
+ Add prototype for _assuan_domain_init.
+ * assuan-domain-connect.c: New file.
+ * assuan-domain-server.c: New file.
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-domain-connect.c
+ and assuan-domain-server.c
+
+2002-11-23 Neal H. Walfield <neal@g10code.de>
+
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+ * assuan-io.c: Restore.
+ (_assuan_simple_read): Rename from _assuan_read.
+ (_assuan_simple_write): Rename from _assuan_write.
+ * assuan-defs.h (_assuan_simple_read): New prototype.
+ (_assuan_simple_write): Likewise.
+ * assuan-pipe-server.c (pipe_reader): Remove.
+ (pipe_writer): Remove.
+ (_assuan_new_context): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-connect.c (socket_reader): Remove.
+ (socket_writer): Remove.
+ (assuan_socket_connect): Initialize IO is with _assuan_simple_read
+ and _assuan_simple_write.
+ * assuan-socket-server.c (io): New local variable.
+ (assuan_init_socket_server): Initialize CTX->io.
+ (assuan_init_connected_socket_server): Likewise.
+
+2002-11-23 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-buffer.c (readline): Use memrchr.
+ (_assuan_read_line): Rewritten to use the string functions.
+
+2002-11-20 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-socket-connect.c (assuan_socket_connect): Pass PF_LOCAL
+ to socket(), not AF_UNIX: it expects a PF_* macro and the former
+ is more portable.
+ (assuan_socket_connect): Use AF_LOCAL, not AF_UNIX which is more
+ POSIXy.
+
+2002-11-20 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-defs.h (struct assuan_io): New structure.
+ (struct assuan_context_s): New field, io.
+ (_assuan_read): Depreciated.
+ (_assuan_write): Likewise.
+ * assuan-pipe-server.c: Include <unistd.h>.
+ (pipe_reader): New function.
+ (pipe_writer): Likewise.
+ (_assuan_new_context.IO): New local static. Set to pipe_reader
+ and pipe_writer. Use it to initialize new context.
+ * assuan-socket-connect.c (socket_reader): New function.
+ (socket_writer): New function.
+ (assuan_socket_connect.IO): New local static. Set to socket_reader
+ and socket_writer. Use it to initialize new context.
+ * assuan-buffer.c (writen): Take an ASSUAN_CONTEXT rather than a
+ file descriptor. Do not use _assuan_write but the write method
+ in the supplied context.
+ (readline): Likewise for _assuan_read.
+ (assuan_write_line): When calling writen, pass CTX; not the file
+ descriptor directly.
+ (_assuan_cookie_write_data): Likewise.
+ (_assuan_cookie_write_flush): Likewise.
+ (_assuan_read_line): Likewise for readline.
+ * Makefile.am (libassuan_a_SOURCES): Remove assuan-io.c.
+ * assuan-io.c: Removed.
+
+2002-11-10 Werner Koch <wk@gnupg.org>
+
+ * assuan-pipe-connect.c (assuan_pipe_connect): Changed the order
+ of the dups to handle cases where we have already used fd 2 for
+ other things.
+
+2002-10-31 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-util.c: Include <ctype.h>.
+ (_assuan_log_print_buffer): Elide the magic numbers preferring the
+ standard isfoo functions. Use putc_unlocked where possible.
+ (_assuan_log_sanitized_string): Rewrite to use putc_unlocked and
+ the isfoo functions.
+
+2002-09-05 Neal H. Walfield <neal@g10code.de>
+
+ * assuan-defs.h (_assuan_read_wrapper): Depreciated.
+ * assuan-util.c (_assuan_read_wrapper): Removed.
+ * assuan-defs.h (_assuan_write_wrapper): Depreciated.
+ * assuan-util.c (_assuan_write_wrapper): Removed.
+ * assuan.h (assuan_set_io_fun): Depreciated.
+ * assuan-util.c (assuan_set_io_fun): Removed.
+
+ * assuan-defs.h (_assuan_read): New function.
+ (_assuan_write): Likewise.
+ * assuan-io.c: New file.
+
+ * assuan-buffer.c (writen): Use _assuan_write rather than doing
+ the work here.
+ (readline): Likewise for _assuan_read.
+
+ * Makefile.am (libassuan_a_SOURCES): Add assuan-io.c.
+
+2002-08-16 Werner Koch <wk@gnupg.org>
+
+ * assuan.h: Renamed Bad_Certificate_Path to Bad_Certificate_Chain.
+
+2002-07-30 Werner Koch <wk@gnupg.org>
+
+ Changed the license from GPL to LGPL.
+
+2002-07-23 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (_IO_cookie_io_functions_t): Define it here if
+ it does not exists.
+
+2002-06-27 Werner Koch <wk@gnupg.org>
+
+ * assuan-pipe-connect.c (assuan_pipe_connect): No special handling
+ for the log_fd and stderr. Connect stderr to /dev/null if it
+ should not be retained.
+
+2002-06-26 Werner Koch <wk@gnupg.org>
+
+ * assuan-buffer.c (assuan_write_line): Make sure we never
+ accidently print an extra LF.
+
+2002-05-23 Werner Koch <wk@gnupg.org>
+
+ * assuan-util.c (assuan_set_io_func): New.
+ * assuan-buffer.c (writen, readline): Use the new functions
+ instead of pth.
+ * assuan-socket-server.c (accept_connection): Don't use the
+ pth_accept - using the assuan included accept code would be a bad
+ idea within Pth so we don't need a replacement function.
+
+2002-05-22 Werner Koch <wk@gnupg.org>
+
+ * assuan-socket-server.c (assuan_init_connected_socket_server): New.
+ (accept_connection): Factored most code out to..
+ (accept_connection_bottom): .. new function.
+
+2002-04-04 Werner Koch <wk@gnupg.org>
+
+ * assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug
+ output.
+
+2002-03-06 Werner Koch <wk@gnupg.org>
+
+ * assuan-client.c (_assuan_read_from_server): Detect END.
+ (assuan_transact): Pass it to the data callback.
+
+2002-02-27 Werner Koch <wk@gnupg.org>
+
+ * assuan-client.c (assuan_transact): Add 2 more arguments to
+ support status lines. Passing NULL yields the old behaviour.
+
+ * assuan-handler.c (process_request): Flush data lines send
+ without using the data fp.
+
+2002-02-14 Werner Koch <wk@gnupg.org>
+
+ * assuan-inquire.c (assuan_inquire): Check for a cancel command
+ and return ASSUAN_Canceled. Allow for non-data inquiry.
+
+ * assuan.h: Add a few token specific error codes.
+
+2002-02-13 Werner Koch <wk@gnupg.org>
+
+ * assuan-defs.h (assuan_context_s): New var CLIENT_PID.
+ * assuan-pipe-server.c (_assuan_new_context): set default value.
+ * assuan-socket-server.c (accept_connection): get the actual pid.
+
+2002-02-12 Werner Koch <wk@gnupg.org>
+
+ * assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write.
+ * assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto.
+
+2002-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (MOSTLYCLEANFILES): New variable.
+
+2002-01-23 Werner Koch <wk@gnupg.org>
+
+ * assuan-socket-connect.c (LOGERRORX): and removed typo.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs.
+
+2002-01-21 Werner Koch <wk@gnupg.org>
+
+ * assuan-connect.c: Move all except assuan_get_pid to...
+ * assuan-pipe-connect.c: this.
+ (assuan_pipe_disconnect): Removed.
+ (do_finish, do_deinit): New
+ (assuan_pipe_connect): and set them into the context.
+ * assuan-socket-connect.c: New.
+
+ * assuan-util.c (_assuan_log_sanitized_string): New.
+
+ * assuan-pipe-server.c (assuan_init_pipe_server): Factored most
+ code out to ...
+ (_assuan_new_context): new func.
+ (_assuan_release_context): New
+ * assuan-connect.c (assuan_pipe_connect): Use the new functions.
+
+2002-01-20 Werner Koch <wk@gnupg.org>
+
+ * assuan.h: Added Invalid Option error code.
+
+ * assuan-handler.c (std_handler_option): New.
+ (std_cmd_tbl): Add OPTION as standard command.
+ (assuan_register_option_handler): New.
+ (dispatch_command): Use case insensitive matching as a fallback.
+ (my_strcasecmp): New.
+
+2002-01-19 Werner Koch <wk@gnupg.org>
+
+ * assuan-buffer.c (_assuan_read_line): Add output logging.
+ (assuan_write_line): Ditto.
+ (_assuan_cookie_write_data): Ditto.
+ (_assuan_cookie_write_flush): Ditto.
+ * assuan-util.c (_assuan_log_print_buffer): New.
+ (assuan_set_log_stream): New.
+ (assuan_begin_confidential): New.
+ (assuan_end_confidential): New.
+
+ * assuan-defs.h: Add a few handler variables.
+ * assuan-pipe-server.c (assuan_deinit_pipe_server): Removed.
+ (deinit_pipe_server): New.
+ (assuan_deinit_server): New. Changed all callers to use this.
+ * assuan-listen.c (assuan_accept): Use the accept handler.
+ * assuan-handler.c (process_request): Use the close Handler.
+ * assuan-socket-server.c: New.
+
+2002-01-14 Werner Koch <wk@gnupg.org>
+
+ * assuan-client.c (_assuan_read_from_server): Skip spaces after
+ the keyword.
+
+2002-01-03 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (assuan_set_okay_line): New.
+ (process_request): And use it here.
+
+2002-01-02 Werner Koch <wk@gnupg.org>
+
+ * assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a
+ hidden 0 behind the buffer so that the buffer can be used as a
+ string in certain contexts.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-connect.c (assuan_pipe_connect): New argument
+ FD_CHILD_LIST. Don't close those fds.
+ * assuan.h: Likewise for prototype.
+
+2001-12-14 Werner Koch <wk@gnupg.org>
+
+ * assuan-listen.c (assuan_close_input_fd): New.
+ (assuan_close_output_fd): New.
+ * assuan-handler.c (std_handler_reset): Always close them after a
+ reset command.
+ (std_handler_bye): Likewise.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use
+ it to save the length of the attic line.
+ Rediddle the code a bit to make it more clear what happens.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH.
+ assuan.h: Define ASSUAN_LINELENGTH.
+
+2001-12-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * assuan-buffer.c (assuan_read_line): Fix order of execution to
+ get correct return values.
+
+2001-12-13 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (assuan_get_active_fds): Fixed silly bug,
+ pretty obvious that nobody ever tested this function.
+
+2001-12-12 Werner Koch <wk@gnupg.org>
+
+ * assuan-connect.c (assuan_pipe_connect): Implemented the inital
+ handshake.
+ * assuan-client.c (read_from_server): Renamed to
+ (_assuan_read_from_server): this and made external.
+
+ * assuan-listen.c (assuan_set_hello_line): New.
+ (assuan_accept): Use a custom hello line is available.
+
+ * assuan-buffer.c (assuan_read_line): New.
+ (assuan_pending_line): New.
+ (_assuan_write_line): Renamed to ..
+ (assuan_write_line): this, made public and changed all callers.
+
+2001-12-04 Werner Koch <wk@gnupg.org>
+
+ * assuan-connect.c (assuan_pipe_connect): Add more error reporting.
+ * assuan-client.c: New.
+
+ * assuan-inquire.c: New.
+ * assuan-handler.c (process_request): Check for nested invocations.
+
+2001-11-27 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (assuan_register_input_notify): New.
+ (assuan_register_output_notify): New.
+
+2001-11-26 Werner Koch <wk@gnupg.org>
+
+ * assuan.h: Added more status codes.
+
+2001-11-25 Werner Koch <wk@gnupg.org>
+
+ * assuan-handler.c (assuan_register_bye_notify)
+ (assuan_register_reset_notify)
+ (assuan_register_cancel_notify): New and call them from the
+ standard handlers.
+ (assuan_process): Moved bulk of function to ..
+ (process_request): .. new.
+ (assuan_process_next): One shot version of above.
+ (assuan_get_active_fds): New.
+
+2001-11-24 Werner Koch <wk@gnupg.org>
+
+ * assuan-connect.c (assuan_get_pid): New.
+
+ * assuan-buffer.c (_assuan_read_line): Deal with reads of more
+ than a line.
+ * assuan-defs.h: Add space in the context for this.
+
+
+ Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/libtdenetwork/libgpgme-copy/assuan/Makefile.am b/libtdenetwork/libgpgme-copy/assuan/Makefile.am
new file mode 100644
index 000000000..aea8f558c
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/Makefile.am
@@ -0,0 +1,58 @@
+# Assuan Makefile
+# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+#
+# This file is part of Assuan.
+#
+# Assuan 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.
+#
+# Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+## Process this file with automake to produce Makefile.in
+
+#EXTRA_DIST = mkerrors
+INCLUDES = -I.. # -I$(top_srcdir)/include
+#BUILT_SOURCES = assuan-errors.c
+#MOSTLYCLEANFILES = assuan-errors.c
+
+noinst_LTLIBRARIES = libassuan.la
+
+AM_CPPFLAGS = -D_ASSUAN_IN_GPGME_BUILD_ASSUAN
+
+#libassuan_la_LDFLAGS =
+libassuan_la_SOURCES = \
+ assuan-util.c \
+ assuan-errors.c \
+ assuan-buffer.c \
+ assuan-handler.c \
+ assuan-inquire.c \
+ assuan-listen.c \
+ assuan-connect.c \
+ assuan-client.c \
+ assuan-pipe-server.c \
+ assuan-socket-server.c \
+ assuan-pipe-connect.c \
+ assuan-socket-connect.c \
+ assuan-socket.c \
+ assuan-io.c \
+ assuan-uds.c \
+ funopen.c \
+ assuan-logging.c
+
+libassuan_la_COMPILE_FIRST=assuan-errors.c
+
+assuan-errors.c : $(srcdir)/assuan.h
+ $(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
+
+CLEANFILES=assuan-errors.c
+
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-buffer.c b/libtdenetwork/libgpgme-copy/assuan/assuan-buffer.c
new file mode 100644
index 000000000..7a1879877
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-buffer.c
@@ -0,0 +1,550 @@
+/* assuan-buffer.c - read and send data
+ * Copyright (C) 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#ifdef HAVE_W32_SYSTEM
+#include <process.h>
+#endif
+#include "assuan-defs.h"
+
+
+/* Extended version of write(2) to guarantee that all bytes are
+ written. Returns 0 on success or -1 and ERRNO on failure. */
+static int
+writen (assuan_context_t ctx, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ ssize_t nwritten = ctx->io->writefnc (ctx, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+
+/* Read an entire line. Returns 0 on success or -1 and ERRNo on
+ failure. EOF is indictated by setting the integer at address
+ R_EOF. */
+static int
+readline (assuan_context_t ctx, char *buf, size_t buflen,
+ int *r_nread, int *r_eof)
+{
+ size_t nleft = buflen;
+ char *p;
+
+ *r_eof = 0;
+ *r_nread = 0;
+ while (nleft > 0)
+ {
+ ssize_t n = ctx->io->readfnc (ctx, buf, nleft);
+
+ if (n < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* read error */
+ }
+ else if (!n)
+ {
+ *r_eof = 1;
+ break; /* allow incomplete lines */
+ }
+ p = buf;
+ nleft -= n;
+ buf += n;
+ *r_nread += n;
+
+ p = memrchr (p, '\n', n);
+ if (p)
+ break; /* at least one full line available - that's enough for now */
+ }
+
+ return 0;
+}
+
+
+/* Function returns an Assuan error. */
+assuan_error_t
+_assuan_read_line (assuan_context_t ctx)
+{
+ char *line = ctx->inbound.line;
+ int nread, atticlen;
+ int rc;
+ char *endp = 0;
+
+ if (ctx->inbound.eof)
+ return _assuan_error (-1);
+
+ atticlen = ctx->inbound.attic.linelen;
+ if (atticlen)
+ {
+ memcpy (line, ctx->inbound.attic.line, atticlen);
+ ctx->inbound.attic.linelen = 0;
+
+ endp = memchr (line, '\n', atticlen);
+ if (endp)
+ /* Found another line in the attic. */
+ {
+ rc = 0;
+ nread = atticlen;
+ atticlen = 0;
+ }
+ else
+ /* There is pending data but not a full line. */
+ {
+ assert (atticlen < LINELENGTH);
+ rc = readline (ctx, line + atticlen,
+ LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
+ }
+ }
+ else
+ /* No pending data. */
+ rc = readline (ctx, line, LINELENGTH,
+ &nread, &ctx->inbound.eof);
+ if (rc)
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd,
+ strerror (errno));
+ return _assuan_error (ASSUAN_Read_Error);
+ }
+ if (!nread)
+ {
+ assert (ctx->inbound.eof);
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [EOF]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ return _assuan_error (-1);
+ }
+
+ ctx->inbound.attic.pending = 0;
+ nread += atticlen;
+
+ if (! endp)
+ endp = memchr (line, '\n', nread);
+
+ if (endp)
+ {
+ unsigned monitor_result;
+ int n = endp - line + 1;
+
+ if (n < nread)
+ /* LINE contains more than one line. We copy it to the attic
+ now as handlers are allowed to modify the passed
+ buffer. */
+ {
+ int len = nread - n;
+ memcpy (ctx->inbound.attic.line, endp + 1, len);
+ ctx->inbound.attic.pending = memrchr (endp + 1, '\n', len) ? 1 : 0;
+ ctx->inbound.attic.linelen = len;
+ }
+
+ if (endp != line && endp[-1] == '\r')
+ endp --;
+ *endp = 0;
+
+ ctx->inbound.linelen = endp - line;
+
+ monitor_result = (ctx->io_monitor
+ ? ctx->io_monitor (ctx, 0,
+ ctx->inbound.line,
+ ctx->inbound.linelen)
+ : 0);
+ if ( (monitor_result & 2) )
+ ctx->inbound.linelen = 0;
+
+ if (ctx->log_fp && !(monitor_result & 1))
+ {
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->inbound.line,
+ ctx->inbound.linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ return 0;
+ }
+ else
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Invalid line]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ *line = 0;
+ ctx->inbound.linelen = 0;
+ return _assuan_error (ctx->inbound.eof
+ ? ASSUAN_Line_Not_Terminated
+ : ASSUAN_Line_Too_Long);
+ }
+}
+
+
+/* Read the next line from the client or server and return a pointer
+ in *LINE to a buffer holding the line. LINELEN is the length of
+ *LINE. The buffer is valid until the next read operation on it.
+ The caller may modify the buffer. The buffer is invalid (i.e. must
+ not be used) if an error is returned.
+
+ Returns 0 on success or an assuan error code.
+ See also: assuan_pending_line().
+*/
+assuan_error_t
+assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
+{
+ assuan_error_t err;
+
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ err = _assuan_read_line (ctx);
+ *line = ctx->inbound.line;
+ *linelen = ctx->inbound.linelen;
+ return err;
+}
+
+
+/* Return true if a full line is buffered (i.e. an entire line may be
+ read without any I/O). */
+int
+assuan_pending_line (assuan_context_t ctx)
+{
+ return ctx && ctx->inbound.attic.pending;
+}
+
+
+assuan_error_t
+_assuan_write_line (assuan_context_t ctx, const char *prefix,
+ const char *line, size_t len)
+{
+ assuan_error_t rc = 0;
+ size_t prefixlen = prefix? strlen (prefix):0;
+ unsigned int monitor_result;
+
+ /* Make sure that the line is short enough. */
+ if (len + prefixlen + 2 > ASSUAN_LINELENGTH)
+ {
+ if (ctx->log_fp)
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
+ "[supplied line too long -truncated]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ if (prefixlen > 5)
+ prefixlen = 5;
+ if (len > ASSUAN_LINELENGTH - prefixlen - 2)
+ len = ASSUAN_LINELENGTH - prefixlen - 2 - 1;
+ }
+
+ monitor_result = (ctx->io_monitor
+ ? ctx->io_monitor (ctx, 1, line, len)
+ : 0);
+
+ /* Fixme: we should do some kind of line buffering. */
+ if (ctx->log_fp && !(monitor_result & 1))
+ {
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ {
+ if (prefixlen)
+ _assuan_log_print_buffer (ctx->log_fp, prefix, prefixlen);
+ _assuan_log_print_buffer (ctx->log_fp, line, len);
+ }
+ putc ('\n', ctx->log_fp);
+ }
+
+ if (prefixlen && !(monitor_result & 2))
+ {
+ rc = writen (ctx, prefix, prefixlen);
+ if (rc)
+ rc = _assuan_error (ASSUAN_Write_Error);
+ }
+ if (!rc && !(monitor_result & 2))
+ {
+ rc = writen (ctx, line, len);
+ if (rc)
+ rc = _assuan_error (ASSUAN_Write_Error);
+ if (!rc)
+ {
+ rc = writen (ctx, "\n", 1);
+ if (rc)
+ rc = _assuan_error (ASSUAN_Write_Error);
+ }
+ }
+ return rc;
+}
+
+
+assuan_error_t
+assuan_write_line (assuan_context_t ctx, const char *line)
+{
+ size_t len;
+ const char *s;
+
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ /* Make sure that we never take a LF from the user - this might
+ violate the protocol. */
+ s = strchr (line, '\n');
+ len = s? (s-line) : strlen (line);
+
+ if (ctx->log_fp && s)
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> "
+ "[supplied line contained a LF - truncated]\n",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+
+ return _assuan_write_line (ctx, NULL, line, len);
+}
+
+
+
+/* Write out the data in buffer as datalines with line wrapping and
+ percent escaping. This function is used for GNU's custom streams. */
+int
+_assuan_cookie_write_data (void *cookie, const char *buffer, size_t orig_size)
+{
+ assuan_context_t ctx = cookie;
+ size_t size = orig_size;
+ char *line;
+ size_t linelen;
+
+ if (ctx->outbound.data.error)
+ return 0;
+
+ line = ctx->outbound.data.line;
+ linelen = ctx->outbound.data.linelen;
+ line += linelen;
+ while (size)
+ {
+ unsigned int monitor_result;
+
+ /* Insert data line header. */
+ if (!linelen)
+ {
+ *line++ = 'D';
+ *line++ = ' ';
+ linelen += 2;
+ }
+
+ /* Copy data, keep space for the CRLF and to escape one character. */
+ while (size && linelen < LINELENGTH-2-2)
+ {
+ if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
+ {
+ sprintf (line, "%%%02X", *(unsigned char*)buffer);
+ line += 3;
+ linelen += 3;
+ buffer++;
+ }
+ else
+ {
+ *line++ = *buffer++;
+ linelen++;
+ }
+ size--;
+ }
+
+
+ monitor_result = (ctx->io_monitor
+ ? ctx->io_monitor (ctx, 1,
+ ctx->outbound.data.line, linelen)
+ : 0);
+
+ if (linelen >= LINELENGTH-2-2)
+ {
+ if (ctx->log_fp && !(monitor_result & 1))
+ {
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->outbound.data.line,
+ linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ *line++ = '\n';
+ linelen++;
+ if ( !(monitor_result & 2)
+ && writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
+ return 0;
+ }
+ line = ctx->outbound.data.line;
+ linelen = 0;
+ }
+ }
+
+ ctx->outbound.data.linelen = linelen;
+ return (int)orig_size;
+}
+
+
+/* Write out any buffered data
+ This function is used for GNU's custom streams */
+int
+_assuan_cookie_write_flush (void *cookie)
+{
+ assuan_context_t ctx = cookie;
+ char *line;
+ size_t linelen;
+ unsigned int monitor_result;
+
+ if (ctx->outbound.data.error)
+ return 0;
+
+ line = ctx->outbound.data.line;
+ linelen = ctx->outbound.data.linelen;
+ line += linelen;
+
+ monitor_result = (ctx->io_monitor
+ ? ctx->io_monitor (ctx, 1,
+ ctx->outbound.data.line, linelen)
+ : 0);
+
+ if (linelen)
+ {
+ if (ctx->log_fp && !(monitor_result & 1))
+ {
+ fprintf (ctx->log_fp, "%s[%u.%d] DBG: -> ",
+ assuan_get_assuan_log_prefix (),
+ (unsigned int)getpid (), ctx->inbound.fd);
+ if (ctx->confidential)
+ fputs ("[Confidential data not shown]", ctx->log_fp);
+ else
+ _assuan_log_print_buffer (ctx->log_fp,
+ ctx->outbound.data.line, linelen);
+ putc ('\n', ctx->log_fp);
+ }
+ *line++ = '\n';
+ linelen++;
+ if ( !(monitor_result & 2)
+ && writen (ctx, ctx->outbound.data.line, linelen))
+ {
+ ctx->outbound.data.error = _assuan_error (ASSUAN_Write_Error);
+ return 0;
+ }
+ ctx->outbound.data.linelen = 0;
+ }
+ return 0;
+}
+
+
+/**
+ * assuan_send_data:
+ * @ctx: An assuan context
+ * @buffer: Data to send or NULL to flush
+ * @length: length of the data to send/
+ *
+ * This function may be used by the server or the client to send data
+ * lines. The data will be escaped as required by the Assuan protocol
+ * and may get buffered until a line is full. To force sending the
+ * data out @buffer may be passed as NULL (in which case @length must
+ * also be 0); however when used by a client this flush operation does
+ * also send the terminating "END" command to terminate the reponse on
+ * a INTQUIRE response. However, when assuan_transact() is used, this
+ * function takes care of sending END itself.
+ *
+ * Return value: 0 on success or an error code
+ **/
+
+assuan_error_t
+assuan_send_data (assuan_context_t ctx, const void *buffer, size_t length)
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!buffer && length)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ if (!buffer)
+ { /* flush what we have */
+ _assuan_cookie_write_flush (ctx);
+ if (ctx->outbound.data.error)
+ return ctx->outbound.data.error;
+ if (!ctx->is_server)
+ return assuan_write_line (ctx, "END");
+ }
+ else
+ {
+ _assuan_cookie_write_data (ctx, buffer, length);
+ if (ctx->outbound.data.error)
+ return ctx->outbound.data.error;
+ }
+
+ return 0;
+}
+
+assuan_error_t
+assuan_sendfd (assuan_context_t ctx, int fd)
+{
+ /* It is explicitly allowed to use (NULL, -1) as a runtime test to
+ check whether descriptor passing is available. */
+ if (!ctx && fd == -1)
+#ifdef USE_DESCRIPTOR_PASSING
+ return 0;
+#else
+ return _assuan_error (ASSUAN_Not_Implemented);
+#endif
+
+ if (! ctx->io->sendfd)
+ return set_error (ctx, Not_Implemented,
+ "server does not support sending and receiving "
+ "of file descriptors");
+ return ctx->io->sendfd (ctx, fd);
+}
+
+assuan_error_t
+assuan_receivefd (assuan_context_t ctx, int *fd)
+{
+ if (! ctx->io->receivefd)
+ return set_error (ctx, Not_Implemented,
+ "server does not support sending and receiving "
+ "of file descriptors");
+ return ctx->io->receivefd (ctx, fd);
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-client.c b/libtdenetwork/libgpgme-copy/assuan/assuan-client.c
new file mode 100644
index 000000000..978c69546
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-client.c
@@ -0,0 +1,234 @@
+/* assuan-client.c - client functions
+ * Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "assuan-defs.h"
+
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+assuan_error_t
+_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
+{
+ char *line;
+ int linelen;
+ assuan_error_t rc;
+
+ *okay = 0;
+ *off = 0;
+ do
+ {
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ return rc;
+ line = ctx->inbound.line;
+ linelen = ctx->inbound.linelen;
+ }
+ while (*line == '#' || !linelen);
+
+ if (linelen >= 1
+ && line[0] == 'D' && line[1] == ' ')
+ {
+ *okay = 2; /* data line */
+ *off = 2;
+ }
+ else if (linelen >= 1
+ && line[0] == 'S'
+ && (line[1] == '\0' || line[1] == ' '))
+ {
+ *okay = 4;
+ *off = 1;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 2
+ && line[0] == 'O' && line[1] == 'K'
+ && (line[2] == '\0' || line[2] == ' '))
+ {
+ *okay = 1;
+ *off = 2;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 3
+ && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (line[3] == '\0' || line[3] == ' '))
+ {
+ *okay = 0;
+ *off = 3;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 7
+ && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
+ && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
+ && line[6] == 'E'
+ && (line[7] == '\0' || line[7] == ' '))
+ {
+ *okay = 3;
+ *off = 7;
+ while (line[*off] == ' ')
+ ++*off;
+ }
+ else if (linelen >= 3
+ && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (line[3] == '\0' || line[3] == ' '))
+ {
+ *okay = 5; /* end line */
+ *off = 3;
+ }
+ else
+ rc = _assuan_error (ASSUAN_Invalid_Response);
+ return rc;
+}
+
+
+
+/**
+ * assuan_transact:
+ * @ctx: The Assuan context
+ * @command: Command line to be send to the server
+ * @data_cb: Callback function for data lines
+ * @data_cb_arg: first argument passed to @data_cb
+ * @inquire_cb: Callback function for a inquire response
+ * @inquire_cb_arg: first argument passed to @inquire_cb
+ * @status_cb: Callback function for a status response
+ * @status_cb_arg: first argument passed to @status_cb
+ *
+ * FIXME: Write documentation
+ *
+ * Return value: 0 on success or error code. The error code may be
+ * the one one returned by the server in error lines or from the
+ * callback functions. Take care: When a callback returns an error
+ * this function returns immediately with an error and thus the caller
+ * will altter return an Assuan error (write erro in most cases).
+ **/
+assuan_error_t
+assuan_transact (assuan_context_t ctx,
+ const char *command,
+ int (*data_cb)(void *, const void *, size_t),
+ void *data_cb_arg,
+ int (*inquire_cb)(void*, const char *),
+ void *inquire_cb_arg,
+ int (*status_cb)(void*, const char *),
+ void *status_cb_arg)
+{
+ assuan_error_t rc;
+ int okay, off;
+ char *line;
+ int linelen;
+
+ rc = assuan_write_line (ctx, command);
+ if (rc)
+ return rc;
+
+ if (*command == '#' || !*command)
+ return 0; /* Don't expect a response for a comment line. */
+
+ again:
+ rc = _assuan_read_from_server (ctx, &okay, &off);
+ if (rc)
+ return rc; /* error reading from server */
+
+ line = ctx->inbound.line + off;
+ linelen = ctx->inbound.linelen - off;
+
+ if (!okay)
+ {
+ rc = atoi (line);
+ if (rc > 0 && rc < 100)
+ rc = _assuan_error (ASSUAN_Server_Fault);
+ else if (rc > 0 && rc <= 128)
+ rc = _assuan_error (rc);
+ }
+ else if (okay == 2)
+ {
+ if (!data_cb)
+ rc = _assuan_error (ASSUAN_No_Data_Callback);
+ else
+ {
+ char *s, *d;
+
+ for (s=d=line; linelen; linelen--)
+ {
+ if (*s == '%' && linelen > 2)
+ { /* handle escaping */
+ s++;
+ *d++ = xtoi_2 (s);
+ s += 2;
+ linelen -= 2;
+ }
+ else
+ *d++ = *s++;
+ }
+ *d = 0; /* add a hidden string terminator */
+ rc = data_cb (data_cb_arg, line, d - line);
+ if (!rc)
+ goto again;
+ }
+ }
+ else if (okay == 3)
+ {
+ if (!inquire_cb)
+ {
+ assuan_write_line (ctx, "END"); /* get out of inquire mode */
+ _assuan_read_from_server (ctx, &okay, &off); /* dummy read */
+ rc = _assuan_error (ASSUAN_No_Inquire_Callback);
+ }
+ else
+ {
+ rc = inquire_cb (inquire_cb_arg, line);
+ if (!rc)
+ rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
+ if (!rc)
+ goto again;
+ }
+ }
+ else if (okay == 4)
+ {
+ if (status_cb)
+ rc = status_cb (status_cb_arg, line);
+ if (!rc)
+ goto again;
+ }
+ else if (okay == 5)
+ {
+ if (!data_cb)
+ rc = _assuan_error (ASSUAN_No_Data_Callback);
+ else
+ {
+ rc = data_cb (data_cb_arg, NULL, 0);
+ if (!rc)
+ goto again;
+ }
+ }
+
+ return rc;
+}
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-connect.c b/libtdenetwork/libgpgme-copy/assuan/assuan-connect.c
new file mode 100644
index 000000000..92995d8c1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-connect.c
@@ -0,0 +1,79 @@
+/* assuan-connect.c - Establish a connection (client)
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/wait.h>
+#endif
+
+#include "assuan-defs.h"
+
+/* Disconnect and release the context CTX. */
+void
+assuan_disconnect (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ assuan_write_line (ctx, "BYE");
+ ctx->finish_handler (ctx);
+ ctx->deinit_handler (ctx);
+ ctx->deinit_handler = NULL;
+ _assuan_release_context (ctx);
+ }
+}
+
+/* Return the PID of the peer or -1 if not known. This function works
+ in some situations where assuan_get_ucred fails. */
+pid_t
+assuan_get_pid (assuan_context_t ctx)
+{
+ return (ctx && ctx->pid)? ctx->pid : -1;
+}
+
+
+/* Return user credentials. PID, UID and GID amy be gived as NULL if
+ you are not interested in this value. For getting the pid of the
+ peer the assuan_get_pid is usually better suited. */
+assuan_error_t
+assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid)
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!ctx->peercred.valid)
+ return _assuan_error (ASSUAN_General_Error);
+ if (pid)
+ *pid = ctx->peercred.pid;
+ if (uid)
+ *uid = ctx->peercred.uid;
+ if (gid)
+ *gid = ctx->peercred.gid;
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-defs.h b/libtdenetwork/libgpgme-copy/assuan/assuan-defs.h
new file mode 100644
index 000000000..fa04f0b29
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-defs.h
@@ -0,0 +1,323 @@
+/* assuan-defs.c - Internal definitions to Assuan
+ * Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef ASSUAN_DEFS_H
+#define ASSUAN_DEFS_H
+
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#else
+#include <windows.h>
+#endif
+#include <unistd.h>
+
+#include "assuan.h"
+
+#ifndef HAVE_W32_SYSTEM
+#define DIRSEP_C '/'
+#else
+#define DIRSEP_C '\\'
+#endif
+
+#ifdef HAVE_W32_SYSTEM
+#define AF_LOCAL AF_UNIX
+/* We need to prefix the structure with a sockaddr_in header so we can
+ use it later for sendto and recvfrom. */
+struct sockaddr_un
+{
+ short sun_family;
+ unsigned short sun_port;
+ struct in_addr sun_addr;
+ char sun_path[108-2-4]; /* Path name. */
+};
+
+/* Not needed anymore because the current mingw32 defines this in
+ sys/types.h */
+/* typedef int ssize_t; */
+
+/* Missing W32 functions */
+int putc_unlocked (int c, FILE *stream);
+void * memrchr (const void *block, int c, size_t size);
+char * stpcpy (char *dest, const char *src);
+#endif
+
+#define LINELENGTH ASSUAN_LINELENGTH
+
+
+struct cmdtbl_s
+{
+ const char *name;
+ int (*handler)(assuan_context_t, char *line);
+};
+
+
+/* A structure to dispatch I/O functions. All these functions need to
+ return 0 on success and set ERRNO on failure. */
+struct assuan_io
+{
+ /* Routine to read from input_fd. */
+ ssize_t (*readfnc) (assuan_context_t, void *, size_t);
+ /* Routine to write to output_fd. */
+ ssize_t (*writefnc) (assuan_context_t, const void *, size_t);
+ /* Send a file descriptor. */
+ assuan_error_t (*sendfd) (assuan_context_t, int);
+ /* Receive a file descriptor. */
+ assuan_error_t (*receivefd) (assuan_context_t, int *);
+};
+
+
+/* The context we use with most functions. */
+struct assuan_context_s
+{
+ assuan_error_t err_no;
+ const char *err_str;
+ int os_errno; /* Last system error number used with certain
+ error codes. */
+
+ /* Context specific flags (cf. assuan_flag_t). */
+ struct
+ {
+ unsigned int no_waitpid:1; /* See ASSUAN_NO_WAITPID. */
+ } flags;
+
+ int confidential;
+ int is_server; /* Set if this is context belongs to a server */
+ int in_inquire;
+ char *hello_line;
+ char *okay_line; /* See assuan_set_okay_line() */
+
+ void *user_pointer; /* For assuan_get_pointer and assuan_set_pointer (). */
+
+ FILE *log_fp;
+
+ struct {
+ int fd;
+ int eof;
+ char line[LINELENGTH];
+ int linelen; /* w/o CR, LF - might not be the same as
+ strlen(line) due to embedded nuls. However a nul
+ is always written at this pos. */
+ struct {
+ char line[LINELENGTH];
+ int linelen ;
+ int pending; /* i.e. at least one line is available in the attic */
+ } attic;
+ } inbound;
+
+ struct {
+ int fd;
+ struct {
+ FILE *fp;
+ char line[LINELENGTH];
+ int linelen;
+ int error;
+ } data;
+ } outbound;
+
+ int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
+ connection and must terminate then. */
+ pid_t pid; /* The pid of the peer. */
+ int listen_fd; /* The fd we are listening on (used by socket servers) */
+ int connected_fd; /* helper */
+
+ struct {
+ int valid; /* Whether this structure has valid information. */
+ pid_t pid; /* The pid of the peer. */
+ uid_t uid; /* The uid of the peer. */
+ gid_t gid; /* The gid of the peer. */
+ } peercred;
+
+ /* Used for Unix domain sockets. */
+ struct sockaddr_un myaddr;
+ struct sockaddr_un serveraddr;
+
+ /* Structure used for unix domain socket buffering. FIXME: We don't
+ use datagrams anymore thus we could get away with a simpler
+ buffering approach. */
+ struct {
+ void *buffer; /* Malloced buffer. */
+ int bufferallocated; /* Memory allocated. */
+ int bufferoffset; /* Offset of start of buffer. */
+ int buffersize; /* Bytes buffered. */
+
+ int pendingfds[5]; /* Array to save received descriptors. */
+ int pendingfdscount; /* Number of received descriptors. */
+ } uds;
+
+ void (*deinit_handler)(assuan_context_t);
+ int (*accept_handler)(assuan_context_t);
+ int (*finish_handler)(assuan_context_t);
+
+ struct cmdtbl_s *cmdtbl;
+ size_t cmdtbl_used; /* used entries */
+ size_t cmdtbl_size; /* allocated size of table */
+
+ void (*bye_notify_fnc)(assuan_context_t);
+ void (*reset_notify_fnc)(assuan_context_t);
+ void (*cancel_notify_fnc)(assuan_context_t);
+ int (*option_handler_fnc)(assuan_context_t,const char*, const char*);
+ void (*input_notify_fnc)(assuan_context_t, const char *);
+ void (*output_notify_fnc)(assuan_context_t, const char *);
+
+ /* This function is called right after a command has been processed.
+ It may be used to command related cleanup. */
+ void (*post_cmd_notify_fnc)(assuan_context_t, int);
+
+ /* If set, this is called right before logging an I/O line. With
+ DIRECTION set to 1 it is called for an output oeration; 0 means
+ an input operation. If bit 0 is set in the return value, the
+ logging of the will be suppressed. With bit 1 set, the entire
+ line will be ignored. */
+ unsigned int (*io_monitor)(assuan_context_t ctx,
+ int direction,
+ const char *line,
+ size_t linelen);
+
+ int input_fd; /* set by INPUT command */
+ int output_fd; /* set by OUTPUT command */
+
+ /* io routines. */
+ struct assuan_io *io;
+};
+
+/*-- assuan-pipe-server.c --*/
+int _assuan_new_context (assuan_context_t *r_ctx);
+void _assuan_release_context (assuan_context_t ctx);
+
+/*-- assuan-uds.c --*/
+void _assuan_uds_close_fds (assuan_context_t ctx);
+void _assuan_uds_deinit (assuan_context_t ctx);
+void _assuan_init_uds_io (assuan_context_t ctx);
+
+
+/*-- assuan-handler.c --*/
+int _assuan_register_std_commands (assuan_context_t ctx);
+
+/*-- assuan-buffer.c --*/
+assuan_error_t _assuan_read_line (assuan_context_t ctx);
+int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
+int _assuan_cookie_write_flush (void *cookie);
+assuan_error_t _assuan_write_line (assuan_context_t ctx, const char *prefix,
+ const char *line, size_t len);
+
+/*-- assuan-client.c --*/
+assuan_error_t _assuan_read_from_server (assuan_context_t ctx,
+ int *okay, int *off);
+
+/*-- assuan-error.c --*/
+
+
+/* Map error codes as used in this implementaion to the libgpg-error
+ codes. */
+assuan_error_t _assuan_error (int oldcode);
+
+/* Extrac the erro code from A. This works for both the old and the
+ new style error codes. This needs to be whenever an error code is
+ compared. */
+#define err_code(a) ((a) & 0x00ffffff)
+
+/* Check whether A is the erro code for EOF. We allow forold and new
+ style EOF error codes here. */
+#define err_is_eof(a) ((a) == (-1) || err_code (a) == 16383)
+
+
+
+/*-- assuan-util.c --*/
+void *_assuan_malloc (size_t n);
+void *_assuan_calloc (size_t n, size_t m);
+void *_assuan_realloc (void *p, size_t n);
+void _assuan_free (void *p);
+
+#define xtrymalloc(a) _assuan_malloc ((a))
+#define xtrycalloc(a,b) _assuan_calloc ((a),(b))
+#define xtryrealloc(a,b) _assuan_realloc((a),(b))
+#define xfree(a) _assuan_free ((a))
+
+#define set_error(c,e,t) \
+ assuan_set_error ((c), _assuan_error (ASSUAN_ ## e), (t))
+
+#ifdef HAVE_W32_SYSTEM
+const char *_assuan_w32_strerror (int ec);
+#define w32_strerror(e) _assuan_w32_strerror ((e))
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/*-- assuan-logging.c --*/
+void _assuan_set_default_log_stream (FILE *fp);
+
+void _assuan_log_printf (const char *format, ...)
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
+ __attribute__ ((format (printf,1,2)))
+#endif
+ ;
+void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
+void _assuan_log_sanitized_string (const char *string);
+
+
+/*-- assuan-io.c --*/
+pid_t _assuan_waitpid (pid_t pid, int *status, int options);
+
+ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size);
+ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer,
+ size_t size);
+ssize_t _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg);
+ssize_t _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg);
+
+/*-- assuan-socket.c --*/
+int _assuan_close (int fd);
+int _assuan_sock_new (int domain, int type, int proto);
+int _assuan_sock_bind (int sockfd, struct sockaddr *addr, int addrlen);
+int _assuan_sock_connect (int sockfd, struct sockaddr *addr, int addrlen);
+
+#ifdef HAVE_FOPENCOOKIE
+/* We have to implement funopen in terms of glibc's fopencookie. */
+FILE *_assuan_funopen(void *cookie,
+ cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn);
+#define funopen(a,r,w,s,c) _assuan_funopen ((a), (r), (w), (s), (c))
+#endif /*HAVE_FOPENCOOKIE*/
+
+/* Prototypes for replacement functions. */
+#ifndef HAVE_MEMRCHR
+void *memrchr (const void *block, int c, size_t size);
+#endif
+#ifndef HAVE_STPCPY
+char *stpcpy (char *dest, const char *src);
+#endif
+#ifndef HAVE_SETENV
+#define setenv _assuan_setenv
+#define unsetenv _assuan_unsetenv
+#define clearenv _assuan_clearenv
+int setenv (const char *name, const char *value, int replace);
+#endif
+#ifndef HAVE_PUTC_UNLOCKED
+int putc_unlocked (int c, FILE *stream);
+#endif
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#define DIMof(type,member) DIM(((type *)0)->member)
+
+
+#endif /*ASSUAN_DEFS_H*/
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-handler.c b/libtdenetwork/libgpgme-copy/assuan/assuan-handler.c
new file mode 100644
index 000000000..866db2259
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-handler.c
@@ -0,0 +1,774 @@
+/* assuan-handler.c - dispatch commands
+ * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "assuan-defs.h"
+
+
+
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+
+static int my_strcasecmp (const char *a, const char *b);
+
+
+
+static int
+dummy_handler (assuan_context_t ctx, char *line)
+{
+ return set_error (ctx, Server_Fault, "no handler registered");
+}
+
+
+static int
+std_handler_nop (assuan_context_t ctx, char *line)
+{
+ return 0; /* okay */
+}
+
+static int
+std_handler_cancel (assuan_context_t ctx, char *line)
+{
+ if (ctx->cancel_notify_fnc)
+ ctx->cancel_notify_fnc (ctx);
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+static int
+std_handler_option (assuan_context_t ctx, char *line)
+{
+ char *key, *value, *p;
+
+ for (key=line; spacep (key); key++)
+ ;
+ if (!*key)
+ return set_error (ctx, Syntax_Error, "argument required");
+ if (*key == '=')
+ return set_error (ctx, Syntax_Error, "no option name given");
+ for (value=key; *value && !spacep (value) && *value != '='; value++)
+ ;
+ if (*value)
+ {
+ if (spacep (value))
+ *value++ = 0; /* terminate key */
+ for (; spacep (value); value++)
+ ;
+ if (*value == '=')
+ {
+ *value++ = 0; /* terminate key */
+ for (; spacep (value); value++)
+ ;
+ if (!*value)
+ return set_error (ctx, Syntax_Error, "option argument expected");
+ }
+ if (*value)
+ {
+ for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
+ ;
+ if (p > value)
+ *++p = 0; /* strip trailing spaces */
+ }
+ }
+
+ if (*key == '-' && key[1] == '-' && key[2])
+ key += 2; /* the double dashes are optional */
+ if (*key == '-')
+ return set_error (ctx, Syntax_Error,
+ "option should not begin with one dash");
+
+ if (ctx->option_handler_fnc)
+ return ctx->option_handler_fnc (ctx, key, value);
+ return 0;
+}
+
+static int
+std_handler_bye (assuan_context_t ctx, char *line)
+{
+ if (ctx->bye_notify_fnc)
+ ctx->bye_notify_fnc (ctx);
+ assuan_close_input_fd (ctx);
+ assuan_close_output_fd (ctx);
+ return -1; /* pretty simple :-) */
+}
+
+static int
+std_handler_auth (assuan_context_t ctx, char *line)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+static int
+std_handler_reset (assuan_context_t ctx, char *line)
+{
+ if (ctx->reset_notify_fnc)
+ ctx->reset_notify_fnc (ctx);
+ assuan_close_input_fd (ctx);
+ assuan_close_output_fd (ctx);
+ _assuan_uds_close_fds (ctx);
+ return 0;
+}
+
+static int
+std_handler_end (assuan_context_t ctx, char *line)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+assuan_error_t
+assuan_command_parse_fd (assuan_context_t ctx, char *line, int *rfd)
+{
+ char *endp;
+
+ if ( (strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
+ || (line[2] != '=' && line[2] != '\0'))
+ return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
+ line += 2;
+ if (*line == '=')
+ {
+ line ++;
+ if (!digitp (*line))
+ return set_error (ctx, Syntax_Error, "number required");
+ *rfd = strtoul (line, &endp, 10);
+ /* Remove that argument so that a notify handler won't see it. */
+ memset (line, ' ', endp? (endp-line):strlen(line));
+
+ if (*rfd == ctx->inbound.fd)
+ return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
+ if (*rfd == ctx->outbound.fd)
+ return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
+ return 0;
+ }
+ else
+ /* Our peer has sent the file descriptor. */
+ return assuan_receivefd (ctx, rfd);
+}
+
+/* Format is INPUT FD=<n> */
+static int
+std_handler_input (assuan_context_t ctx, char *line)
+{
+ int rc, fd;
+
+ rc = assuan_command_parse_fd (ctx, line, &fd);
+ if (rc)
+ return rc;
+ ctx->input_fd = fd;
+ if (ctx->input_notify_fnc)
+ ctx->input_notify_fnc (ctx, line);
+ return 0;
+}
+
+/* Format is OUTPUT FD=<n> */
+static int
+std_handler_output (assuan_context_t ctx, char *line)
+{
+ int rc, fd;
+
+ rc = assuan_command_parse_fd (ctx, line, &fd);
+ if (rc)
+ return rc;
+ ctx->output_fd = fd;
+ if (ctx->output_notify_fnc)
+ ctx->output_notify_fnc (ctx, line);
+ return 0;
+}
+
+
+
+
+
+/* This is a table with the standard commands and handler for them.
+ The table is used to initialize a new context and associate strings
+ with default handlers */
+static struct {
+ const char *name;
+ int (*handler)(assuan_context_t, char *line);
+ int always; /* always initialize this command */
+} std_cmd_table[] = {
+ { "NOP", std_handler_nop, 1 },
+ { "CANCEL", std_handler_cancel, 1 },
+ { "OPTION", std_handler_option, 1 },
+ { "BYE", std_handler_bye, 1 },
+ { "AUTH", std_handler_auth, 1 },
+ { "RESET", std_handler_reset, 1 },
+ { "END", std_handler_end, 1 },
+
+ { "INPUT", std_handler_input },
+ { "OUTPUT", std_handler_output },
+ { "OPTION", std_handler_option, 1 },
+ { NULL }
+};
+
+
+/**
+ * assuan_register_command:
+ * @ctx: the server context
+ * @cmd_name: A string with the command name
+ * @handler: The handler function to be called or NULL to use a default
+ * handler.
+ *
+ * Register a handler to be used for a given command. Note that
+ * several default handlers are already regsitered with a new context.
+ * This function however allows to override them.
+ *
+ * Return value: 0 on success or an error code
+ **/
+int
+assuan_register_command (assuan_context_t ctx,
+ const char *cmd_name,
+ int (*handler)(assuan_context_t, char *))
+{
+ int i;
+ const char *s;
+
+ if (cmd_name && !*cmd_name)
+ cmd_name = NULL;
+
+ if (!cmd_name)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ if (!handler)
+ { /* find a default handler. */
+ for (i=0; (s=std_cmd_table[i].name) && strcmp (cmd_name, s); i++)
+ ;
+ if (!s)
+ { /* Try again but case insensitive. */
+ for (i=0; (s=std_cmd_table[i].name)
+ && my_strcasecmp (cmd_name, s); i++)
+ ;
+ }
+ if (s)
+ handler = std_cmd_table[i].handler;
+ if (!handler)
+ handler = dummy_handler; /* Last resort is the dummy handler. */
+ }
+
+ if (!ctx->cmdtbl)
+ {
+ ctx->cmdtbl_size = 50;
+ ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
+ if (!ctx->cmdtbl)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ ctx->cmdtbl_used = 0;
+ }
+ else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
+ {
+ struct cmdtbl_s *x;
+
+ x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
+ if (!x)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ ctx->cmdtbl = x;
+ ctx->cmdtbl_size += 50;
+ }
+
+ ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
+ ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
+ ctx->cmdtbl_used++;
+ return 0;
+}
+
+int
+assuan_register_post_cmd_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, int))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->post_cmd_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_bye_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->bye_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_reset_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->reset_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_cancel_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->cancel_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_option_handler (assuan_context_t ctx,
+ int (*fnc)(assuan_context_t,
+ const char*, const char*))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->option_handler_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_input_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->input_notify_fnc = fnc;
+ return 0;
+}
+
+int
+assuan_register_output_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *))
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ ctx->output_notify_fnc = fnc;
+ return 0;
+}
+
+
+/* Helper to register the standards commands */
+int
+_assuan_register_std_commands (assuan_context_t ctx)
+{
+ int i, rc;
+
+ for (i=0; std_cmd_table[i].name; i++)
+ {
+ if (std_cmd_table[i].always)
+ {
+ rc = assuan_register_command (ctx, std_cmd_table[i].name, NULL);
+ if (rc)
+ return rc;
+ }
+ }
+ return 0;
+}
+
+
+
+/* Process the special data lines. The "D " has already been removed
+ from the line. As all handlers this function may modify the line. */
+static int
+handle_data_line (assuan_context_t ctx, char *line, int linelen)
+{
+ return set_error (ctx, Not_Implemented, NULL);
+}
+
+/* like ascii_strcasecmp but assume that B is already uppercase */
+static int
+my_strcasecmp (const char *a, const char *b)
+{
+ if (a == b)
+ return 0;
+
+ for (; *a && *b; a++, b++)
+ {
+ if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
+ break;
+ }
+ return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
+}
+
+/* Parse the line, break out the command, find it in the command
+ table, remove leading and white spaces from the arguments, call the
+ handler with the argument line and return the error */
+static int
+dispatch_command (assuan_context_t ctx, char *line, int linelen)
+{
+ char *p;
+ const char *s;
+ int shift, i;
+
+ if (*line == 'D' && line[1] == ' ') /* divert to special handler */
+ return handle_data_line (ctx, line+2, linelen-2);
+
+ for (p=line; *p && *p != ' ' && *p != '\t'; p++)
+ ;
+ if (p==line)
+ return set_error (ctx, Syntax_Error, "leading white-space");
+ if (*p)
+ { /* Skip over leading WS after the keyword */
+ *p++ = 0;
+ while ( *p == ' ' || *p == '\t')
+ p++;
+ }
+ shift = p - line;
+
+ for (i=0; (s=ctx->cmdtbl[i].name); i++)
+ {
+ if (!strcmp (line, s))
+ break;
+ }
+ if (!s)
+ { /* and try case insensitive */
+ for (i=0; (s=ctx->cmdtbl[i].name); i++)
+ {
+ if (!my_strcasecmp (line, s))
+ break;
+ }
+ }
+ if (!s)
+ return set_error (ctx, Unknown_Command, NULL);
+ line += shift;
+ linelen -= shift;
+
+/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
+ return ctx->cmdtbl[i].handler (ctx, line);
+}
+
+
+
+
+static int
+process_request (assuan_context_t ctx)
+{
+ int rc;
+
+ if (ctx->in_inquire)
+ return _assuan_error (ASSUAN_Nested_Commands);
+
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ return rc;
+ if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
+ return 0; /* comment line - ignore */
+
+ ctx->outbound.data.error = 0;
+ ctx->outbound.data.linelen = 0;
+ /* dispatch command and return reply */
+ rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
+ /* check from data write errors */
+ if (ctx->outbound.data.fp)
+ { /* Flush the data lines */
+ fclose (ctx->outbound.data.fp);
+ ctx->outbound.data.fp = NULL;
+ if (!rc && ctx->outbound.data.error)
+ rc = ctx->outbound.data.error;
+ }
+ else /* flush any data send w/o using the data fp */
+ {
+ assuan_send_data (ctx, NULL, 0);
+ if (!rc && ctx->outbound.data.error)
+ rc = ctx->outbound.data.error;
+ }
+ /* Error handling */
+ if (!rc)
+ {
+ rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
+ }
+ else if (err_is_eof (rc))
+ { /* No error checking because the peer may have already disconnect. */
+ assuan_write_line (ctx, "OK closing connection");
+ ctx->finish_handler (ctx);
+ }
+ else
+ {
+ char errline[300];
+
+ if (rc < 100)
+ sprintf (errline, "ERR %d server fault (%.50s)",
+ _assuan_error (ASSUAN_Server_Fault), assuan_strerror (rc));
+ else
+ {
+ const char *text = ctx->err_no == rc? ctx->err_str:NULL;
+
+#if defined(__GNUC__) && defined(__ELF__)
+ /* If we have weak symbol support we try to use the error
+ strings from libgpg-error without creating a dependency.
+ They are used for debugging purposes only, so there is no
+ problem if they are not available. We need to make sure
+ that we are using ELF because only this guarantees that
+ weak symbol support is available in case GNU ld is not
+ used. It seems that old gcc versions don't implement the
+ weak attribute properly but it works with the weak
+ pragma. */
+
+ unsigned int source, code;
+
+ int gpg_strerror_r (unsigned int err, char *buf, size_t buflen)
+ __attribute__ ((weak));
+ const char *gpg_strsource (unsigned int err)
+ __attribute__ ((weak));
+#if !defined(HAVE_W32_SYSTEM) && __GNUC__ < 3
+#pragma weak gpg_strerror_r
+#pragma weak gpg_strsource
+#endif
+
+ source = ((rc >> 24) & 0xff);
+ code = (rc & 0x00ffffff);
+ if (source && gpg_strsource && gpg_strerror_r)
+ {
+ /* Assume this is an libgpg-error. */
+ char ebuf[50];
+
+ gpg_strerror_r (rc, ebuf, sizeof ebuf );
+ sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
+ rc,
+ ebuf,
+ gpg_strsource (rc),
+ text? " - ":"", text?text:"");
+ }
+ else
+#endif /* __GNUC__ && __ELF__ */
+ sprintf (errline, "ERR %d %.50s%s%.100s",
+ rc, assuan_strerror (rc), text? " - ":"", text?text:"");
+ }
+ rc = assuan_write_line (ctx, errline);
+ }
+
+ if (ctx->post_cmd_notify_fnc)
+ ctx->post_cmd_notify_fnc (ctx, rc);
+
+ ctx->confidential = 0;
+ if (ctx->okay_line)
+ {
+ xfree (ctx->okay_line);
+ ctx->okay_line = NULL;
+ }
+ return rc;
+}
+
+/**
+ * assuan_process:
+ * @ctx: assuan context
+ *
+ * This function is used to handle the assuan protocol after a
+ * connection has been established using assuan_accept(). This is the
+ * main protocol handler.
+ *
+ * Return value: 0 on success or an error code if the assuan operation
+ * failed. Note, that no error is returned for operational errors.
+ **/
+int
+assuan_process (assuan_context_t ctx)
+{
+ int rc;
+
+ do {
+ rc = process_request (ctx);
+ } while (!rc);
+
+ if (err_is_eof (rc))
+ rc = 0;
+
+ return rc;
+}
+
+
+/**
+ * assuan_process_next:
+ * @ctx: Assuan context
+ *
+ * Same as assuan_process() but the user has to provide the outer
+ * loop. He should loop as long as the return code is zero and stop
+ * otherwise; -1 is regular end.
+ *
+ * See also: assuan_get_active_fds()
+ * Return value: -1 for end of server, 0 on success or an error code
+ **/
+int
+assuan_process_next (assuan_context_t ctx)
+{
+ return process_request (ctx);
+}
+
+
+/**
+ * assuan_get_active_fds:
+ * @ctx: Assuan context
+ * @what: 0 for read fds, 1 for write fds
+ * @fdarray: Caller supplied array to store the FDs
+ * @fdarraysize: size of that array
+ *
+ * Return all active filedescriptors for the given context. This
+ * function can be used to select on the fds and call
+ * assuan_process_next() if there is an active one. The first fd in
+ * the array is the one used for the command connection.
+ *
+ * Note, that write FDs are not yet supported.
+ *
+ * Return value: number of FDs active and put into @fdarray or -1 on
+ * error which is most likely a too small fdarray.
+ **/
+int
+assuan_get_active_fds (assuan_context_t ctx, int what,
+ int *fdarray, int fdarraysize)
+{
+ int n = 0;
+
+ if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
+ return -1;
+
+ if (!what)
+ {
+ if (ctx->inbound.fd != -1)
+ fdarray[n++] = ctx->inbound.fd;
+ }
+ else
+ {
+ if (ctx->outbound.fd != -1)
+ fdarray[n++] = ctx->outbound.fd;
+ if (ctx->outbound.data.fp)
+ fdarray[n++] = fileno (ctx->outbound.data.fp);
+ }
+
+ return n;
+}
+
+
+/* Two simple wrappers to make the expected function types match. */
+#ifdef HAVE_FUNOPEN
+static int
+fun1_cookie_write (void *cookie, const char *buffer, int orig_size)
+{
+ return _assuan_cookie_write_data (cookie, buffer, orig_size);
+}
+#endif /*HAVE_FUNOPEN*/
+#ifdef HAVE_FOPENCOOKIE
+static ssize_t
+fun2_cookie_write (void *cookie, const char *buffer, size_t orig_size)
+{
+ return _assuan_cookie_write_data (cookie, buffer, orig_size);
+}
+#endif /*HAVE_FOPENCOOKIE*/
+
+/* Return a FP to be used for data output. The FILE pointer is valid
+ until the end of a handler. So a close is not needed. Assuan does
+ all the buffering needed to insert the status line as well as the
+ required line wappping and quoting for data lines.
+
+ We use GNU's custom streams here. There should be an alternative
+ implementaion for systems w/o a glibc, a simple implementation
+ could use a child process */
+FILE *
+assuan_get_data_fp (assuan_context_t ctx)
+{
+#if defined (HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
+ if (ctx->outbound.data.fp)
+ return ctx->outbound.data.fp;
+
+#ifdef HAVE_FUNOPEN
+ ctx->outbound.data.fp = funopen (ctx, 0, fun1_cookie_write,
+ 0, _assuan_cookie_write_flush);
+#else
+ ctx->outbound.data.fp = funopen (ctx, 0, fun2_cookie_write,
+ 0, _assuan_cookie_write_flush);
+#endif
+
+ ctx->outbound.data.error = 0;
+ return ctx->outbound.data.fp;
+#else
+ errno = ENOSYS;
+ return NULL;
+#endif
+}
+
+
+/* Set the text used for the next OK reponse. This string is
+ automatically reset to NULL after the next command. */
+assuan_error_t
+assuan_set_okay_line (assuan_context_t ctx, const char *line)
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!line)
+ {
+ xfree (ctx->okay_line);
+ ctx->okay_line = NULL;
+ }
+ else
+ {
+ /* FIXME: we need to use gcry_is_secure() to test whether
+ we should allocate the entire line in secure memory */
+ char *buf = xtrymalloc (3+strlen(line)+1);
+ if (!buf)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ strcpy (buf, "OK ");
+ strcpy (buf+3, line);
+ xfree (ctx->okay_line);
+ ctx->okay_line = buf;
+ }
+ return 0;
+}
+
+
+
+assuan_error_t
+assuan_write_status (assuan_context_t ctx,
+ const char *keyword, const char *text)
+{
+ char buffer[256];
+ char *helpbuf;
+ size_t n;
+ assuan_error_t ae;
+
+ if ( !ctx || !keyword)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!text)
+ text = "";
+
+ n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
+ if (n < sizeof (buffer))
+ {
+ strcpy (buffer, "S ");
+ strcat (buffer, keyword);
+ if (*text)
+ {
+ strcat (buffer, " ");
+ strcat (buffer, text);
+ }
+ ae = assuan_write_line (ctx, buffer);
+ }
+ else if ( (helpbuf = xtrymalloc (n)) )
+ {
+ strcpy (helpbuf, "S ");
+ strcat (helpbuf, keyword);
+ if (*text)
+ {
+ strcat (helpbuf, " ");
+ strcat (helpbuf, text);
+ }
+ ae = assuan_write_line (ctx, helpbuf);
+ xfree (helpbuf);
+ }
+ else
+ ae = 0;
+ return ae;
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-inquire.c b/libtdenetwork/libgpgme-copy/assuan/assuan-inquire.c
new file mode 100644
index 000000000..897e0773b
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-inquire.c
@@ -0,0 +1,241 @@
+/* assuan-inquire.c - handle inquire stuff
+ * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "assuan-defs.h"
+
+#define digitp(a) ((a) >= '0' && (a) <= '9')
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+struct membuf
+{
+ size_t len;
+ size_t size;
+ char *buf;
+ int out_of_core;
+ int too_large;
+ size_t maxlen;
+};
+
+
+
+/* A simple implemnation of a dynamic buffer. Use init_membuf() to
+ create a buffer, put_membuf to append bytes and get_membuf to
+ release and return the buffer. Allocation errors are detected but
+ only returned at the final get_membuf(), this helps not to clutter
+ the code with out of core checks. */
+
+static void
+init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
+{
+ mb->len = 0;
+ mb->size = initiallen;
+ mb->out_of_core = 0;
+ mb->too_large = 0;
+ mb->maxlen = maxlen;
+ /* we need to allocate one byte more for get_membuf */
+ mb->buf = xtrymalloc (initiallen+1);
+ if (!mb->buf)
+ mb->out_of_core = 1;
+}
+
+static void
+put_membuf (struct membuf *mb, const void *buf, size_t len)
+{
+ if (mb->out_of_core || mb->too_large)
+ return;
+
+ if (mb->maxlen && mb->len + len > mb->maxlen)
+ {
+ mb->too_large = 1;
+ return;
+ }
+
+ if (mb->len + len >= mb->size)
+ {
+ char *p;
+
+ mb->size += len + 1024;
+ /* we need to allocate one byte more for get_membuf */
+ p = xtryrealloc (mb->buf, mb->size+1);
+ if (!p)
+ {
+ mb->out_of_core = 1;
+ return;
+ }
+ mb->buf = p;
+ }
+ memcpy (mb->buf + mb->len, buf, len);
+ mb->len += len;
+}
+
+static void *
+get_membuf (struct membuf *mb, size_t *len)
+{
+ char *p;
+
+ if (mb->out_of_core || mb->too_large)
+ {
+ xfree (mb->buf);
+ mb->buf = NULL;
+ return NULL;
+ }
+
+ mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
+ p = mb->buf;
+ *len = mb->len;
+ mb->buf = NULL;
+ mb->out_of_core = 1; /* don't allow a reuse */
+ return p;
+}
+
+static void
+free_membuf (struct membuf *mb)
+{
+ xfree (mb->buf);
+ mb->buf = NULL;
+}
+
+
+/**
+ * assuan_inquire:
+ * @ctx: An assuan context
+ * @keyword: The keyword used for the inquire
+ * @r_buffer: Returns an allocated buffer
+ * @r_length: Returns the length of this buffer
+ * @maxlen: If not 0, the size limit of the inquired data.
+ *
+ * A Server may use this to Send an inquire. r_buffer, r_length and
+ * maxlen may all be NULL/0 to indicate that no real data is expected.
+ *
+ * Return value: 0 on success or an ASSUAN error code
+ **/
+assuan_error_t
+assuan_inquire (assuan_context_t ctx, const char *keyword,
+ unsigned char **r_buffer, size_t *r_length, size_t maxlen)
+{
+ assuan_error_t rc;
+ struct membuf mb;
+ char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INTQUIRE ")+CR,LF) */
+ unsigned char *line, *p;
+ int linelen;
+ int nodataexpected;
+
+ if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
+ return _assuan_error (ASSUAN_Invalid_Value);
+ nodataexpected = !r_buffer && !r_length && !maxlen;
+ if (!nodataexpected && (!r_buffer || !r_length))
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!ctx->is_server)
+ return _assuan_error (ASSUAN_Not_A_Server);
+ if (ctx->in_inquire)
+ return _assuan_error (ASSUAN_Nested_Commands);
+
+ ctx->in_inquire = 1;
+ if (nodataexpected)
+ memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
+ else
+ init_membuf (&mb, maxlen? maxlen:1024, maxlen);
+
+ strcpy (stpcpy (cmdbuf, "INTQUIRE "), keyword);
+ rc = assuan_write_line (ctx, cmdbuf);
+ if (rc)
+ goto leave;
+
+ for (;;)
+ {
+ do
+ {
+ rc = _assuan_read_line (ctx);
+ if (rc)
+ goto leave;
+ line = (unsigned char *) ctx->inbound.line;
+ linelen = ctx->inbound.linelen;
+ }
+ while (*line == '#' || !linelen);
+ if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
+ && (!line[3] || line[3] == ' '))
+ break; /* END command received*/
+ if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
+ {
+ rc = _assuan_error (ASSUAN_Canceled);
+ goto leave;
+ }
+ if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
+ {
+ rc = _assuan_error (ASSUAN_Unexpected_Command);
+ goto leave;
+ }
+ if (linelen < 3)
+ continue;
+ line += 2;
+ linelen -= 2;
+
+ p = line;
+ while (linelen)
+ {
+ for (;linelen && *p != '%'; linelen--, p++)
+ ;
+ put_membuf (&mb, line, p-line);
+ if (linelen > 2)
+ { /* handle escaping */
+ unsigned char tmp[1];
+ p++;
+ *tmp = xtoi_2 (p);
+ p += 2;
+ linelen -= 3;
+ put_membuf (&mb, tmp, 1);
+ }
+ line = p;
+ }
+ if (mb.too_large)
+ {
+ rc = _assuan_error (ASSUAN_Too_Much_Data);
+ goto leave;
+ }
+ }
+
+ if (!nodataexpected)
+ {
+ *r_buffer = get_membuf (&mb, r_length);
+ if (!*r_buffer)
+ rc = _assuan_error (ASSUAN_Out_Of_Core);
+ }
+
+ leave:
+ if (!nodataexpected)
+ free_membuf (&mb);
+ ctx->in_inquire = 0;
+ return rc;
+}
+
+
+
+
+
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-io.c b/libtdenetwork/libgpgme-copy/assuan/assuan-io.c
new file mode 100644
index 000000000..d1f0d5e48
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-io.c
@@ -0,0 +1,87 @@
+/* assuan-io.c - Wraps the read and write functions.
+ * Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#else
+# include <sys/wait.h>
+#endif
+
+#include "assuan-defs.h"
+
+
+#ifndef HAVE_W32_SYSTEM
+pid_t
+_assuan_waitpid (pid_t pid, int *status, int options)
+{
+ return waitpid (pid, status, options);
+}
+#endif
+
+
+ssize_t
+_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
+{
+ return read (ctx->inbound.fd, buffer, size);
+}
+
+ssize_t
+_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
+{
+ return write (ctx->outbound.fd, buffer, size);
+}
+
+
+ssize_t
+_assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
+{
+#ifdef HAVE_W32_SYSTEM
+ return _assuan_error (ASSUAN_Not_Implemented);
+#else
+ int ret;
+ while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
+ ;
+ return ret;
+#endif
+}
+
+
+ssize_t
+_assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
+{
+#ifdef HAVE_W32_SYSTEM
+ return _assuan_error (ASSUAN_Not_Implemented);
+#else
+ int ret;
+ while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
+ ;
+ return ret;
+#endif
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-listen.c b/libtdenetwork/libgpgme-copy/assuan/assuan-listen.c
new file mode 100644
index 000000000..04db68ce0
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-listen.c
@@ -0,0 +1,157 @@
+/* assuan-listen.c - Wait for a connection (server)
+ * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "assuan-defs.h"
+
+assuan_error_t
+assuan_set_hello_line (assuan_context_t ctx, const char *line)
+{
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ if (!line)
+ {
+ xfree (ctx->hello_line);
+ ctx->hello_line = NULL;
+ }
+ else
+ {
+ char *buf = xtrymalloc (3+strlen(line)+1);
+ if (!buf)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ if (strchr (line, '\n'))
+ strcpy (buf, line);
+ else
+ {
+ strcpy (buf, "OK ");
+ strcpy (buf+3, line);
+ }
+ xfree (ctx->hello_line);
+ ctx->hello_line = buf;
+ }
+ return 0;
+}
+
+
+/**
+ * assuan_accept:
+ * @ctx: context
+ *
+ * Cancel any existing connection and wait for a connection from a
+ * client. The initial handshake is performed which may include an
+ * initial authentication or encryption negotiation.
+ *
+ * Return value: 0 on success or an error if the connection could for
+ * some reason not be established.
+ **/
+assuan_error_t
+assuan_accept (assuan_context_t ctx)
+{
+ int rc;
+ const char *p, *pend;
+
+ if (!ctx)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ if (ctx->pipe_mode > 1)
+ return -1; /* second invocation for pipemode -> terminate */
+ ctx->finish_handler (ctx);
+
+ rc = ctx->accept_handler (ctx);
+ if (rc)
+ return rc;
+
+ /* Send the hello. */
+ p = ctx->hello_line;
+ if (p && (pend = strchr (p, '\n')))
+ { /* This is a multi line hello. Send all but the last line as
+ comments. */
+ do
+ {
+ rc = _assuan_write_line (ctx, "# ", p, pend - p);
+ if (rc)
+ return rc;
+ p = pend + 1;
+ pend = strchr (p, '\n');
+ }
+ while (pend);
+ rc = _assuan_write_line (ctx, "OK ", p, strlen (p));
+ }
+ else if (p)
+ rc = assuan_write_line (ctx, p);
+ else
+ rc = assuan_write_line (ctx, "OK Pleased to meet you");
+ if (rc)
+ return rc;
+
+ if (ctx->pipe_mode)
+ ctx->pipe_mode = 2;
+
+ return 0;
+}
+
+
+
+int
+assuan_get_input_fd (assuan_context_t ctx)
+{
+ return ctx? ctx->input_fd : -1;
+}
+
+
+int
+assuan_get_output_fd (assuan_context_t ctx)
+{
+ return ctx? ctx->output_fd : -1;
+}
+
+
+/* Close the fd descriptor set by the command INPUT FD=n. We handle
+ this fd inside assuan so that we can do some initial checks */
+assuan_error_t
+assuan_close_input_fd (assuan_context_t ctx)
+{
+ if (!ctx || ctx->input_fd == -1)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ _assuan_close (ctx->input_fd);
+ ctx->input_fd = -1;
+ return 0;
+}
+
+/* Close the fd descriptor set by the command OUTPUT FD=n. We handle
+ this fd inside assuan so that we can do some initial checks */
+assuan_error_t
+assuan_close_output_fd (assuan_context_t ctx)
+{
+ if (!ctx || ctx->output_fd == -1)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ _assuan_close (ctx->output_fd);
+ ctx->output_fd = -1;
+ return 0;
+}
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-logging.c b/libtdenetwork/libgpgme-copy/assuan/assuan-logging.c
new file mode 100644
index 000000000..cfc3d846f
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-logging.c
@@ -0,0 +1,241 @@
+/* assuan-logging.c - Default logging function.
+ * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#endif /*HAVE_W32_SYSTEM*/
+#include <errno.h>
+#include <ctype.h>
+
+#include "assuan-defs.h"
+
+static char prefix_buffer[80];
+static FILE *_assuan_log;
+static int full_logging;
+
+void
+_assuan_set_default_log_stream (FILE *fp)
+{
+ if (!_assuan_log)
+ {
+ _assuan_log = fp;
+ full_logging = !!getenv ("ASSUAN_FULL_LOGGING");
+ }
+}
+
+void
+assuan_set_assuan_log_stream (FILE *fp)
+{
+ _assuan_log = fp;
+}
+
+
+/* Set the per context log stream. Also enable the default log stream
+ if it has not been set. */
+void
+assuan_set_log_stream (assuan_context_t ctx, FILE *fp)
+{
+ if (ctx)
+ {
+ if (ctx->log_fp)
+ fflush (ctx->log_fp);
+ ctx->log_fp = fp;
+ _assuan_set_default_log_stream (fp);
+ }
+}
+
+
+FILE *
+assuan_get_assuan_log_stream (void)
+{
+ return _assuan_log ? _assuan_log : stderr;
+}
+
+
+/* Set the prefix to be used for logging to TEXT or
+ resets it to the default if TEXT is NULL. */
+void
+assuan_set_assuan_log_prefix (const char *text)
+{
+ if (text)
+ {
+ strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
+ prefix_buffer[sizeof (prefix_buffer)-1] = 0;
+ }
+ else
+ *prefix_buffer = 0;
+}
+
+const char *
+assuan_get_assuan_log_prefix (void)
+{
+ return prefix_buffer;
+}
+
+
+void
+_assuan_log_printf (const char *format, ...)
+{
+ va_list arg_ptr;
+ FILE *fp;
+ const char *prf;
+ int save_errno = errno;
+
+ fp = assuan_get_assuan_log_stream ();
+ prf = assuan_get_assuan_log_prefix ();
+ if (*prf)
+ fprintf (fp, "%s[%u]: ", prf, (unsigned int)getpid ());
+
+ va_start (arg_ptr, format);
+ vfprintf (fp, format, arg_ptr );
+ va_end (arg_ptr);
+ errno = save_errno;
+}
+
+
+/* Dump a possibly binary string (used for debugging). Distinguish
+ ascii text from binary and print it accordingly. This function
+ takes FILE pointer arg becuase logging may be enabled on a per
+ context basis. */
+void
+_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
+{
+ const unsigned char *s;
+ int n;
+
+ for (n=length,s=buffer; n; n--, s++)
+ if ((!isascii (*s) || iscntrl (*s) || !isprint (*s)) && !(*s >= 0x80))
+ break;
+
+ s = buffer;
+ if (!n && *s != '[')
+ fwrite (buffer, length, 1, fp);
+ else
+ {
+#ifdef HAVE_FLOCKFILE
+ flockfile (fp);
+#endif
+ putc_unlocked ('[', fp);
+ if ( length > 16 && !full_logging)
+ {
+ for (n=0; n < 12; n++, s++)
+ fprintf (fp, " %02x", *s);
+ fprintf (fp, " ...(%d bytes skipped)", (int)length - 12);
+ }
+ else
+ {
+ for (n=0; n < length; n++, s++)
+ fprintf (fp, " %02x", *s);
+ }
+ putc_unlocked (' ', fp);
+ putc_unlocked (']', fp);
+#ifdef HAVE_FUNLOCKFILE
+ funlockfile (fp);
+#endif
+ }
+}
+
+/* Log a user supplied string. Escapes non-printable before
+ printing. */
+void
+_assuan_log_sanitized_string (const char *string)
+{
+ const unsigned char *s = (const unsigned char *) string;
+ FILE *fp = assuan_get_assuan_log_stream ();
+
+ if (! *s)
+ return;
+
+#ifdef HAVE_FLOCKFILE
+ flockfile (fp);
+#endif
+
+ for (; *s; s++)
+ {
+ int c = 0;
+
+ switch (*s)
+ {
+ case '\r':
+ c = 'r';
+ break;
+
+ case '\n':
+ c = 'n';
+ break;
+
+ case '\f':
+ c = 'f';
+ break;
+
+ case '\v':
+ c = 'v';
+ break;
+
+ case '\b':
+ c = 'b';
+ break;
+
+ default:
+ if ((isascii (*s) && isprint (*s)) || (*s >= 0x80))
+ putc_unlocked (*s, fp);
+ else
+ {
+ putc_unlocked ('\\', fp);
+ fprintf (fp, "x%02x", *s);
+ }
+ }
+
+ if (c)
+ {
+ putc_unlocked ('\\', fp);
+ putc_unlocked (c, fp);
+ }
+ }
+
+#ifdef HAVE_FUNLOCKFILE
+ funlockfile (fp);
+#endif
+}
+
+
+
+#ifdef HAVE_W32_SYSTEM
+const char *
+_assuan_w32_strerror (int ec)
+{
+ static char strerr[256];
+
+ if (ec == -1)
+ ec = (int)GetLastError ();
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ strerr, sizeof (strerr)-1, NULL);
+ return strerr;
+}
+#endif /*HAVE_W32_SYSTEM*/
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-connect.c b/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-connect.c
new file mode 100644
index 000000000..8ee9c748b
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-connect.c
@@ -0,0 +1,889 @@
+/* assuan-pipe-connect.c - Establish a pipe connection (client)
+ * Copyright (C) 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/wait.h>
+#else
+#include <windows.h>
+#endif
+
+#include "assuan-defs.h"
+
+/* Hacks for Slowaris. */
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+# define PF_LOCAL PF_UNIX
+# else
+# define PF_LOCAL AF_UNIX
+# endif
+#endif
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
+
+#ifdef _POSIX_OPEN_MAX
+#define MAX_OPEN_FDS _POSIX_OPEN_MAX
+#else
+#define MAX_OPEN_FDS 20
+#endif
+
+#ifdef HAVE_W32_SYSTEM
+/* We assume that a HANDLE can be represented by an int which should
+ be true for all i386 systems (HANDLE is defined as void *) and
+ these are the only systems for which Windows is available. Further
+ we assume that -1 denotes an invalid handle. */
+#define fd_to_handle(a) ((HANDLE)(a))
+#define handle_to_fd(a) ((int)(a))
+#define pid_to_handle(a) ((HANDLE)(a))
+#define handle_to_pid(a) ((int)(a))
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* This should be called to make sure that SIGPIPE gets ignored. */
+static void
+fix_signals (void)
+{
+#ifndef _ASSUAN_NO_FIXED_SIGNALS
+#ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */
+ static int fixed_signals;
+
+ if (!fixed_signals)
+ {
+ struct sigaction act;
+
+ sigaction (SIGPIPE, NULL, &act);
+ if (act.sa_handler == SIG_DFL)
+ {
+ act.sa_handler = SIG_IGN;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction (SIGPIPE, &act, NULL);
+ }
+ fixed_signals = 1;
+ /* FIXME: This is not MT safe */
+ }
+#endif /*HAVE_DOSISH_SYSTEM*/
+#endif /*!_ASSUAN_NO_FIXED_SIGNALS*/
+}
+
+
+#ifndef HAVE_W32_SYSTEM
+static int
+writen (int fd, const char *buffer, size_t length)
+{
+ while (length)
+ {
+ int nwritten = write (fd, buffer, length);
+
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return -1; /* write error */
+ }
+ length -= nwritten;
+ buffer += nwritten;
+ }
+ return 0; /* okay */
+}
+#endif
+
+static int
+do_finish (assuan_context_t ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ _assuan_close (ctx->inbound.fd);
+ if (ctx->inbound.fd == ctx->outbound.fd)
+ ctx->outbound.fd = -1;
+ ctx->inbound.fd = -1;
+ }
+ if (ctx->outbound.fd != -1)
+ {
+ _assuan_close (ctx->outbound.fd);
+ ctx->outbound.fd = -1;
+ }
+ if (ctx->pid != -1 && ctx->pid)
+ {
+#ifndef HAVE_W32_SYSTEM
+#ifndef _ASSUAN_USE_DOUBLE_FORK
+ if (!ctx->flags.no_waitpid)
+ _assuan_waitpid (ctx->pid, NULL, 0);
+ ctx->pid = -1;
+#endif
+#endif /*!HAVE_W32_SYSTEM*/
+ }
+ return 0;
+}
+
+static void
+do_deinit (assuan_context_t ctx)
+{
+ do_finish (ctx);
+}
+
+
+/* Helper for pipe_connect. */
+static assuan_error_t
+initial_handshake (assuan_context_t *ctx)
+{
+ int okay, off;
+ assuan_error_t err;
+
+ err = _assuan_read_from_server (*ctx, &okay, &off);
+ if (err)
+ _assuan_log_printf ("can't connect server: %s\n",
+ assuan_strerror (err));
+ else if (okay != 1)
+ {
+ _assuan_log_printf ("can't connect server: `%s'\n",
+ (*ctx)->inbound.line);
+ err = _assuan_error (ASSUAN_Connect_Failed);
+ }
+
+ if (err)
+ {
+ assuan_disconnect (*ctx);
+ *ctx = NULL;
+ }
+ return err;
+}
+
+
+#ifndef HAVE_W32_SYSTEM
+#define pipe_connect pipe_connect_unix
+/* Unix version of the pipe connection code. We use an extra macro to
+ make ChangeLog entries easier. */
+static assuan_error_t
+pipe_connect_unix (assuan_context_t *ctx,
+ const char *name, const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue)
+{
+ assuan_error_t err;
+ int rp[2];
+ int wp[2];
+ char mypidstr[50];
+
+ if (!ctx || !name || !argv || !argv[0])
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ fix_signals ();
+
+ sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+ if (pipe (rp) < 0)
+ return _assuan_error (ASSUAN_General_Error);
+
+ if (pipe (wp) < 0)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ err = _assuan_new_context (ctx);
+ if (err)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ close (wp[0]);
+ close (wp[1]);
+ return err;
+ }
+ (*ctx)->pipe_mode = 1;
+ (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
+ (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
+ (*ctx)->deinit_handler = do_deinit;
+ (*ctx)->finish_handler = do_finish;
+
+ /* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID
+ stored here is actually soon useless. */
+ (*ctx)->pid = fork ();
+ if ((*ctx)->pid < 0)
+ {
+ close (rp[0]);
+ close (rp[1]);
+ close (wp[0]);
+ close (wp[1]);
+ _assuan_release_context (*ctx);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ if ((*ctx)->pid == 0)
+ {
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ pid_t pid;
+
+ if ((pid = fork ()) == 0)
+#endif
+ {
+ int i, n;
+ char errbuf[512];
+ int *fdp;
+
+ if (atfork)
+ atfork (atforkvalue, 0);
+
+ /* Dup handles to stdin/stdout. */
+ if (rp[1] != STDOUT_FILENO)
+ {
+ if (dup2 (rp[1], STDOUT_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2 failed in child: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ }
+ if (wp[0] != STDIN_FILENO)
+ {
+ if (dup2 (wp[0], STDIN_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2 failed in child: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ }
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ int fd = open ("/dev/null", O_WRONLY);
+ if (fd == -1)
+ {
+ _assuan_log_printf ("can't open `/dev/null': %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ if (dup2 (fd, STDERR_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ }
+
+
+ /* Close all files which will not be duped and are not in the
+ fd_child_list. */
+ n = sysconf (_SC_OPEN_MAX);
+ if (n < 0)
+ n = MAX_OPEN_FDS;
+ for (i=0; i < n; i++)
+ {
+ if ( i == STDIN_FILENO || i == STDOUT_FILENO
+ || i == STDERR_FILENO)
+ continue;
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ while (*fdp != -1 && *fdp != i)
+ fdp++;
+ }
+
+ if (!(fdp && *fdp != -1))
+ close(i);
+ }
+ errno = 0;
+
+ /* We store our parents pid in the environment so that the
+ execed assuan server is able to read the actual pid of the
+ client. The server can't use getppid because it might have
+ been double forked before the assuan server has been
+ initialized. */
+ setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+ /* Make sure that we never pass a connection fd variable
+ when using a simple pipe. */
+ unsetenv ("_assuan_connection_fd");
+
+ execv (name, (char *const *) argv);
+ /* oops - use the pipe to tell the parent about it */
+ snprintf (errbuf, sizeof(errbuf)-1,
+ "ERR %d can't exec `%s': %.50s\n",
+ _assuan_error (ASSUAN_Problem_Starting_Server),
+ name, strerror (errno));
+ errbuf[sizeof(errbuf)-1] = 0;
+ writen (1, errbuf, strlen (errbuf));
+ _exit (4);
+ }
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ if (pid == -1)
+ _exit (1);
+ else
+ _exit (0);
+#endif
+ }
+
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ _assuan_waitpid ((*ctx)->pid, NULL, 0);
+ (*ctx)->pid = -1;
+#endif
+
+ close (rp[1]);
+ close (wp[0]);
+
+ return initial_handshake (ctx);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+#ifndef HAVE_W32_SYSTEM
+/* This function is similar to pipe_connect but uses a socketpair and
+ sets the I/O up to use sendmsg/recvmsg. */
+static assuan_error_t
+socketpair_connect (assuan_context_t *ctx,
+ const char *name, const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue)
+{
+ assuan_error_t err;
+ int fds[2];
+ char mypidstr[50];
+
+ if (!ctx
+ || (name && (!argv || !argv[0]))
+ || (!name && argv))
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ fix_signals ();
+
+ sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+ if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
+ {
+ _assuan_log_printf ("socketpair failed: %s\n", strerror (errno));
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ err = _assuan_new_context (ctx);
+ if (err)
+ {
+ close (fds[0]);
+ close (fds[1]);
+ return err;
+ }
+ (*ctx)->pipe_mode = 1;
+ (*ctx)->inbound.fd = fds[0];
+ (*ctx)->outbound.fd = fds[0];
+ _assuan_init_uds_io (*ctx);
+ (*ctx)->deinit_handler = _assuan_uds_deinit;
+ (*ctx)->finish_handler = do_finish;
+
+ (*ctx)->pid = fork ();
+ if ((*ctx)->pid < 0)
+ {
+ close (fds[0]);
+ close (fds[1]);
+ _assuan_release_context (*ctx);
+ *ctx = NULL;
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ if ((*ctx)->pid == 0)
+ {
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ pid_t pid;
+
+ if ((pid = fork ()) == 0)
+#endif
+ {
+ int fd, i, n;
+ char errbuf[512];
+ int *fdp;
+
+ if (atfork)
+ atfork (atforkvalue, 0);
+
+ /* Connect stdin and stdout to /dev/null. */
+ fd = open ("/dev/null", O_RDONLY);
+ if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2(dev/null) failed: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ fd = open ("/dev/null", O_WRONLY);
+ if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2(dev/null) failed: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ fd = open ("/dev/null", O_WRONLY);
+ if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
+ {
+ _assuan_log_printf ("dup2(dev/null) failed: %s\n",
+ strerror (errno));
+ _exit (4);
+ }
+ }
+
+
+ /* Close all files which will not be duped, are not in the
+ fd_child_list and are not the connection fd. */
+ n = sysconf (_SC_OPEN_MAX);
+ if (n < 0)
+ n = MAX_OPEN_FDS;
+ for (i=0; i < n; i++)
+ {
+ if ( i == STDIN_FILENO || i == STDOUT_FILENO
+ || i == STDERR_FILENO || i == fds[1])
+ continue;
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ while (*fdp != -1 && *fdp != i)
+ fdp++;
+ }
+
+ if (!(fdp && *fdp != -1))
+ close(i);
+ }
+ errno = 0;
+
+ /* We store our parents pid in the environment so that the
+ execed assuan server is able to read the actual pid of the
+ client. The server can't use getppid becuase it might have
+ been double forked before the assuan server has been
+ initialized. */
+ setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
+
+ /* Now set the environment variable used to convey the
+ connection's file descriptor. */
+ sprintf (mypidstr, "%d", fds[1]);
+ if (setenv ("_assuan_connection_fd", mypidstr, 1))
+ {
+ _assuan_log_printf ("setenv failed: %s\n", strerror (errno));
+ _exit (4);
+ }
+
+ if (!name && !argv)
+ {
+ /* No name and no args given, thus we don't do an exec
+ but continue the forked process. */
+ _assuan_release_context (*ctx);
+ *ctx = NULL;
+ return 0;
+ }
+
+ execv (name, (char *const *) argv);
+ /* oops - use the pipe to tell the parent about it */
+ snprintf (errbuf, sizeof(errbuf)-1,
+ "ERR %d can't exec `%s': %.50s\n",
+ _assuan_error (ASSUAN_Problem_Starting_Server),
+ name, strerror (errno));
+ errbuf[sizeof(errbuf)-1] = 0;
+ writen (fds[1], errbuf, strlen (errbuf));
+ _exit (4);
+ }
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ if (pid == -1)
+ _exit (1);
+ else
+ _exit (0);
+#endif
+ }
+
+
+#ifdef _ASSUAN_USE_DOUBLE_FORK
+ _assuan_waitpid ((*ctx)->pid, NULL, 0);
+ (*ctx)->pid = -1;
+#endif
+
+ close (fds[1]);
+
+ return initial_handshake (ctx);
+}
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Build a command line for use with W32's CreateProcess. On success
+ CMDLINE gets the address of a newly allocated string. */
+static int
+build_w32_commandline (char * const *argv, char **cmdline)
+{
+ int i, n;
+ const char *s;
+ char *buf, *p;
+
+ *cmdline = NULL;
+ n = 0;
+ for (i=0; (s=argv[i]); i++)
+ {
+ n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
+ for (; *s; s++)
+ if (*s == '\"')
+ n++; /* Need to double inner quotes. */
+ }
+ n++;
+
+ buf = p = xtrymalloc (n);
+ if (!buf)
+ return -1;
+
+ for (i=0; argv[i]; i++)
+ {
+ if (i)
+ p = stpcpy (p, " ");
+ if (!*argv[i]) /* Empty string. */
+ p = stpcpy (p, "\"\"");
+ else if (strpbrk (argv[i], " \t\n\v\f\""))
+ {
+ p = stpcpy (p, "\"");
+ for (s=argv[i]; *s; s++)
+ {
+ *p++ = *s;
+ if (*s == '\"')
+ *p++ = *s;
+ }
+ *p++ = '\"';
+ *p = 0;
+ }
+ else
+ p = stpcpy (p, argv[i]);
+ }
+
+ *cmdline= buf;
+ return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Create pipe where one end end is inheritable. */
+static int
+create_inheritable_pipe (int filedes[2], int for_write)
+{
+ HANDLE r, w, h;
+ SECURITY_ATTRIBUTES sec_attr;
+
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ if (!CreatePipe (&r, &w, &sec_attr, 0))
+ {
+ _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1));
+ return -1;
+ }
+
+ if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w,
+ GetCurrentProcess(), &h, 0,
+ TRUE, DUPLICATE_SAME_ACCESS ))
+ {
+ _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1));
+ CloseHandle (r);
+ CloseHandle (w);
+ return -1;
+ }
+ if (for_write)
+ {
+ CloseHandle (r);
+ r = h;
+ }
+ else
+ {
+ CloseHandle (w);
+ w = h;
+ }
+
+ filedes[0] = handle_to_fd (r);
+ filedes[1] = handle_to_fd (w);
+ return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+#ifdef HAVE_W32_SYSTEM
+#define pipe_connect pipe_connect_w32
+/* W32 version of the pipe connection code. */
+static assuan_error_t
+pipe_connect_w32 (assuan_context_t *ctx,
+ const char *name, const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue)
+{
+ assuan_error_t err;
+ int rp[2];
+ int wp[2];
+ char mypidstr[50];
+ char *cmdline;
+ SECURITY_ATTRIBUTES sec_attr;
+ PROCESS_INFORMATION pi =
+ {
+ NULL, /* Returns process handle. */
+ 0, /* Returns primary thread handle. */
+ 0, /* Returns pid. */
+ 0 /* Returns tid. */
+ };
+ STARTUPINFO si;
+ int fd, *fdp;
+ HANDLE nullfd = INVALID_HANDLE_VALUE;
+
+ if (!ctx || !name || !argv || !argv[0])
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ fix_signals ();
+
+ sprintf (mypidstr, "%lu", (unsigned long)getpid ());
+
+ /* Build the command line. */
+ if (build_w32_commandline (argv, &cmdline))
+ return _assuan_error (ASSUAN_Out_Of_Core);
+
+ /* Create thew two pipes. */
+ if (create_inheritable_pipe (rp, 0))
+ {
+ xfree (cmdline);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ if (create_inheritable_pipe (wp, 1))
+ {
+ CloseHandle (fd_to_handle (rp[0]));
+ CloseHandle (fd_to_handle (rp[1]));
+ xfree (cmdline);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+
+ err = _assuan_new_context (ctx);
+ if (err)
+ {
+ CloseHandle (fd_to_handle (rp[0]));
+ CloseHandle (fd_to_handle (rp[1]));
+ CloseHandle (fd_to_handle (wp[0]));
+ CloseHandle (fd_to_handle (wp[1]));
+ xfree (cmdline);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ (*ctx)->pipe_mode = 1;
+ (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
+ (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
+ (*ctx)->deinit_handler = do_deinit;
+ (*ctx)->finish_handler = do_finish;
+
+
+ /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
+ variable. However this requires us to write a full environment
+ handler, because the strings are expected in sorted order. The
+ suggestion given in the MS Reference Library, to save the old
+ value, changeit, create proces and restore it, is not thread
+ safe. */
+
+ /* Start the process. */
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ memset (&si, 0, sizeof si);
+ si.cb = sizeof (si);
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = fd_to_handle (wp[0]);
+ si.hStdOutput = fd_to_handle (rp[1]);
+
+ /* Dup stderr to /dev/null unless it is in the list of FDs to be
+ passed to the child. */
+ fd = fileno (stderr);
+ fdp = fd_child_list;
+ if (fdp)
+ {
+ for (; *fdp != -1 && *fdp != fd; fdp++)
+ ;
+ }
+ if (!fdp || *fdp == -1)
+ {
+ nullfd = CreateFile ("nul", GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (nullfd == INVALID_HANDLE_VALUE)
+ {
+ _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1));
+ CloseHandle (fd_to_handle (rp[0]));
+ CloseHandle (fd_to_handle (rp[1]));
+ CloseHandle (fd_to_handle (wp[0]));
+ CloseHandle (fd_to_handle (wp[1]));
+ xfree (cmdline);
+ _assuan_release_context (*ctx);
+ return -1;
+ }
+ si.hStdError = nullfd;
+ }
+ else
+ si.hStdError = fd_to_handle (_get_osfhandle (fd));
+
+
+ /* Note: We inherit all handles flagged as inheritable. This seems
+ to be a security flaw but there seems to be no way of selecting
+ handles to inherit. */
+ /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
+ /* name, cmdline); */
+ if (!CreateProcess (name, /* Program to start. */
+ cmdline, /* Command line arguments. */
+ &sec_attr, /* Process security attributes. */
+ &sec_attr, /* Thread security attributes. */
+ TRUE, /* Inherit handles. */
+ (CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ())
+ | CREATE_SUSPENDED), /* Creation flags. */
+ NULL, /* Environment. */
+ NULL, /* Use current drive/directory. */
+ &si, /* Startup information. */
+ &pi /* Returns process information. */
+ ))
+ {
+ _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1));
+ CloseHandle (fd_to_handle (rp[0]));
+ CloseHandle (fd_to_handle (rp[1]));
+ CloseHandle (fd_to_handle (wp[0]));
+ CloseHandle (fd_to_handle (wp[1]));
+ if (nullfd != INVALID_HANDLE_VALUE)
+ CloseHandle (nullfd);
+ xfree (cmdline);
+ _assuan_release_context (*ctx);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+ xfree (cmdline);
+ cmdline = NULL;
+ if (nullfd != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (nullfd);
+ nullfd = INVALID_HANDLE_VALUE;
+ }
+
+ CloseHandle (fd_to_handle (rp[1]));
+ CloseHandle (fd_to_handle (wp[0]));
+
+ /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
+ /* " dwProcessID=%d dwThreadId=%d\n", */
+ /* pi.hProcess, pi.hThread, */
+ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
+
+ ResumeThread (pi.hThread);
+ CloseHandle (pi.hThread);
+ (*ctx)->pid = 0; /* We don't use the PID. */
+ CloseHandle (pi.hProcess); /* We don't need to wait for the process. */
+
+ return initial_handshake (ctx);
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Connect to a server over a pipe, creating the assuan context and
+ returning it in CTX. The server filename is NAME, the argument
+ vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file
+ descriptors not to close in the child. */
+assuan_error_t
+assuan_pipe_connect (assuan_context_t *ctx, const char *name,
+ const char *const argv[], int *fd_child_list)
+{
+ return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL);
+}
+
+
+
+assuan_error_t
+assuan_pipe_connect2 (assuan_context_t *ctx,
+ const char *name, const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue)
+{
+ return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
+}
+
+
+/* Connect to a server over a full-duplex socket (i.e. created by
+ socketpair), creating the assuan context and returning it in CTX.
+ The server filename is NAME, the argument vector in ARGV.
+ FD_CHILD_LIST is a -1 terminated list of file descriptors not to
+ close in the child. ATFORK is called in the child right after the
+ fork; ATFORKVALUE is passed as the first argument and 0 is passed
+ as the second argument. The ATFORK function should only act if the
+ second value is 0.
+
+ For now FLAGS may either take the value 0 to behave like
+ assuan_pipe_connect2 or 1 to enable the described full-duplex
+ socket behaviour.
+
+ If NAME as well as ARGV are NULL, no exec is done but the same
+ process is continued. However all file descriptors are closed and
+ some special environment variables are set. To let the caller
+ detect whether the child or the parent continues, the child returns
+ a CTX of NULL. */
+assuan_error_t
+assuan_pipe_connect_ext (assuan_context_t *ctx,
+ const char *name, const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *opaque, int reserved),
+ void *atforkvalue, unsigned int flags)
+{
+ if ((flags & 1))
+ {
+#ifdef HAVE_W32_SYSTEM
+ return _assuan_error (ASSUAN_Not_Implemented);
+#else
+ return socketpair_connect (ctx, name, argv, fd_child_list,
+ atfork, atforkvalue);
+#endif
+ }
+ else
+ return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue);
+}
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-server.c b/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-server.c
new file mode 100644
index 000000000..f88516143
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-pipe-server.c
@@ -0,0 +1,187 @@
+/* assuan-pipe-server.c - Assuan server working over a pipe
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#include <fcntl.h>
+#endif
+
+#include "assuan-defs.h"
+
+
+static void
+deinit_pipe_server (assuan_context_t ctx)
+{
+ /* nothing to do for this simple server */
+}
+
+static int
+accept_connection (assuan_context_t ctx)
+{
+ /* This is a NOP for a pipe server */
+ return 0;
+}
+
+static int
+finish_connection (assuan_context_t ctx)
+{
+ /* This is a NOP for a pipe server */
+ return 0;
+}
+
+/* Create a new context. Note that the handlers are set up for a pipe
+ server/client - this way we don't need extra dummy functions */
+int
+_assuan_new_context (assuan_context_t *r_ctx)
+{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write,
+ 0, 0 };
+
+ assuan_context_t ctx;
+ int rc;
+
+ *r_ctx = NULL;
+ ctx = xtrycalloc (1, sizeof *ctx);
+ if (!ctx)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ ctx->io = &io;
+
+ ctx->listen_fd = -1;
+ /* Use the pipe server handler as a default. */
+ ctx->deinit_handler = deinit_pipe_server;
+ ctx->accept_handler = accept_connection;
+ ctx->finish_handler = finish_connection;
+
+ rc = _assuan_register_std_commands (ctx);
+ if (rc)
+ xfree (ctx);
+ else
+ *r_ctx = ctx;
+ return rc;
+}
+
+
+/* Returns true if atoi(S) denotes a valid socket. */
+static int
+is_valid_socket (const char *s)
+{
+ struct stat buf;
+
+ if ( fstat (atoi (s), &buf ) )
+ return 0;
+ return S_ISSOCK (buf.st_mode);
+}
+
+
+int
+assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
+{
+ int rc;
+
+ rc = _assuan_new_context (r_ctx);
+ if (!rc)
+ {
+ assuan_context_t ctx = *r_ctx;
+ const char *s;
+ unsigned long ul;
+
+ ctx->is_server = 1;
+#ifdef HAVE_W32_SYSTEM
+ /* MS Windows has so many different types of handle that one
+ needs to tranlsate them at many place forth and back. Also
+ make sure that the fiel descriptos are in binary mode. */
+ setmode (filedes[0], O_BINARY);
+ setmode (filedes[1], O_BINARY);
+ ctx->inbound.fd = _get_osfhandle (filedes[0]);
+ ctx->outbound.fd = _get_osfhandle (filedes[1]);
+#else
+ s = getenv ("_assuan_connection_fd");
+ if (s && *s && is_valid_socket (s) )
+ {
+ /* Well, we are called with an bi-directional file
+ descriptor. Prepare for using sendmsg/recvmsg. In this
+ case we ignore the passed file descriptors. */
+ ctx->inbound.fd = ctx->outbound.fd = atoi (s);
+ _assuan_init_uds_io (ctx);
+ ctx->deinit_handler = _assuan_uds_deinit;
+ }
+ else if (filedes && filedes[0] != -1 && filedes[1] != -1 )
+ {
+ /* Standard pipe server. */
+ ctx->inbound.fd = filedes[0];
+ ctx->outbound.fd = filedes[1];
+ }
+ else
+ {
+ _assuan_release_context (*r_ctx);
+ *r_ctx = NULL;
+ return ASSUAN_Problem_Starting_Server;
+ }
+#endif
+ ctx->pipe_mode = 1;
+
+ s = getenv ("_assuan_pipe_connect_pid");
+ if (s && (ul=strtoul (s, NULL, 10)) && ul)
+ ctx->pid = (pid_t)ul;
+ else
+ ctx->pid = (pid_t)-1;
+
+ }
+ return rc;
+}
+
+
+void
+_assuan_release_context (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ xfree (ctx->hello_line);
+ xfree (ctx->okay_line);
+ xfree (ctx->cmdtbl);
+ xfree (ctx);
+ }
+}
+
+void
+assuan_deinit_server (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ /* We use this function pointer to avoid linking other server
+ when not needed but still allow for a generic deinit function. */
+ ctx->deinit_handler (ctx);
+ ctx->deinit_handler = NULL;
+ _assuan_release_context (ctx);
+ }
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-socket-connect.c b/libtdenetwork/libgpgme-copy/assuan/assuan-socket-connect.c
new file mode 100644
index 000000000..5953f1c33
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-socket-connect.c
@@ -0,0 +1,184 @@
+/* assuan-socket-connect.c - Assuan socket based client
+ * Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#else
+#include <windows.h>
+#endif
+
+#include "assuan-defs.h"
+
+/* Hacks for Slowaris. */
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+# define PF_LOCAL PF_UNIX
+# else
+# define PF_LOCAL AF_UNIX
+# endif
+#endif
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
+#ifndef SUN_LEN
+# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ + strlen ((ptr)->sun_path))
+#endif
+
+
+static int
+do_finish (assuan_context_t ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ _assuan_close (ctx->inbound.fd);
+ }
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ return 0;
+}
+
+static void
+do_deinit (assuan_context_t ctx)
+{
+ do_finish (ctx);
+}
+
+
+/* Make a connection to the Unix domain socket NAME and return a new
+ Assuan context in CTX. SERVER_PID is currently not used but may
+ become handy in the future. */
+assuan_error_t
+assuan_socket_connect (assuan_context_t *r_ctx,
+ const char *name, pid_t server_pid)
+{
+ return assuan_socket_connect_ext (r_ctx, name, server_pid, 0);
+}
+
+
+/* Make a connection to the Unix domain socket NAME and return a new
+ Assuan context in CTX. SERVER_PID is currently not used but may
+ become handy in the future. With flags set to 1 sendmsg and
+ recvmesg are used. */
+assuan_error_t
+assuan_socket_connect_ext (assuan_context_t *r_ctx,
+ const char *name, pid_t server_pid,
+ unsigned int flags)
+{
+ static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
+
+ assuan_error_t err;
+ assuan_context_t ctx;
+ int fd;
+ struct sockaddr_un srvr_addr;
+ size_t len;
+ const char *s;
+
+ if (!r_ctx || !name)
+ return _assuan_error (ASSUAN_Invalid_Value);
+ *r_ctx = NULL;
+
+ /* We require that the name starts with a slash, so that we
+ eventually can reuse this function for other socket types. To
+ make things easier we allow an optional dirver prefix. */
+ s = name;
+ if (*s && s[1] == ':')
+ s += 2;
+ if (*s != DIRSEP_C && *s != '/')
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
+ return _assuan_error (ASSUAN_Invalid_Value);
+
+ err = _assuan_new_context (&ctx);
+ if (err)
+ return err;
+ ctx->deinit_handler = ((flags&1))? _assuan_uds_deinit : do_deinit;
+ ctx->finish_handler = do_finish;
+
+ fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ _assuan_log_printf ("can't create socket: %s\n", strerror (errno));
+ _assuan_release_context (ctx);
+ return _assuan_error (ASSUAN_General_Error);
+ }
+
+ memset (&srvr_addr, 0, sizeof srvr_addr);
+ srvr_addr.sun_family = AF_LOCAL;
+ strncpy (srvr_addr.sun_path, name, sizeof (srvr_addr.sun_path) - 1);
+ srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0;
+ len = SUN_LEN (&srvr_addr);
+
+
+ if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1)
+ {
+ _assuan_log_printf ("can't connect to `%s': %s\n",
+ name, strerror (errno));
+ _assuan_release_context (ctx);
+ _assuan_close (fd);
+ return _assuan_error (ASSUAN_Connect_Failed);
+ }
+
+ ctx->inbound.fd = fd;
+ ctx->outbound.fd = fd;
+ ctx->io = &io;
+ if ((flags&1))
+ _assuan_init_uds_io (ctx);
+
+ /* initial handshake */
+ {
+ int okay, off;
+
+ err = _assuan_read_from_server (ctx, &okay, &off);
+ if (err)
+ _assuan_log_printf ("can't connect to server: %s\n",
+ assuan_strerror (err));
+ else if (okay != 1)
+ {
+ /*LOG ("can't connect to server: `");*/
+ _assuan_log_sanitized_string (ctx->inbound.line);
+ fprintf (assuan_get_assuan_log_stream (), "'\n");
+ err = _assuan_error (ASSUAN_Connect_Failed);
+ }
+ }
+
+ if (err)
+ {
+ assuan_disconnect (ctx);
+ }
+ else
+ *r_ctx = ctx;
+ return 0;
+}
+
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-socket-server.c b/libtdenetwork/libgpgme-copy/assuan/assuan-socket-server.c
new file mode 100644
index 000000000..45c227d6d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-socket-server.c
@@ -0,0 +1,187 @@
+/* assuan-socket-server.c - Assuan socket based server
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#else
+#include <windows.h>
+#endif
+
+#include "assuan-defs.h"
+
+static struct assuan_io io = { _assuan_simple_read,
+ _assuan_simple_write };
+
+
+static int
+accept_connection_bottom (assuan_context_t ctx)
+{
+ int fd = ctx->connected_fd;
+
+ ctx->peercred.valid = 0;
+#ifdef HAVE_SO_PEERCRED
+ {
+ struct ucred cr;
+ socklen_t cl = sizeof cr;
+
+ if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
+ {
+ ctx->peercred.pid = cr.pid;
+ ctx->peercred.uid = cr.uid;
+ ctx->peercred.gid = cr.gid;
+ ctx->peercred.valid = 1;
+
+ /* This overrides any already set PID if the function returns
+ a valid one. */
+ if (cr.pid != (pid_t)-1 && cr.pid)
+ ctx->pid = cr.pid;
+ }
+ }
+#endif
+
+ ctx->inbound.fd = fd;
+ ctx->inbound.eof = 0;
+ ctx->inbound.linelen = 0;
+ ctx->inbound.attic.linelen = 0;
+ ctx->inbound.attic.pending = 0;
+
+ ctx->outbound.fd = fd;
+ ctx->outbound.data.linelen = 0;
+ ctx->outbound.data.error = 0;
+
+ ctx->confidential = 0;
+
+ return 0;
+}
+
+
+static int
+accept_connection (assuan_context_t ctx)
+{
+ int fd;
+ struct sockaddr_un clnt_addr;
+ socklen_t len = sizeof clnt_addr;
+
+ fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
+ if (fd == -1)
+ {
+ ctx->os_errno = errno;
+ return _assuan_error (ASSUAN_Accept_Failed);
+ }
+
+ ctx->connected_fd = fd;
+ return accept_connection_bottom (ctx);
+}
+
+static int
+finish_connection (assuan_context_t ctx)
+{
+ if (ctx->inbound.fd != -1)
+ {
+ _assuan_close (ctx->inbound.fd);
+ }
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+ return 0;
+}
+
+
+static void
+deinit_socket_server (assuan_context_t ctx)
+{
+ finish_connection (ctx);
+}
+
+/* Initialize a server for the socket LISTEN_FD which has already be
+ put into listen mode */
+int
+assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd)
+{
+ return assuan_init_socket_server_ext (r_ctx, listen_fd, 0);
+}
+
+/* Initialize a server using the already accepted socket FD. This
+ fucntion is deprecated. */
+int
+assuan_init_connected_socket_server (assuan_context_t *r_ctx, int fd)
+{
+ return assuan_init_socket_server_ext (r_ctx, fd, 2);
+}
+
+
+/*
+ Flag bits: 0 - use sendmsg/recvmsg to allow descriptor passing
+ 1 - FD has already been accepted.
+*/
+int
+assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+ unsigned int flags)
+{
+ assuan_context_t ctx;
+ int rc;
+
+ *r_ctx = NULL;
+ ctx = xtrycalloc (1, sizeof *ctx);
+ if (!ctx)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ ctx->is_server = 1;
+ if ((flags & 2))
+ ctx->pipe_mode = 1; /* We want a second accept to indicate EOF. */
+ ctx->input_fd = -1;
+ ctx->output_fd = -1;
+
+ ctx->inbound.fd = -1;
+ ctx->outbound.fd = -1;
+
+ if ((flags & 2))
+ {
+ ctx->listen_fd = -1;
+ ctx->connected_fd = fd;
+ }
+ else
+ {
+ ctx->listen_fd = fd;
+ ctx->connected_fd = -1;
+ }
+ ctx->deinit_handler = (flags & 1)? _assuan_uds_deinit:deinit_socket_server;
+ ctx->accept_handler = ((flags & 2)
+ ? accept_connection_bottom
+ : accept_connection);
+ ctx->finish_handler = finish_connection;
+
+ ctx->io = &io;
+ if ((flags & 1))
+ _assuan_init_uds_io (ctx);
+
+ rc = _assuan_register_std_commands (ctx);
+ if (rc)
+ xfree (ctx);
+ else
+ *r_ctx = ctx;
+ return rc;
+}
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-socket.c b/libtdenetwork/libgpgme-copy/assuan/assuan-socket.c
new file mode 100644
index 000000000..6aa570896
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-socket.c
@@ -0,0 +1,148 @@
+/* assuan-socket.c
+ * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#include <io.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+#include "assuan-defs.h"
+
+/* Hacks for Slowaris. */
+#ifndef PF_LOCAL
+# ifdef PF_UNIX
+# define PF_LOCAL PF_UNIX
+# else
+# define PF_LOCAL AF_UNIX
+# endif
+#endif
+#ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+#endif
+
+int
+_assuan_close (int fd)
+{
+#ifndef HAVE_W32_SYSTEM
+ return close (fd);
+#else
+ int rc = closesocket (fd);
+ if (rc && WSAGetLastError () == WSAENOTSOCK)
+ rc = close (fd);
+ return rc;
+#endif
+}
+
+
+int
+_assuan_sock_new (int domain, int type, int proto)
+{
+#ifndef HAVE_W32_SYSTEM
+ return socket (domain, type, proto);
+#else
+ if (domain == AF_UNIX || domain == AF_LOCAL)
+ domain = AF_INET;
+ return socket (domain, type, proto);
+#endif
+}
+
+
+int
+_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
+{
+#ifndef HAVE_W32_SYSTEM
+ return connect (sockfd, addr, addrlen);
+#else
+ struct sockaddr_in myaddr;
+ struct sockaddr_un * unaddr;
+ FILE * fp;
+ int port = 0;
+
+ unaddr = (struct sockaddr_un *)addr;
+ fp = fopen (unaddr->sun_path, "rb");
+ if (!fp)
+ return -1;
+ fscanf (fp, "%d", &port);
+ fclose (fp);
+ /* XXX: set errno in this case */
+ if (port < 0 || port > 65535)
+ return -1;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = port;
+ myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ /* we need this later. */
+ unaddr->sun_family = myaddr.sin_family;
+ unaddr->sun_port = myaddr.sin_port;
+ unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
+
+ return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
+#endif
+}
+
+
+int
+_assuan_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
+{
+#ifndef HAVE_W32_SYSTEM
+ return bind (sockfd, addr, addrlen);
+#else
+ if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
+ {
+ struct sockaddr_in myaddr;
+ struct sockaddr_un * unaddr;
+ FILE * fp;
+ int len = sizeof myaddr;
+ int rc;
+
+ myaddr.sin_port = 0;
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
+ if (rc)
+ return rc;
+ rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
+ if (rc)
+ return rc;
+ unaddr = (struct sockaddr_un *)addr;
+ fp = fopen (unaddr->sun_path, "wb");
+ if (!fp)
+ return -1;
+ fprintf (fp, "%d", myaddr.sin_port);
+ fclose (fp);
+
+ /* we need this later. */
+ unaddr->sun_family = myaddr.sin_family;
+ unaddr->sun_port = myaddr.sin_port;
+ unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
+
+ return 0;
+ }
+ return bind (sockfd, addr, addrlen);
+#endif
+}
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-uds.c b/libtdenetwork/libgpgme-copy/assuan/assuan-uds.c
new file mode 100644
index 000000000..e9e81016c
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-uds.c
@@ -0,0 +1,311 @@
+/* assuan-uds.c - Assuan unix domain socket utilities
+ * Copyright (C) 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/socket.h>
+#include <sys/un.h>
+#else
+#include <windows.h>
+#endif
+#if HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+#include "assuan-defs.h"
+
+#ifdef USE_DESCRIPTOR_PASSING
+/* Provide replacement for missing CMSG maccros. We assume that
+ size_t matches the tqalignment requirement. */
+#define MY_ALIGN(n) ((((n))+ sizeof(size_t)-1) & (size_t)~(sizeof(size_t)-1))
+#ifndef CMSG_SPACE
+#define CMSG_SPACE(n) (MY_ALIGN(sizeof(struct cmsghdr)) + MY_ALIGN((n)))
+#endif
+#ifndef CMSG_LEN
+#define CMSG_LEN(n) (MY_ALIGN(sizeof(struct cmsghdr)) + (n))
+#endif
+#ifndef CMSG_FIRSTHDR
+#define CMSG_FIRSTHDR(mhdr) \
+ ((size_t)(mhdr)->msg_controllen >= sizeof (struct cmsghdr) \
+ ? (struct cmsghdr*) (mhdr)->msg_control : (struct cmsghdr*)NULL)
+#endif
+#ifndef CMSG_DATA
+#define CMSG_DATA(cmsg) ((unsigned char*)((struct cmsghdr*)(cmsg)+1))
+#endif
+#endif /*USE_DESCRIPTOR_PASSING*/
+
+
+/* Read from a unix domain socket using sendmsg.
+
+ FIXME: We don't need the buffering. It is a leftover from the time
+ when we used datagrams. */
+static ssize_t
+uds_reader (assuan_context_t ctx, void *buf, size_t buflen)
+{
+ int len = ctx->uds.buffersize;
+
+#ifndef HAVE_W32_SYSTEM
+ if (!ctx->uds.bufferallocated)
+ {
+ ctx->uds.buffer = xtrymalloc (2048);
+ if (!ctx->uds.buffer)
+ return _assuan_error (ASSUAN_Out_Of_Core);
+ ctx->uds.bufferallocated = 2048;
+ }
+
+ while (!len) /* No data is buffered. */
+ {
+ struct msghdr msg;
+ struct iovec iovec;
+#ifdef USE_DESCRIPTOR_PASSING
+ union {
+ struct cmsghdr cm;
+ char control[CMSG_SPACE(sizeof (int))];
+ } control_u;
+ struct cmsghdr *cmptr;
+#endif /*USE_DESCRIPTOR_PASSING*/
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iovec;
+ msg.msg_iovlen = 1;
+ iovec.iov_base = ctx->uds.buffer;
+ iovec.iov_len = ctx->uds.bufferallocated;
+#ifdef USE_DESCRIPTOR_PASSING
+ msg.msg_control = control_u.control;
+ msg.msg_controllen = sizeof (control_u.control);
+#endif
+
+ len = _assuan_simple_recvmsg (ctx, &msg);
+ if (len < 0)
+ return -1;
+
+ ctx->uds.buffersize = len;
+ ctx->uds.bufferoffset = 0;
+
+#ifdef USE_DESCRIPTOR_PASSING
+ cmptr = CMSG_FIRSTHDR (&msg);
+ if (cmptr && cmptr->cmsg_len == CMSG_LEN (sizeof(int)))
+ {
+ if (cmptr->cmsg_level != SOL_SOCKET
+ || cmptr->cmsg_type != SCM_RIGHTS)
+ _assuan_log_printf ("unexpected ancillary data received\n");
+ else
+ {
+ int fd = *((int*)CMSG_DATA (cmptr));
+
+ if (ctx->uds.pendingfdscount >= DIM (ctx->uds.pendingfds))
+ {
+ _assuan_log_printf ("too many descriptors pending - "
+ "closing received descriptor %d\n", fd);
+ _assuan_close (fd);
+ }
+ else
+ ctx->uds.pendingfds[ctx->uds.pendingfdscount++] = fd;
+ }
+ }
+#endif /*USE_DESCRIPTOR_PASSING*/
+ }
+
+#else /*HAVE_W32_SYSTEM*/
+
+ len = recvfrom (ctx->inbound.fd, buf, buflen, 0, NULL, NULL);
+
+#endif /*HAVE_W32_SYSTEM*/
+
+ /* Return some data to the user. */
+
+ if (len > buflen) /* We have more than the user requested. */
+ len = buflen;
+
+ memcpy (buf, ctx->uds.buffer + ctx->uds.bufferoffset, len);
+ ctx->uds.buffersize -= len;
+ assert (ctx->uds.buffersize >= 0);
+ ctx->uds.bufferoffset += len;
+ assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated);
+
+ return len;
+}
+
+
+/* Write to the domain server. */
+static ssize_t
+uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
+{
+#ifndef HAVE_W32_SYSTEM
+ struct msghdr msg;
+ struct iovec iovec;
+ ssize_t len;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iovlen = 1;
+ msg.msg_iov = &iovec;
+ iovec.iov_base = (void*)buf;
+ iovec.iov_len = buflen;
+
+ len = _assuan_simple_sendmsg (ctx, &msg);
+#else /*HAVE_W32_SYSTEM*/
+ int len;
+
+ len = sendto (ctx->outbound.fd, buf, buflen, 0,
+ (struct sockaddr *)&ctx->serveraddr,
+ sizeof (struct sockaddr_in));
+#endif /*HAVE_W32_SYSTEM*/
+ return len;
+}
+
+
+static assuan_error_t
+uds_sendfd (assuan_context_t ctx, int fd)
+{
+#ifdef USE_DESCRIPTOR_PASSING
+ struct msghdr msg;
+ struct iovec iovec;
+ union {
+ struct cmsghdr cm;
+ char control[CMSG_SPACE(sizeof (int))];
+ } control_u;
+ struct cmsghdr *cmptr;
+ int len;
+ char buffer[80];
+
+ /* We need to send some real data so that a read won't return 0
+ which will be taken as an EOF. It also helps with debugging. */
+ snprintf (buffer, sizeof(buffer)-1, "# descriptor %d is in flight\n", fd);
+ buffer[sizeof(buffer)-1] = 0;
+
+ memset (&msg, 0, sizeof (msg));
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iovlen = 1;
+ msg.msg_iov = &iovec;
+ iovec.iov_base = buffer;
+ iovec.iov_len = strlen (buffer);
+
+ msg.msg_control = control_u.control;
+ msg.msg_controllen = sizeof (control_u.control);
+ cmptr = CMSG_FIRSTHDR (&msg);
+ cmptr->cmsg_len = CMSG_LEN(sizeof(int));
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ *((int*)CMSG_DATA (cmptr)) = fd;
+
+ len = _assuan_simple_sendmsg (ctx, &msg);
+ if (len < 0)
+ {
+ _assuan_log_printf ("uds_sendfd: %s\n", strerror (errno));
+ return _assuan_error (ASSUAN_Write_Error);
+ }
+ else
+ return 0;
+#else
+ return _assuan_error (ASSUAN_Not_Implemented);
+#endif
+}
+
+
+static assuan_error_t
+uds_receivefd (assuan_context_t ctx, int *fd)
+{
+#ifdef USE_DESCRIPTOR_PASSING
+ int i;
+
+ if (!ctx->uds.pendingfdscount)
+ {
+ _assuan_log_printf ("no pending file descriptors!\n");
+ return _assuan_error (ASSUAN_General_Error);
+ }
+ assert (ctx->uds.pendingfdscount <= DIM(ctx->uds.pendingfds));
+
+ *fd = ctx->uds.pendingfds[0];
+ for (i=1; i < ctx->uds.pendingfdscount; i++)
+ ctx->uds.pendingfds[i-1] = ctx->uds.pendingfds[i];
+ ctx->uds.pendingfdscount--;
+
+ return 0;
+#else
+ return _assuan_error (ASSUAN_Not_Implemented);
+#endif
+}
+
+
+/* Close all pending fds. */
+void
+_assuan_uds_close_fds (assuan_context_t ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->uds.pendingfdscount; i++)
+ _assuan_close (ctx->uds.pendingfds[i]);
+ ctx->uds.pendingfdscount = 0;
+}
+
+/* Deinitialize the unix domain socket I/O functions. */
+void
+_assuan_uds_deinit (assuan_context_t ctx)
+{
+ /* First call the finish_handler which should close descriptors etc. */
+ ctx->finish_handler (ctx);
+
+ if (ctx->uds.buffer)
+ {
+ assert (ctx->uds.bufferallocated);
+ ctx->uds.bufferallocated = 0;
+ xfree (ctx->uds.buffer);
+ }
+
+ _assuan_uds_close_fds (ctx);
+}
+
+
+/* Helper function to initialize a context for domain I/O. */
+void
+_assuan_init_uds_io (assuan_context_t ctx)
+{
+ static struct assuan_io io = { uds_reader, uds_writer,
+ uds_sendfd, uds_receivefd };
+
+ ctx->io = &io;
+ ctx->uds.buffer = 0;
+ ctx->uds.bufferoffset = 0;
+ ctx->uds.buffersize = 0;
+ ctx->uds.bufferallocated = 0;
+ ctx->uds.pendingfdscount = 0;
+}
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan-util.c b/libtdenetwork/libgpgme-copy/assuan/assuan-util.c
new file mode 100644
index 000000000..d12277fcc
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan-util.c
@@ -0,0 +1,171 @@
+/* assuan-util.c - Utility functions for Assuan
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "assuan-defs.h"
+
+static void *(*alloc_func)(size_t n) = malloc;
+static void *(*realloc_func)(void *p, size_t n) = realloc;
+static void (*free_func)(void*) = free;
+
+void
+assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
+ void *(*new_realloc_func)(void *p, size_t n),
+ void (*new_free_func)(void*) )
+{
+ alloc_func = new_alloc_func;
+ realloc_func = new_realloc_func;
+ free_func = new_free_func;
+}
+
+void *
+_assuan_malloc (size_t n)
+{
+ return alloc_func (n);
+}
+
+void *
+_assuan_realloc (void *a, size_t n)
+{
+ return realloc_func (a, n);
+}
+
+void *
+_assuan_calloc (size_t n, size_t m)
+{
+ void *p;
+ size_t nbytes;
+
+ nbytes = n * m;
+ if (m && nbytes / m != n)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ p = _assuan_malloc (nbytes);
+ if (p)
+ memset (p, 0, nbytes);
+ return p;
+}
+
+void
+_assuan_free (void *p)
+{
+ if (p)
+ free_func (p);
+}
+
+
+/* Store the error in the context so that the error sending function
+ can take out a descriptive text. Inside the assuan code, use the
+ macro set_error instead of this function. */
+int
+assuan_set_error (assuan_context_t ctx, int err, const char *text)
+{
+ ctx->err_no = err;
+ ctx->err_str = text;
+ return err;
+}
+
+void
+assuan_set_pointer (assuan_context_t ctx, void *pointer)
+{
+ if (ctx)
+ ctx->user_pointer = pointer;
+}
+
+void *
+assuan_get_pointer (assuan_context_t ctx)
+{
+ return ctx? ctx->user_pointer : NULL;
+}
+
+
+void
+assuan_begin_confidential (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ ctx->confidential = 1;
+ }
+}
+
+void
+assuan_end_confidential (assuan_context_t ctx)
+{
+ if (ctx)
+ {
+ ctx->confidential = 0;
+ }
+}
+
+
+void
+assuan_set_io_monitor (assuan_context_t ctx,
+ unsigned int (*monitor)(assuan_context_t ctx,
+ int direction,
+ const char *line,
+ size_t linelen))
+{
+ if (ctx)
+ {
+ ctx->io_monitor = monitor;
+ }
+}
+
+
+
+
+/* For context CTX, set the flag FLAG to VALUE. Values for flags
+ are usually 1 or 0 but certain flags might allow for other values;
+ see the description of the type assuan_flag_t for details. */
+void
+assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value)
+{
+ if (!ctx)
+ return;
+ switch (flag)
+ {
+ case ASSUAN_NO_WAITPID: ctx->flags.no_waitpid = value; break;
+ }
+}
+
+/* Return the VALUE of FLAG in context CTX. */
+int
+assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag)
+{
+ if (!ctx)
+ return 0;
+ switch (flag)
+ {
+ case ASSUAN_NO_WAITPID: return ctx->flags.no_waitpid;
+ }
+ return 0;
+}
+
+
diff --git a/libtdenetwork/libgpgme-copy/assuan/assuan.h b/libtdenetwork/libgpgme-copy/assuan/assuan.h
new file mode 100644
index 000000000..8d0a3960d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/assuan.h
@@ -0,0 +1,565 @@
+/* assuan.c - Definitions for the Assuan IPC library
+ * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef ASSUAN_H
+#define ASSUAN_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+/* To use this file with libraries the following macros are useful:
+
+ #define _ASSUAN_EXT_SYM_PREFIX _foo_
+
+ This prefixes all external symbols with "_foo_".
+
+ #define _ASSUAN_ONLY_GPG_ERRORS
+
+ If this is defined all old-style Assuan error codes are made
+ inactive as well as other dereacted stuff.
+
+ The follwing macros are used internally in the implementation of
+ libassuan:
+
+ #define _ASSUAN_NO_PTH
+
+ This avoids inclusion of special GNU Pth hacks.
+
+ #define _ASSUAN_NO_FIXED_SIGNALS
+
+ This disables changing of certain signal handler; i.e. SIGPIPE.
+
+ #define _ASSUAN_USE_DOUBLE_FORK
+
+ Use a double fork approach when connecting to a server through
+ a pipe.
+ */
+/**** Begin GPGME specific modifications. ******/
+#define _ASSUAN_EXT_SYM_PREFIX _gpgme_
+#define _ASSUAN_NO_PTH
+#define _ASSUAN_NO_FIXED_SIGNALS
+#define _ASSUAN_USE_DOUBLE_FORK
+
+#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN
+int _gpgme_io_read (int fd, void *buffer, size_t count);
+int _gpgme_io_write (int fd, const void *buffer, size_t count);
+ssize_t _gpgme_ath_waitpid (pid_t pid, int *status, int options);
+#ifdef HAVE_W32_SYSTEM
+int _gpgme_ath_accept (int s, void *addr, int *length_ptr);
+#else /*!HAVE_W32_SYSTEM*/
+struct sockaddr;
+struct msghdr;
+ssize_t _gpgme_ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout);
+int _gpgme_ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
+int _gpgme_ath_connect (int s, struct sockaddr *addr, socklen_t length);
+int _gpgme_ath_sendmsg (int s, const struct msghdr *msg, int flags);
+int _gpgme_ath_recvmsg (int s, struct msghdr *msg, int flags);
+int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
+int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
+#endif /*!HAVE_W32_SYSTEM*/
+
+#define read _gpgme_io_read
+#define write _gpgme_io_write
+#define waitpid _gpgme_ath_waitpid
+#define select _gpgme_ath_select
+#define accept _gpgme_ath_accept
+#define connect _gpgme_ath_connect
+#define sendmsg _gpgme_io_sendmsg
+#define recvmsg _gpgme_io_recvmsg
+#endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
+/**** End GPGME specific modifications. ******/
+
+
+#ifdef _ASSUAN_EXT_SYM_PREFIX
+#define _ASSUAN_PREFIX1(x,y) x ## y
+#define _ASSUAN_PREFIX2(x,y) _ASSUAN_PREFIX1(x,y)
+#define _ASSUAN_PREFIX(x) _ASSUAN_PREFIX2(_ASSUAN_EXT_SYM_PREFIX,x)
+#define assuan_ _ASSUAN_PREFIX(assuan_)
+#define assuan_register_command _ASSUAN_PREFIX(assuan_register_command)
+#define assuan_register_post_cmd_notify \
+ _ASSUAN_PREFIX(assuan_register_post_cmd_notify)
+#define assuan_register_bye_notify _ASSUAN_PREFIX(assuan_register_bye_notify)
+#define assuan_register_reset_notify \
+ _ASSUAN_PREFIX(assuan_register_reset_notify)
+#define assuan_register_cancel_notify \
+ _ASSUAN_PREFIX(assuan_register_cancel_notify)
+#define assuan_register_input_notify \
+ _ASSUAN_PREFIX(assuan_register_input_notify)
+#define assuan_register_output_notify \
+ _ASSUAN_PREFIX(assuan_register_output_notify)
+#define assuan_register_option_handler \
+ _ASSUAN_PREFIX(assuan_register_option_handler)
+#define assuan_process _ASSUAN_PREFIX(assuan_process)
+#define assuan_process_next _ASSUAN_PREFIX(assuan_process_next)
+#define assuan_get_active_fds _ASSUAN_PREFIX(assuan_get_active_fds)
+#define assuan_get_data_fp _ASSUAN_PREFIX(assuan_get_data_fp)
+#define assuan_set_okay_line _ASSUAN_PREFIX(assuan_set_okay_line)
+#define assuan_write_status _ASSUAN_PREFIX(assuan_write_status)
+#define assuan_command_parse_fd _ASSUAN_PREFIX(assuan_command_parse_fd)
+#define assuan_set_hello_line _ASSUAN_PREFIX(assuan_set_hello_line)
+#define assuan_accept _ASSUAN_PREFIX(assuan_accept)
+#define assuan_get_input_fd _ASSUAN_PREFIX(assuan_get_input_fd)
+#define assuan_get_output_fd _ASSUAN_PREFIX(assuan_get_output_fd)
+#define assuan_close_input_fd _ASSUAN_PREFIX(assuan_close_input_fd)
+#define assuan_close_output_fd _ASSUAN_PREFIX(assuan_close_output_fd)
+#define assuan_init_pipe_server _ASSUAN_PREFIX(assuan_init_pipe_server)
+#define assuan_deinit_server _ASSUAN_PREFIX(assuan_deinit_server)
+#define assuan_init_socket_server _ASSUAN_PREFIX(assuan_init_socket_server)
+#define assuan_init_connected_socket_server \
+ _ASSUAN_PREFIX(assuan_init_connected_socket_server)
+#define assuan_init_socket_server_ext \
+ _ASSUAN_PREFIX(assuan_init_socket_server_ext)
+#define assuan_pipe_connect _ASSUAN_PREFIX(assuan_pipe_connect)
+#define assuan_pipe_connect_ext _ASSUAN_PREFIX(assuan_pipe_connect_ext)
+#define assuan_socket_connect _ASSUAN_PREFIX(assuan_socket_connect)
+#define assuan_socket_connect_ext _ASSUAN_PREFIX(assuan_socket_connect_ext)
+#define assuan_disconnect _ASSUAN_PREFIX(assuan_disconnect)
+#define assuan_get_pid _ASSUAN_PREFIX(assuan_get_pid)
+#define assuan_get_peercred _ASSUAN_PREFIX(assuan_get_peercred)
+#define assuan_transact _ASSUAN_PREFIX(assuan_transact)
+#define assuan_inquire _ASSUAN_PREFIX(assuan_inquire)
+#define assuan_read_line _ASSUAN_PREFIX(assuan_read_line)
+#define assuan_pending_line _ASSUAN_PREFIX(assuan_pending_line)
+#define assuan_write_line _ASSUAN_PREFIX(assuan_write_line)
+#define assuan_send_data _ASSUAN_PREFIX(assuan_send_data)
+#define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd)
+#define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd)
+#define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks)
+#define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream)
+#define assuan_set_error _ASSUAN_PREFIX(assuan_set_error)
+#define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer)
+#define assuan_get_pointer _ASSUAN_PREFIX(assuan_get_pointer)
+#define assuan_set_io_monitor _ASSUAN_PREFIX(assuan_set_io_monitor)
+#define assuan_begin_confidential _ASSUAN_PREFIX(assuan_begin_confidential)
+#define assuan_end_confidential _ASSUAN_PREFIX(assuan_end_confidential)
+#define assuan_strerror _ASSUAN_PREFIX(assuan_strerror)
+#define assuan_set_assuan_err_source \
+ _ASSUAN_PREFIX(assuan_set_assuan_err_source)
+#define assuan_set_assuan_log_stream \
+ _ASSUAN_PREFIX(assuan_set_assuan_log_stream)
+#define assuan_get_assuan_log_stream \
+ _ASSUAN_PREFIX(assuan_get_assuan_log_stream)
+#define assuan_get_assuan_log_prefix \
+ _ASSUAN_PREFIX(assuan_get_assuan_log_prefix)
+#define assuan_set_flag _ASSUAN_PREFIX(assuan_set_flag)
+#define assuan_get_flag _ASSUAN_PREFIX(assuan_get_flag)
+
+/* And now the internal functions, argh... */
+#define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line)
+#define _assuan_cookie_write_data _ASSUAN_PREFIX(_assuan_cookie_write_data)
+#define _assuan_cookie_write_flush _ASSUAN_PREFIX(_assuan_cookie_write_flush)
+#define _assuan_read_from_server _ASSUAN_PREFIX(_assuan_read_from_server)
+#define _assuan_domain_init _ASSUAN_PREFIX(_assuan_domain_init)
+#define _assuan_register_std_commands \
+ _ASSUAN_PREFIX(_assuan_register_std_commands)
+#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
+#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
+#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read)
+#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write)
+#define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context)
+#define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context)
+#define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc)
+#define _assuan_realloc _ASSUAN_PREFIX(_assuan_realloc)
+#define _assuan_calloc _ASSUAN_PREFIX(_assuan_calloc)
+#define _assuan_free _ASSUAN_PREFIX(_assuan_free)
+#define _assuan_log_print_buffer _ASSUAN_PREFIX(_assuan_log_print_buffer)
+#define _assuan_log_sanitized_string \
+ _ASSUAN_PREFIX(_assuan_log_sanitized_string)
+#define _assuan_log_printf _ASSUAN_PREFIX(_assuan_log_printf)
+#define _assuan_set_default_log_stream \
+ _ASSUAN_PREFIX(_assuan_set_default_log_stream)
+#define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror)
+#define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line)
+#define _assuan_close _ASSUAN_PREFIX(_assuan_close)
+#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new)
+#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind)
+#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect)
+
+#endif /*_ASSUAN_EXT_SYM_PREFIX*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0
+}
+#endif
+#endif
+
+
+/* Check for compiler features. */
+#if __GNUC__
+#define _ASSUAN_GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+#if _ASSUAN_GCC_VERSION > 30100
+#define _ASSUAN_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+#endif
+#ifndef _ASSUAN_DEPRECATED
+#define _ASSUAN_DEPRECATED
+#endif
+
+
+/* Assuan error codes. These are only used by old applications or
+ those applications which won't make use of libgpg-error. */
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_No_Error 0
+#endif
+#define ASSUAN_General_Error 1
+#define ASSUAN_Out_Of_Core 2
+#define ASSUAN_Invalid_Value 3
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Timeout 4
+#endif
+#define ASSUAN_Read_Error 5
+#define ASSUAN_Write_Error 6
+#define ASSUAN_Problem_Starting_Server 7
+#define ASSUAN_Not_A_Server 8
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Not_A_Client 9
+#endif
+#define ASSUAN_Nested_Commands 10
+#define ASSUAN_Invalid_Response 11
+#define ASSUAN_No_Data_Callback 12
+#define ASSUAN_No_Inquire_Callback 13
+#define ASSUAN_Connect_Failed 14
+#define ASSUAN_Accept_Failed 15
+
+ /* Error codes above 99 are meant as status codes */
+#define ASSUAN_Not_Implemented 100
+#define ASSUAN_Server_Fault 101
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Invalid_Command 102
+#endif
+#define ASSUAN_Unknown_Command 103
+#define ASSUAN_Syntax_Error 104
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Parameter_Error 105
+#endif
+#define ASSUAN_Parameter_Conflict 106
+#define ASSUAN_Line_Too_Long 107
+#define ASSUAN_Line_Not_Terminated 108
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_No_Input 109
+#define ASSUAN_No_Output 110
+#endif
+#define ASSUAN_Canceled 111
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Unsupported_Algorithm 112
+#define ASSUAN_Server_Resource_Problem 113
+#define ASSUAN_Server_IO_Error 114
+#define ASSUAN_Server_Bug 115
+#define ASSUAN_No_Data_Available 116
+#define ASSUAN_Invalid_Data 117
+#endif
+#define ASSUAN_Unexpected_Command 118
+#define ASSUAN_Too_Much_Data 119
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Inquire_Unknown 120
+#define ASSUAN_Inquire_Error 121
+#define ASSUAN_Invalid_Option 122
+#define ASSUAN_Invalid_Index 123
+#define ASSUAN_Unexpected_tqStatus 124
+#define ASSUAN_Unexpected_Data 125
+#define ASSUAN_Invalid_tqStatus 126
+#define ASSUAN_Locale_Problem 127
+#endif
+#define ASSUAN_Not_Confirmed 128
+
+ /* Warning: Don't use the Error codes, below they are deprecated. */
+#ifndef _ASSUAN_IN_LIBASSUAN
+#define ASSUAN_Bad_Certificate 201
+#define ASSUAN_Bad_Certificate_Chain 202
+#define ASSUAN_Missing_Certificate 203
+#define ASSUAN_Bad_Signature 204
+#define ASSUAN_No_Agent 205
+#define ASSUAN_Agent_Error 206
+#define ASSUAN_No_Public_Key 207
+#define ASSUAN_No_Secret_Key 208
+#define ASSUAN_Invalid_Name 209
+
+#define ASSUAN_Cert_Revoked 301
+#define ASSUAN_No_CRL_For_Cert 302
+#define ASSUAN_CRL_Too_Old 303
+#define ASSUAN_Not_Trusted 304
+
+#define ASSUAN_Card_Error 401
+#define ASSUAN_Invalid_Card 402
+#define ASSUAN_No_PKCS15_App 403
+#define ASSUAN_Card_Not_Present 404
+#define ASSUAN_Invalid_Id 405
+
+ /* Error codes in the range 1000 to 9999 may be used by applications
+ at their own discretion. */
+#define ASSUAN_USER_ERROR_FIRST 1000
+#define ASSUAN_USER_ERROR_LAST 9999
+#endif
+
+typedef int assuan_error_t;
+
+typedef assuan_error_t AssuanError _ASSUAN_DEPRECATED;
+
+/* This is a list of pre-registered ASSUAN commands */
+/* Note, these command IDs are now deprectated and solely exists for
+ compatibility reasons. */
+typedef enum
+{
+ ASSUAN_CMD_NOP = 0,
+ ASSUAN_CMD_CANCEL, /* cancel the current request */
+ ASSUAN_CMD_BYE,
+ ASSUAN_CMD_AUTH,
+ ASSUAN_CMD_RESET,
+ ASSUAN_CMD_OPTION,
+ ASSUAN_CMD_DATA,
+ ASSUAN_CMD_END,
+ ASSUAN_CMD_INPUT,
+ ASSUAN_CMD_OUTPUT,
+
+ ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/
+} AssuanCommand;
+
+
+#else /*!_ASSUAN_ONLY_GPG_ERRORS*/
+
+typedef int assuan_error_t;
+
+#endif /*!_ASSUAN_ONLY_GPG_ERRORS*/
+
+
+/* Definitions of flags for assuan_set_flag(). */
+typedef enum
+ {
+ /* When using a pipe server, by default Assuan will wait for the
+ forked process to die in assuan_disconnect. In certain cases
+ this is not desirable. By setting this flag, the waitpid will
+ be skipped and the caller is responsible to cleanup a forked
+ process. */
+ ASSUAN_NO_WAITPID = 1
+ }
+assuan_flag_t;
+
+#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
+
+struct assuan_context_s;
+typedef struct assuan_context_s *assuan_context_t;
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+typedef struct assuan_context_s *ASSUAN_CONTEXT _ASSUAN_DEPRECATED;
+#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
+
+/*-- assuan-handler.c --*/
+int assuan_register_command (assuan_context_t ctx,
+ const char *cmd_string,
+ int (*handler)(assuan_context_t, char *));
+int assuan_register_post_cmd_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, int));
+int assuan_register_bye_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t));
+int assuan_register_reset_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t));
+int assuan_register_cancel_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t));
+int assuan_register_input_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *));
+int assuan_register_output_notify (assuan_context_t ctx,
+ void (*fnc)(assuan_context_t, const char *));
+
+int assuan_register_option_handler (assuan_context_t ctx,
+ int (*fnc)(assuan_context_t,
+ const char*, const char*));
+
+int assuan_process (assuan_context_t ctx);
+int assuan_process_next (assuan_context_t ctx);
+int assuan_get_active_fds (assuan_context_t ctx, int what,
+ int *fdarray, int fdarraysize);
+
+
+FILE *assuan_get_data_fp (assuan_context_t ctx);
+assuan_error_t assuan_set_okay_line (assuan_context_t ctx, const char *line);
+assuan_error_t assuan_write_status (assuan_context_t ctx,
+ const char *keyword, const char *text);
+
+/* Negotiate a file descriptor. If LINE contains "FD=N", returns N
+ assuming a local file descriptor. If LINE contains "FD" reads a
+ file descriptor via CTX and stores it in *RDF (the CTX must be
+ capable of passing file descriptors). */
+assuan_error_t assuan_command_parse_fd (assuan_context_t ctx, char *line,
+ int *rfd);
+
+/*-- assuan-listen.c --*/
+assuan_error_t assuan_set_hello_line (assuan_context_t ctx, const char *line);
+assuan_error_t assuan_accept (assuan_context_t ctx);
+int assuan_get_input_fd (assuan_context_t ctx);
+int assuan_get_output_fd (assuan_context_t ctx);
+assuan_error_t assuan_close_input_fd (assuan_context_t ctx);
+assuan_error_t assuan_close_output_fd (assuan_context_t ctx);
+
+
+/*-- assuan-pipe-server.c --*/
+int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]);
+void assuan_deinit_server (assuan_context_t ctx);
+
+/*-- assuan-socket-server.c --*/
+int assuan_init_socket_server (assuan_context_t *r_ctx, int listen_fd);
+int assuan_init_connected_socket_server (assuan_context_t *r_ctx,
+ int fd) _ASSUAN_DEPRECATED;
+int assuan_init_socket_server_ext (assuan_context_t *r_ctx, int fd,
+ unsigned int flags);
+
+/*-- assuan-pipe-connect.c --*/
+assuan_error_t assuan_pipe_connect (assuan_context_t *ctx,
+ const char *name,
+ const char *const argv[],
+ int *fd_child_list);
+assuan_error_t assuan_pipe_connect2 (assuan_context_t *ctx,
+ const char *name,
+ const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void*, int),
+ void *atforkvalue) _ASSUAN_DEPRECATED;
+assuan_error_t assuan_pipe_connect_ext (assuan_context_t *ctx,
+ const char *name,
+ const char *const argv[],
+ int *fd_child_list,
+ void (*atfork) (void *, int),
+ void *atforkvalue,
+ unsigned int flags);
+
+/*-- assuan-socket-connect.c --*/
+assuan_error_t assuan_socket_connect (assuan_context_t *ctx,
+ const char *name,
+ pid_t server_pid);
+assuan_error_t assuan_socket_connect_ext (assuan_context_t *ctx,
+ const char *name,
+ pid_t server_pid,
+ unsigned int flags);
+
+/*-- assuan-connect.c --*/
+void assuan_disconnect (assuan_context_t ctx);
+pid_t assuan_get_pid (assuan_context_t ctx);
+assuan_error_t assuan_get_peercred (assuan_context_t ctx,
+ pid_t *pid, uid_t *uid, gid_t *gid);
+
+/*-- assuan-client.c --*/
+assuan_error_t
+assuan_transact (assuan_context_t ctx,
+ const char *command,
+ int (*data_cb)(void *, const void *, size_t),
+ void *data_cb_arg,
+ int (*inquire_cb)(void*, const char *),
+ void *inquire_cb_arg,
+ int (*status_cb)(void*, const char *),
+ void *status_cb_arg);
+
+
+/*-- assuan-inquire.c --*/
+assuan_error_t assuan_inquire (assuan_context_t ctx, const char *keyword,
+ unsigned char **r_buffer, size_t *r_length,
+ size_t maxlen);
+
+/*-- assuan-buffer.c --*/
+assuan_error_t assuan_read_line (assuan_context_t ctx,
+ char **line, size_t *linelen);
+int assuan_pending_line (assuan_context_t ctx);
+assuan_error_t assuan_write_line (assuan_context_t ctx, const char *line );
+assuan_error_t assuan_send_data (assuan_context_t ctx,
+ const void *buffer, size_t length);
+
+/* The file descriptor must be pending before assuan_receivefd is
+ called. This means that assuan_sendfd should be called *before* the
+ trigger is sent (normally via assuan_write_line ("INPUT FD")). */
+assuan_error_t assuan_sendfd (assuan_context_t ctx, int fd);
+assuan_error_t assuan_receivefd (assuan_context_t ctx, int *fd);
+
+/*-- assuan-util.c --*/
+void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
+ void *(*new_realloc_func)(void *p, size_t n),
+ void (*new_free_func)(void*) );
+void assuan_set_log_stream (assuan_context_t ctx, FILE *fp);
+int assuan_set_error (assuan_context_t ctx, int err, const char *text);
+void assuan_set_pointer (assuan_context_t ctx, void *pointer);
+void *assuan_get_pointer (assuan_context_t ctx);
+
+void assuan_begin_confidential (assuan_context_t ctx);
+void assuan_end_confidential (assuan_context_t ctx);
+
+void assuan_set_io_monitor (assuan_context_t ctx,
+ unsigned int (*monitor)(assuan_context_t ctx,
+ int direction,
+ const char *line,
+ size_t linelen));
+
+/* For context CTX, set the flag FLAG to VALUE. Values for flags
+ are usually 1 or 0 but certain flags might allow for other values;
+ see the description of the type assuan_flag_t for details. */
+void assuan_set_flag (assuan_context_t ctx, assuan_flag_t flag, int value);
+
+/* Return the VALUE of FLAG in context CTX. */
+int assuan_get_flag (assuan_context_t ctx, assuan_flag_t flag);
+
+
+/*-- assuan-errors.c --*/
+
+#ifndef _ASSUAN_ONLY_GPG_ERRORS
+/* Return a string describing the assuan error. The use of this
+ function is deprecated; it is better to call
+ assuan_set_assuan_err_source once and then make use libgpg-error. */
+const char *assuan_strerror (assuan_error_t err);
+#endif /*_ASSUAN_ONLY_GPG_ERRORS*/
+
+/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
+ sources. Note, that this function is not thread-safe and should be
+ used right at startup. Switching back to the old style mode is not
+ supported. */
+void assuan_set_assuan_err_source (int errsource);
+
+/*-- assuan-logging.c --*/
+
+/* Set the stream to which assuan should log message not associated
+ with a context. By default, this is stderr. The default value
+ will be changed when the first log stream is associated with a
+ context. Note, that this function is not thread-safe and should
+ in general be used right at startup. */
+extern void assuan_set_assuan_log_stream (FILE *fp);
+
+/* Return the stream which is currently being using for global logging. */
+extern FILE *assuan_get_assuan_log_stream (void);
+
+/* Set the prefix to be used at the start of a line emitted by assuan
+ on the log stream. The default is the empty string. Note, that
+ this function is not thread-safe and should in general be used
+ right at startup. */
+void assuan_set_assuan_log_prefix (const char *text);
+
+/* Return a prefix to be used at the start of a line emitted by assuan
+ on the log stream. The default implementation returns the empty
+ string, i.e. "" */
+const char *assuan_get_assuan_log_prefix (void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ASSUAN_H */
diff --git a/libtdenetwork/libgpgme-copy/assuan/funopen.c b/libtdenetwork/libgpgme-copy/assuan/funopen.c
new file mode 100644
index 000000000..ac31007a6
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/funopen.c
@@ -0,0 +1,64 @@
+/* funopen.c - Replacement for funopen.
+ * Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of Assuan.
+ *
+ * Assuan 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.
+ *
+ * Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+
+/* Replacement for the *BSD function:
+
+ FILE *funopen (void *cookie,
+ int (*readfn)(void *, char *, int),
+ int (*writefn)(void *, const char *, int),
+ fpos_t (*seekfn)(void *, fpos_t, int),
+ int (*closefn)(void *));
+
+ The functions to provide my either be NULL if not required or
+ similar to the unistd function with the exception of using the
+ cookie instead of the fiel descripor.
+*/
+
+
+#ifdef HAVE_FOPENCOOKIE
+FILE *
+_assuan_funopen(void *cookie,
+ cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn)
+{
+ cookie_io_functions_t io = { NULL };
+
+ io.read = readfn;
+ io.write = writefn;
+ io.seek = seekfn;
+ io.close = closefn;
+
+ return fopencookie (cookie,
+ readfn ? ( writefn ? "rw" : "r" )
+ : ( writefn ? "w" : ""), io);
+}
+#else
+#error No known way to implement funopen.
+#endif
diff --git a/libtdenetwork/libgpgme-copy/assuan/mkerrors b/libtdenetwork/libgpgme-copy/assuan/mkerrors
new file mode 100755
index 000000000..57485411a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/assuan/mkerrors
@@ -0,0 +1,228 @@
+#!/bin/sh
+# mkerrors - Extract error strings from assuan.h
+# and create C source for assuan_strerror
+# Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
+#
+# This file is part of Assuan.
+#
+# Assuan 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.
+#
+# Assuan 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+cat <<EOF
+/* Generated automatically by mkerrors */
+/* Do not edit! See mkerrors for copyright notice. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#undef _ASSUAN_IN_LIBASSUAN /* undef to get all error codes. */
+#include "assuan.h"
+
+/* If true the modern gpg-error style error codes are used in the
+ API. */
+static unsigned int err_source;
+
+/* Enable gpg-error style error codes. ERRSOURCE is one of gpg-error
+ sources. Note, that this function is not thread-safe and should be
+ used right at startup. Switching back to the old style mode is not
+ supported. */
+void
+assuan_set_assuan_err_source (int errsource)
+{
+ errsource &= 0xff;
+ err_source = errsource? errsource : 31 /*GPG_ERR_SOURCE_ANY*/;
+}
+
+
+/* Helper to map old style Assuan error codes to gpg-error codes.
+ This is used internally to keep an compatible ABI. */
+assuan_error_t
+_assuan_error (int oldcode)
+{
+ unsigned int n;
+
+ if (!err_source)
+ return (oldcode & 0x00ffffff); /* Make sure that the gpg-error
+ source part is cleared. */
+
+ switch (oldcode)
+ {
+ case ASSUAN_General_Error: n = 257; break;
+ case ASSUAN_Accept_Failed: n = 258; break;
+ case ASSUAN_Connect_Failed: n = 259; break;
+ case ASSUAN_Invalid_Response: n = 260; break;
+ case ASSUAN_Invalid_Value: n = 261; break;
+ case ASSUAN_Line_Not_Terminated: n = 262; break;
+ case ASSUAN_Line_Too_Long: n = 263; break;
+ case ASSUAN_Nested_Commands: n = 264; break;
+ case ASSUAN_No_Data_Callback: n = 265; break;
+ case ASSUAN_No_Inquire_Callback: n = 266; break;
+ case ASSUAN_Not_A_Server: n = 267; break;
+ case ASSUAN_Not_Implemented: n = 69; break;
+ case ASSUAN_Parameter_Conflict: n = 280; break;
+ case ASSUAN_Problem_Starting_Server: n = 269; break;
+ case ASSUAN_Server_Fault: n = 80; break;
+ case ASSUAN_Syntax_Error: n = 276; break;
+ case ASSUAN_Too_Much_Data: n = 273; break;
+ case ASSUAN_Unexpected_Command: n = 274; break;
+ case ASSUAN_Unknown_Command: n = 275; break;
+ case ASSUAN_Canceled: n = 277; break;
+ case ASSUAN_No_Secret_Key: n = 17; break;
+ case ASSUAN_Not_Confirmed: n = 114; break;
+
+ case ASSUAN_Read_Error:
+ switch (errno)
+ {
+ case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
+ default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break;
+ }
+ break;
+
+ case ASSUAN_Write_Error:
+ switch (errno)
+ {
+ case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break;
+ default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break;
+ }
+ break;
+
+ case ASSUAN_Out_Of_Core:
+ switch (errno)
+ {
+ case 0: /* Should not happen but a user might have provided
+ an incomplete implemented malloc function. Give
+ him a chance to correct this fault but make sure
+ an error is indeed returned. */
+ n = 16381; /*GPG_ERR_MISSING_ERRNO*/
+ break;
+ case ENOMEM: n = (1 << 15) | 86; break;
+ default:
+ n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/
+ break;
+ }
+ break;
+
+ case -1: n = 16383 /*GPG_ERR_EOF*/; break;
+
+ default:
+ n = 257;
+ break;
+ }
+
+ return ((err_source << 24) | (n & 0x00ffffff));
+
+}
+
+
+/**
+ * assuan_strerror:
+ * @err: Error code
+ *
+ * This function returns a textual representaion of the given
+ * errorcode. If this is an unknown value, a string with the value
+ * is returned (Beware: it is hold in a static buffer).
+ *
+ * Return value: String with the error description.
+ **/
+const char *
+assuan_strerror (assuan_error_t err)
+{
+ const char *s;
+ static char buf[50];
+
+ switch (err)
+ {
+EOF
+
+awk '
+/ASSUAN_No_Error/ { okay=1 }
+!okay {next}
+/^#define[ ]+ASSUAN_[A-Za-z_]*/ { print_code($2) }
+/ASSUAN_USER_ERROR_LAST/ { exit 0 }
+
+
+function print_code( s )
+{
+printf " case %s: s=\"", s ;
+gsub(/_/, " ", s );
+printf "%s\"; break;\n", tolower(substr(s,8));
+}
+'
+
+cat <<EOF
+ case -1: s = "EOF (-1)"; break;
+ default:
+ {
+ unsigned int source, code, n;
+
+ source = ((err >> 24) & 0xff);
+ code = (err & 0x00ffffff);
+ if (source)
+ {
+ /* Assume this is an libgpg-error and try to map the codes
+ back. */
+ switch (code)
+ {
+ case 257: n = ASSUAN_General_Error ; break;
+ case 258: n = ASSUAN_Accept_Failed ; break;
+ case 259: n = ASSUAN_Connect_Failed ; break;
+ case 260: n = ASSUAN_Invalid_Response ; break;
+ case 261: n = ASSUAN_Invalid_Value ; break;
+ case 262: n = ASSUAN_Line_Not_Terminated ; break;
+ case 263: n = ASSUAN_Line_Too_Long ; break;
+ case 264: n = ASSUAN_Nested_Commands ; break;
+ case 265: n = ASSUAN_No_Data_Callback ; break;
+ case 266: n = ASSUAN_No_Inquire_Callback ; break;
+ case 267: n = ASSUAN_Not_A_Server ; break;
+ case 69: n = ASSUAN_Not_Implemented ; break;
+ case 280: n = ASSUAN_Parameter_Conflict ; break;
+ case 269: n = ASSUAN_Problem_Starting_Server; break;
+ case 270: n = ASSUAN_Read_Error ; break;
+ case 271: n = ASSUAN_Write_Error ; break;
+ case 80: n = ASSUAN_Server_Fault ; break;
+ case 276: n = ASSUAN_Syntax_Error ; break;
+ case 273: n = ASSUAN_Too_Much_Data ; break;
+ case 274: n = ASSUAN_Unexpected_Command ; break;
+ case 275: n = ASSUAN_Unknown_Command ; break;
+ case 277: n = ASSUAN_Canceled ; break;
+ case 114: n = ASSUAN_Not_Confirmed ; break;
+ case ((1<<15)|86): n = ASSUAN_Out_Of_Core ; break;
+ default: n = 0; break;
+ }
+ if (n)
+ s = assuan_strerror (n);
+ else
+ {
+ sprintf (buf, "ec=%u.%u", source, code );
+ s=buf;
+ }
+ }
+ else
+ {
+ sprintf (buf, "ec=%d", err );
+ s=buf;
+ }
+ }
+ break;
+ }
+
+ return s;
+}
+
+EOF
diff --git a/libtdenetwork/libgpgme-copy/configure.in.in b/libtdenetwork/libgpgme-copy/configure.in.in
new file mode 100644
index 000000000..afcc995c2
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/configure.in.in
@@ -0,0 +1,364 @@
+# configure.in for GPGME
+# Copyright (C) 2000 Werner Koch (dd9jn)
+# Copyright (C) 2001, 2002, 2003 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 General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+# (Process this file with autoconf to produce a configure script.)
+
+#AC_PREREQ(2.57)
+#min_automake_version="1.7.6"
+
+# Version number: Remember to change it immediately *after* a release.
+#AC_INIT(gpgme, 0.4.4, [bug-gpgme@gnupg.org])
+# LT Version numbers, remember to change them just *before* a release.
+# (Code changed: REVISION++)
+# (Interfaces added/removed/changed: CURRENT++, REVISION=0)
+# (Interfaces added: AGE++)
+# (Interfaces removed: AGE=0)
+#
+#LIBGPGME_LT_CURRENT=12
+#LIBGPGME_LT_AGE=1
+#LIBGPGME_LT_REVISION=1
+NEED_GPG_VERSION=1.2.2
+NEED_GPGSM_VERSION=1.9.3
+##############################################
+#AC_PREREQ(2.52)
+#AC_REVISION($Revision$)
+
+#PACKAGE=$PACKAGE_NAME
+#VERSION=$PACKAGE_VERSION
+
+#AC_CONFIG_SRCDIR(gpgme/gpgme.h)
+#AM_CONFIG_HEADER(config.h)
+#AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
+#AM_MAINTAINER_MODE
+#AC_CANONICAL_HOST
+
+AH_VERBATIM([_GNU_SOURCE],
+[/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif])
+
+dnl AH_VERBATIM([_REENTRANT],
+dnl [/* To allow the use of GPGME in multithreaded programs we have to use
+dnl special features from the library.
+dnl IMPORTANT: gpgme is not yet fully reentrant and you should use it
+dnl only from one thread. */
+dnl #ifndef _REENTRANT
+dnl # define _REENTRANT 1
+dnl #endif])
+
+
+dnl AC_PROG_CC
+
+
+dnl AC_SUBST(LIBGPGME_LT_CURRENT)
+dnl AC_SUBST(LIBGPGME_LT_AGE)
+dnl AC_SUBST(LIBGPGME_LT_REVISION)
+AC_DEFINE_UNQUOTED(NEED_GPG_VERSION, "$NEED_GPG_VERSION",
+ [Min. needed GnuPG version.])
+AC_DEFINE_UNQUOTED(NEED_GPGSM_VERSION, "$NEED_GPGSM_VERSION",
+ [Min. needed GPGSM version.])
+
+dnl AC_SUBST(PACKAGE)
+dnl AC_SUBST(VERSION)
+dnl AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
+dnl AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
+
+# Don't default to build static libs.
+dnl AC_DISABLE_STATIC
+dnl AC_PROG_LIBTOOL
+
+dnl # For now we hardcode the use of version scripts. It would be better
+dnl # to write a test for this or even implement this within libtool.
+dnl have_ld_version_script=no
+dnl case "${host}" in
+dnl *-*-linux*)
+dnl have_ld_version_script=yes
+dnl ;;
+dnl *-*-gnu*)
+dnl have_ld_version_script=yes
+dnl ;;
+dnl esac
+dnl AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
+
+GPG_DEFAULT=no
+GPGSM_DEFAULT=no
+component_system=None
+case "${host}" in
+ *-*-mingw32* | i?86-emx-os2 | i?86-*-os2*emx | i?86-*-msdosdjgpp* )
+ # special stuff for Windoze NT
+ # OS/2 with the EMX environment
+ # DOS with the DJGPP environment
+ AC_DEFINE(HAVE_DRIVE_LETTERS, ,
+ [Defined if we run on some of the PCDOS like systems (DOS,
+ Windoze, OS/2) with special properties like no file modes.])
+ AC_DEFINE(HAVE_DOSISH_SYSTEM, ,
+ [Defined if the filesystem uses driver letters.])
+ have_dosish_system=yes
+ GPG_DEFAULT='c:\\gnupg\\gpg.exe'
+ # XXX Assuan is not supported in this configuration.
+ #GPGSM_DEFAULT='c:\\gnupg\\gpgsm.exe'
+ #component_system='COM+'
+ ;;
+ *)
+dnl AC_CHECK_PTH(1.2.0,,,no,have_pth=yes)
+dnl if test "$have_pth" = yes; then
+dnl AC_DEFINE(HAVE_PTH, ,[Define if we have Pth.])
+dnl CFLAGS="$CFLAGS $PTH_CFLAGS"
+dnl fi
+dnl AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
+dnl if test "$have_pthread" = yes; then
+dnl AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.])
+dnl fi
+
+ # XXX: Probably use exec-prefix here?
+# GPG_DEFAULT='/usr/bin/gpg'
+# GPGSM_DEFAULT='/usr/bin/gpgsm'
+ ;;
+esac
+
+if test "$have_dosish_system" = yes; then
+ AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
+ [Defined if we run on some of the PCDOS like systems·
+ (DOS, Windoze. OS/2) with special properties like
+ no file modes])
+fi
+AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = "yes")
+dnl AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes")
+dnl AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
+dnl dnl
+
+# Checks for header files.
+AC_CHECK_HEADERS(sys/select.h)
+
+
+# Type checks.
+AC_CHECK_SIZEOF(unsigned int)
+
+
+# Checks for compiler features.
+dnl if test "$GCC" = yes; then
+dnl GPGME_OWN_CFLAGS="-Wall -Wcast-align -Wshadow -Wstrict-prototypes"
+dnl else
+dnl GPGME_OWN_CFLAGS=""
+dnl fi
+dnl AC_SUBST(GPGME_OWN_CFLAGS)
+
+
+# Checks for library functions.
+AC_CHECK_FUNCS(stpcpy)
+
+AC_CHECK_FUNCS(vasprintf)
+if test "$ac_cv_func_vasprintf" != yes; then
+ GNUPG_CHECK_VA_COPY
+fi
+
+# Try to find a thread-safe version of getenv().
+have_thread_safe_getenv=no
+
+dnl Definition of jm_GLIBC21 inlined:
+ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
+ ac_cv_gnu_library_2_1,
+ [AC_EGREP_CPP([Lucky GNU user],
+ [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+ Lucky GNU user
+ #endif
+#endif
+ ],
+ ac_cv_gnu_library_2_1=yes,
+ ac_cv_gnu_library_2_1=no)
+ ]
+ )
+ AC_SUBST(GLIBC21)
+ GLIBC21="$ac_cv_gnu_library_2_1"
+
+dnl
+
+if test $GLIBC21 = yes; then
+ have_thread_safe_getenv=yes
+fi
+if test $have_thread_safe_getenv = yes; then
+ AC_DEFINE(HAVE_THREAD_SAFE_GETENV, [1], [Define if getenv() is thread-safe])
+fi
+have_getenv_r=no
+AC_CHECK_FUNCS(getenv_r, have_getenv_r=yes)
+if test $have_getenv_r = no && test $have_thread_safe_getenv = no; then
+ AC_MSG_WARN([
+***
+*** getenv() is not thread-safe and getenv_r() does not exist
+***])
+fi
+
+# For converting time strings to seconds since Epoch, we need the timegm
+# function.
+AC_CHECK_FUNCS(timegm)
+if test "$ac_cv_func_timegm" != yes; then
+ AC_MSG_WARN([
+***
+*** timegm() not available - a non-thread-safe kludge will be used
+*** and the TZ variable might be changed at runtime.
+***])
+fi
+
+# Add a few constants to help porting to W32
+AH_VERBATIM([SEPCONSTANTS],
+[
+/* Separators as used in file names and $PATH. Please note that the
+ string version must not contain more than one character because
+ the using code assumes strlen()==1 */
+#ifdef HAVE_DOSISH_SYSTEM
+#define DIRSEP_C '\\\\'
+#define EXTSEP_C '.'
+#define DIRSEP_S "\\\\"
+#define EXTSEP_S "."
+#define PATHSEP_C ';'
+#define PATHSEP_S ";"
+#else
+#define DIRSEP_C '/'
+#define EXTSEP_C '.'
+#define DIRSEP_S "/"
+#define EXTSEP_S "."
+#define PATHSEP_C ':'
+#define PATHSEP_S ":"
+#endif
+])
+
+AH_BOTTOM([
+/* Definition of GCC specific attributes. */
+#if __GNUC__ > 2
+# define GPGME_GCC_A_PURE __attribute__ ((__pure__))
+#else
+# define GPGME_GCC_A_PURE
+#endif
+])
+
+dnl # Checking for libgpg-error.
+dnl AM_PATH_GPG_ERROR(0.5,, AC_MSG_ERROR([libgpg-error was not found]))
+dnl AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
+dnl [The default error source for GPGME.])
+
+
+
+# Checks for system services
+NO_OVERRIDE=no
+AC_ARG_WITH(gpg,
+ AC_HELP_STRING([--with-gpg=PATH], [use GnuPG binary at PATH]),
+ GPG=$withval, NO_OVERRIDE=yes)
+if test "$NO_OVERRIDE" = "yes" || test "$GPG" = "yes"; then
+ GPG=
+ NO_OVERRIDE=yes
+ if test "$cross_compiling" != "yes"; then
+ AC_PATH_PROG(GPG, gpg)
+ fi
+ if test -z "$GPG"; then
+ GPG="$GPG_DEFAULT"
+ fi
+fi
+if test "$GPG" = no; then
+ if test "$NO_OVERRIDE" = "yes"; then
+ if test "$cross_compiling" != "yes"; then
+ AC_MSG_WARN([
+***
+*** Could not find GnuPG, install GnuPG or use --with-gpg=PATH to enable it
+***])
+ else
+ AC_MSG_ERROR([
+***
+*** Can not determine path to GnuPG when cross-compiling, use --with-gpg=PATH
+***])
+ fi
+ fi
+else
+ AC_DEFINE_UNQUOTED(GPG_PATH, "$GPG", [Path to the GnuPG binary.])
+ AC_SUBST(GPG)
+fi
+AM_CONDITIONAL(RUN_GPG_TESTS,
+ [test "$cross_compiling" != "yes" && test -n "$GPG" && test -r "$GPG"])
+AC_SUBST(GPG_PATH)
+
+NO_OVERRIDE=no
+AC_ARG_WITH(gpgsm,
+ AC_HELP_STRING([--with-gpgsm=PATH], [use GpgSM binary at PATH]),
+ GPGSM=$withval, NO_OVERRIDE=yes)
+if test "$NO_OVERRIDE" = "yes" || test "$GPGSM" = "yes"; then
+ GPGSM=
+ NO_OVERRIDE=yes
+ if test "$cross_compiling" != "yes"; then
+ AC_PATH_PROG(GPGSM, gpgsm)
+ fi
+ if test -z "$GPGSM"; then
+ GPGSM="$GPGSM_DEFAULT"
+ fi
+fi
+if test "$GPGSM" = no; then
+ if test "$NO_OVERRIDE" = "yes"; then
+ if test "$cross_compiling" != "yes"; then
+ AC_MSG_WARN([
+***
+*** Could not find GpgSM, install GpgSM or use --with-gpgsm=PATH to enable it
+***])
+ else
+ AC_MSG_ERROR([
+***
+*** Can not determine path to GpgSM when cross-compiling, use --with-gpgsm=PATH
+***])
+ fi
+ fi
+else
+ AC_DEFINE_UNQUOTED(GPGSM_PATH, "$GPGSM", [Path to the GPGSM binary.])
+ AC_SUBST(GPGSM)
+fi
+AM_CONDITIONAL(HAVE_GPGSM, [test -n "$GPGSM" && test -r "$GPGSM"])
+dnl AM_CONDITIONAL(RUN_GPGSM_TESTS,
+dnl [test "$cross_compiling" != "yes" && test -n "$GPGSM" && test -r "$GPGSM"])
+
+dnl # FIXME: Only build if supported.
+dnl AM_CONDITIONAL(BUILD_ASSUAN, test "$GPGSM" != "no")
+
+AC_CHECK_FUNCS(funopen)
+
+if test "$GPGSM" != "no"; then
+ if test $ac_cv_func_funopen != yes; then
+ # No funopen but we can implement that in terms of fopencookie.
+ AC_CHECK_FUNCS(fopencookie, funopen, AC_MSG_ERROR([[No implementation of fopencookie or funopen available.]]))
+ fi
+
+ dnl it's a #define !!!
+ dnl AC_CHECK_FUNCS(isascii)
+
+ AC_CHECK_FUNCS(putc_unlocked)
+ AC_CHECK_FUNCS(memrchr)
+fi
+
+# More assuan checks.
+AC_CHECK_HEADERS([sys/uio.h])
+
+echo "
+ GPGME v${VERSION} has been configured as follows:
+
+ GnuPG version: min. $NEED_GPG_VERSION
+ GnuPG path: $GPG
+
+ GpgSM version: min. $NEED_GPGSM_VERSION
+ GpgSM path: $GPGSM
+"
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ChangeLog b/libtdenetwork/libgpgme-copy/gpgme/ChangeLog
new file mode 100644
index 000000000..85fd28d30
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ChangeLog
@@ -0,0 +1,5312 @@
+2007-02-26 Werner Koch <wk@g10code.com>
+
+ * verify.c (op_data_t): New element PLAINTEXT_SEEN.
+ (_gpgme_verify_status_handler): Return an error if more than one
+ plaintext has been seen.
+ (parse_error): New arg SET_STATUS. Also detect it based on an
+ ERROR status (gpg > 1.4.6).
+
+2007-01-26 Werner Koch <wk@g10code.com>
+
+ * w32-io.c (build_commandline): Fixed stupid quoting bug.
+ * w32-glib-io.c (build_commandline): Ditto.
+
+ * rungpg.c (gpg_set_locale): Avoid dangling pointer after free.
+
+ * gpgme-config.in: New options --get-gpg and --get-gpgsm.
+
+2007-01-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.h (_gpgme_data_get_fd): Add prototype.
+ (gpgme_data_get_fd_cb): New type.
+ (struct _gpgme_data_cbs): New member get_fd.
+ * data.c (_gpgme_data_get_fd): New function.
+ * data-fd.c (fd_get_fd): New function.
+ (fd_cbs): Add fd_get_fd.
+ * data-stream.c (stream_get_fd): New function.
+ (stream_cbs): Add stream_get_fd.
+ * data-mem.c (mem_cbs): Add NULL for get_fd callback.
+ * data-user.c (user_cbs): Likewise.
+ * engine-gpgsm.c (gpgsm_set_fd) [USE_DESCRIPTOR_PASSING]: Try to
+ short-cut by passing the data descriptor directly.
+
+2007-01-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-io.c (build_commandline): Quote all command line arguments.
+ * w32-glib-io.c (build_commandline): Likewise.
+
+2007-01-10 Werner Koch <wk@g10code.com>
+
+ * ttyname_r.c (ttyname_r) [W32]: Return a dummy name.
+
+2007-01-08 Werner Koch <wk@g10code.com>
+
+ * version.c (do_subsystem_inits): Do assuan init only if building
+ with Assuan.
+ * setenv.c: Include assuan-def.h only if building with Assuan
+ support.
+
+ * op-support.c (_gpgme_op_reset): Set LC_MESSAGES only if
+ if defined.
+ * engine-gpgsm.c (gpgsm_set_locale): Ditto.
+ * rungpg.c (gpg_set_locale): Ditto.
+
+2006-12-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_protocol): Shut down the engine when
+ switching protocols.
+ (gpgme_ctx_set_engine_info): Likewise for engine info.
+ * engine.h (_gpgme_engine_reset): New function prototype.
+ * engine.c (_gpgme_engine_reset): New function.
+ * engine-backend.h (struct engine_ops): New member RESET.
+ * rungpg.c (_gpgme_engine_ops_gpg): Add NULL for reset function.
+ * engine-gpgsm.c (_gpgme_engine_ops_gpgsm)
+ [USE_DESCRIPTOR_PASSING]: Add gpgsm_reset for reset.
+ (_gpgme_engine_ops_gpgsm) [!USE_DESCRIPTOR_PASSING]: Add NULL for
+ reset function.
+ (gpgsm_reset) [USE_DESCRIPTOR_PASSING]: New function.
+ * op-support.c (_gpgme_op_reset): Try to use the engine's reset
+ function if available.
+ * engine-gpgsm.c (gpgsm_new): Move code to dup status_fd to ...
+ (start): ... here.
+ * posix-io.c (_gpgme_io_recvmsg, _gpgme_io_sendmsg): New functions.
+
+ * engine.h (_gpgme_engine_new): Remove arguments lc_ctype and
+ lc_messages from prototype.
+ (_gpgme_engine_set_locale): New prototype.
+ * engine.c (_gpgme_engine_set_locale): New function.
+ * op-support.c (_gpgme_op_reset): Call _gpgme_engine_set_locale.
+ * engine-backend.h (struct engine_ops): Add new member SET_LOCALE.
+ Remove arguments lc_messages and lc_ctype from member NEW.
+ * engine-gpgsm.c (struct engine_gpgsm): New members lc_ctype_set
+ and lc_messages_set.
+ (gpgsm_new): Remove lc_messages and lc_ctype
+ arguments.
+ (gpgsm_set_locale): New function.
+ (_gpgme_engine_ops_gpgsm): Add gpgsm_set_locale.
+ * rungpg.c (struct engine_gpg): Add new members lc_messages and
+ lc_ctype.
+ (gpg_release): Release lc_messages and lc_ctype if set.
+ (gpg_new): Remove lc_messages and lc_ctype arguments.
+ (gpg_set_locale): New function.
+ (_gpgme_engine_ops_gpg): Add gpg_set_locale.
+ (add_arg): Implement in terms of:
+ (add_arg_ext): New function.
+ (start): Set lc-messages and lc-ctype arguments here.
+
+2006-12-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (struct engine_gpgsm): Move members
+ input_fd_server, output_fd_server, message_fd_server to ...
+ (iocb_data): ... here (as server_fd).
+ (close_notify_handler): Reset tags as well.
+ (gpgsm_new): Implement support for descriptor
+ passing.
+ (fd_type_t): New type.
+ (gpgsm_clear_fd): New function. Use it instead of _gpgsm_io_close
+ for unused communication channels.
+ (gpgsm_set_fd): Rewritten to support descriptor passing. All
+ relevant callers adjusted as well (previously of _gpgme_io_close).
+
+2006-12-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * version.c: Include "assuan.h".
+ (do_subsystem_inits): Call assuan_set_assuan_err_source.
+
+2006-12-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_real_la_SOURCES): Rename to main_sources.
+ (libgpgme_la_SOURCES, libgpgme_pthread_la_SOURCES,
+ libgpgme_glib_la_SOURCES, libgpgme_pth_la_SOURCES): Add
+ $(main_sources).
+ (libgpgme_la_DEPENDENCIES, libgpgme_la_LIBADD,
+ libgpgme_pthread_la_DEPENDENCIES, libgpgme_pthread_la_LIBADD,
+ libgpgme_pth_la_DEPENDENCIES, libgpgme_pth_la_LIBADD,
+ libgpgme_glib_la_DEPENDENCIES, libgpgme_glib_la_LIBADD): Remove
+ libgpgme-real.la.
+ (noinst_LTLIBRARIES): Removed.
+ (libgpgme_glib_la_CFLAGS, libgpgme_pth_la_CFLAGS): Removed.
+ (AM_CFLAGS): New variable.
+
+2006-11-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c: Replace AssuanError with gpg_error_t and
+ ASSUAN_CONTEXT with assuan_context_t.
+
+2006-11-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_new): Check return value of
+ assuan_pipe_connect.
+
+ * rungpg.c: Include <unistd.h>.
+ (gpg_new): Support --display, --ttyname, --ttytype, --lc-ctype and
+ --lc-messages. Fixes issue 734.
+
+2006-10-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * trustlist.c (gpgme_op_trustlist_next): Return error if OPD is
+ NULL.
+
+2006-10-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait-global.c (gpgme_wait): Unlock CTX_LIST_LOCK while calling
+ _gpgme_engine_io_event().
+
+ * keylist.c (gpgme_op_keylist_next): Return error if OPD is NULL.
+
+2006-09-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-mem.c (gpgme_data_release_and_get_mem): Release the data
+ object properly.
+
+2006-09-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (keylist_colon_handler): Move debug output after
+ initialising KEY.
+
+2006-07-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in (Options): Add NETLIBS.
+ * Makefile.am (libgpgme_la_LIBADD, libgpgme_pthread_la_LIBADD,
+ libgpgme_pth_la_LIBADD, libgpgme_glib_la_LIBADD): Add NETLIBS.
+
+ * rungpg.c (read_status): Fix comparison disguising as an
+ assignment.
+
+2005-03-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_locale): Remove conditional on
+ HAVE_W32_SYSTEM, and just check for LC_MESSAGES.
+
+2006-07-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (read_status): Strip potential carriage return.
+ * genkey.c (get_key_parameter): Skip potential carriage return.
+ * version.c (_gpgme_get_program_version): Strip potential carriage
+ return.
+
+ * data.c (gpgme_data_set_file_name): Allow to clear the file name
+ by passing NULL.
+
+2006-06-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (gpgme_get_key): Also clone the engine info.
+
+2006-03-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in (cflags_pth): Revert accidential removal of
+ pthread support with last change.
+
+2006-02-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-glib-io.c (O_BINARY) [!O_BINARY]: New macro.
+ (_gpgme_io_pipe): Open pipes in binary mode.
+
+2006-02-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c (gpgme_engine_check_version): Reimplemented to allow
+ checking the version correctly even after changing the engine
+ information. Bug reported by Stéphane Corthésy.
+
+ * rungpg.c (read_colon_line): Invoke colon preprocess handler if
+ it is set.
+ (colon_preprocessor_t): New type.
+ (struct engine_gpg): New member colon.preprocess_fnc.
+ (gpg_keylist_preprocess): New function.
+ * keylist.c (keylist_colon_handler): Allow short key IDs.
+
+2006-02-15 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-io.c (create_writer): Make C->have_data a manually resetted
+ event.
+ (writer): Move code from end of if block to beginning, so it
+ is also run the first time.
+ (_gpgme_io_write): Move assert check after error check. Reset
+ the is_empty event, and also do it eagerly.
+ (_gpgme_io_select): Unconditionally wait for the is_empty event.
+
+2006-01-26 Werner Koch <wk@g10code.com>
+
+ * w32-util.c (_gpgme_get_conf_int): New.
+ * posix-util.c (_gpgme_get_conf_int): New.
+ * w32-io.c (get_desired_thread_priority): New.
+ (create_reader, create_writer): Use it here.
+
+2006-01-04 Werner Koch <wk@g10code.com>
+
+ * debug.h (_gpgme_debug_srcname): New. Use it with the debug macros.
+
+ * w32-glib-io.c (_gpgme_io_set_nonblocking): Add debug
+ statements. Disable error return for failed nonblocking call.
+
+2006-01-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-glib-io.c (_gpgme_io_close): Only close fd if there is no
+ channel for it.
+
+2005-12-31 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-glib-io.c (find_channel): Set channel to unbuffered.
+ (_gpgme_io_select): Fix debug output.
+
+2005-12-23 Werner Koch <wk@g10code.com>
+
+ * gpgme.h (struct _gpgme_signature): Append field PKA_ADDRESS.
+ * verify.c (release_op_data, _gpgme_verify_status_handler): Set
+ this field.
+
+2005-12-20 Werner Koch <wk@g10code.com>
+
+ * gpgme.h (gpgme_status_code_t): Added GPGME_STATUS_PKA_TRUST_BAD
+ and GPGME_STATUS_PKA_TRUST_GOOD.
+ (struct _gpgme_signature): New field pka_trust.
+ * verify.c (_gpgme_verify_status_handler): Set pka_trust.
+
+2005-12-06 Werner Koch <wk@g10code.com>
+
+ * keylist.c (keylist_colon_handler): Store fingerprints of the
+ subkeys. Reset the secret flag of subkeys for stub secret keys.
+ (NR_FIELDS): Bumped up to 16
+
+2005-11-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c (_gpgme_set_engine_info): Use new_file_name in
+ engine_get_version invocation. Reported by Stéphane Corthésy.
+
+2005-11-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-glib-io.c (_gpgme_io_fd2str): Remove debug printf.
+
+2005-11-18 Werner Koch <wk@g10code.com>
+
+ * w32-glib-io.c: Include glib.h before windows to avoid a symbol
+ shadowing warning.
+ (find_channel): Better use g_io_channel_win32_new_fd instead of
+ the autodetection function g_io_channel_unix_new.
+ (_gpgme_io_select): Rewritten. It is now a fully working select
+ implementation.
+
+2005-11-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * priv-io.h (_gpgme_io_fd2str): New prototype.
+ * posix-io.c (_gpgme_io_fd2str): New function.
+ * w32-io.c (_gpgme_io_fd2str): New function.
+ * rungpg.c: Use this new function.
+ * w32-glib-io.c (_gpgme_io_fd2str): Rewrote the file handle code
+ again. Two's company, three's the musketeers.
+
+ * w32-glib-io.c: Rewrote the file handle code. We don't create
+ system fds for every handle (doesn't work for inherited handles),
+ but we create pseudo fds in a private namespace that designate a
+ handle and potentially a giochannel.
+
+2005-11-18 Werner Koch <wk@g10code.com>
+
+ * versioninfo.rc.in: Set file version to LT-version + Svn-revision.
+
+2005-11-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-glib-io.c: New file.
+ * gpgme.def (gpgme_get_giochannel): Add symbol.
+ * Makefile.am (system_components) [HAVE_DOSISH_SYSTEM]: Remove
+ w32-io.c.
+ (ltlib_gpgme_extra): New variable.
+ (lib_LTLIBRARIES): Add $(ltlib_gpgme_extra).
+ (system_components_not_extra): New variable.
+ (libgpgme_la_SOURCES, libgpgme_pthread_la_SOURCES,
+ (libgpgme_pth_la_SOURCES): Add $(system_components_not_extra).
+ (libgpgme_glib_la_LDFLAGS, libgpgme_glib_la_DEPENDENCIES,
+ (libgpgme_glib_la_LIBADD, libgpgme_glib_la_CFLAGS)
+ [BUILD_W32_GLIB]: New variables.
+ * gpgme-config.in (glib): New option.
+ * gpgme.m4 (AM_PATH_GPGME_GLIB): New macro.
+
+2005-11-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * priv-io.h (_gpgme_io_waitpid, _gpgme_io_kill): Removed.
+ * w32-io.c (_gpgme_io_waitpid, _gpgme_io_kill): Removed.
+ * posix-io.c (_gpgme_io_kill): Removed.
+ (_gpgme_io_waitpid): Declare static.
+
+2005-10-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-io.c (_gpgme_io_spawn): Don't minimize window, hide it.
+
+2005-10-21 Werner Koch <wk@g10code.com>
+
+ * Makefile.am: Fixed cut+paste problem
+
+2005-10-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am: Build versioninfo.lo, not versioninfo.o. Also, fix
+ the whole mess.
+
+2005-10-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (gpg_edit): Don't add a key argument if in card edit
+ mode.
+
+2005-10-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (gpgme.dll gpgme.dll.a): Use $(srcdir) for
+ gpgme.def.
+
+ * gpgme.h (gpgme_free): New prototype.
+ * data-mem.c (gpgme_free): New function.
+ * libgpgme.vers (GPGME_1.1): Add gpgme_free.
+ * gpgme.def: Add gpgme_free.
+
+2005-10-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * util.h (_gpgme_decode_percent_string): Add new argument BINARY
+ to prototype.
+ * verify.c (parse_notation): Likewise for invocation.
+ * conversion.c (_gpgme_decode_percent_string): Likewise to
+ declaration. If set, do not replace '\0' characters with a
+ printable string.
+ * gpgme.h (struct _gpgme_key_sig): New field notations.
+ * ops.h (_gpgme_parse_notation): New prototype.
+ * sig-notation.c (_gpgme_parse_notation): New function.
+ * key.c (gpgme_key_unref): Free all signature notations.
+ * keylist.c (op_data_t): New member tmp_keysig.
+ (finish_key): Clear OPD->tmp_keysig.
+ * gpgme.c (gpgme_set_keylist_mode): Remove check.
+ * rungpg.c (gpg_keylist): Support listing signature notations.
+ (gpg_keylist_ext): Likewise.
+
+2005-10-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.h (_gpgme_set_engine_info): Add prototype.
+ * engine-backend.h (struct engine_ops): Change return type of
+ get_file_name() to const char * to silence gcc warning.
+ * engine.c (engine_get_file_name): Change return type to const
+ char * to silence gcc warning.
+ (gpgme_get_engine_info): Use transitional variable to go from
+ const char * to char * to silence gcc warning.
+ (_gpgme_set_engine_info): Likewise.
+ * engine-gpgsm.c (struct engine_gpgsm): Change type of LINE to
+ char * to silence gcc warning.
+ (gpgsm_new): Make ARGV a pointer to const char.
+ (status_handler): Change type of SRC, END, DST, ALINE and NEWLINE
+ to char * to silence gcc warning.
+
+ * gpgme.def: Add gpgme_data_set_file_name,
+ gpgme_data_get_file_name, gpgme_sig_notation_clear,
+ gpgme_sig_notation_add and gpgme_sig_notation_get.
+ * libgpgme.vers: Add gpgme_sig_notation_clear,
+ gpgme_sig_notation_add and gpgme_sig_notation_get.
+ * Makefile.am (libgpgme_real_la_SOURCES): Add sig-notation.c.
+ * context.h (struct gpgme_context): New field sig_notations.
+ * gpgme.h (struct _gpgme_sig_notation): New member value_len and
+ critical.
+ (GPGME_SIG_NOTATION_CRITICAL): New symbol.
+ (gpgme_sig_notation_flags_t): New type.
+ (gpgme_sig_notation_add, gpgme_sig_notation_clear,
+ gpgme_sig_notation_get): New prototypes.
+ * ops.h (_gpgme_sig_notation_create, _gpgme_sig_notation_free):
+ New prototypes.
+ * sig-notation.c (_gpgme_sig_notation_free): New file.
+ * verify.c (parse_notation): Use support functions.
+ (release_op_data): Likewise.
+ * rungpg.c (append_args_from_sig_notations): New function.
+ (gpg_encrypt_sign, gpg_sign): Call it.
+
+2005-09-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.h (struct gpgme_data): New member file_name.
+ * data.c (gpgme_data_set_filename): New function.
+ (_gpgme_data_release): Free DH->filename if necessary.
+ (gpgme_data_get_filename): New function.
+ * rungpg.c (gpg_encrypt): Set filename option.
+ (gpg_encrypt_sign): Likewise.
+ (gpg_sign): Likewise.
+ * libgpgme.vers (GPGME_1.1): Add gpgme_data_set_file_name and
+ gpgme_data_get_file_name.
+
+ * decrpyt.c, verify.c, gpgme.h: Replace plaintext_filename with
+ file_name.
+
+2005-09-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_key): Add field is_qualified.
+ (struct _gpgme_subkey): Likewise.
+ * keylist.c (set_subkey_capability, set_mainkey_capability): Set
+ field is_qualified.
+
+2005-09-23 Werner Koch <wk@g10code.com>
+
+ * w32-io.c (_gpgme_io_pipe): Removed use of environment variable
+ again.
+ (create_reader, create_writer): Set thread priority higher.
+
+2005-09-19 Werner Koch <wk@g10code.com>
+
+ * w32-io.c (_gpgme_io_pipe): New environment variable to change
+ the size of the pipe buffer.
+
+2005-09-13 Werner Koch <wk@g10code.com>
+
+ * ath.c: Changes to make it work under W32.
+
+2005-09-12 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_la_SOURCES): Set to ath.h and ath.c.
+ (ath_pth_src, ath_pthread_src): Removed.
+ (w32_o_files): Replace ath-compat.o with ath.o.
+ (libgpgme_pth_la_CFLAGS): New variable.
+ * ath-compat.c, ath-pthread-compat.c, ath-pth-compat.c: Removed.
+ * ath.h (ath_pthread_available, ath_pth_available): Removed.
+ (ath_init) [!_ATH_EXT_SYM_PREFIX]: Do not define macro.
+ (struct ath_ops, ath_init) [_ATH_COMPAT]: Removed.
+ (_ATH_COMPAT): Macro removed.
+ * posix-sema.c (_gpgme_sema_subsystem_init): Do not call
+ _gpgme_ath_init.
+
+2005-09-12 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (release_op_data): Do not free opd->tmp_uid.
+
+2005-09-07 Werner Koch <wk@g10code.com>
+
+ * w32-io.c (build_commandline): Quote argv[0].
+
+2005-08-26 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (command_handler): Use _gpgme_io_write instead of write.
+
+ * edit.c (command_handler): Do not depend on PROCESSED being
+ available.
+
+ * engine.h (engine_command_handler_t): Add new argument processed.
+ * ops.h (_gpgme_passphrase_command_handler_internal): Rename
+ prototype to ...
+ (_gpgme_passphrase_command_handler): ... this one.
+ * passphrase.c (_gpgme_passphrase_command_handler_internal):
+ Rename to ...
+ (_gpgme_passphrase_command_handler): ... this one.
+ * edit.c (command_handler): Add new argument processed. Remove
+ local variable with the same name. Always return processed as
+ true.
+ * rungpg.c (command_handler): Send a newline character if the
+ handler did not.
+
+2005-08-26 Werner Koch <wk@g10code.com>
+
+ * w32-util.c (read_w32_registry_string): Updated from code used by
+ GnuPG. This allows for expanding strings and features the
+ implicit fallback key.
+ (w32_shgetfolderpath, find_program_at_standard_place): New.
+ (_gpgme_get_gpg_path, _gpgme_get_gpgsm_path): With no registry
+ entry, locate the programs at the standard place.
+ (dlopen, dlsym, dlclose): New, so that we can keep on using what
+ we are accustomed to.
+
+ * debug.c (debug_init): Use PATHSEP_C so that under W32 a
+ semicolon is used which allows us to create files with drive
+ letters.
+
+ * w32-io.c (_gpgme_io_read, _gpgme_io_write): Print content in
+ debug mode too.
+
+2005-08-19 Werner Koch <wk@g10code.com>
+
+ * gpgme.def: New.
+ * versioninfo.rc.in: New.
+ * Makefile.am: Addes support for building a W32 DLL.
+
+ * ttyname_r.c (ttyname_r) [W32]: Return error.
+ * ath-compat.c [W32]: select and co are not yet supported; return
+ error.
+ * data-stream.c (stream_seek): Use ftell if ftello is not available.
+
+2005-08-08 Werner Koch <wk@g10code.com>
+
+ * util.h (stpcpy): Renamed to ..
+ (_gpgme_stpcpy): .. this and made inline. This avoids duplicate
+ definitions when linking statically.
+ * stpcpy.c: Removed.
+
+2005-07-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_PLAINTEXT.
+ (struct _gpgme_op_decrypt_result): New member plaintext_filename.
+ (struct _gpgme_op_verify_result): Likewise.
+ * ops.h (_gpgme_parse_plaintext): Add prototype.
+ * op-support.c (_gpgme_parse_plaintext): New function.
+ * decrypt.c (release_op_data): Release
+ OPD->result.plaintext_filename.
+ (_gpgme_decrypt_status_handler): Handle GPGME_STATUS_PLAINTEXT.
+ * verify.c (release_op_data): Release
+ OPD->result.plaintext_filename.
+ (_gpgme_verify_status_handler): Handle GPGME_STATUS_PLAINTEXT.
+
+2005-07-26 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (gpgme_get_key): Allow key IDs.
+
+2005-06-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.m4: Only call GPGME_CONFIG if found.
+
+2005-06-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_signature): New members pubkey_algo and
+ hash_algo.
+ * verify.c (parse_valid_sig): Parse pubkey and hash algo numbers.
+ (parse_new_sig): Parse pubkey, hash algo and timestamp for ERRSIG.
+
+ (_gpgme_decrypt_status_handler): Fix last change.
+
+ * gpgme.h (struct _gpgme_recipient): New structure.
+ (gpgme_recipient_t): New type.
+ (struct _gpgme_op_decrypt_result): Add member recipients.
+ * decrypt.c (op_data_t): New member last_recipient_p.
+ (_gpgme_op_decrypt_init_result): Initialize last_recipient_p.
+ (parse_enc_to): New function.
+ (_gpgme_decrypt_status_handler): Handle status ENC_TO and
+ NO_SECKEY.
+
+ * wait-global.c (gpgme_wait): Break out of the fd processing loop
+ after an error.
+ Reported by Igor Belyi <gpgme@katehok.ac93.org>.
+
+2005-06-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.h (_gpgme_run_io_cb): New prototype.
+ * wait.c (_gpgme_run_io_cb): New function.
+ * wait-global.c (gpgme_wait): Call it.
+ * wait-user.c (_gpgme_user_io_cb_handler): Likewise.
+ * wait-private.c (_gpgme_wait_on_condition): Likewise.
+
+2005-06-02 Werner Koch <wk@g10code.com>
+
+ * passphrase.c (_gpgme_passphrase_status_handler): Take care of
+ GPGME_STATUS_NEED_PASSPHRASE_PIN.
+ (_gpgme_passphrase_command_handler_internal): Also act on the key
+ "passphrase.pin.ask".
+
+ * gpgme.h: Added status codes GPGME_STATUS_SIG_SUBPACKET,
+ GPGME_STATUS_NEED_PASSPHRASE_PIN, GPGME_STATUS_SC_OP_FAILURE,
+ GPGME_STATUS_SC_OP_SUCCESS, GPGME_STATUS_CARDCTRL,
+ GPGME_STATUS_BACKUP_KEY_CREATED.
+
+2005-05-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-user.c: Include <errno.h>.
+
+2005-05-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_new): Set the CTX->include_certs default to the
+ default.
+
+2005-05-11 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-io.c (_gpgme_io_select): Fix loop increment.
+
+2005-05-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-user.c (user_release): Only call user hook if provided.
+ (user_seek): Return EBADF if no user hook is provided.
+ (user_read): Likewise.
+ (user_write): Likewise.
+
+2005-04-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (GPGME_INCLUDE_CERTS_DEFAULT): New macro.
+ * engine-gpgsm.c (gpgsm_sign): Send the include-certs option after
+ the reset, just for cleanliness, and do not sent it at all if the
+ default is requested.
+ * gpgme.c (gpgme_set_include_certs): Allow to use
+ GPGME_INCLUDE_CERTS_DEFAULT.
+
+2005-04-21 Werner Koch <wk@g10code.com>
+
+ * verify.c (calc_sig_summary): Set the key revoked bit.
+
+2005-04-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait-global.c (gpgme_wait): Use LI->ctx when checking a context
+ in the list, not the user-provided CTX.
+ Reported by Igor Belyi <gpgme@katehok.ac93.org>.
+
+ * wait-global.c (gpgme_wait): If no context is found, and we
+ should not hang, set *status to 0 and return NULL.
+ Reported by Igor Belyi <gpgme@katehok.ac93.org>.
+
+2005-03-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.h (EOPNOTSUPP) [_WIN32]: Remove definition.
+ * data.c (EOPNOTSUPP) [HAVE_W32_SYSTEM]: Remove definition.
+ (gpgme_data_read, gpgme_data_write, gpgme_data_seek): Return
+ ENOSYS instead EOPNOTSUPP.
+ * data-compat.c (EOPNOTSUPP) [HAVE_W32_SYSTEM]: Remove definition.
+ (gpgme_error_to_errno): Map GPG_ERR_NOT_SUPPORTED
+ to ENOSYS.
+
+2005-03-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * io.h: Rename to ...
+ * priv-io.h: ... this.
+ * Makefile.am (libgpgme_real_la_SOURCES): Change io.h to priv-io.h.
+ * data.c, engine-gpgsm.c, posix-io.c, rungpg.c, version.c,
+ w32-io.c, wait-private.c, wait-global.c, wait-user.c, wait.c:
+ Change all includes of "io.h" to "priv-io.h"
+
+2005-03-09 Werner Koch <wk@g10code.com>
+
+ * w32-util.c (_gpgme_get_gpg_path, _gpgme_get_gpgsm_path): Do not
+ cast away type checks.
+
+ * io.h [W32]: Do not include stdio.h. If it is needed do it at
+ the right place.
+
+ * data.h [W32]: Removed kludge for EOPNOTSUP.
+ * data.c, data-compat.c [W32]: Explicitly test for it here.
+
+ Replaced use of _WIN32 by HAVE_W32_SYSTEM except for public header
+ files.
+
+2005-03-07 Timo Schulz <twoaday@g10code.de>
+
+ * gpgme.h: [_WIN32] Removed ssize_t typedef.
+ * ath.h: [_WIN32] Added some (dummy) types.
+ * io.h: [_WIN32] include stdio.h.
+ * data.h: [_WIN32] Define EOPNOTSUPP.
+ * w32-io.c [_WIN32] (_gpgme_io_subsystem_init): New.
+ * gpgme.c [_WIN32] (gpgme_set_locale): Disabled.
+
+2004-12-12 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c (_gpgme_set_engine_info): Fix assertion.
+
+2004-12-11 Marcus Brinkmann <marcus@g10code.de>
+
+ * util.h [HAVE_CONFIG_H && HAVE_TTYNAME_R] (ttyname_r): Define
+ prototype.
+ * ttyname_r.c: New file.
+
+2004-12-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * putc_unlocked.c, funopen.c: I just claim copyright on these
+ files and change their license to LGPL, because they are totally
+ trivial wrapper functions.
+ * isascii.c: Change copyright notice to the one from ctype/ctype.h
+ in the GNU C Library (CVS Head 2004-10-10), where isascii is
+ defined as a macro doing exactly the same as the function in this
+ file.
+ * memrchr.c: Update from the GNU C Library (CVS Head 2001-07-06).
+ * stpcpy.c: Update from the GNU C Library (CVS Head 2004-10-10).
+ * ath.c, ath-compat.c, ath.h, ath-pth.c, ath-pth-compat.c,
+ ath-pthread.c, ath-pthread-compat.c, context.h, conversion.c,
+ data.c, data-compat.c, data-fd.c, data.h, data-mem.c,
+ data-stream.c, data-user.c, debug.c, debug.h, decrypt.c,
+ decrypt-verify.c, delete.c, edit.c, encrypt.c, encrypt-sign.c,
+ engine-backend.h, engine.c, engine-gpgsm.c, engine.h, error.c,
+ export.c, genkey.c, get-env.c, gpgme.c, gpgme.h, import.c, io.h,
+ key.c, keylist.c, mkstatus, Makefile.am, ops.h, op-support.c,
+ passphrase.c, posix-io.c, posix-sema.c, posix-util.c, progress.c,
+ rungpg.c, sema.h, sign.c, signers.c, trust-item.c, trustlist.c,
+ util.h, verify.c, version.c, w32-io.c, w32-sema.c, w32-util.c,
+ wait.c, wait-global.c, wait.h, wait-private.c, wait-user.c: Change
+ license to LGPL.
+
+2004-12-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * libgpgme.vers (GPGME_1.1): New version.
+ * engine-backend.h (struct engine_ops): Add argument FILE_NAME to
+ member get_version(). Add arguments FILE_NAME and HOME_DIR to
+ member new(). Change return type of get_file_name and get_version
+ to char *.
+ * engine-gpgsm.c (gpgsm_get_version): Change return type to char
+ pointer. Do not cache result.
+ (gpgsm_new): Add file_name and home_dir argument, and use them
+ instead of the defaults, if set.
+ * rungpg.c (struct engine_gpg): New member file_name.
+ (gpg_get_version): Change return type to char pointer, and do not
+ cache result.
+ (gpg_release): Free gpg->file_name.
+ (gpg_new): Take new arguments file_name and home_dir. Set the
+ --homedir argument if HOME_DIR is not NULL. Set gpg->file_name.
+ (start): Use gpg->file_name instead _gpgme_get_gpg_path, if set.
+ * engine.h (_gpgme_engine_info_copy, _gpgme_engine_info_release):
+ New prototypes.
+ (_gpgme_engine_new): Change first argument to gpgme_engine_info_t
+ info.
+ * engine.c: Include <assert.h>.
+ (gpgme_get_engine_info): Set *INFO within the lock. Move
+ ENGINE_INFO and ENGINE_INFO_LOCK to ....
+ (engine_info, engine_info_lock): ... here. New static variables.
+ (engine_get_version): Add file_name argument to
+ get_version invocation. Change return type to char pointer.
+ (gpgme_engine_check_version): Rewritten to free() the return value
+ of engine_get_version after using it.
+ (_gpgme_engine_info_release): New function.
+ (gpgme_get_engine_info): Rewritten.
+ (_gpgme_engine_info_copy): New function.
+ (_gpgme_set_engine_info): New function.
+ (gpgme_set_engine_info): New function.
+ (_gpgme_engine_new): Change first argument to gpgme_engine_info_t
+ info, and use that.
+ * gpgme.h (struct _gpgme_engine_info): Change type of file_name
+ and version to char * (remove the const). New member home_dir.
+ (gpgme_set_engine_info, gpgme_ctx_get_engine_info,
+ gpgme_ctx_set_engine_info): New prototypes.
+ * context.h (struct gpgme_context): New member engine_info.
+ * gpgme.c (gpgme_new): Allocate CTX->engine_info.
+ (gpgme_release): Deallocate CTX->engine_info.
+ (gpgme_ctx_get_engine_info, gpgme_ctx_set_engine_info): New
+ functions.
+ * op-support.c (_gpgme_op_reset): Look for correct engine info and
+ pass it to _gpgme_engine_new.
+ * version.c (gpgme_check_version): Adjust to
+ _gpgme_compare_versions returning an int.
+ (_gpgme_compare_versions): Return an int value, not a const char
+ pointer.
+ * ops.h (_gpgme_compare_versions): Same for prototype.
+
+2004-10-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (parse_trust): If no reason is provided, set
+ SIG->validity_reason to 0.
+ (calc_sig_summary): Set GPGME_SIGSUM_CRL_TOO_OLD if appropriate.
+
+2004-10-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (map_assuan_error): Return 0 if ERR is 0.
+ (start): Call map_assuan_error on return value of
+ assuan_write_line.
+
+2004-10-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * op-support.c (_gpgme_op_data_lookup): Use char pointer for
+ pointer arithmetic.
+
+2004-09-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.m4: Implement the --api-version check.
+
+ * rungpg.c (read_status): Move the polling of the output data pipe
+ to just before removing the command fd, from just before adding
+ it. This avoids buffering problems.
+
+ * data.c (_gpgme_data_inbound_handler): Use _gpgme_io_read, not
+ read, to improve debug output.
+
+2004-09-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (GPGME_IMPORT_NEW, GPGME_IMPORT_UID, GPGME_IMPORT_SIG,
+ GPGME_IMPORT_SUBKEY, GPGME_IMPORT_SECRET,
+ (GPGME_KEYLIST_MODE_LOCAL, GPGME_KEYLIST_MODERN_EXTERN,
+ GPGME_KEYLIST_MODE_SIGS, GPGME_KEYLIST_MODE_VALIDATE): Change from
+ enum to macros.
+ (gpgme_keylist_mode_t): Define as unsigned int.
+ (gpgme_key_t): Change type of keylist_mode to
+ gpgme_keylist_mode_t.
+
+2004-09-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.c (_gpgme_data_outbound_handler): Close the file descriptor
+ if we get an EPIPE.
+
+ * data-stream.c (stream_seek): Call ftello and return the current
+ offset.
+ * data.h (struct gpgme_data): Change type of data.mem.offset to
+ off_t.
+ * data.c (gpgme_data_seek): Check dh->cbs->seek callback, not read
+ callback. If SEEK_CUR, adjust the offset by the pending buffer
+ size. Clear pending buffer on success.
+
+
+2004-09-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.m4: Add copyright notice.
+
+2004-08-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * passphrase.c (_gpgme_passphrase_status_handler): Always run the
+ status handler.
+
+2004-08-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (build_argv): Use --no-sk-comment, not --no-comment.
+
+2004-06-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * key.c (_gpgme_key_append_name): Make sure tail points to the
+ byte following the uid.
+ (_gpgme_key_add_sig): Likewise. Don't use calloc, but malloc and
+ memset.
+
+2004-06-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * libgpgme.vers: Remove C-style comment, which is not supported by
+ older binutils.
+
+2004-05-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in (Options): Support --api-version.
+
+ * libgpgme.vers: List all gpgme symbols under version GPGME_1.0.
+
+ * decrypt.c (_gpgme_decrypt_status_handler): Fix last change.
+ * verify.c (parse_error): Likewise.
+
+ * verify.c (parse_error): Do not skip location of where token.
+
+ * gpgme.h (gpgme_status_code_t): Add GPGME_STATUS_REVKEYSIG.
+ * verify.c (_gpgme_verify_status_handler): Add handling of
+ GPGME_STATUS_REVKEYSIG.
+ (parse_trust): Likewise.
+
+2004-05-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_decrypt_result): New fields
+ wrong_key_usage and _unused.
+ * decrypt.c (_gpgme_decrypt_status_handler): Don't skip over
+ character after a matched string, as in a protocol error this
+ could skip over the trailing binary zero.
+ Handle decrypt.keyusage error notifications.
+
+ * gpgme.h (struct _gpgme_key): New member keylist_mode.
+ * keylist.c (keylist_colon_handler): Set the keylist_mode of KEY.
+
+2004-04-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_signature): Change member WRONG_KEY_USAGE
+ to unsigned int. Same for member _unused.
+
+ * keylist.c (set_mainkey_trust_info): Rewritten.
+ (set_subkey_capability): Handle 'd' (disabled).
+ (set_mainkey_capability): Rewritten.
+
+2004-04-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.m4: Quote first argument to AC_DEFUN.
+
+2004-04-21 Werner Koch <wk@gnupg.org>
+
+ * key.c (gpgme_key_unref): Allow passing NULL like free does.
+ The rule of least surprise.
+
+2004-04-15 Werner Koch <wk@gnupg.org>
+
+ * verify.c (prepare_new_sig, _gpgme_verify_status_handler): Remove
+ unused result.signatures items.
+
+ * keylist.c (gpgme_get_key): Return an error if FPR is NULL.
+
+2004-04-08 Werner Koch <wk@gnupg.org>
+
+ * verify.c (_gpgme_verify_status_handler): Ignore the error status
+ if we can't process it.
+ * decrypt-verify.c (decrypt_verify_status_handler): Backed out
+ yesterday's hack. It is not any longer required.
+
+2004-04-07 Werner Koch <wk@gnupg.org>
+
+ * decrypt-verify.c (decrypt_verify_status_handler): Hack to cope
+ with meaningless error codes from the verify status function.
+
+2004-04-05 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h: Add GPGME_STATUS_NEWSIG.
+
+ * verify.c (parse_error): Compare only the last part of the where
+ token.
+ (prepare_new_sig): New.
+ (parse_new_sig): Use prepare_new_sig when required.
+ (_gpgme_verify_status_handler): Handle STATUS_NEWSIG.
+
+ * engine-gpgsm.c (gpgsm_keylist_ext): Send with-validation
+ option. Fixed pattern construction.
+ (status_handler): Add debugging output.
+
+2004-03-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_new): Protect _only_ tty related code with
+ isatty(). Submitted by Bernhard Herzog.
+
+2004-03-11 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_new): Protect all tty related code with
+ isatty().
+
+ * rungpg.c (gpg_cancel): Set GPG->fd_data_map to NULL after
+ releasing it.
+ * engine-gpgsm.c (gpgsm_cancel): Only call assuan_disconnect if
+ GPGSM->assuan_ctx is not NULL. Set it to NULL afterwards.
+
+2004-03-07 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in: Do not emit include and lib directory for
+ prefix "/usr" or "".
+
+2004-03-03 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (gpgsm_export_ext): Properly insert a space
+ beween patterns.
+
+2004-02-18 Werner Koch <wk@gnupg.org>
+
+ * gpgme-config.in: Ignore setting of --prefix.
+
+2004-02-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (gpg_cancel): New function.
+ (gpg_release): Call it here.
+ (_gpgme_engine_ops_gpg): Add it here.
+ * engine-gpgsm.c (gpgsm_cancel): Fix last change.
+
+2004-02-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_cancel): New function.
+ * engine-backend.h (struct engine_ops): New member cancel.
+ * engine.h (_gpgme_engine_cancel): New prototype.
+ * engine.c (_gpgme_engine_cancel): New function.
+ * engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Add new member cancel.
+ (gpgsm_cancel): New function.
+ (gpgsm_release): Use it.
+ * rungpg.c (_gpgme_engine_ops_gpg): Add new member cancel.
+
+2004-02-17 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h: Add GPGME_KEYLIST_MODE_VALIDATE.
+ * engine-gpgsm.c (gpgsm_keylist): Send this to gpgsm.
+
+2004-02-15 Werner Koch <wk@gnupg.org>
+
+ * memrchr.c (memrchr): Fixed implementation. Problem pointed out
+ by Adriaan de Groot.
+
+2004-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (build_argv): Use --no-comment, not --comment "".
+
+ * data-compat.c (gpgme_data_new_from_filepart): Call fseeko if
+ available.
+ * data-stream.c (stream_seek): Likewise.
+
+2004-01-16 Werner Koch <wk@gnupg.org>
+
+ * conversion.c (_gpgme_map_gnupg_error): Handle numerical codes as
+ used by GnuPG 1.9.x
+
+2004-01-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_key_sig): Fix comment on REVOKED.
+
+2004-01-12 Werner Koch <wk@gnupg.org>
+
+ * sign.c: Include util.h for prototype of _gpgme_parse_timestamp.
+
+2003-12-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (_GPGME_D_CLASS): Revert this change.
+ (struct _gpgme_key_sig): For C++ compilers, rename class
+ member to _obsolete_class. Add new member sig_class.
+ (struct _gpgme_new_signature): Same here.
+ * key.c (gpgme_key_sig_get_ulong_attr): Use CERTSIG->sig_class,
+ not CERTSIG->class.
+ * keylist.c (keylist_colon_handler): Likewise for KEYSIG, but keep
+ setting KEYSIG->class, too. Rename variable CLASS to SIG_CLASS.
+ * sign.c (parse_sig_created): Set SIG->sig_class.
+
+2003-12-22 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h (_GPGME_D_CLASS): Kludge for C++ compatibility without
+ changing the C API.
+
+2003-11-19 Werner Koch <wk@gnupg.org>
+
+ * conversion.c (_gpgme_parse_timestamp): New.
+ (atoi_1, atoi_2, atoi_4): New.
+ * keylist.c (parse_timestamp): Removed. Changed all callers to use
+ the new function.
+ * verify.c (parse_valid_sig): Ditto. Repalced the errno check.
+ * sign.c (parse_sig_created): Ditto.
+
+2003-10-31 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (parse_timestamp): Detect ISO 8601 timestamps and try
+ to convert them.
+
+2003-10-10 Marcus Brinkmann <marcus@g10code.de>
+
+ * genkey.c (get_key_parameter): Make a copy of the key parameters.
+ Submitted by Miguel Coca <e970095@zipi.fi.upm.es>.
+
+2003-10-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-compat.c: Include <sys/time.h> before <sys/stat.h> for
+ broken systems.
+
+ * engine-gpgsm.c (map_assuan_error): If ERR is -1, return sensible
+ error.
+
+ * io.h (_gpgme_io_subsystem_init): New prototype.
+ * posix-io.c (_gpgme_io_subsystem_init): Add function.
+ (_gpgme_io_spawn): Do not fixup signal handler here.
+ * version.c (do_subsystem_inits): Call _gpgme_io_subsystem_init.
+
+ * debug.c (debug_init): Drop const qualifier from E.
+
+ * ath.h (struct ath_ops): Make ADDR argument of CONNECT prototype
+ const.
+ (ath_connect): Make ADDR argument const.
+ * ath-pthread.c (ath_connect): Likewise.
+ * ath-pth.c (ath_connect): Likewise.
+ * ath-compat.c (ath_connect): Likewise.
+ * ath.c (ath_connect): Likewise.
+
+ * ath.h [HAVE_SYS_SELECT_H]: Include <sys/select.h> for fd_set.
+ [!HAVE_SYS_SELECT_H]: Include <sys/time.h>.
+
+ * conversion.c (_gpgme_hextobyte): Drop "unsigned" from type of
+ SRC argument.
+ * util.h (_gpgme_hextobyte): Likewise for prototype.
+
+ * gpgme.h: Remove trailing comma in enum.
+
+ * rungpg.c: Do not include <time.h>, <sys/time.h>, <sys/types.h>,
+ <signal.h>, <fcntl.h>, or "unistd.h".
+
+2003-10-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-backend.h (struct engine_ops): Add argument TYPE.
+ * engine.c (_gpgme_engine_op_edit): Likewise.
+ * engine.h: Likewise.
+ * rungpg.c (gpg_edit): Likewise. Use it.
+ * edit.c (edit_start): Likewise. Pass it on.
+ (gpgme_op_edit_start, gpgme_op_edit): Likewise.
+ (gpgme_op_card_edit_start, gpgme_op_card_edit): New functions.
+
+2003-09-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpg_strerror_r): Change prototype to match
+ gpg_strerror_r change.
+ * error.c (gpg_strerror_r): Likewise, also update implementation.
+
+ * gpgme.c (gpgme_hash_algo_name): Change name of RMD160 to
+ RIPEMD160, name of TIGER to TIGER192, name of CRC32-RFC1510 to
+ CRC32RFC1510, and name of CRC24-RFC2440 to CRC24RFC2440.
+
+2003-09-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add prototype for gpgme_set_locale.
+
+ * gpgme.h: Define macro _GPGME_INLINE depending on the compiler
+ characteristics and use that instead __inline__.
+
+ * context.h (struct gpgme_context): New members lc_ctype and
+ lc_messages.
+ * gpgme.c: Include <locale.h>.
+ (def_lc_lock, def_lc_ctype, def_lc_messages): New static
+ variables.
+ (gpgme_set_locale): New function.
+ * engine.c (_gpgme_engine_new): Add arguments lc_ctype and
+ lc_messages.
+ * engine.h (_gpgme_engine_new): Likewise.
+ * engine-gpgsm.c (gpgsm_new): Likewise.
+ * rungpg.c (gpg_new): Likewise.
+ * engine-backend.h (struct engine_ops): Likewise to NEW.
+ * op-support.c (_gpgme_op_reset): Likewise to invocation of
+ _gpgme_engine_new.
+
+2003-09-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_strerror_r): New prototype.
+ * error.c (gpgme_strerror_r): New function.
+
+ * get-env.c: New file.
+ * util.h (_gpgme_getenv): Add prototype.
+ * Makefile.am (libgpgme_real_la_SOURCES): Add get-env.c.
+ * rungpg.c (build_argv): Use _gpgme_getenv.
+ * debug.c (debug_init): Likewise.
+ * engine-gpgsm.c (gpgsm_new): Likewise.
+ (gpgsm_new): Use ttyname_r.
+ * w32-io.c (_gpgme_io_spawn): Disable debugging for now.
+
+2003-09-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in: Use $libdir, not @libdir@, for the echo
+ command.
+
+ * gpgme-config.in: Rewritten.
+ * gpgme.m4: Rewritten.
+
+2003-08-19 Marcus Brinkmann <marcus@g10code.de>
+
+ The ath files (ath.h, ath.c, ath-pth.c, ath-pthread.c,
+ ath-compat.c, ath-pth-compat.c and ath-pthread-compat.c) have been
+ updated to have better thread support, and the Makefile.am was
+ changed to reflect that.
+
+ * util.h [!HAVE_FOPENCOOKIE]: Remove fopencookie declaration.
+ * engine-gpgsm.c (gpgsm_assuan_simple_command): Set ERR to return
+ value of status_fnc.
+ * rungpg.c (start): Return SAVED_ERRNO, not errno.
+
+2003-08-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (start): Use saved_errno instead errno.
+
+2003-08-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * funopen.c, putc_unlocked.c, isascii.c, memrchr.c: New files.
+ * fopencookie.c: File removed.
+
+2003-08-15 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in: Put gpg-error related flags after gpgme's.
+
+2003-08-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_new_signature): Rename member CLASS to
+ _OBSOLETE_CLASS, add member CLASS with type unsigned int.
+ * sign.c (parse_sig_created): Also set SIG->_unused_class for
+ backward compatibility.
+
+2003-08-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (parse_new_sig): Fix status parsing case.
+
+2003-07-31 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_subkey): Add flag CAN_AUTHENTICATE.
+ Lower _UNUSED to 23 bits.
+ (struct _gpgme_key): Likewise.
+ * keylist.c (set_mainkey_capability): Support 'a' and 'A'.
+ (set_subkey_capability): Support 'a'.
+
+ * keylist.c (gpgme_get_key): Check if there is more than one key
+ listed, and return GPG_ERR_AMBIGUOUS_NAME in that case.
+
+ * util.h (_gpgme_decode_c_string): Change type of LEN argument to
+ size_t.
+ (_gpgme_decode_percent_string): Likewise.
+ * conversion.c (_gpgme_decode_c_string): Likewise.
+ (_gpgme_decode_percent_string): Likewise.
+ (_gpgme_map_gnupg_error): Change type of I to unsigned int.
+ * signers.c (gpgme_signers_clear): Likewise.
+ (gpgme_signers_enum): New unsigned variable SEQNO, set to SEQ.
+ Use SEQNO instead SEQ.
+ * wait.c (fd_table_put): Change type of I and J to unsigned int.
+ * wait-global.c (_gpgme_wait_global_event_cb): Change type of IDX
+ to unsigned int.
+ (gpgme_wait): Change type of I and IDX to unsigned int.
+ * wait-private.c (_gpgme_wait_on_condition): Change type of IDX
+ and I to unsigned int.
+ * posix-io.c (_gpgme_io_close): Cast return value of macro DIM to
+ int to suppress gcc warning.
+ (_gpgme_io_set_close_notify): Likewise.
+ (_gpgme_io_select): Change type of I to unsigned int.
+ * engine.c (gpgme_get_engine_info): Change type of PROTO to
+ unsigned int.
+ * wait-user.c (_gpgme_user_io_cb_handler): Change type of IDX and
+ I to unsigned int.
+
+2003-07-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * decrypt-verify.c (decrypt_verify_status_handler): Expand silly
+ and wrong expression.
+ * encrypt-sign.c (encrypt_sign_status_handler): Likewise.
+ * encrypt.c (encrypt_sym_status_handler): Likewise.
+ * sign.c (sign_status_handler): Likewise.
+ * verify.c (verify_status_handler): Likewise.
+ * decrypt.c (decrypt_status_handler): Likewise.
+
+ * engine.c (gpgme_get_engine_info): Initialize NULL.
+
+2003-07-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme-config.in (gpg_error_libs): Quote GPG_ERROR_CFLAGS and
+ GPG_ERROR_LIBS when setting the corresponding variables.
+ Reported by Stéphane Corthésy.
+
+2003-07-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (set_recipients): Move declaration of NEWLEN to
+ the beginning of the block.
+
+2003-06-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-mem.c (mem_write): Copy original buffer content.
+
+2003-06-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_user_ids_release, gpgme_user_ids_append): Remove
+ prototypes.
+
+2003-06-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (AM_CPPFLAGS): Add @GPG_ERROR_CFLAGS@.
+ * gpgme-config.in (gpg_error_libs, gpg_error_cflags): New variables.
+ Print them.
+
+ * op-support.c (_gpgme_parse_inv_userid): Rename to
+ _gpgme_parse_inv_recp and change to new datatype.
+ * ops.h (_gpgme_parse_inv_key): Fix prototype.
+ * gpgme.h (struct _gpgme_invalid_user_id): Rename to
+ __gpgme_invalid_key. Rename field ID to KEY.
+ (gpgme_invalid_user_id_t): Rename to gpgme_invalid_key_t.
+ (struct _gpgme_op_encrypt_result): Here, too.
+ (struct _gpgme_op_sign_result): Likewise.
+ * encrypt.c (struct op_data): Likewise.
+ (release_op_data): Likewise.
+ * sign.c (struct op_data): Likewise.
+ (release_op_data): Likewise.
+
+ * posix-io.c (_gpgme_io_read): Save errno across debug calls.
+ (_gpgme_io_write): Likewise.
+ (_gpgme_io_pipe): Likewise.
+ (_gpgme_io_select): Likewise.
+
+ * rungpg.c (struct engine_gpg): Remove arg_error.
+ (add_arg): Don't set arg_error.
+ (add_data): Likewise.
+ (start): Don't check arg_error.
+ (gpg_new): Check return value of add_arg.
+ * verify.c (parse_notation): Free allocated memory at error.
+
+2003-06-05 Marcus Brinkmann <marcus@g10code.de>
+
+ Everywhere: Use libgpg-error error codes.
+
+ * Makefile.am (EXTRA_DIST): Remove mkerrors.
+ (BUILT_SOURCES): Remove errors.c.
+ (MOSTLYCLEANFILES): Likewise.
+ (libgpgme_la_SOURCES): Likewise. Add error.c.
+ (errors.c): Remove target.
+ * mkerrors: File removed.
+ * error.c: New file.
+
+ * gpgme.h (gpgme_error_t): Change to type gpg_error_t.
+ (gpgme_err_code_t, gpgme_err_source_t): New types.
+ (gpgme_err_code, gpgme_err_source, gpgme_error, gpgme_err_make):
+ New static inline functions.
+ (gpgme_strsource, gpgme_err_code_from_errno,
+ gpgme_err_code_to_errno, gpgme_err_make_from_errno,
+ gpgme_error_from_errno): New prototypes.
+
+2003-05-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_op_export_start): Change second arg to const char *.
+ (gpgme_op_export): Likewise.
+ (gpgme_op_export_ext_start): New prototype.
+ (gpgme_op_export_ext): Likewise.
+ * engine.h: Likewise for _gpgme_engine_op_export and
+ _gpgme_engine_op_export_ext.
+ * engine-backend.h (struct engine_ops): Change second argument of
+ prototype of export to const char *, and add reserverd int as
+ third argument. Add prototype for export_ext.
+ * engine.c (_gpgme_engine_op_export_ext): New function.
+ (_gpgme_engine_op_export): Change second argument of prototype of
+ export to const char *, and add reserverd int as third argument.
+ * rungpg.c (gpg_export): Change second argument of prototype of
+ export to const char *, and add reserverd int as third argument.
+ (gpg_export_ext): New function.
+ (gpg_keylist_ext): Break loop at error.
+ (_gpgme_engine_ops_gpg): Add gpg_export_ext.
+ * engine-gpgsm.c (gpgsm_export): Change second argument of
+ prototype of export to const char *, and add reserverd int as
+ third argument.
+ (gpgsm_export_ext): New function.
+ (_gpgme_engine_ops_gpgsm): Add gpgsm_export_ext.
+ * export.c (export_start): Change second argument of prototype of
+ export to const char *, and add reserverd int as third argument.
+ (gpgme_op_export_start): Likewise.
+ (export_ext_start): New function.
+ (gpgme_op_export_ext_start): Likewise.
+ (gpgme_op_export_ext): Likewise.
+
+ * gpgme.h (gpgme_keylist_mode_t): New type for anonymous enum.
+ (gpgme_sigsum_t): New type for anonymous enum.
+
+ * encrypt-sign.c (encrypt_sign_start): Check for errors earlier,
+ and return an error if RECP is not set.
+
+ * Makefile.am (libgpgme_la_SOURCES): Remove user-id.c.
+ * user-id.c: Remove file.
+ * ops.h: Remove prototype for _gpgme_user_ids_all_valid.
+ * gpgme.h (gpgme_encrypt_flags_t): New type.
+ (gpgme_op_encrypt_start): Change second parameter to type
+ gpgme_key_t[], and add third parameter.
+ (gpgme_op_encrypt): Likewise.
+ (gpgme_op_encrypt_sign_start): Likewise.
+ (gpgme_op_encrypt_sign): Likewise.
+ * encrypt.c (encrypt_start): Likewise.
+ (gpgme_op_encrypt_start): Likewise.
+ (gpgme_op_encrypt): Likewise. Pass flags to engine.
+ * encrypt-sign.c (encrypt_sign_start): Likewise.
+ (gpgme_op_encrypt_sign_start): Likewise.
+ (gpgme_op_encrypt_sign): Likewise.
+ * engine-backend.h (struct engine_ops): Likewise for prototypes of
+ encrypt and encrypt_sign.
+ * engine.h: Likewise for prototypes of _gpgme_engine_op_encrypt
+ and _gpgme_engine_op_encrypt_sign.
+ * engine.c (_gpgme_engine_op_encrypt): Likewise.
+ (_gpgme_engine_op_encrypt_sign): Likewise.
+ * rungpg.c (gpg_encrypt): Likewise.
+ (gpg_encrypt_sign): Likewise.
+ * rungpg.c (gpg_encrypt): Check flags for always trust option.
+ * engine-gpgsm.c (gpgsm_encrypt): Likewise.
+ (set_recipients): Rewritten to use keys instead user IDs.
+ * rungpg.c (append_args_from_recipients): Rewritten to use keys
+ instead user IDs.
+ * encrypt.c (_gpgme_encrypt_status_handler): Change errors
+ returned to GPGME_Invalid_Key and GPGME_General_Error.
+
+2003-05-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c: Rename GpgsmObject to engine_gpgsm_t.
+ (struct gpgsm_object_s): Rename to struct engine_gpgsm.
+ * rungpg.c: Rename GpgObject to engine_gpg_t.
+ (struct gpg_object_s): Rename to struct engine_gpg.
+
+ * context.h (struct gpgme_context): Change EngineObject to
+ engine_object_t.
+ (enum ctx_op_data_type): Rename to ctx_op_data_id_t.
+ (ctx_op_data_t): New type.
+ (struct gpgme_context): Use it.
+ * ops.h (_gpgme_op_data_lookup): Use new type name.
+ * op-support.c (_gpgme_op_data_lookup): Likewise.
+ * engine.c: Rename EngineObject to engine_t in the file. Also
+ EngineStatusHandler to engine_status_handler_t,
+ EngineCommandHandler to engine_command_handler_t and
+ EngineColonLineHandler to engine_colon_line_handler.
+ * rungpg.c (start): Likewise.
+ * engine-gpgsm.c: Likewise.
+ * engine-backend.h (struct engine_ops): Likewise
+ * engine.h (struct engine_object_s): Rename to struct engine.
+ (EngineObject): Rename to engine_t. Also everywhere else in the
+ file.
+ (EngineStatusHandler): Rename to engine_status_handler_t.
+ (EngineColonLineHandler): Rename to engine_colon_line_handler_t.
+ (EngineCommandHandler): Rename to engine_command_handler_t.
+
+ * engine-gpgsm.c (gpgsm_export): Fix bug in last change.
+
+ * Makefile.am (libgpgme_la_SOURCES): Remove recipient.c, add
+ user-id.c.
+ * gpgme.h (gpgme_recipients_t): Removed.
+ (gpgme_recipients_new, gpgme_recipients_release,
+ gpgme_recipients_add_name,
+ gpgme_recipients_add_name_with_validity, gpgme_recipients_count,
+ gpgme_recipients_enum_open, gpgme_recipients_enum_read,
+ gpgme_recipients_enum_close): Removed.
+ (gpgme_op_encrypt, gpgme_op_encrypt_start, gpgme_op_encrypt_sign,
+ gpgme_op_encrypt_sign_start, gpgme_op_export_start,
+ gpgme_op_export): Change second argument to gpgme_user_id_t.
+ (gpgme_user_ids_release): New prototype.
+ (gpgme_user_ids_append): Likewise.
+ * ops.h (_gpgme_recipients_all_valid): Remove.
+ (_gpgme_user_ids_all_valid): Add.
+ * context.h (struct gpgme_recipients): Removed.
+ * user-id.c: New file.
+ * recipient.c: Removed file.
+ * rungpg.c (append_args_from_recipients): Change last arg to
+ gpgme_user_id_t. Reimplement.
+ (gpg_encrypt): Change second arg to gpgme_user_id_t.
+ (gpg_encrypt_sign): Likewise.
+ (gpg_export): Likewise. Rewrite user ID list code.
+ * engine.c (_gpgme_engine_op_encrypt): Change second arg to
+ gpgme_user_id_t.
+ (_gpgme_engine_op_encrypt_sign): Likewise.
+ (_gpgme_engine_op_export): Likewise.
+ * engine.h (_gpgme_engine_op_encrypt, _gpgme_engine_op_encrypt_sign,
+ _gpgme_engine_op_export): Likewise.
+ * engine-gpgsm.c (set_recipients): Likewise. Rewrite loop code.
+ (gpgsm_encrypt): Likewise.
+ (gpgsm_export): Likewise.
+ * engine-backend.h (struct engine_ops): Likewise for members
+ ENCRYPT, ENCRYPT_SIGN and EXPORT.
+ * export.c (export_start, gpgme_op_export_start, gpgme_op_export):
+ Likewise.
+ * encrypt.c (encrypt_start): Likewise. Don't check for count of
+ recipients.
+ (gpgme_op_encrypt_start): Likewise.
+ (gpgme_op_encrypt): Likewise.
+ * encrypt-sign.c (encrypt_sign_start): Likewise.
+ (gpgme_op_encrypt_sign): Likewise.
+ (gpgme_op_encrypt_sign_start): Likewise.
+
+2003-05-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_op_import_result): Add skipped_new_keys.
+ * import.c (parse_import_res): Add skipped_new_keys parser.
+
+ * op-support.c (_gpgme_parse_inv_userid): Add missing break
+ statements.
+ * encrypt.c (gpgme_op_encrypt): Use gpgme_error_t instead of int.
+
+2003-05-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * encrypt.c (gpgme_op_encrypt_result): Use intermediate variable
+ HOOK to avoid compiler warning. Don't ask, you don't want to know.
+ (_gpgme_encrypt_status_handler): Likewise.
+ (_gpgme_op_encrypt_init_result): Likewise.
+ * decrypt.c (gpgme_op_decrypt_result): Likewise.
+ (_gpgme_decrypt_status_handler): Likewise.
+ (_gpgme_op_decrypt_init_result): Likewise.
+ * verify.c (gpgme_op_verify_result): Likewise.
+ (_gpgme_verify_status_handler): Likewise.
+ (_gpgme_op_verify_init_result): Likewise.
+ * edit.c (edit_status_handler): Likewise.
+ (command_handler): Likewise.
+ (edit_start): Likewise.
+ * genkey.c (gpgme_op_genkey_result): Likewise.
+ (genkey_status_handler): Likewise.
+ (genkey_start): Likewise.
+ * import.c (gpgme_op_import_result): Likewise.
+ (import_status_handler): Likewise.
+ (_gpgme_op_import_start): Likewise.
+ * trustlist.c (gpgme_op_trustlist_next): Likewise.
+ (_gpgme_op_trustlist_event_cb): Likewise.
+ (gpgme_op_trustlist_start): Likewise.
+ * keylist.c (gpgme_op_keylist_result): Likewise.
+ (keylist_colon_handler): Likewise.
+ (keylist_status_handler): Likewise.
+ (_gpgme_op_keylist_event_cb): Likewise.
+ (gpgme_op_keylist_start): Likewise.
+ (gpgme_op_keylist_ext_start): Likewise.
+ (gpgme_op_keylist_next): Likewise.
+ * passphrase.c (_gpgme_passphrase_status_handler): Likewise.
+ (_gpgme_passphrase_command_handler_internal): Likewise.
+ * sign.c (gpgme_op_sign_result): Likewise.
+ (_gpgme_sign_status_handler): Likewise.
+ (_gpgme_op_sign_init_result): Likewise.
+
+ * passphrase.c (_gpgme_passphrase_command_handler_internal): Fix
+ access to pointer type.
+
+2003-05-26 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.h (EngineCommandHandler): Change last argument to int fd.
+ * gpgme.h (gpgme_passphrase_cb_t): Rewritten to take parts of the
+ description and fd.
+ (gpgme_edit_cb_t): Change last argument to int fd.
+ * ops.h (_gpgme_passphrase_command_handler_internal): New prototype.
+ * passphrase.c: Include <assert.h>.
+ (op_data_t): Rename userid_hint to uid_hint, remove last_pw_handle.
+ (release_op_data): Check values before calling free.
+ (_gpgme_passphrase_status_handler): Likewise.
+ (_gpgme_passphrase_command_handler_internal): New function.
+ (_gpgme_passphrase_command_handler): Rewritten.
+ * edit.c (edit_status_handler): Pass -1 as fd argument.
+ (command_handler): Update prototype. New variable processed. Use
+ it to store return value of
+ _gpgme_passphrase_command_handler_internal which is now used
+ instead _gpgme_passphrase_command_handler. Use it also to check
+ if we should call the user's edit function. Pass fd to user's
+ edit function.
+ * rungpg.c (struct gpg_object_s): Change type of cmd.cb_data to
+ void *.
+ (gpg_release): Check value before calling free. Do not release
+ cmd.cb_data.
+ (command_cb): Function removed.
+ (command_handler): New function. Thus we don't use a data object
+ for command handler stuff anymore, but handle it directly. This
+ allows proper error reporting (cancel of passphrase requests, for
+ example). Also all callbacks work via direct writes to the file
+ descriptor (so that passphrases are not kept in insecure memory).
+ (gpg_set_command_handler): Rewritten to use even more ugly hacks.
+ (read_status): Check cmd.keyword before calling free. Install
+ command_handler as the I/O callback handler with GPG as private
+ data.
+
+ * rungpg.c (gpg_new): Add --enable-progress-filter to gpg
+ invocation.
+ * decrypt-verify.c (_gpgme_op_decrypt_verify_start): Rename to
+ decrypt_verify_start.
+ (gpgme_op_decrypt_verify_start): Call decrypt_verify_start.
+ (gpgme_op_decrypt_verify): Likewise.
+ * verify.c (verify_status_handler): New function that also calls
+ progress status handler.
+ (_gpgme_op_verify_start): Set status handler to verify_status_handler.
+ Rename to (verify_start).
+ (gpgme_op_verify_start): Call verify_start.
+ (gpgme_op_verify): Likewise.
+ * encrypt.c (encrypt_status_handler): New function.
+ (_gpgme_encrypt_sym_status_handler): Call progress status handler.
+ Make static. Rename to encrypt_sym_status_handler.
+ (encrypt_start): Set status handler to encrypt_sym_status_handler
+ or encrypt_status_handler.
+ * sign.c (sign_status_handler): New function.
+ (sign_start): Set status handler to sign_status_handler.
+ * decrypt.c (decrypt_status_handler): New function that also calls
+ progress status handler.
+ (decrypt_start): Set status handler to decrypt_status_handler.
+ * encrypt-sign.c (encrypt_sign_status_handler): Likewise.
+ * decrypt-verify.c (decrypt_verify_status_handler): Call
+ _gpgme_progress_status_handler.
+
+ * conversion.c (_gpgme_decode_c_string): Add missing break
+ statement.
+
+ * recipient.c (gpgme_recipients_add_name_with_validity): Add one
+ to buffer to allocate.
+
+2003-05-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (parse_new_sig): Fix ERRSIG case.
+ Submitted by Benjamin Lee <benjaminlee@users.sf.net>.
+
+2003-05-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: The following types are renamed. The old name is kept
+ as a deprecated typedef.
+ (GpgmeCtx): Rename to gpgme_ctx_t.
+ (GpgmeData): Rename to gpgme_data_t.
+ (GpgmeRecipients): Rename to gpgme_recipients_t.
+ (GpgmeError): Rename to gpgme_error_t.
+ (GpgmeDataEncoding): Rename to gpgme_data_encoding_t.
+ (GpgmePubKeyAlgo): Rename to gpgme_pubkey_algo_t.
+ (GpgmeHashAlgo): Rename to gpgme_hash_algo_t.
+ (GpgmeSigStat): Rename to gpgme_sig_stat_t.
+ (GpgmeSigMode): Rename to gpgme_sig_mode_t.
+ (GpgmeAttr): Rename to gpgme_attr_t.
+ (GpgmeValidity): Rename to gpgme_validity_t.
+ (GpgmeProtocol): Rename to gpgme_protocol_t.
+ (GpgmeStatusCode): Rename to gpgme_status_code_t.
+ (GpgmeEngineInfo): Rename to gpgme_engine_info_t.
+ (GpgmeSubkey): Rename to gpgme_subkey_t.
+ (GpgmeKeySig): Rename to gpgme_keysig_t.
+ (GpgmeUserID): Rename to gpgme_user_id_t.
+ (GpgmePassphraseCb): Rename to gpgme_passphrase_cb_t.
+ (GpgmeProgressCb): Rename to gpgme_progress_cb_t.
+ (GpgmeEditCb): Rename to gpgme_edit_cb_t.
+ (GpgmeIOCb): Rename to gpgme_io_cb_t.
+ (GpgmeRegisterIOCb): Rename to gpgme_register_io_cb_t.
+ (GpgmeRemoveIOCb): Rename to gpgme_remove_io_cb_t.
+ (GpgmeEventIO): Rename to gpgme_event_io_t.
+ (GpgmeEventIOCb): Rename to gpgme_event_io_cb_t.
+ (GpgmeIOCbs): Rename to gpgme_io_cbs.
+ (gpgme_io_cbs_t): New type.
+ (GpgmeDataReadCb): Rename to gpgme_data_read_cb_t.
+ (GpgmeDataWriteCb): Rename to gpgme_data_write_cb_t.
+ (GpgmeDataSeekCb): Rename to gpgme_data_seek_cb_t.
+ (GpgmeDataReleaseCb): Rename to gpgme_data_release_cb_t.
+ (GpgmeDataCbs): Rename to gpgme_data_cbs.
+ (gpgme_data_cbs_t): New type.
+ (GpgmeInvalidUserID): Rename to gpgme_invalid_user_id_t.
+ (GpgmeEncryptResult): Rename to gpgme_encrypt_result_t.
+ (GpgmeDecryptResult): Rename to gpgme_decrypt_result_t.
+ (GpgmeNewSignature): Rename to gpgme_new_signature_t.
+ (GpgmeSignResult): Rename to gpgme_sign_result_t.
+ (GpgmeSigNotation): Rename to gpgme_sig_notation_t.
+ (GpgmeSignature): Rename to gpgme_signature_t.
+ (GpgmeVerifyResult): Rename to gpgme_verify_result_t.
+ (GpgmeImporttqStatus): Rename to gpgme_import_status_t.
+ (GpgmeImportResult): Rename to gpgme_import_result_t.
+ (GpgmeGenKeyResult): Rename to gpgme_genkey_result_t.
+ (GpgmeKeyListResult): Rename to gpgme_keylist_result_t.
+ (GpgmeTrustItem): Rename to gpgme_trust_item_t.
+ * gpgme.h (gpgme_deprecated_error_t): New type, swallowing macros
+ GPGME_No_Recipients, GPGME_Invalid_Recipient and
+ GPGME_No_Passphrase.
+ * data.h (struct gpgme_data_s): Rename to struct gpgme_data.
+ * context.h (struct gpgme_context_s): Rename to struct
+ gpgme_context.
+ (struct gpgme_recipients_s): Rename to gpgme_recipients.
+
+2003-05-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (finish_key): Clear OPD->tmp_uid.
+
+2003-05-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (_gpgme_verify_status_handler): Return GPGME_No_Data
+ for NODATA status without signatures.
+
+2003-05-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * key.c (_gpgme_key_append_name): Use decoded string to parse user id.
+ (_gpgme_key_add_sig): Likewise.
+
+2003-05-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * context.h (struct gpgme_context_s): Remove member op_info.
+
+ * key.c (_gpgme_key_add_sig): Initialize SIG->uid.
+
+ * gpgme.h (GpgmeError): Add deprecated values for
+ GPGME_Invalid_Type and GPGME_Invalid_Mode.
+
+2003-04-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_get_op_info): Remove prototype.
+ * ops.h (_gpgme_set_op_info,
+ _gpgme_data_release_and_return_string, _gpgme_data_get_as_string,
+ _gpgme_data_append, _gpgme_data_append_string,
+ _gpgme_data_append_string_for_xml, _gpgme_data_append_for_xml,
+ _gpgme_data_append_percentstring_for_xml): Likewise.
+ (_gpgme_progress_status_handler): Change first arg to void *.
+ * progress.c (_gpgme_progress_status_handler): Likewise.
+ * conversion.c: Do not include <string.h>, <errno.h>, <ctype.h>,
+ and <sys/types.h>, but <string.h>.
+ (_gpgme_data_append): Remove function.
+ (_gpgme_data_append_string): Likewise.
+ (_gpgme_data_append_for_xml): Likewise.
+ (_gpgme_data_append_string_for_xml): Likewise.
+ (_gpgme_data_append_percentstring_for_xml): Likewise.
+ * data-mem.c (_gpgme_data_get_as_string): Likewise.
+ (_gpgme_data_release_and_return_string): Likewise.
+ * gpgme.c (gpgme_get_op_info): Likewise.
+ (_gpgme_set_op_info): Likewise.
+
+ * gpgme.h (struct _gpgme_key): New structure.
+ (GpgmeKey): Define using _gpgme_key.
+ (struct _gpgme_subkey): New structure.
+ (GpgmeSubKey): New type.
+ (struct _gpgme_key_sig): New structure.
+ (GpgmeKeySig): New type.
+ (struct _gpgme_user_id): New structure.
+ (GpgmeUserID): New type.
+ (struct _gpgme_op_keylist_result): New structure.
+ (GpgmeKeyListResult): New type.
+ (gpgme_op_keylist_result): New function.
+ (gpgme_key_get_as_xml): Remove prototype.
+ * context.h (struct gpgme_context_s): Remove members tmp_key,
+ tmp_uid, key_cond and key_queue.
+ (struct key_queue_item_s): Remove structure.
+ (struct user_id_s): Remove structure.
+ (struct gpgme_recipients_s): Replace with simple
+ GpgmeUserID list.
+ * gpgme.c (gpgme_release): Do not release CTX->tmp_key.
+ * ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name,
+ _gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes.
+ * rungpg.c (command_cb): Return GpgmeError instead int.
+ New variable ERR. Use it to hold return value of cmd handler.
+ (gpg_delete): Access fingerprint of key directly.
+ (append_args_from_signers): Likewise.
+ (gpg_edit): Likewise.
+ (append_args_from_recipients): Use GpgmeUserID for recipient list.
+ * engine-gpgsm.c: Do not include "key.h".
+ (gpgsm_delete): Access fingerprint of key directly.
+ (gpgsm_sign): Likewise.
+ (set_recipients): Use GpgmeUserID for recipients. Invert invalid
+ user ID flag.
+ * key.h: File removed.
+ * key.c: Completely reworked to use exposed GpgmeKey data types.
+ * keylist.c: Likewise.
+ * recipient.c: Completely reworked to use GpgmeUserID.
+
+2003-04-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_get_key): Remove force_update argument.
+ * key-cache.c: File removed.
+ * Makefile.am (libgpgme_la_SOURCES): Remove key-cache.c.
+ * ops.h (_gpgme_key_cache_add, _gpgme_key_cache_get): Remove
+ prototypes.
+ * keylist.c (_gpgme_op_keylist_event_cb): Don't call
+ _gpgme_key_cache_add.
+ (gpgme_get_key): New function.
+ * verify.c (gpgme_get_sig_key): Remove last argument to
+ gpgme_get_key invocation.
+
+ * gpgme.h (struct _gpgme_trust_item): New structure.
+ (GpgmeTrustItem): New type.
+ (gpgme_trust_item_ref, gpgme_trust_item_unref): New prototypes.
+ * context.h (struct trust_queue_item_s): Remove structure.
+ (struct gpgme_context_s): Remove trust_queue member.
+ * Makefile.am (libgpgme_la_SOURCES): Add trust-item.c.
+ * trust-item.c: New file.
+ * trustlist.c: Do not include <stdio.h> or <time.h>, but
+ "gpgme.h".
+ (struct trust_queue_item_s): Change to new type op_data_t.
+ (trust_status_handler): Change first argument to void *.
+ (trust_colon_handler): Likewise.
+ (_gpgme_op_trustlist_event_cb): Use op_data_t type.
+ (gpgme_op_trustlist_start): Use op_data_t and rework error
+ handling.
+ (gpgme_op_trustlist_next): Use op_data_t.
+ (gpgme_trust_item_release): Remove function.
+ (gpgme_trust_item_get_string_attr): Likewise.
+ (gpgme_trust_item_get_int_attr): Likewise.
+
+ * verify.c (calc_sig_summary): Do not set GPGME_SIGSUM_SYS_ERROR
+ for bad signatures.
+
+2003-04-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * context.h: Remove OPDATA_VERIFY_COLLECTING.
+ (struct gpgme_context_s): Remove member notation.
+ * gpgme.h: Make enum for GPGME_KEYLIST_MODE_* values.
+
+ * gpgme.h (struct _gpgme_sig_notation): New structure.
+ (GpgmeSigNotation): New type.
+ (struct _gpgme_signature): New structure.
+ (GpgmeSignature): New type.
+ (struct _gpgme_op_verify_result): New structure.
+ (GpgmeVerifyResult): New type.
+ (gpgme_op_verify_result): New prototype.
+ (gpgme_get_notation): Remove prototype.
+ * ops.h (_gpgme_op_verify_init_result): New prototype.
+ (_gpgme_verify_status_handler): Change first argument to void *.
+ * util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error):
+ New prototypes.
+ * conversion.c (_gpgme_decode_percent_string): New function.
+ (gnupg_errors): New static global.
+ (_gpgme_map_gnupg_error): New function.
+ * gpgme.c (gpgme_release): Don't release CTX->notation.
+ (gpgme_get_notation): Remove function.
+ * decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call
+ _gpgme_op_verify_init_result.
+ * verify.c: Do not include <stdio.h>, <assert.h> and "key.h", but
+ do include "gpgme.h".
+ (struct verify_result): Replace with ...
+ (op_data_t): ... this type.
+ (release_verify_result): Remove function.
+ (release_op_data): New function.
+ (is_token): Remove function.
+ (skip_token): Remove function.
+ (copy_token): Remove function.
+ (gpgme_op_verify_result): New function.
+ (calc_sig_summary): Rewritten.
+ (finish_sig): Remove function.
+ (parse_new_sig): New function.
+ (parse_valid_sig): New function.
+ (parse_notation): New function.
+ (parse_trust): New function.
+ (parse_error): New function.
+ (_gpgme_verify_status_handler): Rewritten. Change first argument
+ to void *.
+ (_gpgme_op_verify_start): Rework error handling. Call
+ _gpgme_op_verify_init_result.
+ (gpgme_op_verify): Do not release or clear CTX->notation.
+ (gpgme_get_sig_status): Rewritten.
+ (gpgme_get_sig_string_attr): Likewise.
+ (gpgme_get_sig_ulong_attr): Likewise.
+ (gpgme_get_sig_key): Likewise.
+
+ * gpgme.h (struct _gpgme_op_decrypt_result): New structure.
+ (GpgmeDecryptResult): New type.
+ (gpgme_op_decrypt_result): New prototype.
+ * ops.h (_gpgme_op_decrypt_init_result): New prototype.
+ (_gpgme_decrypt_status_handler): Fix prototype.
+ (_gpgme_decrypt_start): Remove prototype.
+ * decrypt-verify.c: Do not include <stdio.h>, <stdlib.h>,
+ <string.h> and <assert.h>, "util.h" and "context.h", but
+ "gpgme.h".
+ (decrypt_verify_status_handler): Change first argument to void *,
+ and rework error handling.
+ (_gpgme_op_decrypt_verify_start): New function.
+ (gpgme_op_decrypt_verify_start): Rewrite using
+ _gpgme_op_decrypt_verify_start.
+ (gpgme_op_decrypt_verify): Likewise.
+ * decrypt.c: Include <string.h>, "gpgme.h" and "util.h".
+ (struct decrypt_result): Change to typedef op_data_t, rewritten.
+ (is_token): Remove function.
+ (release_op_data): New function.
+ (skip_token): Remove function.
+ (gpgme_op_decrypt_result): New function.
+ (_gpgme_decrypt_status_handler): Change first argument to void *.
+ Rework error handling.
+ (_gpgme_decrypt_start): Rename to ...
+ (decrypt_start): ... this. Call _gpgme_op_decrypt_init_result.
+ (_gpgme_op_decrypt_init_result): New function.
+ (gpgme_op_decrypt_start): Use decrypt_start.
+ (gpgme_op_decrypt): Likewise.
+
+2003-04-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * encrypt-sign.c: Do not include <stddef.h>, <stdio.h>,
+ <stdlib.h>, <string.h>, <assert.h> and "util.h", but "gpgme.h".
+ (_gpgme_op_encrypt_sign_start): Rename to ...
+ (encrypt_sign_start): ... this.
+ (gpgme_op_encrypt_sign_start): Use encrypt_sign_start, not
+ _gpgme_op_encrypt_sign_start.
+ (gpgme_op_encrypt_sign): Likewise.
+
+ * gpgme.h (GpgmeEncryptResult): New data type.
+ (gpgme_op_encrypt_result): New prototype.
+ * ops.h (_gpgme_op_encrypt_init_result): New prototype.
+ (_gpgme_op_encrypt_status_handler): Fix prototype.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Call
+ _gpgme_op_encrypt_init_result.
+ * encrypt.c: Do not include <stdio.h>, <assert.h>, "util.h" and
+ "wait.h". Include <errno.h> and "gpgme.h".
+ (SKIP_TOKEN_OR_RETURN): Remove macro.
+ (struct encrypt_result): Rename to ...
+ (op_data_t): ... new data type. Rewrite for user result data.
+ (append_xml_encinfo): Remove function.
+ (release_op_data): New function.
+ (gpgme_op_encrypt_result): New function.
+ (_gpgme_op_encrypt_status_handler): Change first argument to void *.
+ Rewrite result parsing.
+ (_gpgme_op_encrypt_sym_status_handler): Change first argument to
+ void *.
+ (_gpgme_op_encrypt_init_result): New function.
+ (_gpgme_op_encrypt_start): Rename to ...
+ (encrypt_start): ... this.
+ (gpgme_op_encrypt_start): Use encrypt_start, not
+ gpgme_op_encrypt_start.
+ (gpgme_op_encrypt): Likewise.
+
+ * gpgme.h (GpgmePubKeyAlgo, GpgmeHashAlgo, GpgmeInvalidUserID,
+ GpgmeNewSignature, GpgmeSignResult): New data types.
+ (gpgme_op_sign_result, gpgme_pubkey_algo_name,
+ gpgme_hash_algo_name): New prototypes.
+ * gpgme.c (gpgme_pubkey_algo_name): New function.
+ (gpgme_hash_algo_name): Likewise.
+ * ops.h (_gpgme_parse_inv_userid, _gpgme_op_sign_init_result): New
+ prototype.
+ (_gpgme_op_sign_status_handler): Fix prototype.
+ * op-support.c: Include <errno.h> and <string.h>.
+ (_gpgme_parse_inv_userid): New function.
+ * sign.c: Include <errno.h> and "gpgme.h", but not <stdio.h>,
+ <assert.h> and "util.h".
+ (SKIP_TOKEN_OR_RETURN): Remove macro.
+ (struct sign_result): Change to op_data_t type and rework it.
+ (release_sign_result): Rename to ...
+ (release_op_data): ... this and rewrite it.
+ (append_xml_info): Remove function.
+ (gpgme_op_sign_result): New function.
+ (parse_sig_created): New function.
+ (_gpgme_sign_status_handler): Change first argument to void *.
+ Rewrite the function to use the new result structure and functions.
+ (_gpgme_op_sign_init_result): New function.
+ (_gpgme_op_sign_start): Rename to ...
+ (sign_start): ... this. Call _gpgme_op_sign_init_result.
+ (gpgme_op_sign_start): Use sign_start instead _gpgme_op_sign_start.
+ (gpgme_op_sign): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Call
+ _gpgme_op_sign_init_result.
+
+ * delete.c: Include <errno.h> and "gpgme.h", but not "util.h" or
+ "key.h".
+ (enum delete_problem): Move into function delete_status_handler.
+ (delete_status_handler): Change first argument to void *. Parse
+ delete problem with strtol instead atoi. Return better error
+ values.
+ (_gpgme_op_delete_start): Rename to ...
+ (delete_start): ... this. Rework error handling.
+ (gpgme_op_delete_start): Use delete_start instead
+ _gpgme_op_delete_start.
+ (gpgme_op_delete): Likewise.
+ * gpgme.h (GpgmeDataType): Removed.
+
+2003-04-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Change GPGME_IMPORT_PRIVATE to GPGME_IMPORT_SECRET.
+ * import.c (parse_import_res): Parse unchanged field.
+
+ * gpgme.h: New enum for GPGME_IMPORT_NEW, GPGME_IMPORT_UID,
+ GPGME_IMPORT_SIG, GPGME_IMPORT_SUBKEY, GPGME_IMPORT_PRIVATE.
+ (GpgmeError): GPGME_Unknown_Reason, GPGME_Not_Found,
+ GPGME_Ambiguous_Specification, GPGME_Wrong_Key_Usage,
+ GPGME_Key_Revoked, GPGME_Key_Expired, GPGME_No_CRL_Known,
+ GPGME_CRL_Too_Old, GPGME_Policy_Mismatch, GPGME_No_Secret_Key,
+ GPGME_Key_Not_Trusted, GPGME_Issuer_Missing, GPGME_Chain_Too_Long,
+ GPGME_Unsupported_Algorithm, GPGME_Sig_Expired,
+ GPGME_Bad_Signature, GPGME_No_Public_Key added as new error codes.
+ (struct _gpgme_import_status): New structure.
+ (GpgmeImporttqStatus): New type.
+ (struct _gpgme_op_import_result): New structure.
+ (GpgmeImportResult): New type.
+ (gpgme_op_import_result): New function.
+ * import.c: Include <errno.h> and "gpgme.h", but not "util.h".
+ (struct import_result): Change to type op_data_t.
+ (release_import_result): Rename to ...
+ (release_op_data): ... this.
+ (append_xml_impinfo): Function removed.
+ (gpgme_op_import_result): New function.
+ (parse_import): New function.
+ (parse_import_res): Likewise.
+ (import_status_handler): Change first argument to void *. Rewrite
+ to use new functions.
+ (_gpgme_op_import_start): Rework error handling.
+
+ * edit.c: Do not include <assert.h>, "util.h", but "gpgme.h".
+ (edit_resut): Change to typedef for op_data_t.
+ (edit_status_handler): Change first argument to void *.
+ Rework error handling.
+ (command_handler): Rework error handling.
+ (_gpgme_op_edit_start): Rename to ...
+ (edit_start): ... this. Rework error handling.
+ (gpgme_op_edit_start): Rewrite using edit_start.
+ (gpgme_op_edit): Likewise.
+
+ * ops.h (_gpgme_passphrase_start): Remove prototype.
+ * passphrase.c: Do not include <assert.h>, "util.h" or
+ "debug.h", but "gpgme.h".
+ (struct passphrase_result): Change to typedef for op_data_t.
+ (release_passphrase_result): Rename to release_op_data.
+ (_gpgme_passphrase_status_handler): Change first argument to void *.
+ Use new op_data_t type.
+ (_gpgme_passphrase_command_handler): Use new op_data_t type.
+ (_gpgme_passphrase_start): Remove function.
+ * decrypt.c (_gpgme_decrypt_start): Rewrite error handling. Do
+ not call _gpgme_passphrase_start, but install command handler.
+ * encrypt.c (_gpgme_op_encrypt_start): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise.
+ * sign.c (_gpgme_op_sign_start): Likewise.
+
+ * context.h (struct gpgme_context_s): Remove member initialized,
+ use_cms and help_data_1. Add member protocol. Make use_armor and
+ use_textmode bit flags. Make keylist_mode, include_certs,
+ signers_len and signers_size unsigned.
+ * gpgme.c (gpgme_new): Initialize CTX->protocol.
+ (gpgme_set_protocol): Do not check CTX. Use CTX->protocol.
+ (gpgme_get_protocol): Likewise.
+ (gpgme_release): Do not release CTX->help_data_1.
+ * op-support.c (_gpgme_op_reset): Use CTX->protocol.
+
+ * wait-private.c (_gpgme_wait_private_event_cb): Remove variable CTX.
+
+ * data.c: Do not include <assert.h>, but "gpgme.h".
+ (_gpgme_data_inbound_handler): Expand _gpgme_data_append, because
+ it will go. Do not assert DH.
+ (_gpgme_data_outbound_handler): Do not assert DH.
+
+ * export.c: Do not include <stdlib.h>, "debug.h" and "util.h", but
+ "gpgme.h".
+ (export_status_handler): Change type of first argument to void *.
+ (_gpgme_op_export_start): Rename to ...
+ (export_start): ... this. Rework error handling.
+ (gpgme_op_export_start): Rewritten to use export_start instead
+ _gpgme_op_export_start.
+ (gpgme_op_export): Likewise.
+
+ * gpgme.h (GpgmeError): Add GPGME_Busy, GPGME_No_Request.
+ (GPGME_No_Recipients, GPGME_Invalid_Recipient,
+ GPGME_No_Passphrase): New macros.
+
+ * key.c (gpgme_key_get_string_attr): Fix validity attribute.
+
+2003-04-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (struct _gpgme_op_genkey_result): New structure.
+ (GpgmeGenKeyResult): New type.
+ (gpgme_op_genkey): Drop last argument.
+ (gpgme_op_genkey_result): New function.
+ * genkey.c: Do not include "util.h", but "gpgme.h".
+ (struct genkey_result): Replace with ...
+ (op_data_t): ... this new type.
+ (release_genkey_result): Replace with ...
+ (release_op_data): ... this new function.
+ (gpgme_op_genkey_result): New function.
+ (genkey_status_handler): Rewritten using new op_data_t type.
+ (get_key_parameter): New function.
+ (_gpgme_op_genkey_start): Renamed to
+ (genkey_start): ... this and rewritten.
+ (gpgme_op_genkey_start): Use genkey_start instead
+ _gpgme_op_genkey_start.
+ (gpgme_op_genkey): Rewritten. Remove FPR argument.
+
+ * context.h (struct gpgme_context_s): Remove member verbosity.
+ * gpgme.c (gpgme_new): Do not set member verbosity.
+ * engine.h (_gpgme_engine_set_verbosity): Remove prototype.
+ * engine.c (_gpgme_engine_set_verbosity): Remove function.
+ * engine-backend.h (struct engine_ops): Remove set_verbosity.
+ * engine-gpgsm.c (_gpgme_engine_ops_gpgsm): Remove set_verbosity member.
+ * rungpg.c (_gpgme_engine_ops_gpg): Likewise.
+ (gpg_set_verbosity): Remove function.
+ * decrypt.c (_gpgme_decrypt_start): Don't call
+ _gpgme_engine_set_verbosity.
+ * delete.c (_gpgme_op_delete_start): Likewise.
+ * edit.c (_gpgme_op_edit_start): Likewise.
+ * encrypt.c (_gpgme_op_encrypt_start): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise.
+ * export.c (_gpgme_op_export_start): Likewise.
+ * genkey.c (_gpgme_op_genkey_start): Likewise.
+ * import.c (_gpgme_op_import_start): Likewise.
+ * keylist.c (gpgme_op_keylist_start): Likewise.
+ (gpgme_op_keylist_ext_start): Likewise.
+ * sign.c (_gpgme_op_sign_start): Likewise.
+ * verify.c (_gpgme_op_verify_start): Likewise.
+
+ * Makefile.am (libgpgme_la_SOURCES): Add key-cache.c.
+ * key.c (key_cache_initialized, key_cache_size,
+ key_cache_max_chain_length, ): Removed.
+ (struct key_cache_item_s, key_cache_lock, key_cache,
+ key_cache_unused_items, hash_key, _gpgme_key_cache_add,
+ _gpgme_key_cache_get, gpgme_get_key): Moved to ...
+ * key-cache.c: ... here. New file.
+ * key.h (_gpgme_key_cache_init): Remove prototypes.
+ (_gpgme_key_cache_add,_gpgme_key_cache_get): Move to ...
+ * ops.h: ... here.
+ * version.c: Do not include "key.h".
+ (do_subsystem_inits): Do not call _gpgme_key_cache_init.
+
+ * mkstatus: Strip trailing comma.
+ * gpgme.h (GpgmetqStatus): Pretty print.
+
+ * gpgme.h (GpgmeError): Rename GPGME_No_Passphrase to
+ GPGME_Bad_Passphrase.
+ * passphrase.c (_gpgme_passphrase_status_handler): Use
+ GPGME_Bad_Passphrase instead GPGME_No_Passphrase.
+
+ * gpgme.h (GpgmeError): Rename GPGME_No_Recipients to
+ GPGME_No_UserID and GPGME_Invalid_Recipient to
+ GPGME_Invalid_UserID.
+ * encrypt.c (_gpgme_encrypt_status_handler): Use GPGME_No_UserID
+ instead GPGME_No_Recipients and GPGME_Invalid_UserID instead
+ GPGME_Invalid_Recipient.
+ (_gpgme_op_encrypt_start): Likewise.
+
+ * gpgme.h (GpgmeError): Remove GPGME_Busy and GPGME_No_Request.
+ * wait-user.c (_gpgme_wait_user_event_cb): Don't clear CTX->pending.
+ * wait-private.c (_gpgme_wait_private_event_cb): Likewise.
+ * wait-global.c (gpgme_wait): Likewise.
+ * verify.c (_gpgme_op_verify_start): Likewise.
+ (gpgme_get_sig_status): Don't check pending flag.
+ (gpgme_get_sig_string_attr): Likewise.
+ (gpgme_get_sig_ulong_attr): Likewise.
+ (gpgme_get_sig_key): Likewise.
+ * op-support.c (_gpgme_op_reset): Likewise.
+ * trustlist.c (gpgme_op_trustlist_start): Don't clear pending flag.
+ (gpgme_op_trustlist_next): Don't check or clear pending flag.
+ (gpgme_op_trustlist_end): Likewise.
+ * sign.c (_gpgme_op_sign_start): Likewise.
+ * context.h (struct gpgme_context_s): Remove member PENDING.
+ * decrypt.c (_gpgme_decrypt_start): Likewise.
+ * delete.c (_gpgme_op_delete_start): Likewise.
+ * edit.c (_gpgme_op_edit_start): Likewise.
+ * encrypt.c (_gpgme_op_encrypt_start): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise.
+ * export.c (_gpgme_op_export_start): Likewise.
+ * genkey.c (_gpgme_op_genkey_start): Likewise.
+ * import.c (_gpgme_op_import_start): Likewise.
+ * key.c (gpgme_get_key): Likewise.
+ * keylist.c (gpgme_op_keylist_start): Likewise.
+ (gpgme_op_keylist_ext_start): Likewise.
+ (gpgme_op_keylist_next): Likewise.
+ (gpgme_op_keylist_end): Likewise.
+ * data-compat.c (gpgme_error_to_errno): Don't convert EBUSY.
+
+2003-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (GpgmePassphraseCb): Change type to return GpgmeError,
+ and add argument for returning the result string.
+ (gpgme_cancel): Remove prototype.
+ * gpgme.c (gpgme_cancel): Remove function.
+ * context.h (struct gpgme_context_s): Remove member cancel.
+ * passphrase.c (_gpgme_passphrase_command_handler): Call the
+ passphrase callback in the new way.
+
+2003-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * edit.c (_gpgme_edit_status_handler): Call the progress status
+ handler.
+
+2003-02-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait-user.c (_gpgme_wait_user_remove_io_cb): Move check for no
+ I/O handlers left to ...
+ (_gpgme_user_io_cb_handler): ... here.
+
+2003-02-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * trustlist.c (trustlist_colon_handler): Release ITEM if name
+ could not be allocated.
+ (gpgme_trust_item_release): Only release name if it is allocated.
+ Reported by Marc Mutz <Marc.Mutz@uni-bielefeld.de>.
+
+2003-02-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (read_status): If he status handler returns an error,
+ return it.
+ (status_handler): If read_status fails, just return the error.
+
+2003-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (start): Handle all errors, not only most of
+ them.
+ (xtoi_1, xtoi_2): Remove macro.
+ (status_handler): Replace use of xtoi_2 with _gpgme_hextobyte.
+
+2003-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (map_assuan_error): Replace
+ ASSUAN_Bad_Certificate_Path with ASSUAN_Bad_Certificate_Chain.
+ (gpgsm_new): Use assuan_pipe_connect instead assuan_pipe_connect2.
+
+ * util.h (DIMof): Remove macro.
+
+ * ops.h (_gpgme_op_event_cb, _gpgme_op_event_cb_user,
+ _gpgme_data_unread): Prototypes removed.
+
+2003-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * types.h: File removed.
+ * Makefile.am (libgpgme_la_SOURCES): Remove types.h.
+ * io.h (struct spawn_fd_item_s): Do not include "types.h".
+ * key.h: Likewise.
+ * context.h: Likewise.
+ * cengine-gpgsm.h: Likewise.
+ * engine.h: Include "gpgme.h" instead "types.h". Add prototypes
+ for EngineStatusHandler, EngineColonLineHandler and
+ EngineCommandHandler.
+ (_gpgme_engine_set_status_handler): Change parameter type from
+ GpgmeStatusHandler to EngineStatusHandler.
+ (_gpgme_engine_set_command_handler): Change parameter type from
+ GpgmeCommandHandler to EngineCommandHandler.
+ (_gpgme_engine_set_colon_line_handler): Change parameter type from
+ GpgmeColonLineHandler to EngineColonLineHandler.
+ * engine-backend.h: Include "engine.h" instead "types.h".
+ (struct engine_ops): Change Gpgme*Handler parameters in members
+ set_command_handler, set_colon_line_handler and set_status_handler
+ to Engine*Handler.
+ * engine.c (_gpgme_engine_set_status_handler): Change parameter
+ type from GpgmeStatusHandler to EngineStatusHandler.
+ (_gpgme_engine_set_command_handler): Change parameter type from
+ GpgmeCommandHandler to EngineCommandHandler.
+ (_gpgme_engine_set_colon_line_handler): Change parameter type from
+ GpgmeColonLineHandler to EngineColonLineHandler.
+ * rungpg.c (struct gpg_object_s): Change type of member status.fnc
+ from GpgmeStatusHandler to EngineStatusHandler. Change type of
+ member colon.fnc from GpgmeColonLineHandler to
+ EngineColonLineHandler. Change type of member cmd.fnc from
+ GpgmeCommandHandler to EngineCommandHandler.
+ * engine-gpgsm.c (struct gpgsm_object_s): Likewise.
+ * rungpg.c (gpg_set_status_handler): Change parameter type from
+ GpgmeStatusHandler to EngineStatusHandler.
+ * engine-gpgsm.c (gpgsm_set_status_handler): Likewise.
+ (assuan_simple_command): Likewise.
+ * rungpg.c (gpg_set_colon_line_handler): Change parameter type
+ from GpgmeColonLineHandler to EngineColonLineHandler.
+ * engine-gpgsm.c (gpgsm_set_colon_line_handler): Likewise.
+ * rungpg.c (gpg_set_command_handler): Change parameter type from
+ GpgmeCommandHandler to EngineCommandHandler.
+
+ * engine-gpgsm.c (status_handler): Do not close status fd at end
+ of function.
+
+ * ops.h (_gpgme_op_data_lookup): Add prototype.
+ * op-support.c: Include <stdlib.h>.
+ (_gpgme_op_data_lookup): New function.
+ * decrypt.c (_gpgme_release_decrypt_result): Function removed.
+ (struct decrypt_result_s): Rename to ...
+ (struct decrypt_resul): ... this.
+ (DecryptResult): New type.
+ (_gpgme_decrypt_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ * sign.c (_gpgme_release_sign_result): Function removed.
+ (release_sign_result): New function.
+ (struct sign_result_s): Rename to ...
+ (struct sign_result): ... this.
+ (SignResult): New type.
+ (_gpgme_sign_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ * encrypt.c (struct encrypt_result_s): Rename to ...
+ (struct encrypt_result): ... this.
+ (_gpgme_release_encrypt_result): Function removed.
+ (release_encrypt_result): New function.
+ (_gpgme_encrypt_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ * verify.c (struct verify_result_s): Rename to ...
+ (struct verify_result): ... this. Remove member next.
+ (VerifyResult): New type.
+ (_gpgme_release_verify_result): Function removed.
+ (release_verify_result): New function.
+ (finish_sig): Change first argument to type VerifyResult. Diddle
+ the type of the op_data structure.
+ (add_notation): Change first argument to type VerifyResult.
+ (_gpgme_verify_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ * passphrase.c (struct passphrase_result_s): Rename to ...
+ (struct passphrase_result): ... this. Remove member next.
+ (PassphraseResult): New type.
+ (_gpgme_release_passphrase_result): Function removed.
+ (release_passphrase_result): New function.
+ (_gpgme_passphrase_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ (_gpgme_passphrase_command_handler): Likewise.
+ * keylist.c (struct keylist_result_s): Rename to ...
+ (struct keylist_result): ... this. Remove member next.
+ (KeylistResult): New type.
+ (_gpgme_release_keylist_result): Function removed.
+ (release_keylist_result): New function.
+ (keylist_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ * edit.c (struct edit_result_s): Rename to ...
+ (struct edit_result): ... this. Remove member next.
+ (EditResult): New type.
+ (_gpgme_release_edit_result): Function removed.
+ (release_edit_result): New function.
+ (edit_status_handler): Don't use
+ test_and_allocate_result, but use _gpgme_op_data_lookup to
+ retrieve result data object.
+ (command_handler): Likewise.
+ * types.h (DecryptResult, SignResult, EncryptResult,
+ PassphraseResult, ImportResult, DeleteResult, GenKeyResult,
+ KeylistResult, EditResult): Types removed.
+ * ops.h: Don't include "types.h", but "gpgme.h" and "context.h".
+ (test_and_allocate_result): Remove macro.
+ (_gpgme_release_decrypt_result): Remove prototype.
+ (_gpgme_decrypt_result): Remove prototype.
+ (_gpgme_release_sign_result): Remove prototype.
+ (_gpgme_release_encrypt_result): Remove prototype.
+ (_gpgme_release_passphrase_result): Remove prototype.
+ (_gpgme_release_import_result): Remove prototype.
+ (_gpgme_release_delete_result): Remove prototype.
+ (_gpgme_release_genkey_result): Remove prototype.
+ (_gpgme_release_keylist_result): Remove prototype.
+ (_gpgme_release_edit_result): Remove prototype.
+ (_gpgme_release_verify_result): Remove prototype.
+ * gpgme.c (_gpgme_release_result): Rewritten.
+ * context.h (enum ctx_op_data_type): New enum.
+ (struct ctx_op_data): New structure.
+ (struct gpgme_context_s): Replace the member result with a member
+ op_data.
+ (fail_on_pending_request): Remove macro.
+ * op-support.c (_gpgme_op_reset): Expand macro
+ fail_on_pending_request.
+ * util.h: Don't include "types.h" or "debug.h", but include "gpgme.h".
+
+2003-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * types.h (EngineObject): Move typedef to ...
+ * engine.h: ... here.
+ * types.h (GpgObject): Move typedef to ...
+ * rungpg.c: ... here.
+ * types.h (GpgsmObject): Move typedef to ...
+ * engine-gpgsm.c: ... here.
+
+ * util.h (return_if_fail, return_null_if_fail,
+ return_val_if_fail): Remove macro.
+ * gpgme.c (gpgme_cancel): Don't use return_if_fail.
+ * key.c (gpgme_key_ref): Likewise.
+ * signers.c (gpgme_signers_enum): Likewise.
+ (gpgme_signers_clear): Likewise.
+
+ * engine-backend.h (struct engine_ops): Rename get_path to
+ get_file_name.
+ * gpgme.h (struct _gpgme_engine_info): Rename member path to
+ file_name.
+ * version.c: Do not include <stdio.h>, <stdlib.h>, context.h and
+ util.h. Other clean ups.
+ (parse_version_number): Protect more seriously against
+ overflow.
+ (gpgme_get_engine_info): Move to ...
+ * engine.c (gpgme_get_engine_info): ... here.
+ (_gpgme_engine_get_info): Function removed.
+ (_gpgme_engine_get_path): Make static and rename to ...
+ (engine_get_file_name): .. this.
+ (_gpgme_engine_get_version): Make static and rename to ...
+ (engine_get_version): ... this.
+ (_gpgme_engine_get_req_version): Make static and rename to ...
+ (engine_get_req_version): ... this.
+ * engine.h (_gpgme_engine_get_path, _gpgme_engine_get_version,
+ _gpgme_engine_req_version, _gpgme_engine_get_info.): Remove
+ prototypes.
+
+ * gpgme.h (enum GpgmeProtocol): Remove GPGME_PROTOCOL_AUTO.
+ * gpgme.c (gpgme_set_protocol): Don't handle GPGME_PROTOCOL_AUTO.
+ (gpgme_get_protocol_name): New function.
+
+ * engine-backend.h (struct engine_ops): New member
+ get_req_version, remove member check_version.
+ * engine.h (_gpgme_Engine_get_version): New prototype.
+ * rungpg.c (gpg_get_req_version): New function.
+ (gpg_check_version): Function removed.
+ (_gpgme_engine_ops_gpg): Add gpg_get_req_version, remove
+ gpg_check_version.
+ * engine-gpgsm.c (gpgsm_get_req_version): New function.
+ (gpgsm_check_version): Function removed.
+ (_gpgme_engine_ops_gpgsm): Add gpgsm_get_req_version, remove
+ gpgsm_check_version.
+ * engine.c: Include ops.h.
+ (_gpgme_engine_get_req_version): New function.
+ (gpgme_engine_check_version): Rewritten.
+ * version.c (gpgme_get_engine_info): Rewritten.
+ * gpgme.h (gpgme_engine_info): New structure.
+ (GpgmeEngineInfo): New type.
+
+2003-01-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * types.h: Remove byte and ulong types.
+ * util.h (_gpgme_hextobyte): Change prototype to unsigned char
+ instead byte.
+ * conversion.c (_gpgme_hextobyte): Change argument to unsigned
+ char instead byte.
+ (_gpgme_decode_c_string): Likewise, and beautify. Also support a
+ few more escaped characters. Be more strict about buffer size.
+ (_gpgme_data_append_percentstring_for_xml): Change type of SRC,
+ BUF and DST to unsigned char instead byte.
+ * progress.c (_gpgme_progress_status_handler): Use unsigned char
+ instead byte.
+ * debug.c (trim_spaces): Likewise.
+
+ * util.h (mk_error): Remove macro.
+ * conversion.c, data.c, data-compat.c, decrypt.c, delete.c,
+ edit.c, encrypt.c, encrypt-sign.c, engine.c, engine-gpgsm.c,
+ export.c, genkey.c, gpgme.c, import.c, key.c, keylist.c,
+ passphrase.c, progress.c, recipient.c, rungpg.c, sign.c,
+ signers.c, trustlist.c, verify.c, wait.c, wait-global.c,
+ wait-private (literally everywhere): Expand the mk_error macro.
+
+ * context.h (wait_on_request_or_fail): Remove macro.
+
+ * context.h (gpgme_context_s): Remove member ERROR.
+ * types.h (GpgmeStatusHandler): Change return type to GpgmeError.
+ (GpgmeCommandHandler): Change return type to GpgmeError and add
+ new argument RESULT.
+ * gpgme.h (GpgmeIOCb): Change return type to GpgmeError.
+ (GpgmeEventIO): New event GPGME_EVENT_START.
+ (GpgmeIdleFunc): Remove type.
+ (gpgme_register_idle): Remove prototype.
+ * data.c: Include <assert.h>.
+ (_gpgme_data_inbound_handler): Change return type to GpgmeError.
+ Return any error instead ignoring it, don't close file descriptor
+ on error.
+ (_gpgme_data_outbound_handler): Likewise.
+ * decrypt.c: Do not include <stdio.h>, <string.h> and <assert.h>.
+ (_gpgme_decrypt_status_handler): Change return type to GpgmeError.
+ Return error instead setting ctx->error. Return success at end of
+ function.
+ (gpgme_op_decrypt): Don't work around the old kludge anymore.
+ * decrypt-verify.c (decrypt_verify_status_handler): Change return
+ type to GpgmeError. Return possible errors.
+ * delete.c: Do not include <stdio.h>, <string.h>, <time.h> and
+ <assert.h>.
+ (delete_status_handler): Change return type to GpgmeError. Return
+ error instead setting ctx->error. Return success at end of
+ function.
+ * edit.c: Do not include <stdio.h> and <string.h>.
+ (_gpgme_edit_status_handler): Change type to GpgmeError,
+ make static and rename to ...
+ (edit_status_handler): ... this. Return error directly.
+ (command_handler): Change return type to GpgmeError, add result
+ argument. Return error directly.
+ * encrypt.c (status_handler_finish): Remove function.
+ (_gpgme_encrypt_status_handler): Change return type to GpgmeError.
+ Return error directly.
+ (_gpgme_encrypt_sym_status_handler): Likewise.
+ * encrypt-sign.c (encrypt_sign_status_handler): Likewise.
+ * engine-gpgsm.c (close_notify_handler): Do not signal done event
+ anymore.
+ (status_handler): Change return type to GpgmeError. Diddle things
+ around a bit to return errors directly.
+ (start): Send start event.
+ * export.c: Do not include <stdio.h>, <string.h> and <assert.h>.
+ (export_status_handler): Change return type to GpgmeError. Don't
+ check ctx->error.
+ * genkey.c: Do not include <stdio.h> and <assert.h>.
+ (genkey_status_handler): Change return type to GpgmeError. Don't
+ check ctx->error. Return errors directly.
+ * gpgme.c (_gpgme_release_result): Do not initialize ctx->error.
+ (_gpgme_op_event_cb): Function removed.
+ (_gpgme_op_event_cb_user): Likewise.
+ * import.c: Do not include <stdio.h>, <string.h> and <assert.h>.
+ (import_status_handler): Change return type to GpgmeError. Don't
+ check ctx->error.
+ * keylist.c (keylist_colon_handler, keylist_status_handler, finish_key):
+ Change return type to GpgmeError, return error directly.
+ * Makefile (libgpgme_la_SOURCES): Add wait-global.c,
+ wait-private.c and wait-user.c
+ * ops.h (test_and_allocate_result): Return error instead setting
+ ctx->error.
+ (_gpgme_data_inbound_handler, _gpgme_data_outbound_handler,
+ _gpgme_verify_status_handler, _gpgme_decrypt_status_handler,
+ _gpgme_sign_status_handler, _gpgme_encrypt_staus_handler,
+ _gpgme_passphrase_status_handler, _gpgme_progress_status_handler):
+ Change return type to GpgmeError.
+ (_gpgme_passphease_command_handler): Change return type to
+ GpgmeError and add new argument RESULT.
+ * op-support.c: Use new callback functions, and change private
+ data to ctx everywhere.
+ * passphrase.c (_gpgme_passphrase_status_handler): Change return
+ type to GpgmeError, return error directly.
+ (_gpgme_passphrase_command_handler): Change return type to
+ GpgmeError, add result argument. Return results accordingly.
+ * progress.c (_gpgme_progress_status_handler): Change return type
+ to GpgmeError, return errors directly.
+ * rungpg.c (status_handler): Change return type to GpgmeError.
+ Return error directly.
+ (close_notify_handler): Don't send done event.
+ (colon_line_handler): Change return type to GpgmeError, return
+ errors directly.
+ * rungpg.c (start): Send start event.
+ * sign.c (_gpgme_sign_status_handler): Change return type to
+ GpgmeError, return errors directly.
+ * trustlist.c (trustlist_status_handler): Change return type to
+ GpgmeError. Return 0.
+ (trustlist_colon_handler): Change return type GpgmeError. Return
+ errors directly.
+ * verify.c (add_notation): Change return type to GpgmeError,
+ return errors directly.
+ (_gpgme_verify_status_handler): Likewise.
+ * wait.h (struct fd_table): Remove lock member.
+ (struct wait_item_s): Moved here from wait.c.
+ (struct tag): New structure.
+ (_gpgme_wait_event_cb): Remove prototype.
+ (_gpgme_wait_private_event_cb, _gpgme_wait_global_event_cb,
+ _gpgme_wait_user_add_io_cb, _gpgme_wait_user_remove_io_cb,
+ _gpgme_wait_user_event_io_cb): New prototypes.
+ * wait.c: Don't include <stdio.h>.
+ (ftd_global, ctx_done_list, ctx_done_list_size,
+ ctx_done_list_length, ctx_done_list_lock, idle_function): Remove
+ global variable.
+ (gpgme_register_idle, do_select, _gpgme_wait_event_cb): Remove
+ function.
+ (gpgme_wait): Move to file wait-global.c.
+ (_gpgme_add_io_cb): Take ctx as private argument, initialize ctx
+ member in wait item and tag.
+ (_gpgme_remove_io_cb): Take ctx from tag. Don't use FDT lock.
+ (_gpgme_wait_one, _gpgme_wait_on_condition): Move to
+ wait-private.c.
+ (gpgme_fd_table_init): Don't initialize FDT->lock.
+ (gpgme_fd_table_deinit): Don't destroy FDT->lock.
+ (_gpgme_fd_table_put): Make static and rename to ...
+ (fd_table_put): ... this function. Don't use FDT->lock.
+ (struct wait_item_s): Move to wait.h.
+ * wait-global.c: New file.
+ * wait-private.c: New file.
+ * wait-user.c: New file.
+
+ * key.c (gpgme_key_sig_get_string_attr): Use validity_to_string
+ instead otrust_to_string to calculate validity.
+
+2003-01-19 Miguel Coca <mcoca@gnu.org>
+
+ * w32-io.c (_gpgme_io_select): Add missing argument in calls to
+ DEBUG_BEGIN.
+ * w32-util.c: Include "sema.h".
+ (find_program_in_registry): Change DEBUG1 to DEBUG2, fixes compilation
+ error.
+
+2003-01-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_engine_ops_gpg): Remove gpg_start.
+ (gpg_start): Rename to ...
+ (start): ... this function. Change arguments to GpgObject.
+ (gpg_decrypt): Call start.
+ (gpg_edit): Likewise.
+ (gpg_encrypt): Likewise.
+ (gpg_encrypt_sign): Likewise.
+ (gpg_export): Likewise.
+ (gpg_import): Likewise.
+ (gpg_keylist): Likewise.
+ (gpg_keylist_ext): Likewise.
+ (gpg_trustlist): Likewise.
+ (gpg_verify): Likewise.
+
+ * engine-gpgsm.c (_gpgme_engine_ops_encrypt): Remove gpgsm_start.
+ (gpgsm_start): Rename to ...
+ (struct gpgsm_object_s): Remove member command.
+ (gpgsm_release): Don't free command.
+ (start): ... this function. Change arguments to GpgsmObject and
+ const char *.
+ (gpgsm_decrypt): Call start.
+ (gpgsm_delete): Likewise.
+ (gpgsm_encrypt): Likewise.
+ (gpgsm_export): Likewise.
+ (gpgsm_genkey): Likewise.
+ (gpgsm_import): Likewise.
+ (gpgsm_keylist): Likewise.
+ (gpgsm_keylist_ext): Likewise.
+ (gpgsm_verify): Likewise.
+
+ * decrypt.c (_gpgme_decrypt_start): Don't call
+ _gpgme_engine_start.
+ * delete.c (_gpgme_op_delete_start): Likewise.
+ * edit.c (_gpgme_op_edit_start): Likewise.
+ * encrypt.c (_gpgme_op_encrypt_start):
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start):
+ * export.c (_gpgme_op_export_start): Likewise.
+ * genkey.c (_gpgme_op_genkey_start): Likewise.
+ * import.c (_gpgme_op_import_start): Likewise.
+ * keylist.c (gpgme_op_keylist_ext_start): Likewise.
+ (gpgme_op_keylist_start): Likewise.
+ * sign.c (_gpgme_op_sign_start): Likewise.
+ * trustlist.c (gpgme_op_trustlist_start): Likewise.
+ * verify.c (_gpgme_op_verify_start): Likewise.
+
+ * engine-backend.h (struct engine_ops): Remove member start.
+
+ * engine.h (_gpgme_engine_start): Remove prototype.
+ * engine.c (_gpgme_engine_start): Remove function.
+
+2003-01-06 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (set_mainkey_capability): Handle 'd' and 'D' used
+ since gpg 1.3 to denote disabled keys.
+
+2003-01-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-mem.c: Include <string.h>.
+ * engine.c: Likewise.
+
+2003-01-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_la_DEPENDENCIES): Correct bug in last change.
+
+2002-12-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_op_verify, gpgme_op_decrypt_verify): Drop R_STAT
+ argument.
+ * decrypt-verify.c (gpgme_op_decrypt_verify): Drop R_STAT
+ argument.
+ * verify.c (gpgme_op_verify): Drop R_STAT argument.
+ (_gpgme_intersect_stati): Function removed.
+ * ops.h (_gpgme_intersect_stati): Remove prototype.
+
+2002-12-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * libgpgme.vers: New file.
+ * Makefile.am (EXTRA_DIST): Add libgpgme.vers.
+ (libgpgme_version_script_cmd): New variable.
+ (libgpgme_la_LDFLAGS): Add libgpgme_version_script_cmd here.
+ (libgpgme_la_DEPENDENCIES): New variable.
+
+2002-12-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * key.c (gpgme_key_get_string_attr): Don't accept GPGME_ATTR_IS_SECRET.
+ (otrust_to_string): New function.
+ (gpgme_key_get_as_xml): Use it.
+ (validity_to_string): New function.
+ (gpgme_key_get_string_attr): Beautify using above functions.
+ (gpgme_key_get_ulong_attr): Likewise.
+
+2002-12-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * data-mem.c (mem_release): Fix gcc warning.
+ * data-user.c (user_release): Likewise.
+
+2002-12-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.h (gpgme_data_release_cb): Change return type to void.
+ (gpgme_data_read_cb): Change return type to ssize_t.
+ * data.c (gpgme_data_read): Likewise.
+ * data-stream.c (stream_read): Likewise.
+ * data-fd.c (fd_read): Likewise.
+ * data-mem.c (mem_read): Likewise.
+ (mem_release): Change return type to void.
+ * data-user.c (user_read): Change return type to ssize_t.
+ (user_release): Change return type to void.
+ * data-compat.c (old_user_read): Change return type to ssize_t.
+ * gpgme.h (GpgmeDataReadCb): Likewise.
+ (gpgme_data_read): Likewise.
+ (GpgmeDataSeekCb): Change return type to off_t.
+
+2002-12-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add prototype for gpgme_get_key.
+ * key.c (gpgme_get_key): New function.
+ * verify.c (gpgme_get_sig_key): Rewrite using gpgme_get_key.
+
+ * gpgme.h: Add prototypes for new interfaces
+ gpgme_key_sig_get_string_attr and gpgme_key_get_ulong_attr.
+ (enum GpgmeAttr): New attribute GPGME_ATTR_SIG_CLASS.
+ * gpgme.c (gpgme_set_keylist_mode): Allow GPGME_KEYLIST_MODE_SIGS.
+ * key.h (struct certsig_s): New members ALGO, NAME_PART,
+ EMAIL_PART, COMMENT_PART, NAME, SIG_STAT and SIG_CLASS.
+
+ * conversion.c (_gpgme_decode_c_string): Add new parameter LEN.
+ Use that to determine if allocation is desired or not.
+ * util.h: Adjust prototype of _gpgme_decode_c_string.
+ * keylist.c (keylist_colon_handler): Adjust caller of
+ _gpgme_decode_c_string.
+
+ * key.h (struct gpgme_key_s): New member last_uid.
+ * key.c (_gpgme_key_append_name): Rewritten using
+ _gpgme_decode_c_string and the last_uid pointer.
+ (my_isdigit): Macro removed.
+ (ALLOC_CHUNK): Likewise.
+ * keylist.c (set_userid_flags): Use last_uid member of KEY.
+
+ * context.h (struct user_id_s): New member last_certsig.
+ * key.h: Add prototype for _gpgme_key_add_certsig.
+ * key.c (_gpgme_key_add_certsig): New function.
+ (set_user_id_part): Move function before _gpgme_key_add_certsig.
+ (parse_user_id): Change first argument to SRC, add new arguments
+ NAME, EMAIL and COMMENT. Change code to use these arguments
+ instead going through UID. Move function before
+ _gpgme_add_certsig.
+ (parse_x509_user_id): Likewise.
+ (_gpgme_key_append_name): Adjust arguments to parse_x509_user_id
+ and parse_user_id invocation.
+ (one_certsig_as_xml): New function.
+ (one_uid_as_xml): Print signatures.
+ * context.h (struct gpgme_context_s): New member TMP_UID.
+ * keylist.c (keylist_colon_handler): Rewritten, implement "sig"
+ record entries.
+
+ * key.c (get_certsig): New function.
+ (gpgme_key_sig_get_string_attr): Likewise.
+ (gpgme_key_sig_get_ulong_attr): Likewise.
+
+ * keylist.c: Include <ctype.h>.
+ (my_isdigit): Macro removed.
+ (set_mainkey_trust_info): Use isdigit, not my_isdigit.
+ (set_userid_flags): Likewise.
+ (set_subkey_trust_info): Likewise.
+ (set_ownertrust): Likewise.
+ (finish_key): Move function up a bit and remove prototype.
+
+ * rungpg.c (gpg_keylist_ext): Correct precedence of signature
+ listing mode.
+ (gpg_keylist_ext): Implement signature listing mode.
+
+2002-11-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_spawn): Do not set parent fds to -1.
+ * posix-io.c (_gpgme_io_spawn): Call _gpgme_io_close instead close
+ for parent fds.
+ * w32-io.c (_gpgme_io_spawn): Call _gpgme_io_close instead
+ CloseHandle for parent fds.
+
+2002-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h [_MSC_VER]: Define ssize_t as long.
+
+2002-11-22 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): Save the result of a first
+ setlocale before doing another setlocale.
+
+2002-11-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * decrypt.c: Some beautyfication.
+
+ * verify.c (_gpgme_verify_status_handler): Treat
+ GPGME_STATUS_UNEXPECTED like GPGME_STATUS_NODATA.
+ Reported by Miguel Coca <e970095@zipi.fi.upm.es>.
+
+2002-11-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * genkey.c: Only include <config.h> if [HAVE_CONFIG_H].
+ (struct genkey_result_s): Add new member FPR.
+ (_gpgme_release_genkey_result): Free RESULT->fpr if set.
+ (genkey_status_handler): Extract the fingerprint from the status
+ line.
+ (gpgme_op_genkey): Add new argument FPR and return the fingerprint
+ in it.
+ * gpgme.h: Adjust prototype of gpgme_op_genkey.
+
+2002-11-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (gpg_keylist): Add --with-fingerprint to gpg invocation
+ twice, to get fingerprints on subkeys. Suggested by Timo Schulz
+ <twoaday@freakmail.de>.
+ (gpg_keylist_ext): Likewise.
+
+2002-11-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * import.c (append_xml_impinfo): Use
+ _gpgme_data_append_string_for_xml rather than
+ _gpgme_data_append_string for the field content.
+ Submitted by Miguel Coca <e970095@zipi.fi.upm.es>.
+
+2002-10-10 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.h, engine-gpgsm.h: File removed.
+ * engine-backend.h: New file.
+ * Makefile.am (gpgsm_components): New variable, set depending on
+ automake conditional HAVE_GPGSM.
+ (libgpgme_la_SOURCES): Add engine-backend.h, remove rungpg.h and
+ engine-gpgsm.h. Replace engine-gpgsm.c with ${gpgsm_components}.
+ (status-table.h): Depend on gpgme.h, not rungpg.h.
+ * conversion.c: Include <stdlib.h>.
+ * engine-gpgsm.c: Do not set ENABLE_GPGSM here. Include
+ "engine-backend.h" instead "engine-gpgsm.h". Reorder some
+ functions and remove all function prototypes.
+ (_gpgme_gpgsm_get_version): Make static and rename to ...
+ (gpgsm_get_version): ... this.
+ (_gpgme_gpgsm_check_version): Make static and rename to ...
+ (gpgsm_check_version): ... this.
+ (_gpgme_gpgsm_new): Make static. Change argument type from
+ GpgsmObject * to void **. Call gpgsm_release instead
+ _gpgme_gpgsm_release.
+ (_gpgme_gpgsm_op_decrypt): Make static and rename to ...
+ (gpgsm_check_decrypt): ... this.
+ (_gpgme_gpgsm_op_delete): Make static and rename to ...
+ (gpgsm_check_delete): ... this.
+ (_gpgme_gpgsm_set_recipients): Make static and rename to ...
+ (gpgsm_check_set_recipients): ... this.
+ (_gpgme_gpgsm_op_encrypt): Make static and rename to ...
+ (gpgsm_encrypt): ... this.
+ (_gpgme_gpgsm_op_export): Make static and rename to ...
+ (gpgsm_export): ... this.
+ (_gpgme_gpgsm_op_genkey): Make static and rename to ...
+ (gpgsm_genkey): ... this.
+ (_gpgme_gpgsm_op_import): Make static and rename to ...
+ (gpgsm_import): ... this.
+ (_gpgme_gpgsm_op_keylist): Make static and rename to ...
+ (gpgsm_keylist): ... this.
+ (_gpgme_gpgsm_op_keylist_ext): Make static and rename to ...
+ (gpgsm_keylist_ext): ... this.
+ (_gpgme_gpgsm_op_sign): Make static and rename to ...
+ (gpgsm_sign): ... this.
+ (_gpgme_gpgsm_op_trustlist): Make static and rename to ...
+ (gpgsm_trustlist): ... this.
+ (_gpgme_gpgsm_op_verify): Make static and rename to ...
+ (gpgsm_verify): ... this.
+ (gpgsm_status_handler): Rename to ...
+ (status_handler): ... this.
+ (_gpgme_gpgsm_set_status_handler): Make static and rename to ...
+ (gpgsm_set_status_handler): ... this.
+ (_gpgme_gpgsm_set_colon_line_handler): Make static and rename to ...
+ (gpgsm_set_colon_line_handler): ... this.
+ (_gpgme_gpgsm_add_io_cb): Rename to ...
+ (add_io_cb): ... this.
+ (_gpgme_gpgsm_start): Make static and rename to ...
+ (gpgsm_start): ... this.
+ (_gpgme_gpgsm_set_io_cb): Make static and rename to ...
+ (gpgsm_set_io_cb): ... this.
+ (_gpgme_gpgsm_io_event): Make static and rename to ...
+ (gpgsm_io_event): ... this.
+ (struct _gpgme_engine_ops_gpgsm): New variable.
+ [!ENABLE_GPGSM]: Removed.
+ * engine.c: Do not include <time.h>, <sys/types.h>, <string.h>,
+ <assert.h>, "io.h", "rungpg.h" and "engine-gpgsm.h". Include
+ <stdlib.h> and "engine-backend.h".
+ (struct engine_object_s): Rewritten.
+ (engine_ops): New variable.
+ * engine.c (_gpgme_engine_get_path, _gpgme_engine_get_version,
+ _gpgme_engine_check_version, _gpgme_engine_new,
+ _gpgme_engine_release, _gpgme_engine_set_verbosity,
+ _gpgme_engine_set_status_handler,
+ _gpgme_engine_set_command_handler,
+ _gpgme_engine_set_colon_line_handler, _gpgme_engine_op_decrypt,
+ _gpgme_engine_op_delete, _gpgme_engine_op_edit,
+ _gpgme_engine_op_encrypt, _gpgme_engine_op_encrypt_sign,
+ _gpgme_engine_op_export, _gpgme_engine_op_genkey,
+ _gpgme_engine_op_import, _gpgme_engine_op_keylist,
+ _gpgme_engine_op_keylist_ext, _gpgme_engine_op_sign,
+ _gpgme_engine_op_trustlist, _gpgme_engine_op_verify,
+ _gpgme_engine_start, _gpgme_engine_set_io_cbs,
+ _gpgme_engine_io_event): Reimplement.
+ * engine.h: Fix a few comments and a variable name in a prototype.
+ * ops.h: Do not include "rungpg.h".
+ * passphrase.c: Include config.h only if [HAVE_CONFIG_H]. Do not
+ include "rungpg.h".
+ * recipient.c: Likewise.
+ * signers.c: Likewise.
+ * version.c: Likewise.
+ * rungpg.c: Likewise. Include "engine-backend.h". Reorder
+ functions and remove prototypes.
+ (_gpgme_gpg_get_version): Make static and rename to ...
+ (gpg_get_version): ... this.
+ (_gpgme_gpg_check_version): Make static and rename to ...
+ (gpg_check_version): ... this.
+ (_gpgme_gpg_new): Make static. Change argument type from
+ GpgObject * to void **. Call gpg_release instead
+ _gpgme_gpg_release.
+ (_gpgme_gpg_op_decrypt): Make static and rename to ...
+ (gpg_check_decrypt): ... this.
+ (_gpgme_gpg_op_delete): Make static and rename to ...
+ (gpg_check_delete): ... this.
+ (_gpgme_gpg_set_recipients): Make static and rename to ...
+ (gpg_check_set_recipients): ... this.
+ (_gpgme_gpg_op_encrypt): Make static and rename to ...
+ (gpg_encrypt): ... this.
+ (_gpgme_gpg_op_export): Make static and rename to ...
+ (gpg_export): ... this.
+ (_gpgme_gpg_op_genkey): Make static and rename to ...
+ (gpg_genkey): ... this.
+ (_gpgme_gpg_op_import): Make static and rename to ...
+ (gpg_import): ... this.
+ (_gpgme_gpg_op_keylist): Make static and rename to ...
+ (gpg_keylist): ... this.
+ (_gpgme_gpg_op_keylist_ext): Make static and rename to ...
+ (gpg_keylist_ext): ... this.
+ (_gpgme_gpg_op_sign): Make static and rename to ...
+ (gpg_sign): ... this.
+ (_gpgme_gpg_op_trustlist): Make static and rename to ...
+ (gpg_trustlist): ... this.
+ (_gpgme_gpg_op_verify): Make static and rename to ...
+ (gpg_verify): ... this.
+ (gpg_status_handler): Rename to ...
+ (status_handler): ... this.
+ (_gpgme_gpg_set_status_handler): Make static and rename to ...
+ (gpg_set_status_handler): ... this.
+ (_gpgme_gpg_set_colon_line_handler): Make static and rename to ...
+ (gpg_set_colon_line_handler): ... this.
+ (gpgme_gpg_add_io_cb): Rename to ...
+ (add_io_cb): ... this.
+ (_gpgme_gpg_start): Make static and rename to ...
+ (gpg_start): ... this.
+ (_gpgme_gpg_set_io_cb): Make static and rename to ...
+ (gpg_set_io_cb): ... this.
+ (_gpgme_gpg_io_event): Make static and rename to ...
+ (gpg_io_event): ... this.
+ (struct _gpgme_engine_ops_gpg): New variable.
+
+2002-10-10 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_verify) [!ENABLE_GPGSM]: Add
+ missing argument.
+
+2002-10-09 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.h, data-user.c, data-stream.c, data-mem.c, data-fd.c,
+ data-compat.c: New file. Really check them in this time, completes
+ 2002-10-08 change.
+
+ * rungpg.h (GpgStatusHandler): Rename type to GpgmeStatusHandler
+ and move to ...
+ * types.h (GpgmeStatusHandler): ... here.
+ * rungpg.h (GpgColonLineHandler): Rename type to GpgmeColonLineHandler.
+ and move to ...
+ * types.h (GpgmeColonLineHandler): ... here.
+ * rungpg.h (GpgCommandHandler): Rename type to GpgmeCommandHandler.
+ and move to ...
+ * types.h (GpgmeCommandHandler): ... here.
+ * engine.h: Don't include "rungpg.h".
+ (_gpgme_engine_set_status_handler): Change type of
+ argument from GpgStatusHandler to GpgmeStatusHandler.
+ (_gpgme_engine_set_colon_line_handler): Change type of
+ argument from GpgColonLineHandler to GpgmeColonLineHandler.
+ (_gpgme_engine_set_command_handler): Change type of
+ argument from GpgCommandHandler to GpgmeCommandHandler.
+ * engine-gpgsm.h: Don't include "rungpg.h".
+ (_gpgme_gpgsm_set_status_handler): Change type of
+ argument from GpgStatusHandler to GpgmeStatusHandler.
+ (_gpgme_gpgsm_set_colon_line_handler): Change type of
+ argument from GpgColonLineHandler to GpgmeColonLineHandler.
+ * engine-gpgsm.c: Do not include "rungpg.h".
+ (struct gpgsm_object_s): Change type of
+ status.fnc to GpgmeStatusHandler. Change type of colon.fnc to
+ GpgmeColonLineHandler.
+ (gpgsm_assuan_simple_command): Change type of argument from
+ GpgStatusHandler to GpgmeStatusHandler.
+ (_gpgme_gpgsm_set_status_handler): Likewise.
+ (_gpgme_gpgsm_set_colon_line_handler): Change type of argument from
+ GpgColonLineHandler to GpgmeColonLineHandler.
+ * rungpg.h (_gpgme_gpg_set_status_handler): Change type of
+ argument from GpgStatusHandler to GpgmeStatusHandler.
+ (_gpgme_gpg_set_colon_line_handler): Change type of
+ argument from GpgColonLineHandler to GpgmeColonLineHandler.
+ (_gpgme_gpg_set_command_handler): Change type of
+ argument from GpgCommandHandler to GpgmeCommandHandler.
+ * rungpg.c (struct gpg_object_s): Change type of status.fnc to
+ GpgmeStatusHandler. Change type of colon.fnc to
+ GpgmeColonLineHandler. Change type of cmd.fnc to
+ GpgmeCommandLineHandler.
+ (_gpgme_gpg_set_status_handler): Change type of argument FNC to
+ GpgmeStatusHandler.
+ (_gpgme_gpg_set_colon_line_handler): Change type of argument FNC
+ to GpgmeColonLineHandler.
+ (_gpgme_gpg_set_command_handler): Change type of argument FNC to
+ GpgmeCommandHandler.
+ * engine.c (_gpgme_engine_set_status_handler): Change type of
+ argument FNC to GpgmeStatusHandler.
+ (_gpgme_engine_set_colon_line_handler): Change type of argument FNC
+ to GpgmeColonLineHandler.
+ (_gpgme_engine_set_command_handler): Change type of argument FNC to
+ GpgmeCommandHandler.
+
+ * rungpg.h (_gpgme_gpg_enable_pipemode): Remove prototype.
+ * rungpg.c (struct gpg_object_s): Remove PM.
+ (pipemode_cb): Prototype removed.
+ (add_pm_data): Function removed.
+ (_gpgme_gpg_enable_pipemode): Likewise.
+ (pipemode_copy): Likewise.
+ (pipemode_cb): Likewise.
+ (add_arg): Don't check for pipemode.
+ (add_data): Likewise.
+ (_gpgme_gpg_set_status_handler): Likewise.
+ (_gpgme_gpg_set_colon_line_handler): Likewise.
+ (_gpgme_gpg_set_command_handler): Likewise.
+ (_gpgme_gpg_spawn): Likewise.
+ (_gpgme_gpg_spawn): Don't set PM.active.
+ (_gpgme_gpg_op_verify): Remove pipemode case.
+ * verify.c (_gpgme_op_verify_start): Remove pipemode case.
+
+ * rungpg.h (_gpgme_gpg_add_arg, _gpgme_gpg_add_data,
+ _gpgme_gpg_add_pm_data, _gpgme_gpg_housecleaning,
+ _gpgme_gpg_set_simple_line_handler): Prototype removed.
+ (_gpgme_gpg_set_verbosity): New prototype.
+ * rungpg.c (_gpgme_gpg_add_data): Make static and rename to ...
+ (add_data): ... this.
+ (_gpgme_gpg_add_pm_data): Call add_data, not _gpgme_gpg_add_data.
+ (_gpgme_gpg_set_command_handler): Likewise.
+ (_gpgme_gpg_op_decrypt, _gpgme_gpg_op_edit, _gpgme_gpg_op_encrypt,
+ _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export,
+ _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_sign,
+ _gpgme_gpg_op_verify): Likewise.
+ (_gpgme_gpg_add_pm_data): Rename to ...
+ (add_pm_data): ... this.
+ (_gpgme_gpg_op_verify): Call add_pm_data, not
+ _gpgme_gpg_add_pm_data.
+ (_gpgme_gpg_add_arg): Make static and rename to ...
+ (add_arg): ... this.
+ (_gpgme_gpg_set_command_handler, _gpgme_gpg_new,
+ _gpgme_gpg_op_decrypt, _gpgme_gpg_op_delete,
+ _gpgme_append_gpg_args_from_signers, _gpgme_gpg_op_edit,
+ _gpgme_append_gpg_args_from_recipients, _gpgme_gpg_op_encrypt,
+ _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export,
+ _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_keylist,
+ _gpgme_gpg_op_keylist_ext, _gpgme_gpg_op_trustlist,
+ _gpgme_gpg_op_sign, _gpgme_gpg_op_verify): Use add_arg, not
+ _gpgme_gpg_add_arg.
+ (_gpgme_gpg_set_verbosity): New function.
+ (struct gpg_object_s): Remove member simple from colon.
+ (_gpgme_gpg_set_colon_line_handler): Don't initialize simple.
+ (_gpgme_gpg_set_simple_line_handler): Removed function.
+ (read_colon_line): Don't check the GPG->colon.simple.
+ * engine.c (_gpgme_engine_set_verbosity): Call
+ _gpgme_gpg_set_verbosity instead _gpgme_gpg_add_arg.
+
+2002-10-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * util.h (_gpgme_malloc, _gpgme_realloc, _gpgme_calloc,
+ _gpgme_strdup, _gpgme_free): Remove prototypes.
+ (xtrymalloc, xtrycalloc, xtryrealloc, xtrystrdup, xfree): Remove
+ macros.
+ * util.c: File removed.
+ * Makefile.am (libgpgme_la_SOURCES): Remove util.h.
+ * conversion.c (_gpgme_decode_c_string): Use malloc instead of
+ xtrymalloc, realloc instead of xtryrealloc, calloc instead of
+ xtrycalloc, free instead of xfree.
+ (_gpgme_data_append_percentstring_for_xml): Likewise.
+ * data.c (_gpgme_data_new, _gpgme_data_release): Likewise.
+ * data-compat.c (gpgme_data_new_from_filepart): Likewise.
+ * data-mem.c (mem_write, mem_release, gpgme_data_new_from_mem,
+ _gpgme_data_get_as_string): Likewise.
+ * debug.c (debug_init): Likewise.
+ * decrypt.c (_gpgme_release_decrypt_result): Likewise.
+ * delete.c (_gpgme_release_delete_result): Likewise.
+ * edit.c (_gpgme_release_edit_result, _gpgme_op_edit_start):
+ Likewise.
+ * encrypt.c (_gpgme_release_encrypt_result): Likewise.
+ * engine.c (_gpgme_engine_get_info, _gpgme_engine_new,
+ _gpgme_engine_release): Likewise.
+ * engine-gpgsm.c (_gpgme_gpgsm_new, _gpgme_gpgsm_release,
+ _gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete,
+ gpgsm_set_recipients, _gpgme_gpgsm_op_encrypt,
+ _gpgme_gpgsm_op_export, _gpgme_gpgsm_op_genkey,
+ _gpgme_gpgsm_op_import, _gpgme_gpgsm_op_keylist,
+ _gpgme_gpgsm_op_keylist_ext, _gpgme_gpgsm_op_sign,
+ _gpgme_gpgsm_op_verify, gpgsm_status_handler): Likewise.
+ * genkey.c (_gpgme_release_genkey_result): Likewise.
+ * gpgme.c (gpgme_new, gpgme_release): Likewise.
+ * import.c (_gpgme_release_import_result): Likewise.
+ * key.c (_gpgme_key_cache_init, _gpgme_key_cache_add, key_new,
+ add_subkey, gpgme_key_release, _gpgme_key_append_name): Likewise.
+ * keylist.c (_gpgme_release_keylist_result, keylist_colon_handler,
+ _gpgme_op_keylist_event_cb, gpgme_op_keylist_next): Likewise.
+ * ops.h (test_and_allocate_result): Likewise.
+ * passphrase.c (_gpgme_release_passphrase_result,
+ _gpgme_passphrase_status_handler,
+ _gpgme_passphrase_command_handler): Likewise.
+ * progress.c (_gpgme_progress_status_handler): Likewise.
+ * recipient.c (gpgme_recipients_new, gpgme_recipients_release,
+ gpgme_recipients_add_name_with_validity): Likewise.
+ * rungpg.c (_gpgme_gpg_new, _gpgme_gpg_release,
+ _gpgme_gpg_add_arg, _gpgme_gpg_add_data,
+ _gpgme_gpg_set_colon_line_handler, free_argv, free_fd_data_map,
+ build_argv, _gpgme_gpg_spawn, read_status, read_colon_line):
+ Likewise.
+ * sign.c (_gpgme_release_sign_result): Likewise.
+ * signers.c (_gpgme_signers_add): Likewise.
+ * trustlist.c (trust_item_new, trustlist_colon_handler,
+ _gpgme_op_trustlist_event_cb, gpgme_op_trustlist_next,
+ gpgme_trustitem_release): Likewise.
+ * verify.c (_gpgme_release_verify_result, finish_sig): Likewise.
+ * version.c (gpgme_get_engine_info, _gpgme_get_program_version):
+ Likewise.
+ * w32-io.c (create_reader, create_writer, destroy_reader,
+ destroy_writer, build_commandline, _gpgme_io_spawn): Likewise.
+ * w32-sema.c (critsect_init, _gpgme_sema_cs_destroy): Likewise.
+ * w32-util.c (read_w32_registry_string): Likewise.
+ * wait.c (_gpgme_fd_table_deinit, _gpgme_fd_table_put,
+ _gpgme_wait_event_cb, _gpgme_add_io_cb, _gpgme_remove_io_cb)
+ * data-compat.c: Include <stdlib.h>.
+
+2002-10-08 Marcus Brinkmann <marcus@g10code.de>
+
+ New data object component:
+
+ * gpgme.h (GpgmeDataReadCb, GpgmeDataWriteCb, GpgmeDataSeekCb,
+ GpgmeDataReleaseCb): New types.
+ (struct GpgmeDataCbs): New structure.
+ (gpgme_data_read): Changed prototype to match that of read() closely.
+ (gpgme_data_write): Similar for write().
+ (gpgme_data_seek, gpgme_data_new_from_cbs, gpgme_data_new_from_fd,
+ gpgme_data_new_from_stream): New prototypes.
+ (gpgme_data_get_type, gpgme_check_engine): Prototype removed.
+
+ * Makefile.am (libgpgme_la_SOURCES): Add data.h, data-fd.c,
+ data-stream.c, data-mem.c, data-user.c and data-compat.c.
+ * data.c: Reimplemented from scratch.
+ * (data-compat.c, data-fd.c, data.h, data-mem.c, data-stream.c,
+ data-user.c): New file.
+ * context.h (struct gpgme_data_s): Removed.
+ * conversion.c: Include <errno.h> and <sys/types.h>.
+ (_gpgme_data_append): New function.
+ * data.c (_gpgme_data_append_string): Move to ...
+ * conversion.c (_gpgme_data_append_string): ... here.
+ * data.c (_gpgme_data_append_for_xml): Move to ...
+ * conversion.c (_gpgme_data_append_for_xml): ... here.
+ * data.c (_gpgme_data_append_string_for_xml): Move to ...
+ * conversion.c (_gpgme_data_append_string_for_xml): ... here.
+ * data.c (_gpgme_data_append_percentstring_for_xml): Move to ...
+ * conversion.c (_gpgme_data_append_percentstring_for_xml): ... here.
+
+ * ops.h (_gpgme_data_get_mode, _gpgme_data_set_mode): Prototype
+ removed.
+ * types.h (GpgmeDataMode): Type removed.
+
+ * decrypt.c (_gpgme_decrypt_start): Don't check data type or mode.
+ * edit.c (_gpgme_op_edit_start): Likewise.
+ * encrypt.c (_gpgme_op_encrypt_start): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise.
+ * encrypt-sign.c (_gpgme_op_encrypt_sign_start): Likewise.
+ * export.c (_gpgme_op_export_start): Likewise.
+ * genkey.c (_gpgme_op_genkey_start): Likewise.
+ * import.c (_gpgme_op_import_start): Likewise.
+ * sign.c (_gpgme_op_sign_start): Likewise.
+ * verify.c (_gpgme_op_verify_start): Likewise.
+
+ * encrypt.c (gpgme_op_encrypt): Remove hack that returns invalid
+ no recipient if no data was returned.
+ * encrypt-sign.c (gpgme_op_encrypt_sign): Remove hack that returns
+ no recipient if no data was returned.
+ * encrypt-sign.c (gpgme_op_encrypt_sign): Remove hack that returns
+ no recipient if no data was returned.
+
+ * engine.c (_gpgme_engine_op_verify): Add new argument to
+ differentiate detached from normal signatures.
+ * engine.h (_gpgme_engine_op_verify): Likewise for prototype.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Likewise. Don't check
+ mode of data argument.
+ * engine-gpgsm.h (_gpgme_gpgsm_op_verify): Likewise for prototype.
+ * gpgme.h (gpgme_op_verify_start): Likewise for prototype.
+ (gpgme_op_verify): Likewise for prototype.
+ * rungpg.c (_gpgme_gpg_op_verify): Likewise.
+ * rungpg.h (_gpgme_gpg_op_verify): Likewise for prototype.
+ * verify.c (_gpgme_op_verify_start): Likewise.
+ (gpgme_op_verify_start): Likewise.
+ (gpgme_op_verify): Likewise.
+
+ * rungpg.c (struct arg_and_data_s): New member INBOUND to hold
+ direction of data object.
+ (_gpgme_gpg_add_data): Add new argument INBOUND. Use it to
+ determine direction of data object.
+ (_gpgme_gpg_add_pm_data, _gpgme_gpg_set_command_handler,
+ _gpgme_gpg_op_decrypt, _gpgme_gpg_op_edit, _gpgme_gpg_op_encrypt,
+ _gpgme_gpg_op_encrypt_sign, _gpgme_gpg_op_export,
+ _gpgme_gpg_op_genkey, _gpgme_gpg_op_import, _gpgme_gpg_op_sign,
+ _gpgme_gpg_op_verify): Add new argument to _gpgme_gpg_add_data
+ invocation.
+ (build_argv): Use new member INBOUND to determine direction of
+ file descriptor. Don't check the data type.
+ * rungpg.h (_gpgme_gpg_add_data): Add new argument to prototype.
+
+ * gpgme.c (gpgme_get_op_info): Don't call
+ _gpgme_data_get_as_string if CTX->op_info is NULL.
+
+ * version.c (gpgme_check_engine): Function removed.
+
+2002-09-30 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (keylist_colon_handler): Take care when printing a
+ NULL with the DEBUG.
+
+ * engine-gpgsm.c (struct gpgsm_object_s): New member ANY.
+ (gpgsm_status_handler): Run the colon function to indicate EOF.
+ (_gpgme_gpgsm_set_colon_line_handler): Better reset ANY here.
+
+2002-09-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * conversion.c (_gpgme_hextobyte): Prevent superfluous
+ multiplication with base. Reported by Stéphane Corthésy.
+
+ * keylist.c (gpgme_op_keylist_ext_start): Use private asynchronous
+ operation type in invocation of _gpgme_op_reset.
+
+2002-09-20 Werner Koch <wk@gnupg.org>
+
+ * ath.c: Include sys/time.h if sys/select.h is not available.
+
+2002-09-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (keylist_status_handler): Do not call finish_key() here.
+ (gpgme_op_keylist_ext_start): Set CTX->tmp_key to NULL.
+
+2002-09-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (assuan_libobjs): Remove @LTLIBOBJS@ as we link them
+ into gpgme unconditionally.
+ (libgpgme_la_LIBADD): Change @LIBOBJS@ into @LTLIBOBJS@.
+
+2002-09-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (assuan_libobjs): Use @LTLIBOBJS@ instead @LIBOBJS@.
+
+2002-09-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * debug.c (_gpgme_debug_add): Test *LINE, not LINE.
+ (_gpgme_debug_end): Likewise.
+ Reported by Dr. Stefan Dalibor <Dr.Stefan.Dalibor@bfa.de>.
+
+2002-09-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * posix-io.c (_gpgme_io_select): Don't use a non-constant struct
+ initializer.
+ * version.c (_gpgme_get_program_version): Likewise.
+ Reported by Dr. Stefan Dalibor <Dr.Stefan.Dalibor@bfa.de>.
+
+2002-09-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * conversion.c (_gpgme_decode_c_string): Set DESTP before
+ modifying DEST.
+
+ * conversion.c (_gpgme_decode_c_string): Fix off by one error in
+ last change.
+ * rungpg.c (_gpgme_append_gpg_args_from_signers): Move before
+ _gpgme_op_edit so its prototype is known early on.
+
+ * conversion.c: New file.
+ * util.h: Add prototypes for _gpgme_decode_c_string and
+ _gpgme_hextobyte.
+ * keylist.c (keylist_colon_handler): Call _gpgme_decode_c_string
+ on issuer name.
+ * Makefile.am (libgpgme_la_SOURCES): Add conversion.c
+ * key.c (_gpgme_key_append_name): Replace calls to hextobyte by
+ calls to _gpgme_hextobyte.
+ (hash_key): Likewise.
+
+2002-09-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * op-support.c (_gpgme_op_reset): Set CTX->pending after calling
+ _gpgme_engine_release, as this will reset pending to zero in the
+ event done callback on cancelled operations.
+
+2002-08-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_op_edit): Add args from signers.
+ Suggested by Miguel Coca <e970095@zipi.fi.upm.es>.
+
+ * rungpg.c (_gpgme_gpg_op_edit): Add bogus ctx argument.
+ * rungpg.h: Also to prototype.
+ * engine.c (_gpgme_engine_op_edit): Likewise.
+ * engine.h: Likewise.
+ * edit.c (_gpgme_op_edit_start): Likewise.
+
+2002-08-29 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Implement signer
+ selection.
+ * vasprintf.c (va_copy): Define macro if not yet defined.
+
+2002-08-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * passphrase.c (_gpgme_passphrase_status_handler): Reset
+ CTX->result.passphrase->no_passphrase if passphrase is given (good
+ or bad). Submitted by Jean DIRAISON <jean.diraison@free.fr>.
+
+2002-08-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * posix-io.c (_gpgme_io_spawn): Use a double-fork approach.
+ Return 0 on success, -1 on error.
+ * version.c (_gpgme_get_program_version): Don't wait for the child.
+ * engine.c (_gpgme_engine_housecleaning): Function removed.
+ (do_reaping): Likewise.
+ (_gpgme_engine_add_child_to_reap_list): Likewise.
+ (struct reap_s): Removed.
+ (reap_list): Likewise.
+ (reap_list_lock): Likewise.
+ * engine.h (_gpgme_engine_io_event): Remove prototypes for
+ _gpgme_engine_housecleaning and
+ _gpgme_engine_add_child_to_reap_list.
+ * rungpg.c (_gpgme_gpg_release): Don't add child to reap list.
+ (struct gpg_object_s): Remove PID member.
+ (_gpgme_gpg_new): Don't initialize GPG->pid.
+ (_gpgme_gpg_spawn): Don't set GPG->pid.
+ * wait.c (run_idle): Removed.
+ (gpgme_wait): Run idle_function directly.
+
+2002-08-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * encrypt-sign.c (encrypt_sign_status_handler): Remove dead
+ variables encrypt_info and encrypt_info_len.
+ * trustlist.c (gpgme_op_trustlist_start): Set colon line handler.
+ * posix-sema.c (sema_fatal): Remove function.
+ All these reported by Stéphane Corthésy.
+
+2002-08-23 Werner Koch <wk@gnupg.org>
+
+ * gpgme-config.in: Made --prefix work for --libs.
+
+2002-08-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * ath.h: Update list of symbols that get a prefix: Rename the
+ ath_mutex_*_available symbols to ath_*_available.
+
+2002-08-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * stpcpy.c: New file from gnulib.
+ * Makefile.am (assuan_libobjs): Remove jnlib.
+
+2002-08-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add prototype for gpgme_op_import_ext.
+ * import.c (struct import_result_s): New member `nr_considered'.
+ Rename `any_imported' to `nr_imported'.
+ (import_status_handler): Increment nr_imported. Set nr_considered
+ if appropriate.
+ (gpgme_op_import_ext): New function.
+ (gpgme_op_import): Implement in terms of gpgme_op_import_ext.
+
+2002-08-20 Werner Koch <wk@gnupg.org>
+
+ * gpgme.m4: Replaced with a new and faster version. This does not
+ anymore try to build test programs. If we really need test
+ programs, we should add an option to gpgme-config to do so.
+
+ * vasprintf.c (int_vasprintf): Hack to handle NULL passed for %s.
+
+2002-08-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (_gpgme_set_op_info): Append data on subsequent calls.
+ * encrypt-sign.c (encrypt_sign_status_handler): Remove op_info
+ handling.
+
+2002-08-19 Werner Koch <wk@gnupg.org>
+
+ * decrypt.c (is_token,skip_token): Duplicated from verify.c
+ (gpgme_op_decrypt): Hack to properly return Decryption_Failed..
+ (_gpgme_decrypt_status_handler): Create an operation info.
+
+2002-08-14 Werner Koch <wk@gnupg.org>
+
+ * key.h (struct certsig_s): New. Use it in gpgme_key_s.
+ * key.c (gpgme_key_release): Release it. We need to add more code
+ of course.
+ (_gpgme_key_append_name): Use memset to intialize the struct.
+ * gpgme.h (GPGME_KEYLIST_MODE_SIGS): New.
+ * rungpg.c (_gpgme_gpg_op_keylist): Include sigs in listing depending
+ non the list mode.
+
+ * key.c (gpgme_key_get_string_attr): Use GPGME_ATTR_TYPE to return
+ information about the key type (PGP or X.509).
+ (gpgme_key_get_ulong_attr): Likewise.
+
+ * keylist.c (keylist_colon_handler): Include 1 in the check for
+ valid algorithms so that RSA is usable. Store the issuer name and
+ serial number also for "crs" records. Parse the expire date for
+ subkeys.
+ (set_userid_flags): Put them onto the last appended key.
+
+2002-07-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_op_edit): Use --with-colons.
+
+2002-07-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.c (gpgme_data_read): For GPGME_DATA_TYPE_NONE, return EOF
+ instead an error.
+
+ The following changes make it possible to flush an inbound data
+ pipe before invoking a command handler:
+
+ * posix-io.c (_gpgme_io_select): Accept new argument NONBLOCK to
+ _gpgme_io_select. Set timeout of 0 if this is set.
+ * w32-io.c (_gpgme_io_select): Likewise.
+ * io.h: Add new argument NONBLOCK to _gpgme_io_select prototype.
+ * wait.c (do_select): Add new argument to _gpgme_io_select
+ invocation.
+ * rungpg.h (_gpgme_gpg_set_command_handler): Add new argument
+ linked_data to prototype.
+ * engine.h (_gpgme_engine_set_command_handler): Likewise.
+ * engine.c (_gpgme_engine_set_command_handler): Likewise.
+ * passphrase.c (_gpgme_passphrase_start): Pass NULL as linked_data
+ argument to _gpgme_engine_set_command_handler.
+ * rungpg.c (struct gpg_object_s): New members linked_data and
+ linked_idx in CMD.
+ (_gpgme_gpg_new): Initialize those new members.
+ (_gpgme_gpg_set_command_handler): Accept new argument linked_data.
+ (build_argv): Handle linked_data in the same hack as cb_data.
+ (read_status): If linked_data is in use, flush the pipe before
+ activating the command handler.
+ * gpgme.h: Add prototypes for gpgme_op_edit_start and
+ gpgme_op_edit.
+
+ The next changes export the status codes to the user:
+
+ * decrypt.c (_gpgme_decrypt_status_handler): Likewise, also prefix
+ all STATUS_ with GPGME_.
+ * delete.c (delete_status_handler): Likewise.
+ * decrypt-verify.c (decrypt_verify_status_handler): Likewise.
+ * encrypt.c (_gpgme_encrypt_status_handler): Likewise.
+ (_gpgme_encrypt_sym_status_handler): Likewise.
+ * encrypt-sign.c (encrypt_sign_status_handler): Likewise.
+ * engine-gpgsm.c (parse_status): Likewise.
+ (gpgsm_status_handler): Likewise.
+ (gpgsm_set_recipients): Likewise.
+ * export.c (export_status_handler): Likewise.
+ * genkey.c (genkey_status_handler): Likewise.
+ * import.c (append_xml_impinfo): Likewise.
+ (import_status_handler): Likewise.
+ * keylist.c (keylist_status_handler): Likewise.
+ * passphrase.c (_gpgme_passphrase_status_handler): Likewise.
+ (command_handler): Likewise.
+ * progress.c (_gpgme_progress_status_handler): Likewise.
+ * sign.c (_gpgme_sign_status_handler): Likewise.
+ * trustlist.c (trustlist_status_handler): Likewise.
+ * verify.c (_gpgme_verify_status_handler): Likewise.
+ * gpgme.h (GpgmeEditCb): New type.
+ * rungpg.h (GpgStatusCode): Rename and move to ...
+ * gpgme.h (GpgmeStatusCode): ... this and here.
+ * Makefile.am (status-table.h): Run mkstatus on gpgme.h, not rungpg.h.
+ * mkstatus: Prefix STATUS with GPGME_.
+ * rungpg.h (GpgStatusHandler, GpgCommandHandler): Change type
+ accordingly.
+ * ops.h (_gpgme_verify_status_handler,
+ _gpgme_decrypt_status_handler, _gpgme_sign_status_handler,
+ _gpgme_encrypt_status_handler, _gpgme_passphrase_status_handler,
+ _gpgme_progress_status_handler): Likewise.
+ * rungpg.c (struct gpg_object_s): Likewise for CMD.code.
+
+ These changes add an edit operation to GPGME:
+
+ * context.h (struct gpgme_context_s): New member RESULT.edit. *
+ ops.h: Add prototype for _gpgme_release_edit_result and
+ _gpgme_passphrase_command_handler.
+ * passphrase.c (command_handler): Make non-static and rename to ...
+ (_gpgme_passphrase_command_handler): ... this.
+ (_gpgme_passphrase_start): Use new name for command handler.
+ * types.h: Add EditResult type.
+ * gpgme.c (_gpgme_release_result): Release EDIT result.
+ * edit.c: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add edit.c.
+ (libgpgme_la_LDADD): Rename to libgpgme_la_LIBADD, and include
+ assuan_libobjs.
+ (assuan_libobjs): New variable, set this instead
+ libgpgme_la_LIBADD.
+ * engine.h (_gpgme_engine_op_edit): New prototype.
+ * engine.c (_gpgme_engine_op_edit): New function.
+ * rungpg.h (_gpgme_gpg_op_edit): New prototype.
+ * rungpg.c (_gpgme_gpg_op_edit): New function.
+
+2002-07-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * delete.c (delete_problem): New case ambigious specification.
+ (delete_status_handler): Handle new case (poorly).
+
+2002-07-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_delete): Implement this.
+
+2002-07-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_la_LDADD): Add @LIBOBJS@ for vasprintf and
+ fopencookie.
+ * vasprintf.c: Update to more recent libiberty version.
+ * debug.h: Replace #elsif with #elif.
+
+ Submitted by Stéphane Corthésy:
+ * util.h (vasprintf): Correct prototype.
+ * encrypt-sign.c: Include <stddef.h>.
+ (encrypt_sign_status_handler): Change type of ENCRYPT_INFO_LEN to
+ size_t.
+ * ath-pthread.c: Include <stdlib.h>, not <malloc.h>.
+ * ath-pth.c: Likewise.
+
+2002-07-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.c (fdt_global): Make static. Reported by Stéphane
+ Corthésy.
+
+ * rungpg.c (_gpgme_gpg_op_keylist_ext): Skip empty string
+ patterns. Reported by Stéphane Corthésy.
+
+ * key.c (gpgme_key_get_as_xml): Add OTRUST attribute. Requested
+ by Stéphane Corthésy.
+ (gpgme_key_get_string_attr): Add GPGME_ATTR_SIG_SUMMARY case to
+ silence gcc warning.
+
+ * rungpg.c (_gpgme_gpg_new): Always set utf8 as charset.
+
+2002-07-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_io_cbs): Deal with CTX being NULL.
+
+ * gpgme.c (_gpgme_op_event_cb_user): New function.
+ * op-support.c (_gpgme_op_reset): Support a new mode of operation
+ for private or user event loop. Use new user event callback
+ wrapper.
+ * trustlist.c (gpgme_op_trustlist_start): Use this new mode.
+ * keylist.c (gpgme_op_keylist_start): Likewise.
+
+ * rungpg.c (_gpgme_gpg_io_event): New function.
+ * rungpg.h (_gpgme_gpg_io_event): New prototype.
+ * engine-gpgsm.c (_gpgme_gpg_io_event): New function.
+ * engine-gpgsm.h (_gpgme_gpgsm_io_event): New prototype.
+ * engine.c (_gpgme_engine_io_event): New function.
+ * engine.h (_gpgme_engine_io_event): New prototype.
+ * keylist.c (finish_key): Call _gpgme_engine_io_event, and move
+ the real work for the default IO callback routines to ...
+ (_gpgme_op_keylist_event_cb): ... here. New function.
+ * trustlist.c (trustlist_colon_handler): Signal
+ GPGME_EVENT_NEXT_TRUSTITEM. Move queue manipulation to ...
+ (_gpgme_op_trustlist_event_cb): ... here. New function.
+ * gpgme.c (_gpgme_op_event_cb): Call _gpgme_op_keylist_event_cb
+ and _gpgme_op_trustlist_event_cb when appropriate.
+ * ops.h (_gpgme_op_keylist_event_cb): New prototype.
+ (_gpgme_op_trustlist_event_cb): Likewise.
+ * op-support.c (_gpgme_op_reset): Add comment why we don't use the
+ user provided event handler directly.
+ * gpgme.h (GpgmeRegisterIOCb): Return GpgmeError value, and TAG in
+ a pointer argument.
+ * wait.c (_gpgme_add_io_cb): Likewise.
+ * wait.h (_gpgme_add_io_cb): Likewise for prototype.
+ * rungpg.c (_gpgme_gpg_add_io_cb): Call IO_CBS->add with new
+ argument. Fix up error handling.
+ * engine-gpgsm.c (_gpgme_gpgsm_add_io_cb): Call IO_CBS->add with
+ new argument, fix up error handling.
+
+2002-07-03 Werner Koch <wk@gnupg.org>
+
+ * encrypt.c (status_handler_finish): New.
+ (_gpgme_encrypt_status_handler): Moved some code out to the new
+ function and call this function also in case we get into the
+ status handler with an error which might happen due to a kludge in
+ engine-gpgsm.c
+
+2002-06-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (gpgme_op_keylist_ext_start): Always use our own FD
+ table (eg use synchronous mode).
+
+2002-06-28 Marcus Brinkmann <marcus@g10code.de>
+
+ * ops.h (_gpgme_wait_on_condition): Remove HANG argument from
+ prototype and change return type to GpgmeError.
+ (_gpgme_wait_one): New prototype.
+ * wait.c (gpgme_wait): Replace with the meat from
+ _gpgme_wait_on_condition here, and remove the support for
+ conditions.
+ (_gpgme_wait_on_condition): Remove HANG argument from prototype
+ and change return type to GpgmeError. Replace with meat from
+ _gpgme_wait_one and add support for conditions.
+ (_gpgme_wait_one): Just call _gpgme_wait_on_condition without
+ condition.
+ * keylist.c (gpgme_op_keylist_ext_start): Always use our own FD
+ table (eg use synchronous mode).
+ (gpgme_op_keylist_next): Remove HANG argument from
+ _gpgme_wait_on_condition. Check its return value.
+ * trustlist.c (gpgme_op_trustlist_start): Always use our own FD
+ table (eg use synchronous mode).
+ (gpgme_op_trustlist_next): Remove HANG argument from
+ _gpgme_wait_on_condition. Check its return value.
+
+2002-06-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Fix documentation of key attribute retrieval functions.
+
+2002-06-26 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (map_assuan_error): Map No_Data_Available to EOF.
+
+ * import.c (append_xml_impinfo): Kludge to print fingerprint
+ instead of keyid for use with gpgsm.
+ (import_status_handler): Set a flag to know whether any import
+ occured.
+ (gpgme_op_import): Reurn -1 if no certificate ewas imported.
+
+2002-06-25 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_set_io_cbs) [ENABLE_GPGSM]: Fixed
+ function arguments.
+
+2002-06-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_export): Only export the keys
+ listed in RECP.
+ * export.c (gpgme_op_export): If no data was returned, return
+ GPGME_No_Recipients.
+
+2002-06-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_export): Implement.
+
+2002-06-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_assuan_simple_command): Return ERR.
+ (parse_status): New function.
+ (gpgsm_status_handler): Use parse_status.
+ (gpgsm_assuan_simple_command): Accept new arguments STATUS_FNC and
+ STATUS_FNC_VALUE and process status messages.
+ (gpgsm_set_recipients): Pass new arugments to gpgsm_assuan_simple_command.
+ (gpgsm_set_fd): Likewise.
+ (_gpgme_gpgsm_op_keylist): Likewise.
+ (_gpgme_gpgsm_op_keylist_ext): Likewise.
+ (_gpgme_gpgsm_op_sign): Likewise.
+
+2002-06-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.c (_gpgme_remove_io_cb): Unlock FDT->lock.
+
+2002-06-20 Werner Koch <wk@gnupg.org>
+
+ * rungpg.c (build_argv): Ignore GPG_AGENT_INFO if set but empty.
+
+ * verify.c (calc_sig_summary): Set bad policy for wrong key usage.
+ (skip_token): New.
+ (_gpgme_verify_status_handler): Watch out for wrong key usage.
+ (gpgme_get_sig_string_attr): Hack to return info on the key
+ usage. Does now make use of the former RESERVED argument which
+ has been renamed to WHATIDX.
+ (gpgme_get_sig_ulong_attr): Renamed RESERVED to WHATIDX.
+
+2002-06-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.c (do_select): Return -1 on error, and 0 if nothing to run.
+ (_gpgme_wait_one): Only set HANG to zero if do_select returned an
+ error, or there are no more file descriptors to wait on.
+ (_gpgme_wait_on_condition): Ignore return value from do_select for
+ now.
+
+2002-06-13 Werner Koch <wk@gnupg.org>
+
+ * verify.c (gpgme_op_verify): Make sure that we never access an
+ unitialized result structure.
+
+2002-06-12 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (struct keylist_result_s): New.
+ (_gpgme_release_keylist_result): Release it here
+ (keylist_status_handler): Handle truncated.
+ (append_xml_keylistinfo): New.
+ * gpgme.c (_gpgme_release_result): and use it here.
+ * types.h: Declare the new type here.
+ * context.h (struct gpgme_context_s): Use it here.
+
+2002-06-11 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_release): Close status_cb.fd.
+ (_gpgme_gpgsm_new): Duplicate status file descriptor, so we can
+ use our own close notification mechanism without interfering with
+ assuan.
+
+2002-06-11 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h: Add GPGME_ATTR_SIG_SUMMARY and the GPGME_SIGSUM_
+ constants.
+ * verify.c (calc_sig_summary): New.
+ (gpgme_get_sig_ulong_attr): And use it here.
+
+2002-06-10 Werner Koch <wk@gnupg.org>
+
+ * rungpg.h: Add new status codes TRUNCATED and ERROR.
+ * verify.c (is_token, copy_token): New.
+ (_gpgme_verify_status_handler): Use copy_token, handle the new
+ ERROR status and store the errorcode used withgpgsm and trust
+ status codes.
+ * gpgme.h: New attribute ERRTOK.
+ * key.c (gpgme_key_get_string_attr): Add dummy case for it.
+ (gpgme_get_sig_string_attr): Use it here to return the last error.
+
+2002-06-10 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_start): Move the code that sets the
+ close notification for the status fd to ...
+ (_gpgme_gpgsm_new): ... here.
+ * wait.h: Include "sema.h". Remove prototypes of
+ _gpgme_remove_proc_from_wait_queue and
+ _gpgme_register_pipe_handler. Add prototypes of
+ _gpgme_fd_table_init, _gpgme_fd_table_deinit, _gpgme_fd_table_put,
+ _gpgme_add_io_cb, _gpgme_remove_io_cb, _gpgme_wait_event_cb and
+ _gpgme_wait_one..
+ * wait.c: Remove global variables PROC_QUEUE, PROC_QUEUE_LOCK,
+ FD_TABLE_SIZE, FD_TABLE, FD_TABLE_LOCK. New global variables
+ FDT_GLOBAL, CTX_DONE_LIST, CTX_DONE_LIST_SIZE,
+ CTX_DONE_LIST_LENGTH and CTX_DONE_LIST_LOCK. Remove struct
+ proc_s. Replace struct wait_item_s.
+ (_gpgme_fd_table_init): New function.
+ (_gpgme_fd_table_deinit): Likewise.
+ (_gpgme_fd_table_put): Likewise.
+ (set_process_done): Remove function.
+ (do_select): Take argument FDT. Use that to decide which fds to
+ select on.
+ (_gpgme_remove_proc_from_wait_queue): Remove function.
+ (_gpgme_wait_event_cb): New function.
+ (_gpgme_wait_one): Likewise.
+ (_gpgme_register_pipe_hanldler): Remove function.
+ (_gpgme_add_io_cb): New function.
+ (_gpgme_remove_io_cb): Likewise.
+ (_gpgme_freeze_fd): Remove function.
+ (_gpgme_thaw_fd): Remove function.
+ * rungpg.c (struct fd_data_map_s): Add new member TAG.
+ (struct gpg_object_s): Likewise for STATUS and COLON. Add member
+ IDX to CMD. Add new member IO_CBS.
+ (close_notify_handler): New variables POSSIBLY_DONE and NOT_DONE.
+ For each I/O callback, check if it should be unregistered. If all
+ callbacks have been unregistered, trigger GPGME_EVENT_DONE.
+ Remove member RUNNING.
+ (_gpgme_gpg_new): Initialize new members.
+ (_gpgme_gpg_release): Check PID not RUNNING. Don't call
+ _gpgme_remove_proc_from_wait_queue. Close GPG->CMD.FD if set.
+ (build_argv): Store away the index instead the file descriptor for
+ CMD.
+ (_gpgme_gpg_add_io_cb): New function.
+ (_gpgme_gpg_spawn): Use _gpgme_gpg_add_io_cb to register IO
+ callbacks.
+ (gpg_status_handler): Change return type to void, remove PID
+ argument, close filedescriptor if EOF or error occurs.
+ (read_status): Use _gpgme_gpg_add_io_cb instead _gpgme_thaw_fd.
+ Use IO_CBS->remove instead _gpgme_freeze_fd.
+ (gpg_colon_line_handler): Change return type to void, remove PID
+ argument, close filedescriptor if EOF or error occurs.
+ (command_cb): Use IO_CBS->remove instead _gpgme_freeze_fd.
+ (_gpgme_gpg_set_io_cbs): New function.
+ * rungpg.h (_gpgme_gpg_set_io_cbs): Prototype for
+ _gpgme_gpg_set_io_cbs.
+ * gpgme.h (GpgmeIOCb): New type.
+ (GpgmeRegisterIOCb): Likewise.
+ (GpgmeRemoveIOCb): Likewise.
+ (GpgmeEventIO): Likewise.
+ (GpgmeEventIOCb): Likewise.
+ (struct GpgmeIOCbs): New structure to hold I/O callbacks.
+ (gpgme_set_op_io_cbs): New prototype.
+ (gpgme_get_op_io_cbs): Likewise.
+ * ops.h: New prototype for _gpgme_op_event_cb. Remove prototypes
+ for _gpgme_freeze_fd and _gpgme_thaw_fd. Remove PID argument from
+ _gpgme_data_inbound_handler and _gpgme_data_outbound_handler
+ prototype. Add prototype for _gpgme_op_reset.
+ Add synchronous argument to _gpgme_decrypt_start prototype.
+ * io.h: Beautification.
+ * gpgme.c: Include "wait.h".
+ (gpgme_new): Initialize FDT.
+ (gpgme_set_io_cbs): New function.
+ (gpgme_get_io_cbs): Likewise.
+ (_gpgme_op_event_cb): Likewise.
+ * data.c (_gpgme_data_inbound_handler): Change return type to
+ void. Drop PID argument. Close FD on error and EOF.
+ (write_mem_data): Don't close FD here ...
+ (write_cb_data): ... or here ...
+ (_gpgme_data_outbound_handler): ... but here. Change return type
+ to void. Drop PID argument.
+ * context.h: Include "wait.h".
+ (struct gpgme_context_s): New members FDT and IO_CBS.
+ * op-support.c: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add op-support.c.
+ * ops.h: Add prototype for _gpgme_op_reset().
+ * decrypt.c (_gpgme_decrypt_start): New argument SYNCHRONOUS. Use
+ _gpgme_op_reset.
+ (gpgme_op_decrypt_start): Add synchronous argument.
+ (gpgme_op_decrypt): Likewise. Use _gpgme_wait_one instead
+ gpgme_wait.
+ * delete.c (gpgme_op_delete_start): Rename to ...
+ (_gpgme_op_delete_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_delete_start): Just a wrapper around
+ _gpgme_op_delete_start now.
+ (gpgme_op_delete): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * encrypt.c: Include "wait.h".
+ (ggpgme_op_encrypt_start): Rename to ...
+ (_gpgme_op_encrypt_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_encrypt_start): Just a wrapper around
+ _gpgme_op_encrypt_start now.
+ (gpgme_op_encrypt): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * encrypt_sign.c (gpgme_op_encrypt_sign_start): Rename to ...
+ (_gpgme_op_encrypt_sign_start): ... this. New argument
+ SYNCHRONOUS. Use _gpgme_op_reset. Make function static.
+ (gpgme_op_encrypt_sign_start): Just a wrapper around
+ _gpgme_op_encrypt_sign_start now.
+ (gpgme_op_encrypt_sign): Add synchronous argument. Use
+ _gpgme_wait_one instead gpgme_wait.
+ * export.c (gpgme_op_export_start): Rename to ...
+ (_gpgme_op_export_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_export_start): Just a wrapper around
+ _gpgme_op_export_start now.
+ (gpgme_op_export): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * genkey.c (gpgme_op_genkey_start): Rename to ...
+ (_gpgme_op_genkey_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_genkey_start): Just a wrapper around
+ _gpgme_op_genkey_start now.
+ (gpgme_op_genkey): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * import.c (gpgme_op_import_start): Rename to ...
+ (_gpgme_op_import_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_import_start): Just a wrapper around
+ _gpgme_op_import_start now.
+ (gpgme_op_import): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * keylist.c (gpgme_op_keylist_start): Use _gpgme_op_reset.
+ (gpgme_op_keylist_ext_start): Likewise.
+ * sign.c (gpgme_op_sign_start): Rename to ...
+ (_gpgme_op_sign_start): ... this. New argument SYNCHRONOUS. Use
+ _gpgme_op_reset. Make function static.
+ (gpgme_op_sign_start): Just a wrapper around _gpgme_op_sign_start
+ now.
+ (gpgme_op_sign): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * trustlist.c (gpgme_op_trustlist_start): Use _gpgme_op_reset.
+ * verify.c (gpgme_op_verify_start): Rename to ...
+ (_gpgme_op_verify_start): ... this. New argument SYNCHRONOUS.
+ Use _gpgme_op_reset. Make function static.
+ (gpgme_op_verify_start): Just a wrapper around
+ _gpgme_op_verify_start now.
+ (gpgme_op_verify): Add synchronous argument. Use _gpgme_wait_one
+ instead gpgme_wait.
+ * engine-gpgsm.c (iocb_data_t): New type.
+ (struct gpgsm_object_s): New member status_cb. Replace input_fd
+ and input_data with input_cb. Replace output_fd and output_data
+ with output_cb. Replace message_fd and message_data with
+ message_cb. New member io_cbs.
+ (_gpgme_gpgsm_new): Initialize all new members (and drop the old
+ ones).
+ (close_notify_handler): New variable POSSIBLY_DONE. For each I/O
+ callback, check if it should be unregistered. If all callbacks
+ have been unregistered, trigger GPGME_EVENT_DONE.
+ (_gpgme_gpgsm_release): Remove variable PID. Use new variable
+ names to close the file descriptors.
+ (_gpgme_gpgsm_op_decrypt): Use new variable names,
+ (_gpgme_gpgsm_op_encrypt): Likewise.
+ (_gpgme_gpgsm_op_genkey): Likewise.
+ (_gpgme_gpgsm_op_import): Likewise.
+ (_gpgme_gpgsm_op_keylist): Likewise.
+ (_gpgme_gpgsm_op_keylist_ext): Likewise.
+ (_gpgme_gpgsm_op_sign): Likewise.
+ (_gpgme_gpgsm_op_verify): Likewise.
+ (gpgsm_status_handler): Drop argument PID. Change return type to
+ void. Close status pipe before returning because of EOF or error.
+ (_gpgme_gpgsm_add_io_cb): New function.
+ (_gpgme_gpgsm_start): Use _gpgme_gpgsm_add_io_cb to register
+ callback function.
+ (_gpgme_gpgsm_set_io_cbs): New function.
+ * engine-gpgsm.h: New prototype for _gpgme_gpgsm_set_io_cbs.
+ * engine.c (_gpgme_engine_set_io_cbs): New function.
+ * engine.h: New prototype for _gpgme_engine_set_io_cbs.
+
+2002-06-04 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_la_SOURCES): Remove mutex.h.
+
+2002-06-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * key.c: Include <ctype.h>.
+ (_gpgme_key_append_name): Skip one more char when
+ processing escaped char. Submitted by Marc Mutz <mutz@kde.org>.
+ Handle hexadecimal encodings. Also reported by Marc. Thanks!
+
+2002-06-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * ath.h: Enable the _gpgme_ prefix. Fix all those prefix macros.
+ * posix-sema.c: Use that prefix here.
+ * posix-io.c: Include "ath.h".
+ (_gpgme_io_read): Use _gpgme_ath_read instead read.
+ (_gpgme_io_write): Use _gpgme_ath_write instead write.
+ (_gpgme_io_waitpid): Use _gpgme_ath_waitpid instead waitpid.
+ (_gpgme_io_select): Use _gpgme_ath_select instead select.
+
+2002-06-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (ath_components): New variable.
+ (ath_components_pthread): Likewise.
+ (ath_components_pth): Likewise.
+ (system_components): Add ath_componentes.
+
+ * ath.h: New file.
+ * ath.c: Likewise.
+ * ath-pthread.c: Likewise.
+ * ath-pth.c: Likewise.
+ * posix-sema.c (_gpgme_sema_cs_enter): Rework to use the ATH
+ interface.
+ * mutex.h: Remove file.
+
+2002-05-30 Werner Koch <wk@gnupg.org>
+
+ * key.c (gpgme_key_get_string_attr): Return NULL when asking for
+ an issuer with IDX > 0. We don't support altIssuerNames for now.
+
+2002-05-22 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): Aehmm, added
+ missing variable definition. Oohh - Marcus was faster.
+
+2002-05-22 Marcus Brinkmann <marcus@gnu.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): Fix last change.
+
+2002-05-21 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist)
+ (_gpgme_gpgsm_op_keylist_ext): Pass the keylist mode to gpgsm.
+
+2002-05-10 Werner Koch <wk@gnupg.org>
+
+ * key.h (gpgme_key_s): Add OTRUST.
+ * keylist.c (set_ownertrust): New.
+ (keylist_colon_handler): Get the ownertrust value
+ * key.c (gpgme_key_get_string_attr,gpgme_key_get_ulong_attr):
+ Return that value.
+
+2002-05-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * w32-util.c: New static variable GET_PATH_LOCK.
+ (_gpgme_get_gpg_path): Remove superfluous NULL initializer.
+ Take lock while determining path.
+ (_gpgme_get_gpgsm_path): Likewise.
+ * version.c (do_subsystem_inits): Set DONE to 1 after
+ initialization.
+ (gpgme_get_engine_info): New variable ENGINE_INFO_LOCK. Take lock
+ while determining engine info.
+ * rungpg.c (_gpgme_gpg_get_version): New variable
+ GPG_VERSION_LOCK. Take the lock while determining the program
+ version.
+ * posix-io.c: Include "sema.h".
+ (_gpgme_io_spawn): New variable FIXED_SIGNALS_LOCK. Take the lock
+ while fixing the Q_SIGNALS.
+ (_gpgme_io_select): Make READFDS and WRITEFDS non-static.
+ * key.c: Include "sema.h". New globals KEY_CACHE_LOCK and
+ KEY_REF_LOCK.
+ (capabilities_to_string): Make STRINGS very const.
+ (_gpgme_key_cache_add): Lock the key cache.
+ (_gpgme_key_cache_get): Likewise.
+ (gpgme_key_ref, gpgme_key_release): Lock the key_ref_lock.
+ * import.c (append_xml_impinfo): Make IMPORTED_FIELDS and
+ IMPORT_RES_FIELDS very const. Make FIELD and FIELD_NAME a litle
+ const.
+ * engine.c (_gpgme_engine_get_info): New variable
+ ENGINE_INFO_LOCK. Take lock while determining engine info.
+ * engine-gpgsm.c: Include "sema.h".
+ (_gpgme_gpgsm_get_version): New variable GPGSM_VERSION_LOCK. Take
+ lock while getting program version.
+
+2002-05-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * debug.h: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add debug.h.
+ * util.h: Removed all prototypes and declarations related to
+ debugging. Include "debug.h".
+
+ * debug.c (debug_level): Comment variable and remove superfluous
+ zero initializer.
+ (errfp): Likewise.
+ (_gpgme_debug_enabled): Function removed.
+ (struct debug_control_s): Definition removed.
+ (_gpgme_debug_level): Function removed.
+ (_gpgme_debug_begin): Rewritten to use vasprintf. Accept a
+ pritnf-style format specification and a variable number of
+ arguments.
+ (_gpgme_debug_add): Rewritten using vasprintf. Expect that format
+ starts out with "%s" for simplicity.
+ (_gpgme_debug_end): Rewritten using vasprintf. Do not accept a
+ TEXT argument anymore.
+
+ * posix-io.c (_gpgme_io_select): Use new level argument for
+ DEBUG_BEGIN instead explicit if construct.
+
+ * debug.c (debug_init): Remove superfluous zero initializer,
+ remove volatile flag of INITIALIZED. Do not use the
+ double-checked locking algorithm, it is fundamentally flawed and
+ will empty your fridge (on a more serious note, despite the
+ volatile flag it doesn't give you the guarantee you would expect,
+ for example on a DEC Alpha or an SMP machine. The volatile only
+ serializes accesses to the volatile variable, but not to the other
+ variables).
+
+2002-05-03 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): Redirect any gpgsm error
+ output to /dev/null.
+
+ * verify.c (gpgme_get_sig_key): Set the protocol of the listctx.
+ * gpgme.c (gpgme_get_protocol): New.
+
+ * data.c (gpgme_data_write): Changed type of BUFFER to void*.
+ (gpgme_data_read): Ditto.
+
+ * verify.c (_gpgme_verify_status_handler): Handle TRUST_* status
+ lines so that a claim can be made without looking up the key.
+ (gpgme_get_sig_string_attr): New.
+ (gpgme_get_sig_ulong_attr): New.
+
+ * gpgme.h (GpgmeAttr): Added GPGME_ATTR_SIG_STATUS.
+
+ * rungpg.h: Add new status codes from gpg 1.0.7 and formatted the
+ list to align with the status.h file from gnupg.
+
+ * gpgme.h (GpgmeSigStat): Add _GOOD_EXP and _GOOD_EXPKEY.
+ * verify.c (_gpgme_verify_status_handler, finish_sig): Handle
+ these new status codes. Store the expiration time
+
+2002-04-27 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h (GpgmeData_Encoding): New.
+ * data.c (gpgme_data_get_encoding,gpgme_data_set_encoding): New.
+ * engine-gpgsm.c (map_input_enc): New. Use it in all local
+ functions where the INPUT command gets send.
+
+2002-04-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Close the output
+ descriptor only when we don't need it anymore. Close the message
+ descriptor if we don't need it.
+
+2002-04-26 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am (libgpgme_la_LIBADD): Use libtool libraries.
+
+2002-04-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_release): Call gpgme_data_release on
+ GPG->cmd.cb_data, not xfree.
+
+2002-04-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): Set the display, ttyname,
+ ttytype, lc_ctype and lc_messages options in the server.
+
+2002-04-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (map_assuan_error): Add new error codes.
+
+2002-04-23 Werner Koch <wk@gnupg.org>
+
+ * key.c (gpgme_key_get_ulong_attr): Swapped use of can_encrypt and
+ can_certify to return the requested values.
+
+2002-04-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_get_progress_cb): Allow either return parameter
+ to be NULL.
+ (gpgme_get_passphrase_cb): Likewise.
+
+2002-04-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_get_passphrase_cb): New function.
+ (gpgme_get_progress_cb): New function.
+ * gpgme.h: Add new prototypes for gpgme_get_passphrase_cb and
+ gpgme_get_progress_cb.
+
+2002-03-28 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h (GpgmeAttr): Add values for issuer and chaining.
+ * key.h (gpgme_key_s): Add issuer and chaining elements for X509.
+ * keylist.c (keylist_colon_handler): Store them.
+ * key.c (gpgme_key_release): Free them.
+ (gpgme_key_get_as_xml,gpgme_key_get_string_attr): Print them.
+
+2002-03-26 Werner Koch <wk@gnupg.org>
+
+ * Makefile.am (libgpgme_la_SOURCES): Add mutex.h
+
+2002-03-21 Werner Koch <wk@gnupg.org>
+
+ * util.h [!HAVE_FOPENCOOKIE]: Make sure off_t and ssize_t are
+ defined.
+
+2002-03-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (system_components): New variable, set depending on
+ HAVE_DOSISH_SYSTEM.
+ (libgpgme_la_SOURCES): Use system_components. Remove `syshdr.h'.
+ * syshdr.h: File removed.
+
+ * posix-io.c: Remove !HAVE_DOSISH_SYSTEM safeguard. Clean up source.
+ * posix-sema.c: Likewise.
+ * posix-util.c: Likewise.
+
+ * w32-io.c: Remove HAVE_DOSISH_SYSTEM safeguard.
+ * w32-sema.c: Likewise.
+ * w32-util.c: Likewise.
+
+ * posix-io.c: Include `unistd.h', do not include `syshdr.h'.
+ * posix-sema.c: Likewise.
+ * w32-io.c: Include `io.h', do not include `syshdr.h'
+ * w32-sema.c: Likewise.
+ * w32-util.c: Likewise.
+ * data.c: Do not include `syshdr.h'.
+ * wait.c: Likewise.
+ * wait.h: Code cleanup.
+
+ * mutex.h: New file.
+ * posix-sema.c: Implement.
+
+2002-03-08 Werner Koch <wk@gnupg.org>
+
+ * util.h [!HAVE_FOPENCOOKIE]: Fixed type. Thanks to Frank Heckenbach.
+
+2002-03-07 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h (gpgme_op_keylist_ext_start): Add prototype.
+
+2002-03-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * encrypt.c (_gpgme_encrypt_sym_status_handler): New function.
+ (gpgme_op_encrypt_start): New variable SYMMETRIC, set it if RECP
+ is null, and if it is set, use _gpgme_encrypt_sym_status_handler
+ as status handler and run _gpgme_passphrase_start.
+ * rungpg.c (_gpgme_gpg_op_encrypt): If RECP is zero, do symmetric
+ encryption.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): If RECP is zero,
+ return error value.
+
+ * rungpg.c (_gpgme_gpg_op_verify): Add "--" argument.
+
+2002-03-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * passphrase.c (_gpgme_passphrase_status_handler): Also set the
+ error No_Passphrase if only a bad passphrase was provided.
+
+2002-03-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_op_verify): If TEXT is of mode
+ GPGME_DATA_MODE_IN, construct a command line that stores the
+ plaintext in TEXT.
+ * verify.c (gpgme_op_verify_start): Accept TEXT being
+ uninitialized, and in this case interpret SIG as a normal or
+ cleartext signature and TEXT as a return data object.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Likewise.
+
+2002-03-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext) [!ENABLE_GPGSM]:
+ Add stub function.
+
+2002-02-28 Werner Koch <wk@gnupg.org>
+
+ * key.h (subkey_s): New member expires_at.
+ * keylist.c (keylist_colon_handler): Set it here
+ * key.c (gpgme_key_get_as_xml,gpgme_key_get_ulong_attr): Return it.
+
+2002-02-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.h (_gpgme_gpg_op_keylist_ext): New prototype.
+ * rungpg.c (_gpgme_gpg_op_keylist_ext): New function.
+ * engine-gpgsm.h (_gpgme_gpgsm_op_keylist_ext): New prototype.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): New function.
+ * engine.h (_gpgme_engine_op_keylist_ext): New prototype.
+ * engine.c (_gpgme_engine_op_keylist_ext): New function.
+ * keylist.c (gpgme_op_keylist_ext_start): New function.
+
+2002-02-27 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add new error code GPGME_Invalid_Recipient.
+ * encrypt.c (struct encrypt_result_s): New member invalid_recipients,
+ rename no_recipients to no_valid_recipients.
+ (_gpgme_encrypt_status_handler): Include error for invalid
+ recipients.
+ * engine-gpgsm.c (gpgsm_set_recipients): Change type of first
+ argument to GpgsmObject. Use that to report back the status about
+ the recipients.
+
+2002-02-26 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (_gpgme_verify_status_handler): Fix the last change.
+
+2002-02-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c (_gpgme_engine_op_encrypt_sign): New function.
+ * engine.h (_gpgme_engine_op_encrypt_sign): New prototype.
+ * rungpg.c (_gpgme_append_gpg_args_from_signers): New function.
+ (_gpgme_gpg_op_sign): Use that new function.
+ (_gpgme_gpg_op_encrypt_sign): New function.
+ * rungpg.h (_gpgme_gpg_op_encrypt_sign): New prototype.
+ * gpgme.h (gpgme_op_encrypt_sign_start): New prototype.
+ (gpgme_op_encrypt_sign): Likewise.
+ * Makefile.am (libgpgme_la_SOURCES): Add encrypt-sign.c.
+ * ops.h (_gpgme_encrypt_status_handler): Add prototype.
+ (_gpgme_sign_status_handler): Add prototype.
+ * sign.c (sign_status_handler): Rename to ...
+ (_gpgme_sign_status_handler): ... this and make non-static.
+ * encrypt.c (encrypt_status_handler): Rename to ...
+ (_gpgme_encrypt_status_handler): ... this and make non-static.
+ * encrypt.c (gpgme_op_encrypt_start): Use new status handler name.
+ * sign.c (gpgme_op_sign_start): Likewise.
+
+2002-02-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (_gpgme_verify_status_handler): Parse the args line to
+ see if the problem is due to a missing key, and report that back
+ to the user.
+
+2002-02-25 Marcus Brinkmann <marcus@g10code.de>
+
+ * context.h (struct gpgme_context_s): New member include_certs.
+ * gpgme.h (gpgme_set_include_certs): Add prototype.
+ (gpgme_get_include_certs): Likewise.
+ * gpgme.c (gpgme_set_include_certs): New function.
+ (gpgme_get_include_certs): Likewise.
+ (gpgme_new): Set include_certs to 1 (the default).
+ * engine.c (_gpgme_engine_op_sign): Accept new argument include_certs,
+ and pass it to _gpgme_gpgsm_op_sign.
+ * engine.h (_gpgme_engine_op_sign): Likewise for prototype.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Accept new argument
+ include_certs and handle it.
+ * engine-gpgsm.h (_gpgme_gpgsm_start): Add new argument include_certs.
+ * sign.c (gpgme_op_sign_start): Add new argument to
+ _gpgme_engine_op_sign call.
+
+2002-02-14 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (gpgme_op_keylist_start): Do not use a verbose listing.
+
+2002-02-13 Werner Koch <wk@gnupg.org>
+
+ * vasprintf.c, fopencookie.c: Add replacement functions.
+ * util.h: Add prototypes for them.
+
+2002-02-09 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_assuan_simple_command): Return 0 if we
+ reach the end of the function.
+
+2002-02-09 Marcus Brinkmann <marcus@g10code.de>
+
+ * genkey.c (gpgme_op_genkey_start): Fix logic in validity check.
+ (gpgme_op_genkey_start): Skip newlines after opening tag.
+
+ * engine-gpgsm.c (_gpgme_gpgsm_start): Remove cruft.
+
+2002-02-08 Marcus Brinkmann <marcus@g10code.de>
+
+ * genkey.c (gpgme_op_genkey_start): Allow PUBKEY and SECKEY to be
+ set, and pass them down to the crypto engine.
+ * engine-gpgsm.h (_gpgme_gpgsm_start): New arguments PUBKEY and SECKEY.
+ * engine.h: Likewise.
+ * rungpg.h (_gpgme_gpg_spawn): Likewise.
+ * engine.c (_gpgme_engine_op_genkey): Likewise. Use those
+ arguments.
+ * rungpg.c (_gpgme_gpg_op_genkey): Likewise. Complain if those
+ arguments are set.
+ * engine-gpgsm.c (_gpgme_gpgsm_op_genkey): Likewise. Implement
+ function.
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Beautify comment.
+
+2002-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_op_keylist): Remove handling of keylist
+ mode (for now).
+
+2002-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.c (gpgme_wait): Add new argument STATUS, in which the
+ status of the returned context is returned.
+ (_gpgme_wait_on_condition): Rework the function a bit, to make it
+ aware of cancelled processes, and to allow to use gpgme_wait with
+ CTX being NULL (as documented in the source).
+ (struct proc_s): New member REPORTED.
+ * gpgme.h: Fix prototype.
+ * verify.c (gpgme_op_verify): Fix use of gpgme_wait.
+ * sign.c (gpgme_op_sign): Likewise.
+ * import.c (gpgme_op_import): Likewise.
+ * genkey.c (gpgme_op_genkey): Likewise.
+ * export.c (gpgme_op_export): Likewise.
+ * encrypt.c (gpgme_op_encrypt): Likewise.
+ * delete.c (gpgme_op_delete): Likewise.
+ * decrypt-verify.c (gpgme_op_decrypt_verify): Likewise.
+
+2002-02-06 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_keylist_mode): Possibly return an error
+ value.
+ (gpgme_get_keylist_mode): New function.
+ (gpgme_new): Set the default for keylist_mode member of CTX.
+
+ * gpgme.h (gpgme_set_keylist_mode): Fix prototype.
+ (gpgme_get_keylist_mode): New prototype.
+ (GPGME_KEYLIST_MODE_LOCAL): New macro.
+ (GPGME_KEYLIST_MODE_EXTERN): Likewise..
+
+2002-02-02 Marcus Brinkmann <marcus@g10code.de>
+
+ This patch has gotten a bit large... mmh. The main thing that
+ happens here is that error values are now not determined in the
+ operation function after gpgme_wait completed, but in the status
+ handler when EOF is received. It should always be the case that
+ either an error is flagged or EOF is received, so that after a
+ gpgme_wait you should never have the situation that no error is
+ flagged and EOF is not received. One problem is that the engine
+ status handlers don't have access to the context, a horrible
+ kludge works around this for now. All errors that happen during a
+ pending operation should be catched and reported in ctx->error,
+ including out-of-core and cancellation. This rounds up neatly a
+ couple of loose ends, and makes it possible to pass up any errors
+ in the communication with the backend as well. As a bonus, there
+ will be a function to access gpgme->wait, so that the operations
+ can truly be implemented with their _start function.
+
+ * engine-gpgsm.c (gpgsm_status_handler): Horrible kludge to report
+ error back to the context.
+ * rungpg.c (gpg_status_handler): Same horrible kludge applied here.
+
+ * engine-gpgsm.c (gpgsm_assuan_simple_command): Add error checking.
+
+ * wait.c (_gpgme_wait_on_condition): If canceled, set CTX->error
+ to a value indication that.
+
+ * verify.c (add_notation): Set error, not out_of_core.
+ (finish_sig): Likewise.
+ (gpgme_op_verify_start): Don't clear out_of_core.
+ (_gpgme_verify_status_handler): At EOF, clean up the notation data.
+ (gpgme_op_verify): And don't do it here.
+
+ * trustlist.c (trustlist_status_handler): Check error, not out_of_core.
+ (gpgme_op_trustlist_start): Don't clear out_of_core.
+ (gpgme_op_trustlist_next): Check error, not out_of_core.
+ (gpgme_op_trustlist_end): Likewise.
+
+ * ops.h (test_and_allocate_result): New macro.
+ (_gpgme_passphrase_result): Remove prototype.
+ * delete.c (gpgme_op_delete): Return error from context.
+ (delete_status_handler): Use macro test_and_allocate_result.
+ Perform error checking at EOF.
+ (gpgme_op_delete_start): Release result.
+ * passphrase.c (_gpgme_passphrase_status_handler): Use macro
+ test_and_allocate_result, and perform error checking here.
+ (_gpgme_passphrase_result): Function removed.
+ * sign.c (gpgme_op_sign_start): Do not set out_of_core to zero.
+ (gpgme_op_sign): Just return the error value from the context.
+ (sign_status_handler): Only progress if no error is set yet. If
+ we process an EOF, set the resulting error value (if any).
+ * decrypt.c (_gpgme_decrypt_result): Function removed.
+ (create_result_struct): Function removed.
+ (_gpgme_decrypt_status_handler): Use macro test_and_allocate_result,
+ caclulate error on EOF, do not progress with errors.
+ (_gpgme_decrypt_start): Do not set out_of_core to zero.
+ (gpgme_op_decrypt): Just return the error value from the context.
+ * encrypt.c (encrypt_status_handler): Perform the error checking
+ here.
+ (gpgme_op_encrypt_start): Do not clear out_of_core.
+ * export.c (export_status_handler): Return if error is set in context.
+ (gpgme_op_export_start): Release result.
+ (gpgme_op_export): Return error from context.
+ * decrypt-verify.c (gpgme_op_decrypt_verify): Return the error in
+ the context.
+ * genkey.c (genkey_status_handler): Use macro
+ test_and_allocate_result. Perform error checking at EOF.
+ (gpgme_op_genkey): Just return the error from context.
+ * import.c (gpgme_op_import): Return the error from context.
+ (import_status_handler): Use macro test_and_allocate_result.
+ * keylist.c (gpgme_op_keylist_start): Do not clear out_of_core.
+ (gpgme_op_keylist_next): Return error of context.
+ (keylist_colon_handler): Set error instead out_of_code.
+ (finish_key): Likewise.
+
+ * context.h: Remove member out_of_core, add member error.
+ * gpgme.c (_gpgme_release_result): Clear error flag.
+
+ * engine.h (_gpgme_engine_get_error): New prototype.
+ * engine.c (_gpgme_engine_get_error): New function.
+ * engine-gpgsm.c (_gpgme_gpgsm_get_error): New function.
+
+ * engine-gpgsm.c (map_assuan_error): New function.
+ (gpgsm_assuan_simple_command): Change return type to GpgmeError,
+ use the new function to map error values.
+ (gpgsm_set_fd): Change return type tp GpgmeError.
+ (_gpgme_gpgsm_op_decrypt): Change type of ERR to GpgmeError.
+ (gpgsm_set_recipients): Likewise. Change type of return value
+ equivalently. Adjust error values.
+ (_gpgme_gpgsm_op_import): Likewise.
+ (_gpgme_gpgsm_op_sign): Likewise.
+ (struct gpgsm_object_s): New member error.
+ (gpgsm_status_handler): Set error if error occurs. Determine
+ error number from ERR line received. If assuan_read_line fails,
+ terminate the connection.
+
+2002-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (MOSTLYCLEANFILES): New variable.
+
+2002-02-01 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_status_handler): At error, terminate the
+ connection to the server.
+
+2002-01-31 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.h: Add STATUS_KEY_CREATED.
+
+ * progress.c: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add progress.c.
+
+ * genkey.c (genkey_status_handler): Use
+ _gpgme_progress_status_handler. Add check for status.
+ (struct genkey_result_s): New structure.
+ (_gpgme_release_genkey_result): New function.
+ (gpgme_op_genkey): Check for error.
+ * gpgme.c (_gpgme_release_result): Call
+ _gpgme_release_genkey_result.
+ * ops.h (_gpgme_release_genkey_result): Add prototype.
+ * types.h (GenKeyResult): New type.
+ * context.h (gpgme_context_s): Add GenKeyResult to member result.
+
+2002-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (_gpgme_release_result): Call
+ _gpgme_release_delete_result.
+ * ops.h (_gpgme_release_delete_result): Add prototype.
+ * types.h (DeleteResult): New type.
+ * context.h (gpgme_context_s): Add DeleteResult to member result.
+
+ * delete.c (enum delete_problem): New type.
+ (struct delete_result_s): New structure.
+ (_gpgme_release_delete_result): New function.
+ (delete_status_handler): Implement more status codes.
+ (gpgme_op_delete): Return error on failure.
+
+ * import.c (MAX_IMPORTED_FIELDS): Bump up to 14.
+
+2002-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * import.c (struct import_result_s): New structure.
+ (_gpgme_release_import_result): New function.
+ (append_xml_impinfo): Likewise.
+ (import_status_handler): Implement.
+ * gpgme.c (_gpgme_release_result): Add call to
+ _gpgme_release_import_result.
+ * ops.h (_gpgme_release_import_result): Add prototype.
+ * types.h (ImportResult): New type.
+ * context.h (gpgme_context_s): Add ImportResult to member result.
+
+ * encrypt.c (gpgme_op_encrypt): Code clean up.
+
+2002-01-30 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add lots of comment and fix the formatting. Add
+ gpgme_trustlist_end prototype.
+
+2002-01-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h: Add new type GpgmeIdleFunc. Change type of
+ gpgme_register_idle to return and accept this type.
+ * wait.c (gpgme_register_idle): Fix type.
+ Save and return old value of idle_function.
+
+2002-01-29 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Implement secret only mode.
+
+ * keylist.c (keylist_colon_handler): Add support for the new "crs"
+ record type.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_release): Call assuan_disconnect,
+ not assuan_pipe_disconnect.
+
+ * Makefile.am (libgpgme_la_LIBADD): Change to link assuan and
+ jnlib (needed by assuan) statically into libgpgme. Linking a
+ static library into a shared library this way is not portable.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (GpgmePassphraseCb): Change type of R_HD from void* to
+ void**.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.c (gpgme_data_new_from_filepart): Change type of LENGTH
+ from off_t to size_t.
+ * gpgme.h: Likewise.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * wait.c (_gpgme_wait_on_condition): If the process finished,
+ reset the pending flag. Also if the operation was cancelled.
+
+ (struct proc_s): Rename READY to DONE.
+ (wait_item_s): Likewise.
+ (set_process_ready): Rename to ...
+ (set_process_done): ... this.
+ (_gpgme_remove_proc_from_wait_queue): Call set_process_done
+ instead set_process_ready.
+ (_gpgme_wait_on_condition): Likewise.
+ (do_select): Rename READY to DONE.
+
+ * verify.c (gpgme_op_verify): Do not set pending to zero here.
+ * sign.c (gpgme_op_sign): Likewise.
+ * import.c (gpgme_op_import): Likewise.
+ * genkey.c (gpgme_op_genkey): Likewise.
+ * export.c (gpgme_op_export): Likewise.
+ * encrypt.c (gpgme_op_encrypt): Likewise.
+ * delete.c (gpgme_op_delete): Likewise.
+ * decrypt-verify.c (gpgme_op_decrypt_verify): Likewise.
+ * decrypt.c (gpgme_op_decrypt): Likewise.
+
+2002-01-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * export.c: Cleanup.
+
+2002-01-15 Marcus Brinkmann <marcus@g10code.de>
+
+ * trustlist.c: Various source clean ups.
+ (my_isdigit): Removed.
+ (gpgme_op_trustlist_end): New function.
+
+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>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): Replace General_Error with
+ Pipe_Error where appropriate.
+
+2001-12-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c: Include `string.h'. Reported by Stéphane Corthésy.
+
+ * version.c (get_engine_info): Remove prototype.
+
+2001-12-19 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): New variable CHILD_FDS.
+ Fill it with the servers fds, and pass it to assuan_pipe_connect.
+
+2001-12-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (gpgme_op_keylist_end): New function.
+ * gpgme.h (gpgme_op_keylist_end): New prototype.
+
+ * engine.h (gpgme_engine_check_version): Move prototype to ...
+ * gpgme.h (gpgme_engine_check_version): ... here.
+
+ * genkey.c (gpgme_op_genkey_start): Remove unused variable.
+
+2001-12-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * version.c (gpgme_get_engine_info): Reimplemented.
+ (gpgme_check_engine): Reimplemented.
+ (_gpgme_compare_versions): Return NULL if MY_VERSION is NULL.
+
+ * engine.c: Include `io.h'.
+ (gpgme_engine_get_info): New function.
+ * engine.h (gpgme_engine_check_version, _gpgme_engine_get_info):
+ Add prototype.
+
+2001-12-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (struct reap_s, reap_list, reap_list_lock): Moved to ...
+ * engine.c (struct reap_s, reap_list, reap_list_lock): ... here.
+ Include `time.h', `sys/types.h', `assert.h', and `sema.h'.
+
+ * rungpg.c (_gpgme_engine_add_child_to_reap_list): New function.
+ (do_reaping, _gpgme_gpg_housecleaning): Moved to ...
+ * engine.c (do_reaping, _gpgme_engine_housecleaning): ... here.
+ * rungpg.c (_gpgme_gpg_release): Replace code that is now in its
+ own function by call to _gpgme_engine_add_child_to_reap_list().
+
+ * wait.c: Include `engine.h'.
+ (run_idle): Call _gpgme_engine_housecleaning(), not
+ _gpgme_gpg_housecleaning().
+
+2001-12-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * key.c (_gpgme_key_append_name): Append, not prepend, the uid.
+ Initialize the next field of the uid structure.
+ (gpgme_key_get_as_xml): Do not list last uid first.
+
+2001-12-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_set_colon_line_handler): New
+ function [!ENABLE_GPGSM].
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_verify): Put TEXT into
+ message_data, not SIG.
+ (_gpgme_gpgsm_op_sign): Use `--detached', not `--detach'.
+
+ * sign.c (sign_status_handler): Call
+ _gpgme_passphrase_status_handler early.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c: Revert last change.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_status_handler): Freeze the output file
+ handler when ending this operation, otherwise the wait function
+ will sit on it.
+
+2001-12-14 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic.
+ (_gpgme_gpgsm_new): Initialize some more members.
+ (_gpgme_gpgsm_release): Free the colon line handler's attic line.
+ (gpgsm_status_handler): Rework the inline-data processing.
+
+2001-12-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_spawn): Do not add the fds to the child
+ list that are not dup'ed, for those the close-on-exec flag is set
+ now.
+ * version.c (_gpgme_get_program_version): Remove first entry in
+ CFD, as the close-on-exec flag is now set for this fd.
+
+2001-12-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): Do not add `armor'
+ option to `ENCRYPT'.
+ * engine-gpgsm.c (gpgsm_set_recipients): Free LINE when returning
+ successfully.
+
+2001-12-13 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (close_notify_handler): New function.
+ (_gpgme_gpgsm_new): Manage the file descriptors a
+ bit differently. Do not set close-on-exec flags.
+ (_gpgme_gpgsm_op_decrypt): Do not set message_fd
+ to -1, this is done by the close handler.
+ (_gpgme_gpgsm_op_encrypt): Likewise.
+ (_gpgme_gpgsm_op_import): Likewise (also for output_fd).
+ (_gpgme_gpgsm_op_keylist): Likewise (also for input_fd and output_fd).
+ (_gpgme_gpgsm_op_sign): Likewise.
+ (_gpgme_gpgsm_op_verify): Likewise, but for output_fd.
+
+ * posix-io.c (_gpgme_io_pipe): Set the close-on-exec flag for the
+ non-inherited file descriptor index of the pipe.
+
+2001-12-13 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_set_colon_line_handler): New.
+ (gpgsm_status_handler): Pass datalines to a colon handler
+ * engine.c (_gpgme_engine_set_colon_line_handler): Set the colon
+ handler for gpgsm.
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Allow NULL for
+ pattern.
+ (gpgsm_assuan_simple_command): Removed underscore from
+ assuan_write_line.
+ (_gpgme_gpgsm_start): Ditto.
+ (gpgsm_assuan_simple_command): Replaced interal Assuan read
+ function by the new assuan_read_line. Removed the use of the
+ internal header.
+ (gpgsm_status_handler): Ditto. Use the new assuan_pending_line.
+ (_gpgme_gpgsm_start): Use the documented way to get an fd from
+ assuan.
+
+ * keylist.c (keylist_colon_handler): Handle "crt" records
+ * key.h (gpgme_key_s): Add an x509 flag.
+ * key.c (parse_x509_user_id): New.
+ (_gpgme_key_append_name): Handle x.509 names.
+
+2001-12-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_status_handler): Make it work with current
+ version of assuan.
+
+2001-12-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_set_fd): Accept one more argument OPT.
+ (_gpgme_gpgsm_op_encrypt): Pass armor argument to gpgsm_set_fd for
+ output descriptor.
+ (_gpgme_gpgsm_op_sign): Likewise.
+
+2001-12-05 Marcus Brinkmann <marcus@g10code.de>
+
+ * keylist.c (gpgme_op_keylist_next): Set pending to 0 if EOF
+ occurs.
+
+2001-11-26 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Fix stupid typo.
+
+2001-11-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (gpgsm_status_handler): Don't break if bsearch fails.
+ Deal with assuan read line returning more than one line (for now).
+
+2001-11-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_sign): Implement it according to
+ the current protocol definition.
+
+2001-11-23 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_new): Set CLOEXEC flag for parent
+ ends of the pipe.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c: Include stdlib.h and string.h. Also include,
+ for now, rungpg.h and status-table.h.
+ (gpgsm_status_handler): Implement more of the status handler.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine.c (_gpgme_engine_op_decrypt): Implement CMS case.
+ (_gpgme_engine_op_delete): Likewise.
+ (_gpgme_engine_op_encrypt): Likewise.
+ (_gpgme_engine_op_export): Likewise.
+ (_gpgme_engine_op_genkey): Likewise.
+ (_gpgme_engine_op_keylist): Likewise.
+ (_gpgme_engine_op_sign): Likewise.
+ (_gpgme_engine_op_trustlist): Likewise.
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_encrypt): New function.
+ (gpgsm_assuan_simple_command): Likewise.
+ (gpgsm_set_recipients): Likewise.
+ (gpgsm_set_fd): Reimplement using gpgsm_assuan_simple_command.
+ (_gpgme_gpgsm_op_delete): New function.
+ (_gpgme_gpgsm_op_export): Likewise.
+ (_gpgme_gpgsm_op_genkey): Likewise.
+ (_gpgme_gpgsm_op_sign): Likewise.
+ (_gpgme_gpgsm_op_keylist): Likewise.
+ (_gpgme_gpgsm_op_trustlist): Likewise.
+ (_gpgme_gpgsm_release): Release command.
+ (_gpgme_gpgsm_op_decrypt): Allocate command.
+ (_gpgme_gpgsm_op_import): Likewise.
+ (gpgsm_status_handler): Also treat `ERR' strings as EOF.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.h (gpgme_set_protocol): New prototype.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c (_gpgme_gpgsm_op_decrypt): New function.
+ (_gpgme_gpgsm_op_import): Likewise.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * engine-gpgsm.c: Shuffle around header inclusion a bit, to still
+ keep them seperate.
+ (_gpgme_set_status_handler) [!ENABLE_GPGSM]: New function.
+
+2001-11-22 Werner Koch <wk@gnupg.org>
+
+ * engine-gpgsm.c: Include more headers so that NULL and mk_error
+ is defined even with an undefined GPGSM_PATH.
+
+2001-11-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (gpg_inbound_handler, write_mem_data, write_cb_data,
+ gpg_outbound_handler): Moved to ...
+ * data.c (_gpgme_data_inbound_handler, write_mem_data,
+ write_cb_data, _gpgme_data_outbound_handler): ... here. Make the
+ _gpgme_* ones non-static.
+ * data.c: Include io.h.
+
+ * ops.h (_gpgme_data_inbound_handler): New prototype.
+ (_gpgme_data_outbound_handler): Likewise.
+ (_gpgme_gpg_spawn): Use these new functions.
+
+ * engine-gpgsm.h (_gpgme_gpgsm_op_decrypt, _gpgme_gpgsm_op_delete,
+ _gpgme_gpgsm_op_encrypt, _gpgme_gpgsm_op_export,
+ _gpgme_gpgsm_op_genkey, _gpgme_gpgsm_op_import,
+ _gpgme_gpgsm_op_keylist, _gpgme_gpgsm_op_sign,
+ _gpgme_gpgsm_op_trustlist, _gpgme_gpgsm_op_verify,
+ _gpgme_gpgsm_start, _gpgme_gpgsm_set_status_handler): New prototype.
+ Include <rungpg.h> for status handler function.
+
+ * engine-gpgsm.c (struct gpgsm_object_s): New members input_fd,
+ input_data, output_fd, output_data, message_fd, message_data, command
+ and status.
+ (_gpgme_gpgsm_new): Open input, output and message pipes before
+ connecting to the client. Close server's ends afterwards.
+ (_gpgme_gpgsm_release): Close open file descriptors. Remove
+ server process from wait queue.
+ (_gpgme_gpgsm_op_verify, _gpgme_gpgsm_start,
+ _gpgme_gpgsm_set_status_handler, gpgms_status_handler): New function.
+
+ * engine.c (_gpgme_engine_start): Implement for GPGME_PROTOCOL_CMS.
+ (_gpgme_engine_set_status_handler): Likewise.
+ (_gpgme_engine_op_verify): Likewise.
+
+2001-11-21 Marcus Brinkmann <marcus@g10code.de>
+
+ * context.h: Do not include rungpg.h, but engine.h.
+ (struct gpgme_context_s): Replace member gpg with engine.
+ * gpgme.c (gpgme_release): Release engine, not gpg.
+
+ * recipient.c (_gpgme_append_gpg_args_from_recifgpients): Function
+ moved ...
+ * rungpg.c (_gpgme_append_gpg_args_from_recipients): ... here.
+ Make static, change order of arguments, and return an error value.
+ * ops.h (_gpgme_append_gpg_args_from_recipients): Removed prototype.
+
+ * rungpg.h (_gpgme_gpg_op_verify): Add prototype.
+ (_gpgme_gpg_op_encrypt): Likewise.
+ (_gpgme_gpg_op_decrypt): Likewise.
+ (_gpgme_gpg_op_delete): Likewise.
+ (_gpgme_gpg_op_export): Likewise.
+ (_gpgme_gpg_op_genkey): Likewise.
+ (_gpgme_gpg_op_import): Likewise.
+ (_gpgme_gpg_op_keylist): Likewise.
+ (_gpgme_gpg_op_sign): Likewise.
+ (_gpgme_gpg_op_trustlist): Likewise.
+ * rungpg.c (_gpgme_gpg_op_verify): New function.
+ (_gpgme_gpg_op_encrypt): Likewise.
+ (_gpgme_gpg_op_decrypt): Likewise.
+ (_gpgme_gpg_op_delete): Likewise.
+ (_gpgme_gpg_op_export): Likewise.
+ (_gpgme_gpg_op_genkey): Likewise.
+ (_gpgme_gpg_op_import): Likewise.
+ (_gpgme_gpg_op_keylist): Likewise.
+ (_gpgme_gpg_op_sign): Likewise.
+ (_gpgme_gpg_op_trustlist): Likewise.
+
+ * engine.h (_gpgme_engine_set_status_handler): Add prototype.
+ (_gpgme_engine_set_command_handler): Likewise.
+ (_gpgme_engine_set_colon_line_handler): Likewise.
+ (_gpgme_engine_op_decrypt): Likewise.
+ (_gpgme_engine_op_delete): Likewise.
+ (_gpgme_engine_op_encrypt): Likewise.
+ (_gpgme_engine_op_export): Likewise.
+ (_gpgme_engine_op_genkey): Likewise.
+ (_gpgme_engine_op_import): Likewise.
+ (_gpgme_engine_op_keylist): Likewise.
+ (_gpgme_engine_op_sign): Likewise.
+ (_gpgme_engine_op_trustlist): Likewise.
+ (_gpgme_engine_op_verify): Likewise.
+ (_gpgme_engine_start): Likewise.
+ * engine.c (_gpgme_engine_set_status_handler): New function.
+ (_gpgme_engine_set_command_handler): Likewise.
+ (_gpgme_engine_set_colon_line_handler): Likewise.
+ (_gpgme_engine_op_decrypt): Likewise.
+ (_gpgme_engine_op_delete): Likewise.
+ (_gpgme_engine_op_encrypt): Likewise.
+ (_gpgme_engine_op_export): Likewise.
+ (_gpgme_engine_op_genkey): Likewise.
+ (_gpgme_engine_op_import): Likewise.
+ (_gpgme_engine_op_keylist): Likewise.
+ (_gpgme_engine_op_sign): Likewise.
+ (_gpgme_engine_op_trustlist): Likewise.
+ (_gpgme_engine_op_verify): Likewise.
+ (_gpgme_engine_start): Likewise.
+
+ * verify.c (gpgme_op_verify_start): Reimplement in terms of above
+ functions.
+ * encrypt.c (gpgme_op_encrypt_start): Likewise.
+ * decrypt.c (_gpgme_decrypt_start): Likewise.
+ * passphrase.c (_gpgme_passphrase_start): Likewise.
+ * keylist.c (gpgme_op_keylist_start): Likewise.
+
+2001-11-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * types.h: Add types EngineObject and GpgsmObject.
+
+ * Makefile.am (libgpgme_la_SOURCES): Add engine-gpgsm.h,
+ engine-gpgsm.c, engine.h and engine.c.
+ * engine.h: New file.
+ * engine.c: Likewise.
+ * engine-gpgsm.h: Likewise.
+ * engine-gpgsm.c: Likewise.
+
+ * rungpg.c (_gpgme_gpg_get_version): New function.
+ (_gpgme_gpg_check_version): Likewise.
+ * rungpg.h: Add prototypes for _gpgme_gpg_get_version and
+ _gpgme_gpg_check_version.
+
+ * version.c (compare_versions): Rename to ...
+ (_gpgme_compare_versions): ... this. Make non-static.
+ (gpgme_check_version): Use _gpgme_compare_versions rather than
+ compare_versions.
+ (gpgme_check_engine): Likewise.
+ * ops.h (_gpgme_get_program_version): Add prototype.
+
+2001-11-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * Makefile.am (libgpgme_la_INCLUDES): Remove obsolete directive.
+ (AM_CPPFLAGS): New directive [BUILD_ASSUAN].
+ (libgpgme_la_LIBADD): Likewise.
+
+2001-11-20 Marcus Brinkmann <marcus@g10code.de>
+
+ * version.c: Remove global variables lineno and
+ tmp_engine_version.
+ (version_handler): Removed.
+ (_gpgme_get_program_version): New function.
+ (get_engine_info): Don't use context and version_handler,
+ but _gpgme_get_program_version.
+ * ops.h (_gpgme_get_program_version): Add prototype for
+ _gpgme_get_program_version (we expect to use it elsewhere soon).
+
+2001-11-18 Marcus Brinkmann <marcus@g10code.de>
+
+ * version.c (get_engine_info): If GnuPG is not available, return
+ an error message.
+ * posix-util.c (_gpgme_get_gpg_path): Allow GPG_PATH to be
+ undefined.
+ (_gpgme_get_gpgsm_path): New function.
+ * w32-util.c (find_program_in_registry): New static function.
+ (_gpgme_get_gpg_path): Allow GPG_PATH to be undefined. Rework
+ to use find_program_in_registry.
+ (_gpgme_get_gpgsm_path): New function.
+ (util.h): Prototype _gpgme_get_gpgsm_path).
+ * rungpg.c (_gpgme_gpg_spawn): Verify that _gpgme_get_gpg_path()
+ returns non-null.
+
+2001-11-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * decrypt-verify.c: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add decrypt-verify.c.
+ * types.h: Add decrypt-verify types.
+ * ops.h: Likewise.
+ * context.h: Add result type for decrypt-verify.
+ * gpgme.h: Add decrypt-verify prototypes.
+
+ * decrypt.c (decrypt_status_handler): Renamed to ...
+ (_gpgme_decrypt_status_handler): ... this. Make non-static.
+ (_gpgme_decrypt_start): New function, derived from
+ gpgme_op_decrypt_start.
+ (gpgme_op_decrypt_start): Reimplement in terms of
+ _gpgme_decrypt_start.
+ (_gpgme_decrypt_result): New function to retrieve error value.
+ (gpgme_op_decrypt): Use _gpgme_decrypt_result.
+ * ops.h: Add prototypes for new functions.
+
+ * verify.c (verify_status_handler): Renamed to ...
+ (_gpgme_verify_status_handler): ... this. Make non-static.
+ (gpgme_op_verify_start): Use new function name.
+ (intersect_stati): Renamed to ...
+ (_gpgme_intersect_stati): ... this. Make non-static.
+ (gpgme_op_verify): Use new name.
+ * ops.h: Add prototypes for new functions.
+
+2001-11-16 Marcus Brinkmann <marcus@g10code.de>
+
+ * passphrase.c: New file.
+ * Makefile.am (libgpgme_la_SOURCES): Add passphrase.c.
+ * ops.h (_gpgme_passphrase_result): Add prototypes from
+ passphrase.c.
+ * types.h: Likewise.
+ * context.h: Add member passphrase to result.
+ * gpgme.c (_gpgme_release_result): Release passphrase member.
+
+ * decrypt.c: Some formatting and variable name changes (like
+ CTX instead C).
+ (struct decrypt_result_s): Remove members now found in
+ passphrase result.
+ (_gpgme_release_decrypt_result): Don't release removed members.
+ (decrypt_status_handler): Call _gpgme_passphrase_status_handler,
+ and don't handle the cases catched there.
+ (command_handler): Removed.
+ (gpgme_op_decrypt_start): Don't set command handler, but invoke
+ _gpgme_passphrase_start which does it.
+ (gpgme_op_decrypt): Invoke _gpgme_passphrase_result and drop the
+ cases covered by it.
+
+ * sign.c Some formatting and variable name changes (like
+ CTX instead C).
+ (struct sign_result_s): Remove members now found in
+ passphrase result.
+ (_gpgme_release_sign_result): Don't release removed members.
+ (sign_status_handler): Call _gpgme_passphrase_status_handler,
+ and don't handle the cases catched there.
+ (command_handler): Removed.
+ (gpgme_op_sign_start): Don't set command handler, but invoke
+ _gpgme_passphrase_start which does it.
+ (gpgme_op_sign): Invoke _gpgme_passphrase_result and drop the
+ cases covered by it.
+
+2001-11-15 Marcus Brinkmann <marcus@g10code.de>
+
+ * decrypt.c (command_handler): Fix last change.
+
+2001-11-15 Marcus Brinkmann <marcus@g10code.de>
+
+ * verify.c (_gpgme_release_verify_result): Rename RES to RESULT.
+ Rename R2 to NEXT_RESULT.
+ (intersect_stati): Rename RES to RESULT.
+ (gpgme_get_sig_status): Likewise. Do not check return_type, but
+ the member verify of result.
+ (gpgme_get_sig_key): Likewise.
+
+ * sign.c (_gpgme_release_sign_result): Rename RES to RESULT. If
+ RESULT is zero, return.
+ (sign_status_handler, command_handler): Do not check return_type,
+ but the member sign of result.
+ (gpgme_op_sign): Likewise. Drop assertion.
+
+ * encrypt.c (_gpgme_release_encrypt_result): Rename RES to RESULT.
+ If RESULT is zero, return.
+ (encrypt_status_handler): Do not check return_type, but the member
+ encrypt of result.
+ (gpgme_op_encrypt): Likewise. Drop assertion.
+
+ * decrypt.c (_gpgme_release_decrypt_result): Rename RES to RESULT.
+ (create_result_struct): Do not set result_type.
+ (command_handler, decrypt_status_handler): Do not check
+ return_type, but the member decrypt of result.
+ (gpgme_op_decrypt): Likewise. Drop assertion.
+
+ * context.h (enum ResultType): Removed.
+ (struct gpgme_context_s): Remove member result_type.
+ (struct result): Replaces union result.
+ * gpgme.c: Include string.h.
+ (_gpgme_release_result): Release all members of c->result, which
+ is now a struct. Zero out all members of the struct afterwards.
+
+2001-11-11 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (_gpgme_gpg_release): Release GPG->cmd.cb_data.
+ Release all members of the list GPG->arglist.
+ Reported by Michael Schmidt <mschmidt@cs.uni-sb.de>.
+
+2001-11-02 Marcus Brinkmann <marcus@g10code.de>
+
+ * rungpg.c (pipemode_copy): Change type of NBYTES to size_t.
+
+ * key.c: Include string.h.
+ * data.c: Likewise.
+ * recipient.c: Likewise.
+
+2001-10-29 Marcus Brinkmann <marcus@g10code.de>
+
+ * context.h: New member signers_len.
+ * signers.c (gpgme_signers_clear): Require that signers are
+ non-NULL with assertion. Use signers_len to determine how much
+ keys to release. Add documentation.
+ (gpgme_signers_add): Use signers_len to determine if the buffer is
+ large enough. Use xtryrealloc rather than xtrymalloc and copying.
+ Add documentation.
+ (gpgme_signers_enum): Use signers_len to determine if key is
+ available. Add documentation.
+
+2001-10-22 Marcus Brinkmann <marcus@g10code.de>
+
+ * data.c (_gpgme_data_append): Check if LENGTH is smaller than
+ ALLOC_CHUNK, not DH->length.
+
+2001-10-17 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_set_protocol): Fix last change.
+
+2001-10-15 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h (GpgmeProtocol): New.
+ * gpgme.c (gpgme_set_protocol): New.
+
+2001-09-26 Werner Koch <wk@gnupg.org>
+
+ * gpgme.c (gpgme_set_passphrase_cb): Ignore a NULL context.
+ (gpgme_set_progress_cb): Ditto. Suggested by Mark Mutz.
+
+2001-09-17 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (finish_key): Shortcut for no tmp_key. Changed all
+ callers to use this function without a check for tmp_key.
+
+ * keylist.c (gpgme_op_keylist_next): Reset the key_cond after
+ emptying the queue. Bug reported by Stéphane Corthésy.
+
+2001-09-12 Werner Koch <wk@gnupg.org>
+
+ * data.c (gpgme_data_rewind): Allow rewind for callbacks.
+
+2001-09-07 Werner Koch <wk@gnupg.org>
+
+ * rungpg.h: Add NO_RECP.
+ * encrypt.c (encrypt_status_handler): Take on No_RECP.
+ (gpgme_op_encrypt): Better error return.
+
+ * verify.c (verify_status_handler): Take on NODATA.
+
+2001-09-03 Werner Koch <wk@gnupg.org>
+
+ * rungpg.h: Added STATUS_INV_RECP.
+ * gpgme.c (_gpgme_release_result): Add support for new
+ EncryptResult object.
+ * encrypt.c (append_xml_encinfo): New.
+ (encrypt_status_handler): Add some status parsing.
+ (_gpgme_release_encrypt_result): New.
+
+2001-08-29 Werner Koch <wk@gnupg.org>
+
+ * recipient.c (gpgme_recipients_release): Free the list. By Timo.
+
+ * keylist.c (keylist_colon_handler): Do a finish key if we receive
+ an EOF here. This is probably the reason for a lot of bugs
+ related to keylisting. It is so obvious. Kudos to Enno Cramer
+ for pointing that out.
+
+2001-08-28 Werner Koch <wk@gnupg.org>
+
+ * gpgme.c, gpgme.h (gpgme_get_op_info): New.
+ (_gpgme_set_op_info): New.
+ (_gpgme_release_result): Reset the op_info here.
+ * sign.c (append_xml_siginfo): New.
+ (sign_status_handler): Store the sig create information.
+
+2001-07-31 Werner Koch <wk@gnupg.org>
+
+ * encrypt.c (gpgme_op_encrypt): Hack to detect no valid recipients.
+
+2001-07-30 Werner Koch <wk@gnupg.org>
+
+ * gpgme.c (gpgme_get_armor,gpgme_get_textmode): New.
+
+ * rungpg.c (build_argv): Disable armor comments
+ * w32-io.c (build_commandline): Need to add quotes here
+
+2001-07-24 Werner Koch <wk@gnupg.org>
+
+ * data.c (gpgme_data_read): Add a a way to return the available bytes.
+
+2001-07-23 Werner Koch <wk@gnupg.org>
+
+ * util.c: Removed stpcpy() because we use the version from jnlib.
+
+2001-07-19 Werner Koch <wk@gnupg.org>
+
+ * mkstatus: Define the collating sequence for sort.
+
+2001-06-26 Werner Koch <wk@gnupg.org>
+
+ * rungpg.h: Add STATUS_UNEXPECTED as suggested by Timo.
+
+2001-06-15 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (set_userid_flags): Fixed the assigned values. Kudos
+ to Timo for pointing this out.
+
+2001-06-01 Werner Koch <wk@gnupg.org>
+
+ * debug.c (_gpgme_debug_begin): Fixed a /tmp race. Noted by
+ Johannes Poehlmann.
+
+2001-05-28 Werner Koch <wk@gnupg.org>
+
+ * version.c (gpgme_check_engine): Stop version number parsing at
+ the opening angle and not the closing one. By Tommy Reynolds.
+
+2001-05-01 José Carlos García Sogo <jose@jaimedelamo.eu.org>
+
+ * encrypt.c (gpgme_op_encrypt_start): Deleted the assert ( !c->gpg )
+ line, because it gave an error if another operation had been made
+ before using the same context.
+
+ * decrypt.c (gpgme_op_decrypt_start): The same as above. Also added
+ one line to release the gpg object in the context (if any).
+
+2001-04-26 Werner Koch <wk@gnupg.org>
+
+ * key.c, key.h (_gpgme_key_cache_init): New.
+ (_gpgme_key_cache_add): New.
+ (_gpgme_key_cache_get): New.
+ * version.c (do_subsystem_inits): Init the cache.
+ * keylist.c (finish_key): Put key into the cache
+ * verify.c (gpgme_get_sig_key): First look into the cache.
+
+2001-04-19 Werner Koch <wk@gnupg.org>
+
+ * keylist.c (parse_timestamp): Adjusted for the changed
+ --fixed-list-mode of gpg 1.0.4h.
+
+2001-04-05 Werner Koch <wk@gnupg.org>
+
+ * verify.c (gpgme_op_verify_start): Enabled pipemode for detached sigs.
+
+2001-04-04 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (_gpgme_io_select): Don't select on the writer if there
+ are still bytes pending. Timo found this not easy to track down
+ race condition.
+
+2001-04-02 Werner Koch <wk@gnupg.org>
+
+ * gpgme.h: Add GPGME_ATTR_KEY_{EXPIRED,DISABLED}.
+ * key.c (gpgme_key_get_ulong_attr): And return those attribs.
+
+ * verify.c (gpgme_get_sig_key): Set keyliosting mode depending on
+ the mode set in the current context. Suggested by Timo.
+
+ * key.c (gpgme_key_get_ulong_attr): Return can_certify and not
+ can_encrypt. By Timo.
+
+2001-03-30 Werner Koch <wk@gnupg.org>
+
+ * debug.c (debug_init): Allow to specify a debug file.
+ (_gpgme_debug_level): New.
+
+ * posix-io.c (_gpgme_io_read, _gpgme_io_write): Print output.
+ (_gpgme_io_select): Debug only with level > 2.
+
+2001-03-15 Werner Koch <wk@gnupg.org>
+
+ * rungpg.c: Included time.h.
+
+ * key.h: New keyflags for capabilities.
+ * keylist.c (set_mainkey_capability, set_subkey_capability): New.
+ (keylist_colon_handler): Parse them.
+ * gpgme.h: New attribute values for capabilties.
+ * key.c (gpgme_key_get_string_attr): Return them.
+ (capabilities_to_string): New.
+ (gpgme_key_get_ulong_attr): Return the global caps.
+
+2001-03-14 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (destroy_reader,destroy_writer): Fixed syntax error.
+ Thanks to Jan Oliver Wagner.
+
+2001-03-13 Werner Koch <wk@gnupg.org>
+
+ * context.h: Add invalid and revoke flags to user_id structure.
+ * keylist.c (gpgme_op_keylist_start): Use --fixed-list-mode.
+ (keylist_colon_handler): Adjust for that.
+ (set_userid_flags): New.
+ (set_mainkey_trust_info): Handle new key invalid flag
+ (set_subkey_trust_info): Ditto.
+ * gpgme.h: Add new attributes for key and user ID flags.
+ * key.c (_gpgme_key_append_name): Init these flags
+ (gpgme_key_get_as_xml): Print them.
+ (one_uid_as_xml): New helper for above.
+ (gpgme_key_get_string_attr, gpgme_key_get_ulong_attr):
+ Return the new attributes. Enhanced, so that subkey information
+ can be returned now.
+
+2001-02-28 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (destroy_reader): Set stop_me flag.
+ (writer,create_writer,destroy_writer,find_writer,kill_writer): New.
+ (_gpgme_io_write): Use a writer thread to avaoid blocking.
+ (_gpgme_io_close): Cleanup a writer thread
+ (_gpgme_io_select): Repalce tthe faked wait on writing by a real
+ waiting which is now possible due to the use of a writer thread.
+
+2001-02-20 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (destroy_reader,kill_reader): New.
+ (create_reader, reader): Add a new event to stop the thread.
+ (_gpgme_io_close): Kill the reader thread.
+
+ * posix-io.c (_gpgme_io_select): Handle frozen fds here.
+ * 32-io.c (_gpgme_io_select): Ditto. Removed a bunch of unused code.
+
+ * wait.c: Reworked the whole thing.
+ * rungpg.c (_gpgme_gpg_new): Init pid to -1.
+ (_gpgme_gpg_release): Remove the process from the wait queue.
+
+2001-02-19 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (_gpgme_io_set_close_notify): New.
+ (_gpgme_io_close): Do the notification.
+
+ * posix-io.c (_gpgme_io_select): Use a 1 sec timeout and not 200
+ microseconds.
+
+ * wait.c (remove_process): Don't close the fd here.
+ (do_select): Set the fd to -1 and remove the is_closed flag everywhere.
+ (_gpgme_wait_on_condition): Remove the assert on the queue and
+ break out if we could not find the queue. The whole thing should
+ be reworked.
+
+ * posix-io.c (_gpgme_io_set_close_notify): New.
+ (_gpgme_io_close): Do the notification.
+
+ * rungpg.c (close_notify_handler): New.
+ (_gpgme_gpg_new): Register a callback for the fd.
+ (_gpgme_gpg_set_colon_line_handler): Ditto.
+ (build_argv): Ditto
+
+2001-02-13 Werner Koch <wk@gnupg.org>
+
+ * rungpg.c (struct reap_s): Replaced pid_t by int.
+
+ * types.h: Add ulong typedef.
+
+ * rungpg.c (do_reaping,_gpgme_gpg_housecleaning): New.
+ (_gpgme_gpg_release): Reap tqchildren.
+ * io.h, posix-io.c (_gpgme_io_kill): New.
+ * w32-io.c (_gpgme_io_kill): New (dummy).
+
+ * keylist.c (gpgme_op_keylist_start): Cancel a pending request.
+
+ * posix-io.c (_gpgme_io_read): Add some debug output.
+ (_gpgme_io_write): Ditto.
+ (_gpgme_io_select): Increased the timeout.
+
+2001-02-12 Werner Koch <wk@gnupg.org>
+
+ Enhanced the signature verification, so that it can how handle
+ more than one signature and is able to return more information on
+ the signatures.
+ * verify.c (gpgme_get_sig_key): New.
+ (gpgme_get_sig_status): New.
+
+ * gpgme.h: Add stdio.h.
+ (GpgmeSigStat): New status DIFF.
+
+2001-02-01 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (set_synchronize): Add EVENT_MODIFY_STATE. Add Debug
+ code to all Set/ResetEvent().
+
+ * rungpg.c (read_status): Check for end of stream only if we have
+ an r. By Timo.
+
+2001-01-31 Werner Koch <wk@gnupg.org>
+
+ * wait.c (_gpgme_wait_on_condition): Removed all exit code processing.
+ (propagate_term_results,clear_active_fds): Removed.
+ (count_active_fds): Renamed to ..
+ (count_active_and_thawed_fds): .. this and count only thawed fds.
+
+ * rungpg.c (gpg_colon_line_handler): Return colon.eof and not
+ status.eof ;-)
+
+2001-01-30 Werner Koch <wk@gnupg.org>
+
+ * w32-io.c (_gpgme_io_spawn): Use the supplied path arg.
+
+ * version.c (get_engine_info): Return better error information.
+
+ * posix-util.c, w32-util.c: New.
+ (_gpgme_get_gpg_path): New, suggested by Jan-Oliver.
+ * rungpg.c (_gpgme_gpg_spawn): Use new function to get GPG's path.
+
+ * signers.c (gpgme_signers_add): Ooops, one should test code and
+ not just write it; the newarr was not assigned. Thanks to José
+ for pointing this out. Hmmm, still not tested, why shoudl a coder
+ test his fix :-)
+
+ * w32-io.c: Does now use reader threads, so that we can use
+ WaitForMultipleObjects.
+ * sema.h, posix-sema.c, w32-sema.c: Support for Critcial sections.
+ Does currently only work for W32.
+
+ * debug.c, util.h : New. Changed all fprintfs to use this new
+ set of debugging functions.
+
+2001-01-23 Werner Koch <wk@gnupg.org>
+
+ * data.c (_gpgme_data_release_and_return_string): Fixed string
+ termination.
+
+2001-01-22 Werner Koch <wk@gnupg.org>
+
+ * delete.c: New.
+
+ * signers.c: New.
+ * key.c (gpgme_key_ref, gpgme_key_unref): New.
+ * sign.c (gpgme_op_sign_start): Allow the use of other keys.
+
+ * version.c (gpgme_get_engine_info,gpgme_check_engine): New.
+ * rungpg.c (_gpgme_gpg_set_simple_line_handler): New.
+
+2001-01-05 Werner Koch <wk@gnupg.org>
+
+ * data.c (gpgme_data_rewind): Allow to rewind data_type_none.
+
+
+ Copyright 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/libtdenetwork/libgpgme-copy/gpgme/Makefile.am b/libtdenetwork/libgpgme-copy/gpgme/Makefile.am
new file mode 100644
index 000000000..5ea41e091
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/Makefile.am
@@ -0,0 +1,50 @@
+# Copyright (C) 2000 Werner Koch (dd9jn)
+# Copyright (C) 2001, 2002, 2003 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 General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+## Process this file with automake to produce Makefile.in
+
+noinst_LTLIBRARIES = libgpgme-real.la libgpgme.la
+
+assuan_cppflags = -I$(srcdir)/../assuan
+assuan_libobjs = ../assuan/libassuan.la
+
+libgpgme_real_la_SOURCES = \
+ conversion.c get-env.c \
+ data.c data-fd.c data-stream.c data-mem.c data-user.c \
+ data-compat.c \
+ signers.c \
+ wait.c wait-global.c wait-private.c wait-user.c \
+ op-support.c \
+ encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
+ sign.c passphrase.c progress.c \
+ key.c keylist.c trust-item.c trustlist.c \
+ import.c export.c genkey.c delete.c edit.c \
+ engine.c rungpg.c \
+ posix-util.c posix-sema.c posix-io.c \
+ engine-gpgsm.c sig-notation.c funopen.c \
+ debug.c gpgme.c version.c error.c
+
+libgpgme_la_SOURCES = ath.c
+
+AM_CPPFLAGS = $(assuan_cppflags) -I$(srcdir)/../../libgpg-error-copy -I../../libgpg-error-copy
+
+libgpgme_la_LIBADD = libgpgme-real.la ../../libgpg-error-copy/libgpg-error.la $(assuan_libobjs)
+
+status-table.h : $(srcdir)/gpgme.h
+ $(srcdir)/mkstatus < $(srcdir)/gpgme.h > status-table.h
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath-pth-compat.c b/libtdenetwork/libgpgme-copy/gpgme/ath-pth-compat.c
new file mode 100644
index 000000000..7bdea8762
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath-pth-compat.c
@@ -0,0 +1,123 @@
+/* ath-pth.c - Pth module for self-adapting thread-safeness library
+ * Copyright (C) 2002 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <pth.h>
+
+#include "ath.h"
+
+#pragma weak pth_mutex_init
+#pragma weak pth_mutex_acquire
+#pragma weak pth_mutex_release
+#pragma weak pth_read
+#pragma weak pth_write
+#pragma weak pth_select
+#pragma weak pth_waitpid
+#pragma weak pth_accept
+#pragma weak pth_connect
+
+/* The lock we take while checking for lazy lock initialization. */
+static pth_mutex_t check_init_lock = PTH_MUTEX_INIT;
+
+/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if
+ it is not already initialized. */
+static int
+mutex_pth_init (void **priv, int just_check)
+{
+ int err = 0;
+
+ if (just_check)
+ pth_mutex_acquire (&check_init_lock, 0, NULL);
+ if (!*priv || !just_check)
+ {
+ pth_mutex_t *lock = malloc (sizeof (pth_mutex_t));
+ if (!lock)
+ err = ENOMEM;
+ if (!err)
+ {
+ err = pth_mutex_init (lock);
+ if (err == FALSE)
+ err = errno;
+ else
+ err = 0;
+
+ if (err)
+ free (lock);
+ else
+ *priv = lock;
+ }
+ }
+ if (just_check)
+ pth_mutex_release (&check_init_lock);
+ return err;
+}
+
+
+static int
+mutex_pth_destroy (void *priv)
+{
+ free (priv);
+ return 0;
+}
+
+
+static int
+mutex_pth_lock (void *priv)
+{
+ int ret = pth_mutex_acquire ((pth_mutex_t *) priv, 0, NULL);
+ return ret == FALSE ? errno : 0;
+}
+
+
+static int
+mutex_pth_unlock (void *priv)
+{
+ int ret = pth_mutex_release ((pth_mutex_t *) priv);
+ return ret == FALSE ? errno : 0;
+}
+
+
+static struct ath_ops ath_pth_ops =
+ {
+ mutex_pth_init,
+ mutex_pth_destroy,
+ mutex_pth_lock,
+ mutex_pth_unlock,
+ pth_read,
+ pth_write,
+ pth_select,
+ pth_waitpid,
+ pth_accept,
+ pth_connect,
+ NULL, /* FIXME: When GNU PTh has sendmsg. */
+ NULL /* FIXME: When GNU PTh has recvmsg. */
+ };
+
+
+struct ath_ops *
+ath_pth_available (void)
+{
+ if (pth_mutex_init && pth_mutex_acquire && pth_mutex_release
+ && pth_read && pth_write && pth_select && pth_waitpid)
+ return &ath_pth_ops;
+ else
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath-pth.c b/libtdenetwork/libgpgme-copy/gpgme/ath-pth.c
new file mode 100644
index 000000000..74eb20422
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath-pth.c
@@ -0,0 +1,178 @@
+/* ath-pth.c - Pth module for self-adapting thread-safeness library
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <pth.h>
+
+#include "ath.h"
+
+
+/* The lock we take while checking for lazy lock initialization. */
+static pth_mutex_t check_init_lock = PTH_MUTEX_INIT;
+
+/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if
+ it is not already initialized. */
+static int
+mutex_pth_init (ath_mutex_t *priv, int just_check)
+{
+ int err = 0;
+
+ if (just_check)
+ pth_mutex_acquire (&check_init_lock, 0, NULL);
+ if (!*priv || !just_check)
+ {
+ pth_mutex_t *lock = malloc (sizeof (pth_mutex_t));
+ if (!lock)
+ err = ENOMEM;
+ if (!err)
+ {
+ err = pth_mutex_init (lock);
+ if (err == FALSE)
+ err = errno;
+ else
+ err = 0;
+
+ if (err)
+ free (lock);
+ else
+ *priv = (ath_mutex_t) lock;
+ }
+ }
+ if (just_check)
+ pth_mutex_release (&check_init_lock);
+ return err;
+}
+
+
+void
+ath_init (void)
+{
+ /* Nothing to do. */
+}
+
+
+int
+ath_mutex_init (ath_mutex_t *lock)
+{
+ return mutex_pth_init (lock, 0);
+}
+
+
+int
+ath_mutex_destroy (ath_mutex_t *lock)
+{
+ int err = mutex_pth_init (lock, 1);
+ if (!err)
+ {
+ /* GNU Pth has no destructor function. */
+ free (*lock);
+ }
+ return err;
+}
+
+
+int
+ath_mutex_lock (ath_mutex_t *lock)
+{
+ int ret = mutex_pth_init (lock, 1);
+ if (ret)
+ return ret;
+
+ ret = pth_mutex_acquire ((pth_mutex_t *) *lock, 0, NULL);
+ return ret == FALSE ? errno : 0;
+}
+
+
+int
+ath_mutex_unlock (ath_mutex_t *lock)
+{
+ int ret = mutex_pth_init (lock, 1);
+ if (ret)
+ return ret;
+
+ ret = pth_mutex_release ((pth_mutex_t *) *lock);
+ return ret == FALSE ? errno : 0;
+}
+
+
+ssize_t
+ath_read (int fd, void *buf, size_t nbytes)
+{
+ return pth_read (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_write (int fd, const void *buf, size_t nbytes)
+{
+ return pth_write (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout)
+{
+ return pth_select (nfd, rset, wset, eset, timeout);
+}
+
+
+ssize_t
+ath_waitpid (pid_t pid, int *status, int options)
+{
+ return pth_waitpid (pid, status, options);
+}
+
+
+int
+ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
+{
+ return pth_accept (s, addr, length_ptr);
+}
+
+
+int
+ath_connect (int s, const struct sockaddr *addr, socklen_t length)
+{
+ return pth_connect (s, addr, length);
+}
+
+int
+ath_sendmsg (int s, const struct msghdr *msg, int flags)
+{
+ /* FIXME: GNU Pth is missing pth_sendmsg. */
+ return sendmsg (s, msg, flags);
+}
+
+
+int
+ath_recvmsg (int s, struct msghdr *msg, int flags)
+{
+ /* FIXME: GNU Pth is missing pth_recvmsg. */
+ return recvmsg (s, msg, flags);
+}
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath-pthread-compat.c b/libtdenetwork/libgpgme-copy/gpgme/ath-pthread-compat.c
new file mode 100644
index 000000000..b65fa0514
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath-pthread-compat.c
@@ -0,0 +1,104 @@
+/* ath-pthread.c - pthread module for self-adapting thread-safeness library
+ * Copyright (C) 2002 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "ath.h"
+
+/* Need to include pthread_create in our check, as the GNU C library
+ has the pthread_mutex_* functions in their public interface. */
+#pragma weak pthread_create
+#pragma weak pthread_mutex_init
+#pragma weak pthread_mutex_destroy
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_unlock
+
+/* The lock we take while checking for lazy lock initialization. */
+static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if
+ it is not already initialized. */
+static int
+mutex_pthread_init (void **priv, int just_check)
+{
+ int err = 0;
+
+ if (just_check)
+ pthread_mutex_lock (&check_init_lock);
+ if (!*priv || !just_check)
+ {
+ pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
+ if (!lock)
+ err = ENOMEM;
+ if (!err)
+ {
+ err = pthread_mutex_init (lock, NULL);
+ if (err)
+ free (lock);
+ else
+ *priv = lock;
+ }
+ }
+ if (just_check)
+ pthread_mutex_unlock (&check_init_lock);
+ return err;
+}
+
+
+static int
+mutex_pthread_destroy (void *priv)
+{
+ int err = pthread_mutex_destroy ((pthread_mutex_t *) priv);
+ free (priv);
+ return err;
+}
+
+
+static struct ath_ops ath_pthread_ops =
+ {
+ mutex_pthread_init,
+ mutex_pthread_destroy,
+ (int (*) (void *)) pthread_mutex_lock,
+ (int (*) (void *)) pthread_mutex_unlock,
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* select */
+ NULL, /* waitpid */
+ NULL, /* accept */
+ NULL, /* connect */
+ NULL, /* sendmsg */
+ NULL /* recvmsg */
+ };
+
+
+struct ath_ops *
+ath_pthread_available (void)
+{
+ /* Need to include pthread_create in our check, as the GNU C library
+ has the pthread_mutex_* functions in their public interface. */
+ if (pthread_create
+ && pthread_mutex_init && pthread_mutex_destroy
+ && pthread_mutex_lock && pthread_mutex_unlock)
+ return &ath_pthread_ops;
+ else
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath-pthread.c b/libtdenetwork/libgpgme-copy/gpgme/ath-pthread.c
new file mode 100644
index 000000000..5a70d2e43
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath-pthread.c
@@ -0,0 +1,175 @@
+/* ath-pthread.c - pthread module for self-adapting thread-safeness library
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#else
+# include <sys/time.h>
+#endif
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <pthread.h>
+
+#include "ath.h"
+
+
+/* The lock we take while checking for lazy lock initialization. */
+static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if
+ it is not already initialized. */
+static int
+mutex_pthread_init (ath_mutex_t *priv, int just_check)
+{
+ int err = 0;
+
+ if (just_check)
+ pthread_mutex_lock (&check_init_lock);
+ if (!*priv || !just_check)
+ {
+ pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
+ if (!lock)
+ err = ENOMEM;
+ if (!err)
+ {
+ err = pthread_mutex_init (lock, NULL);
+ if (err)
+ free (lock);
+ else
+ *priv = (ath_mutex_t) lock;
+ }
+ }
+ if (just_check)
+ pthread_mutex_unlock (&check_init_lock);
+ return err;
+}
+
+
+void
+ath_init (void)
+{
+ /* Nothing to do. */
+}
+
+
+int
+ath_mutex_init (ath_mutex_t *lock)
+{
+ return mutex_pthread_init (lock, 0);
+}
+
+
+int
+ath_mutex_destroy (ath_mutex_t *lock)
+{
+ int err = mutex_pthread_init (lock, 1);
+ if (!err)
+ {
+ err = pthread_mutex_destroy ((pthread_mutex_t *) *lock);
+ free (*lock);
+ }
+ return err;
+}
+
+
+int
+ath_mutex_lock (ath_mutex_t *lock)
+{
+ int ret = mutex_pthread_init (lock, 1);
+ if (ret)
+ return ret;
+
+ return pthread_mutex_lock ((pthread_mutex_t *) *lock);
+}
+
+
+int
+ath_mutex_unlock (ath_mutex_t *lock)
+{
+ int ret = mutex_pthread_init (lock, 1);
+ if (ret)
+ return ret;
+
+ return pthread_mutex_unlock ((pthread_mutex_t *) *lock);
+}
+
+
+ssize_t
+ath_read (int fd, void *buf, size_t nbytes)
+{
+ return read (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_write (int fd, const void *buf, size_t nbytes)
+{
+ return write (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout)
+{
+ return select (nfd, rset, wset, eset, timeout);
+}
+
+
+ssize_t
+ath_waitpid (pid_t pid, int *status, int options)
+{
+ return waitpid (pid, status, options);
+}
+
+
+int
+ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
+{
+ return accept (s, addr, length_ptr);
+}
+
+
+int
+ath_connect (int s, const struct sockaddr *addr, socklen_t length)
+{
+ return connect (s, addr, length);
+}
+
+int
+ath_sendmsg (int s, const struct msghdr *msg, int flags)
+{
+ return sendmsg (s, msg, flags);
+}
+
+
+int
+ath_recvmsg (int s, struct msghdr *msg, int flags)
+{
+ return recvmsg (s, msg, flags);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath.c b/libtdenetwork/libgpgme-copy/gpgme/ath.c
new file mode 100644
index 000000000..cb6d80d74
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath.c
@@ -0,0 +1,169 @@
+/* ath.c - Thread-safeness library.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#else
+# include <sys/time.h>
+#endif
+#include <sys/types.h>
+#ifndef HAVE_W32_SYSTEM
+#include <sys/wait.h>
+#endif
+
+#include "ath.h"
+
+
+#define MUTEX_UNLOCKED ((ath_mutex_t) 0)
+#define MUTEX_LOCKED ((ath_mutex_t) 1)
+#define MUTEX_DESTROYED ((ath_mutex_t) 2)
+
+
+int
+ath_mutex_init (ath_mutex_t *lock)
+{
+#ifndef NDEBUG
+ *lock = MUTEX_UNLOCKED;
+#endif
+ return 0;
+}
+
+
+int
+ath_mutex_destroy (ath_mutex_t *lock)
+{
+#ifndef NDEBUG
+ assert (*lock == MUTEX_UNLOCKED);
+
+ *lock = MUTEX_DESTROYED;
+#endif
+ return 0;
+}
+
+
+int
+ath_mutex_lock (ath_mutex_t *lock)
+{
+#ifndef NDEBUG
+ assert (*lock == MUTEX_UNLOCKED);
+
+ *lock = MUTEX_LOCKED;
+#endif
+ return 0;
+}
+
+
+int
+ath_mutex_unlock (ath_mutex_t *lock)
+{
+#ifndef NDEBUG
+ assert (*lock == MUTEX_LOCKED);
+
+ *lock = MUTEX_UNLOCKED;
+#endif
+ return 0;
+}
+
+
+ssize_t
+ath_read (int fd, void *buf, size_t nbytes)
+{
+ return read (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_write (int fd, const void *buf, size_t nbytes)
+{
+ return write (fd, buf, nbytes);
+}
+
+
+ssize_t
+ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return select (nfd, rset, wset, eset, timeout);
+#endif
+}
+
+
+ssize_t
+ath_waitpid (pid_t pid, int *status, int options)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return waitpid (pid, status, options);
+#endif
+}
+
+
+int
+ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return accept (s, addr, length_ptr);
+#endif
+}
+
+
+int
+ath_connect (int s, const struct sockaddr *addr, socklen_t length)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return connect (s, addr, length);
+#endif
+}
+
+
+int
+ath_sendmsg (int s, const struct msghdr *msg, int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return sendmsg (s, msg, flags);
+#endif
+}
+
+
+int
+ath_recvmsg (int s, struct msghdr *msg, int flags)
+{
+#ifdef HAVE_W32_SYSTEM
+ return -1; /* Not supported. */
+#else
+ return recvmsg (s, msg, flags);
+#endif
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ath.h b/libtdenetwork/libgpgme-copy/gpgme/ath.h
new file mode 100644
index 000000000..1a9be5d01
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ath.h
@@ -0,0 +1,89 @@
+/* ath.h - Interfaces for thread-safeness library.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef ATH_H
+#define ATH_H
+
+#ifdef HAVE_W32_SYSTEM
+ /* fixme: Check how we did it in libgcrypt. */
+ struct msghdr { int dummy; };
+ typedef int socklen_t;
+# include <windows.h>
+# include <io.h>
+
+#else /*!HAVE_W32_SYSTEM*/
+
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# include <sys/time.h>
+# endif
+# include <sys/types.h>
+# include <sys/socket.h>
+
+#endif /*!HAVE_W32_SYSTEM*/
+
+
+
+/* Define _ATH_EXT_SYM_PREFIX if you want to give all external symbols
+ a prefix. */
+#define _ATH_EXT_SYM_PREFIX _gpgme_
+
+#ifdef _ATH_EXT_SYM_PREFIX
+#define _ATH_PREFIX1(x,y) x ## y
+#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y)
+#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x)
+#define ath_mutex_init _ATH_PREFIX(ath_mutex_init)
+#define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy)
+#define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock)
+#define ath_mutex_unlock _ATH_PREFIX(ath_mutex_unlock)
+#define ath_read _ATH_PREFIX(ath_read)
+#define ath_write _ATH_PREFIX(ath_write)
+#define ath_select _ATH_PREFIX(ath_select)
+#define ath_waitpid _ATH_PREFIX(ath_waitpid)
+#define ath_connect _ATH_PREFIX(ath_connect)
+#define ath_accept _ATH_PREFIX(ath_accept)
+#define ath_sendmsg _ATH_PREFIX(ath_sendmsg)
+#define ath_recvmsg _ATH_PREFIX(ath_recvmsg)
+#endif
+
+
+typedef void *ath_mutex_t;
+#define ATH_MUTEX_INITIALIZER 0;
+
+/* Functions for mutual exclusion. */
+int ath_mutex_init (ath_mutex_t *mutex);
+int ath_mutex_destroy (ath_mutex_t *mutex);
+int ath_mutex_lock (ath_mutex_t *mutex);
+int ath_mutex_unlock (ath_mutex_t *mutex);
+
+/* Replacement for the POSIX functions, which can be used to allow
+ other (user-level) threads to run. */
+ssize_t ath_read (int fd, void *buf, size_t nbytes);
+ssize_t ath_write (int fd, const void *buf, size_t nbytes);
+ssize_t ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
+ struct timeval *timeout);
+ssize_t ath_waitpid (pid_t pid, int *status, int options);
+int ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr);
+int ath_connect (int s, const struct sockaddr *addr, socklen_t length);
+int ath_sendmsg (int s, const struct msghdr *msg, int flags);
+int ath_recvmsg (int s, struct msghdr *msg, int flags);
+
+#endif /* ATH_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/context.h b/libtdenetwork/libgpgme-copy/gpgme/context.h
new file mode 100644
index 000000000..e74b84c58
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/context.h
@@ -0,0 +1,118 @@
+/* context.h - Definitions for a GPGME context.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include "gpgme.h"
+#include "engine.h"
+#include "wait.h"
+
+
+/* Operations might require to remember arbitrary information and data
+ objects during invocations of the status handler. The
+ ctx_op_data structure provides a generic framework to hook in
+ such additional data. */
+typedef enum
+ {
+ OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
+ OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
+ OPDATA_VERIFY, OPDATA_TRUSTLIST
+ } ctx_op_data_id_t;
+
+
+struct ctx_op_data
+{
+ /* The next element in the linked list, or NULL if this is the last
+ element. */
+ struct ctx_op_data *next;
+
+ /* The type of the hook data, which can be used by a routine to
+ lookup the hook data. */
+ ctx_op_data_id_t type;
+
+ /* The function to release HOOK and all its associated resources.
+ Can be NULL if no special dealllocation routine is necessary. */
+ void (*cleanup) (void *hook);
+
+ /* The hook that points to the operation data. */
+ void *hook;
+};
+typedef struct ctx_op_data *ctx_op_data_t;
+
+
+/* The context defines an environment in which crypto operations can
+ be performed (sequentially). */
+struct gpgme_context
+{
+ /* The engine info for this context. */
+ gpgme_engine_info_t engine_info;
+
+ /* The protocol used by this context. */
+ gpgme_protocol_t protocol;
+
+ /* The running engine process. */
+ engine_t engine;
+
+ /* True if armor mode should be used. */
+ unsigned int use_armor : 1;
+
+ /* True if text mode should be used. */
+ unsigned int use_textmode : 1;
+
+ /* Flags for keylist mode. */
+ gpgme_keylist_mode_t keylist_mode;
+
+ /* Number of certs to be included. */
+ unsigned int include_certs;
+
+ /* The number of keys in signers. */
+ unsigned int signers_len;
+
+ /* Size of the following array. */
+ unsigned int signers_size;
+ gpgme_key_t *signers;
+
+ /* The signature notations for this context. */
+ gpgme_sig_notation_t sig_notations;
+
+ /* The locale for the pinentry. */
+ char *lc_ctype;
+ char *lc_messages;
+
+ /* The operation data hooked into the context. */
+ ctx_op_data_t op_data;
+
+ /* The user provided passphrase callback and its hook value. */
+ gpgme_passphrase_cb_t passphrase_cb;
+ void *passphrase_cb_value;
+
+ /* The user provided progress callback and its hook value. */
+ gpgme_progress_cb_t progress_cb;
+ void *progress_cb_value;
+
+ /* A list of file descriptors in active use by the current
+ operation. */
+ struct fd_table fdt;
+ struct gpgme_io_cbs io_cbs;
+};
+
+#endif /* CONTEXT_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/conversion.c b/libtdenetwork/libgpgme-copy/gpgme/conversion.c
new file mode 100644
index 000000000..01e5cae7e
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/conversion.c
@@ -0,0 +1,414 @@
+/* conversion.c - String conversion helper functions.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "util.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_errno (errno);
+
+ *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_errno (errno);
+
+ *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;
+}
+
+
+/* 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);
+
+ /* 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);
+
+ if (endp)
+ *endp = (char*)(timestamp + 15);
+#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 */
+ }
+ else
+ return (time_t)strtoul (timestamp, endp, 10);
+}
+
+
+
+
+static struct
+{
+ char *name;
+ gpgme_error_t err;
+} gnupg_errors[] =
+ {
+ { "EOF", GPG_ERR_EOF },
+ { "No_Error", GPG_ERR_NO_ERROR },
+ { "General_Error", GPG_ERR_GENERAL },
+ { "Out_Of_Core", GPG_ERR_ENOMEM },
+ { "Invalid_Value", GPG_ERR_INV_VALUE },
+ { "IO_Error", GPG_ERR_GENERAL },
+ { "Resource_Limit", GPG_ERR_RESOURCE_LIMIT },
+ { "Internal_Error", GPG_ERR_INTERNAL },
+ { "Bad_Certificate", GPG_ERR_BAD_CERT },
+ { "Bad_Certificate_Chain", GPG_ERR_BAD_CERT_CHAIN},
+ { "Missing_Certificate", GPG_ERR_MISSING_CERT },
+ { "No_Data", GPG_ERR_NO_DATA },
+ { "Bad_Signature", GPG_ERR_BAD_SIGNATURE },
+ { "Not_Implemented", GPG_ERR_NOT_IMPLEMENTED },
+ { "Conflict", GPG_ERR_CONFLICT },
+ { "Bug", GPG_ERR_BUG },
+ { "Read_Error", GPG_ERR_GENERAL },
+ { "Write_Error", GPG_ERR_GENERAL },
+ { "Invalid_Line", GPG_ERR_GENERAL },
+ { "Incomplete_Line", GPG_ERR_INCOMPLETE_LINE },
+ { "Invalid_Response", GPG_ERR_INV_RESPONSE },
+ { "Agent_Error", GPG_ERR_AGENT },
+ { "No_Public_Key", GPG_ERR_NO_PUBKEY },
+ { "No_Secret_Key", GPG_ERR_NO_SECKEY },
+ { "File_Open_Error", GPG_ERR_GENERAL },
+ { "File_Create_Error", GPG_ERR_GENERAL },
+ { "File_Error", GPG_ERR_GENERAL },
+ { "Not_Supported", GPG_ERR_NOT_SUPPORTED },
+ { "Invalid_Data", GPG_ERR_INV_DATA },
+ { "Assuan_Server_Fault", GPG_ERR_ASSUAN_SERVER_FAULT },
+ { "Assuan_Error", GPG_ERR_ASSUAN },
+ { "Invalid_Session_Key", GPG_ERR_INV_SESSION_KEY },
+ { "Invalid_Sexp", GPG_ERR_INV_SEXP },
+ { "Unsupported_Algorithm", GPG_ERR_UNSUPPORTED_ALGORITHM },
+ { "No_PIN_Entry", GPG_ERR_NO_PIN_ENTRY },
+ { "PIN_Entry_Error", GPG_ERR_NO_PIN_ENTRY },
+ { "Bad_PIN", GPG_ERR_BAD_PIN },
+ { "Bad_Passphrase", GPG_ERR_BAD_PASSPHRASE },
+ { "Invalid_Name", GPG_ERR_INV_NAME },
+ { "Bad_Public_Key", GPG_ERR_BAD_PUBKEY },
+ { "Bad_Secret_Key", GPG_ERR_BAD_SECKEY },
+ { "Bad_Data", GPG_ERR_BAD_DATA },
+ { "Invalid_Parameter", GPG_ERR_INV_PARAMETER },
+ { "Tribute_to_D_A", GPG_ERR_TRIBUTE_TO_D_A },
+ { "No_Dirmngr", GPG_ERR_NO_DIRMNGR },
+ { "Dirmngr_Error", GPG_ERR_DIRMNGR },
+ { "Certificate_Revoked", GPG_ERR_CERT_REVOKED },
+ { "No_CRL_Known", GPG_ERR_NO_CRL_KNOWN },
+ { "CRL_Too_Old", GPG_ERR_CRL_TOO_OLD },
+ { "Line_Too_Long", GPG_ERR_LINE_TOO_LONG },
+ { "Not_Trusted", GPG_ERR_NOT_TRUSTED },
+ { "Canceled", GPG_ERR_CANCELED },
+ { "Bad_CA_Certificate", GPG_ERR_BAD_CA_CERT },
+ { "Certificate_Expired", GPG_ERR_CERT_EXPIRED },
+ { "Certificate_Too_Young", GPG_ERR_CERT_TOO_YOUNG },
+ { "Unsupported_Certificate", GPG_ERR_UNSUPPORTED_CERT },
+ { "Unknown_Sexp", GPG_ERR_UNKNOWN_SEXP },
+ { "Unsupported_Protection", GPG_ERR_UNSUPPORTED_PROTECTION },
+ { "Corrupted_Protection", GPG_ERR_CORRUPTED_PROTECTION },
+ { "Ambiguous_Name", GPG_ERR_AMBIGUOUS_NAME },
+ { "Card_Error", GPG_ERR_CARD },
+ { "Card_Reset", GPG_ERR_CARD_RESET },
+ { "Card_Removed", GPG_ERR_CARD_REMOVED },
+ { "Invalid_Card", GPG_ERR_INV_CARD },
+ { "Card_Not_Present", GPG_ERR_CARD_NOT_PRESENT },
+ { "No_PKCS15_App", GPG_ERR_NO_PKCS15_APP },
+ { "Not_Confirmed", GPG_ERR_NOT_CONFIRMED },
+ { "Configuration_Error", GPG_ERR_CONFIGURATION },
+ { "No_Policy_Match", GPG_ERR_NO_POLICY_MATCH },
+ { "Invalid_Index", GPG_ERR_INV_INDEX },
+ { "Invalid_Id", GPG_ERR_INV_ID },
+ { "No_Scdaemon", GPG_ERR_NO_SCDAEMON },
+ { "Scdaemon_Error", GPG_ERR_SCDAEMON },
+ { "Unsupported_Protocol", GPG_ERR_UNSUPPORTED_PROTOCOL },
+ { "Bad_PIN_Method", GPG_ERR_BAD_PIN_METHOD },
+ { "Card_Not_Initialized", GPG_ERR_CARD_NOT_INITIALIZED },
+ { "Unsupported_Operation", GPG_ERR_UNSUPPORTED_OPERATION },
+ { "Wrong_Key_Usage", GPG_ERR_WRONG_KEY_USAGE }
+ };
+
+
+gpgme_error_t
+_gpgme_map_gnupg_error (char *err)
+{
+ unsigned int i;
+
+ /* Future version of GnuPG might return the error code directly, so
+ we first test for a a numerical value and use that verbatim.
+ Note that this numerical value might be followed by an
+ underschore and the textual representation of the error code. */
+ if (*err >= '0' && *err <= '9')
+ return strtoul (err, NULL, 10);
+
+ /* Well, this is a token, use the mapping table to get the error.
+ The drawback is that we won't receive an error source and have to
+ use GPG as source. */
+ for (i = 0; i < DIM (gnupg_errors); i++)
+ if (!strcmp (gnupg_errors[i].name, err))
+ return gpg_err_make (GPG_ERR_SOURCE_GPG, gnupg_errors[i].err);
+
+ return gpg_err_make (GPG_ERR_SOURCE_GPG, GPG_ERR_GENERAL);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data-compat.c b/libtdenetwork/libgpgme-copy/gpgme/data-compat.c
new file mode 100644
index 000000000..37cb4ff55
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data-compat.c
@@ -0,0 +1,209 @@
+/* data-compat.c - Compatibility interfaces for data objects.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "data.h"
+#include "util.h"
+
+
+/* Create a new data buffer filled with LENGTH bytes starting from
+ OFFSET within the file FNAME or stream STREAM (exactly one must be
+ non-zero). */
+gpgme_error_t
+gpgme_data_new_from_filepart (gpgme_data_t *dh, const char *fname,
+ FILE *stream, off_t offset, size_t length)
+{
+ gpgme_error_t err;
+ char *buf = NULL;
+ int res;
+
+ if (stream && fname)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (fname)
+ stream = fopen (fname, "rb");
+ if (!stream)
+ return gpg_error_from_errno (errno);
+
+#ifdef HAVE_FSEEKO
+ res = fseeko (stream, offset, SEEK_SET);
+#else
+ /* FIXME: Check for overflow, or at least bail at compilation. */
+ res = fseek (stream, offset, SEEK_SET);
+#endif
+
+ if (res)
+ {
+ int saved_errno = errno;
+ if (fname)
+ fclose (stream);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ buf = malloc (length);
+ if (!buf)
+ {
+ int saved_errno = errno;
+ if (fname)
+ fclose (stream);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ while (fread (buf, length, 1, stream) < 1
+ && ferror (stream) && errno == EINTR);
+ if (ferror (stream))
+ {
+ int saved_errno = errno;
+ if (buf)
+ free (buf);
+ if (fname)
+ fclose (stream);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ if (fname)
+ fclose (stream);
+
+ err = gpgme_data_new (dh);
+ if (err)
+ {
+ if (buf)
+ free (buf);
+ return err;
+ }
+
+ (*dh)->data.mem.buffer = buf;
+ (*dh)->data.mem.size = length;
+ (*dh)->data.mem.length = length;
+ return 0;
+}
+
+
+/* Create a new data buffer filled with the content of file FNAME.
+ COPY must be non-zero (delayed reads are not supported yet). */
+gpgme_error_t
+gpgme_data_new_from_file (gpgme_data_t *dh, const char *fname, int copy)
+{
+ struct stat statbuf;
+
+ if (!fname || !copy)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (stat (fname, &statbuf) < 0)
+ return gpg_error_from_errno (errno);
+
+ return gpgme_data_new_from_filepart (dh, fname, NULL, 0, statbuf.st_size);
+}
+
+
+static int
+gpgme_error_to_errno (gpgme_error_t err)
+{
+ int no = gpg_err_code_to_errno (err);
+
+ if (no)
+ {
+ errno = no;
+ return -1;
+ }
+
+ switch (gpg_err_code (err))
+ {
+ case GPG_ERR_EOF:
+ return 0;
+ case GPG_ERR_INV_VALUE:
+ errno = EINVAL;
+ return -1;
+ case GPG_ERR_NOT_SUPPORTED:
+ errno = ENOSYS;
+ return -1;
+ default:
+ /* FIXME: Yeah, well. */
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+
+static ssize_t
+old_user_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ size_t amt;
+ gpgme_error_t err = (*dh->data.old_user.cb) (dh->data.old_user.handle,
+ buffer, size, &amt);
+ if (err)
+ return gpgme_error_to_errno (err);
+ return amt;
+}
+
+
+static off_t
+old_user_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ gpgme_error_t err;
+ if (whence != SEEK_SET || offset)
+ return EINVAL;
+ err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL);
+ if (err)
+ return gpgme_error_to_errno (err);
+ return 0;
+}
+
+
+static struct _gpgme_data_cbs old_user_cbs =
+ {
+ old_user_read,
+ NULL,
+ old_user_seek,
+ NULL
+ };
+
+
+/* Create a new data buffer which retrieves the data from the callback
+ function READ_CB. */
+gpgme_error_t
+gpgme_data_new_with_read_cb (gpgme_data_t *dh,
+ int (*read_cb) (void *, char *, size_t, size_t *),
+ void *read_cb_value)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &old_user_cbs);
+ if (err)
+ return err;
+
+ (*dh)->data.old_user.cb = read_cb;
+ (*dh)->data.old_user.handle = read_cb_value;
+ return 0;
+}
+
+
+gpgme_error_t
+gpgme_data_rewind (gpgme_data_t dh)
+{
+ return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
+ ? gpg_error_from_errno (errno) : 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data-fd.c b/libtdenetwork/libgpgme-copy/gpgme/data-fd.c
new file mode 100644
index 000000000..b543a770d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data-fd.c
@@ -0,0 +1,78 @@
+/* data-fd.c - A file descripor based data object.
+ Copyright (C) 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "data.h"
+
+
+static ssize_t
+fd_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ return read (dh->data.fd, buffer, size);
+}
+
+
+static ssize_t
+fd_write (gpgme_data_t dh, const void *buffer, size_t size)
+{
+ return write (dh->data.fd, buffer, size);
+}
+
+
+static off_t
+fd_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ return lseek (dh->data.fd, offset, whence);
+}
+
+
+static int
+fd_get_fd (gpgme_data_t dh)
+{
+ return (dh->data.fd);
+}
+
+
+static struct _gpgme_data_cbs fd_cbs =
+ {
+ fd_read,
+ fd_write,
+ fd_seek,
+ NULL,
+ fd_get_fd
+ };
+
+
+gpgme_error_t
+gpgme_data_new_from_fd (gpgme_data_t *dh, int fd)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &fd_cbs);
+ if (err)
+ return err;
+
+ (*dh)->data.fd = fd;
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data-mem.c b/libtdenetwork/libgpgme-copy/gpgme/data-mem.c
new file mode 100644
index 000000000..3f9bc95c1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data-mem.c
@@ -0,0 +1,251 @@
+/* data-mem.c - A memory based data object.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+
+#include "data.h"
+#include "util.h"
+
+
+static ssize_t
+mem_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ size_t amt = dh->data.mem.length - dh->data.mem.offset;
+ const char *src;
+
+ if (!amt)
+ return 0;
+
+ if (size < amt)
+ amt = size;
+
+ src = dh->data.mem.buffer ? dh->data.mem.buffer : dh->data.mem.orig_buffer;
+ memcpy (buffer, src + dh->data.mem.offset, amt);
+ dh->data.mem.offset += amt;
+ return amt;
+}
+
+
+static ssize_t
+mem_write (gpgme_data_t dh, const void *buffer, size_t size)
+{
+ size_t unused;
+
+ if (!dh->data.mem.buffer && dh->data.mem.orig_buffer)
+ {
+ size_t new_size = dh->data.mem.size;
+ char *new_buffer;
+
+ if (new_size < dh->data.mem.offset + size)
+ new_size = dh->data.mem.offset + size;
+
+ new_buffer = malloc (new_size);
+ if (!new_buffer)
+ return -1;
+ memcpy (new_buffer, dh->data.mem.orig_buffer, dh->data.mem.length);
+
+ dh->data.mem.buffer = new_buffer;
+ dh->data.mem.size = new_size;
+ }
+
+ unused = dh->data.mem.size - dh->data.mem.offset;
+ if (unused < size)
+ {
+ /* Allocate a large enough buffer with exponential backoff. */
+#define INITIAL_ALLOC 512
+ size_t new_size = dh->data.mem.size
+ ? (2 * dh->data.mem.size) : INITIAL_ALLOC;
+ char *new_buffer;
+
+ if (new_size < dh->data.mem.offset + size)
+ new_size = dh->data.mem.offset + size;
+
+ new_buffer = realloc (dh->data.mem.buffer, new_size);
+ if (!new_buffer && new_size > dh->data.mem.offset + size)
+ {
+ /* Maybe we were too greedy, try again. */
+ new_size = dh->data.mem.offset + size;
+ new_buffer = realloc (dh->data.mem.buffer, new_size);
+ }
+ if (!new_buffer)
+ return -1;
+ dh->data.mem.buffer = new_buffer;
+ dh->data.mem.size = new_size;
+ }
+
+ memcpy (dh->data.mem.buffer + dh->data.mem.offset, buffer, size);
+ dh->data.mem.offset += size;
+ if (dh->data.mem.length < dh->data.mem.offset)
+ dh->data.mem.length = dh->data.mem.offset;
+ return size;
+}
+
+
+static off_t
+mem_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (offset < 0 || offset > dh->data.mem.length)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ dh->data.mem.offset = offset;
+ break;
+ case SEEK_CUR:
+ if ((offset > 0 && dh->data.mem.length - dh->data.mem.offset < offset)
+ || (offset < 0 && dh->data.mem.offset < -offset))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ dh->data.mem.offset += offset;
+ break;
+ case SEEK_END:
+ if (offset > 0 || -offset > dh->data.mem.length)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ dh->data.mem.offset = dh->data.mem.length - offset;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ return dh->data.mem.offset;
+}
+
+
+static void
+mem_release (gpgme_data_t dh)
+{
+ if (dh->data.mem.buffer)
+ free (dh->data.mem.buffer);
+}
+
+
+static struct _gpgme_data_cbs mem_cbs =
+ {
+ mem_read,
+ mem_write,
+ mem_seek,
+ mem_release,
+ NULL
+ };
+
+
+/* Create a new data buffer and return it in R_DH. */
+gpgme_error_t
+gpgme_data_new (gpgme_data_t *dh)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &mem_cbs);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+
+/* Create a new data buffer filled with SIZE bytes starting from
+ BUFFER. If COPY is zero, copying is delayed until necessary, and
+ the data is taken from the original location when needed. */
+gpgme_error_t
+gpgme_data_new_from_mem (gpgme_data_t *dh, const char *buffer,
+ size_t size, int copy)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &mem_cbs);
+ if (err)
+ return err;
+
+ if (copy)
+ {
+ char *bufcpy = malloc (size);
+ if (!bufcpy)
+ _gpgme_data_release (*dh);
+ memcpy (bufcpy, buffer, size);
+ (*dh)->data.mem.buffer = bufcpy;
+ }
+ else
+ (*dh)->data.mem.orig_buffer = buffer;
+
+ (*dh)->data.mem.size = size;
+ (*dh)->data.mem.length = size;
+ return 0;
+}
+
+
+/* Destroy the data buffer DH and return a pointer to its content.
+ The memory has be to released with gpgme_free() by the user. It's
+ size is returned in R_LEN. */
+char *
+gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len)
+{
+ char *str = NULL;
+
+ if (!dh || dh->cbs != &mem_cbs)
+ {
+ gpgme_data_release (dh);
+ return NULL;
+ }
+
+ str = dh->data.mem.buffer;
+ if (!str && dh->data.mem.orig_buffer)
+ {
+ str = malloc (dh->data.mem.length);
+ if (!str)
+ {
+ gpgme_data_release (dh);
+ return NULL;
+ }
+ memcpy (str, dh->data.mem.orig_buffer, dh->data.mem.length);
+ }
+ else
+ /* Prevent mem_release from releasing the buffer memory. We must
+ not fail from this point. */
+ dh->data.mem.buffer = NULL;
+
+ if (r_len)
+ *r_len = dh->data.mem.length;
+
+ gpgme_data_release (dh);
+
+ return str;
+}
+
+
+/* Release the memory returned by gpgme_data_release_and_get_mem(). */
+void
+gpgme_free (void *buffer)
+{
+ if (buffer)
+ free (buffer);
+}
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data-stream.c b/libtdenetwork/libgpgme-copy/gpgme/data-stream.c
new file mode 100644
index 000000000..eb8768d3c
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data-stream.c
@@ -0,0 +1,101 @@
+/* data-stream.c - A stream based data object.
+ Copyright (C) 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "data.h"
+
+
+static ssize_t
+stream_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ size_t amt = fread (buffer, 1, size, dh->data.stream);
+ if (amt > 0)
+ return amt;
+ return ferror (dh->data.stream) ? -1 : 0;
+}
+
+
+static ssize_t
+stream_write (gpgme_data_t dh, const void *buffer, size_t size)
+{
+ size_t amt = fwrite (buffer, 1, size, dh->data.stream);
+ if (amt > 0)
+ return amt;
+ return ferror (dh->data.stream) ? -1 : 0;
+}
+
+
+static off_t
+stream_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ int err;
+
+#ifdef HAVE_FSEEKO
+ err = fseeko (dh->data.stream, offset, whence);
+#else
+ /* FIXME: Check for overflow, or at least bail at compilation. */
+ err = fseek (dh->data.stream, offset, whence);
+#endif
+
+ if (err)
+ return -1;
+
+#ifdef HAVE_FSEEKO
+ return ftello (dh->data.stream);
+#else
+ return ftell (dh->data.stream);
+#endif
+}
+
+
+static int
+stream_get_fd (gpgme_data_t dh)
+{
+ fflush (dh->data.stream);
+ return fileno (dh->data.stream);
+}
+
+
+static struct _gpgme_data_cbs stream_cbs =
+ {
+ stream_read,
+ stream_write,
+ stream_seek,
+ NULL,
+ stream_get_fd
+ };
+
+
+gpgme_error_t
+gpgme_data_new_from_stream (gpgme_data_t *dh, FILE *stream)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &stream_cbs);
+ if (err)
+ return err;
+
+ (*dh)->data.stream = stream;
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data-user.c b/libtdenetwork/libgpgme-copy/gpgme/data-user.c
new file mode 100644
index 000000000..d33d71a06
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data-user.c
@@ -0,0 +1,89 @@
+/* data-user.c - A user callback based data object.
+ Copyright (C) 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+
+#include "data.h"
+
+
+static ssize_t
+user_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ if (!dh->data.user.cbs->read)
+ return EBADF;
+
+ return (*dh->data.user.cbs->read) (dh->data.user.handle, buffer, size);
+}
+
+
+static ssize_t
+user_write (gpgme_data_t dh, const void *buffer, size_t size)
+{
+ if (!dh->data.user.cbs->write)
+ return EBADF;
+
+ return (*dh->data.user.cbs->write) (dh->data.user.handle, buffer, size);
+}
+
+
+static off_t
+user_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ if (!dh->data.user.cbs->seek)
+ return EBADF;
+
+ return (*dh->data.user.cbs->seek) (dh->data.user.handle, offset, whence);
+}
+
+
+static void
+user_release (gpgme_data_t dh)
+{
+ if (dh->data.user.cbs->release)
+ (*dh->data.user.cbs->release) (dh->data.user.handle);
+}
+
+
+static struct _gpgme_data_cbs user_cbs =
+ {
+ user_read,
+ user_write,
+ user_seek,
+ user_release,
+ NULL
+ };
+
+
+gpgme_error_t
+gpgme_data_new_from_cbs (gpgme_data_t *dh, gpgme_data_cbs_t cbs, void *handle)
+{
+ gpgme_error_t err = _gpgme_data_new (dh, &user_cbs);
+ if (err)
+ return err;
+
+ (*dh)->data.user.cbs = cbs;
+ (*dh)->data.user.handle = handle;
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data.c b/libtdenetwork/libgpgme-copy/gpgme/data.c
new file mode 100644
index 000000000..6ffae324e
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data.c
@@ -0,0 +1,293 @@
+/* data.c - An abstraction for data objects.
+ Copyright (C) 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "gpgme.h"
+#include "data.h"
+#include "util.h"
+#include "ops.h"
+#include "priv-io.h"
+
+
+gpgme_error_t
+_gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
+{
+ gpgme_data_t dh;
+
+ if (!r_dh)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ *r_dh = NULL;
+ dh = calloc (1, sizeof (*dh));
+ if (!dh)
+ return gpg_error_from_errno (errno);
+
+ dh->cbs = cbs;
+
+ *r_dh = dh;
+ return 0;
+}
+
+
+void
+_gpgme_data_release (gpgme_data_t dh)
+{
+ if (!dh)
+ return;
+
+ if (dh->file_name)
+ free (dh->file_name);
+ free (dh);
+}
+
+
+/* Read up to SIZE bytes into buffer BUFFER from the data object with
+ the handle DH. Return the number of characters read, 0 on EOF and
+ -1 on error. If an error occurs, errno is set. */
+ssize_t
+gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
+{
+ if (!dh)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (!dh->cbs->read)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+ return (*dh->cbs->read) (dh, buffer, size);
+}
+
+
+/* Write up to SIZE bytes from buffer BUFFER to the data object with
+ the handle DH. Return the number of characters written, or -1 on
+ error. If an error occurs, errno is set. */
+ssize_t
+gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
+{
+ if (!dh)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (!dh->cbs->write)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+ return (*dh->cbs->write) (dh, buffer, size);
+}
+
+
+/* Set the current position from where the next read or write starts
+ in the data object with the handle DH to OFFSET, relativ to
+ WHENCE. */
+off_t
+gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence)
+{
+ if (!dh)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (!dh->cbs->seek)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ /* For relative movement, we must take into account the actual
+ position of the read counter. */
+ if (whence == SEEK_CUR)
+ offset -= dh->pending_len;
+
+ offset = (*dh->cbs->seek) (dh, offset, whence);
+ if (offset >= 0)
+ dh->pending_len = 0;
+
+ return offset;
+}
+
+
+/* Release the data object with the handle DH. */
+void
+gpgme_data_release (gpgme_data_t dh)
+{
+ if (!dh)
+ return;
+
+ if (dh->cbs->release)
+ (*dh->cbs->release) (dh);
+ _gpgme_data_release (dh);
+}
+
+
+/* Get the current encoding meta information for the data object with
+ handle DH. */
+gpgme_data_encoding_t
+gpgme_data_get_encoding (gpgme_data_t dh)
+{
+ return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE;
+}
+
+
+/* Set the encoding meta information for the data object with handle
+ DH to ENC. */
+gpgme_error_t
+gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
+{
+ if (!dh)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (enc < 0 || enc > GPGME_DATA_ENCODING_ARMOR)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ dh->encoding = enc;
+ return 0;
+}
+
+
+/* Set the file name associated with the data object with handle DH to
+ FILE_NAME. */
+gpgme_error_t
+gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name)
+{
+ if (!dh)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (dh->file_name)
+ free (dh->file_name);
+
+ if (file_name)
+ {
+ dh->file_name = strdup (file_name);
+ if (!dh->file_name)
+ return gpg_error_from_errno (errno);
+ }
+ else
+ dh->file_name = 0;
+
+ return 0;
+}
+
+/* Get the file name associated with the data object with handle DH,
+ or NULL if there is none. */
+char *
+gpgme_data_get_file_name (gpgme_data_t dh)
+{
+ if (!dh)
+ return NULL;
+
+ return dh->file_name;
+}
+
+
+/* Functions to support the wait interface. */
+
+gpgme_error_t
+_gpgme_data_inbound_handler (void *opaque, int fd)
+{
+ gpgme_data_t dh = (gpgme_data_t) opaque;
+ char buffer[BUFFER_SIZE];
+ char *bufp = buffer;
+ ssize_t buflen;
+
+ buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
+ if (buflen < 0)
+ return gpg_error_from_errno (errno);
+ if (buflen == 0)
+ {
+ _gpgme_io_close (fd);
+ return 0;
+ }
+
+ do
+ {
+ ssize_t amt = gpgme_data_write (dh, bufp, buflen);
+ if (amt == 0 || (amt < 0 && errno != EINTR))
+ return gpg_error_from_errno (errno);
+ bufp += amt;
+ buflen -= amt;
+ }
+ while (buflen > 0);
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_data_outbound_handler (void *opaque, int fd)
+{
+ gpgme_data_t dh = (gpgme_data_t) opaque;
+ ssize_t nwritten;
+
+ if (!dh->pending_len)
+ {
+ ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
+ if (amt < 0)
+ return gpg_error_from_errno (errno);
+ if (amt == 0)
+ {
+ _gpgme_io_close (fd);
+ return 0;
+ }
+ dh->pending_len = amt;
+ }
+
+ nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
+ if (nwritten == -1 && errno == EAGAIN)
+ return 0;
+
+ if (nwritten == -1 && errno == EPIPE)
+ {
+ /* Not much we can do. The other end closed the pipe, but we
+ still have data. This should only ever happen if the other
+ end is going to tell us what happened on some other channel.
+ Silently close our end. */
+ _gpgme_io_close (fd);
+ return 0;
+ }
+
+ if (nwritten <= 0)
+ return gpg_error_from_errno (errno);
+
+ if (nwritten < dh->pending_len)
+ memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
+ dh->pending_len -= nwritten;
+ return 0;
+}
+
+
+/* Get the file descriptor associated with DH, if possible. Otherwise
+ return -1. */
+int
+_gpgme_data_get_fd (gpgme_data_t dh)
+{
+ if (!dh || !dh->cbs->get_fd)
+ return -1;
+ return (*dh->cbs->get_fd) (dh);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/data.h b/libtdenetwork/libgpgme-copy/gpgme/data.h
new file mode 100644
index 000000000..984c1e1fb
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/data.h
@@ -0,0 +1,132 @@
+/* data.h - Internal data object abstraction interface.
+ Copyright (C) 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef DATA_H
+#define DATA_H
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <limits.h>
+
+#include "gpgme.h"
+
+
+/* Read up to SIZE bytes into buffer BUFFER from the data object with
+ the handle DH. Return the number of characters read, 0 on EOF and
+ -1 on error. If an error occurs, errno is set. */
+typedef ssize_t (*gpgme_data_read_cb) (gpgme_data_t dh, void *buffer,
+ size_t size);
+
+/* Write up to SIZE bytes from buffer BUFFER to the data object with
+ the handle DH. Return the number of characters written, or -1 on
+ error. If an error occurs, errno is set. */
+typedef ssize_t (*gpgme_data_write_cb) (gpgme_data_t dh, const void *buffer,
+ size_t size);
+
+/* Set the current position from where the next read or write starts
+ in the data object with the handle DH to OFFSET, relativ to
+ WHENCE. */
+typedef off_t (*gpgme_data_seek_cb) (gpgme_data_t dh, off_t offset,
+ int whence);
+
+/* Release the data object with the handle DH. */
+typedef void (*gpgme_data_release_cb) (gpgme_data_t dh);
+
+/* Get the FD associated with the handle DH, or -1. */
+typedef int (*gpgme_data_get_fd_cb) (gpgme_data_t dh);
+
+struct _gpgme_data_cbs
+{
+ gpgme_data_read_cb read;
+ gpgme_data_write_cb write;
+ gpgme_data_seek_cb seek;
+ gpgme_data_release_cb release;
+ gpgme_data_get_fd_cb get_fd;
+};
+
+struct gpgme_data
+{
+ struct _gpgme_data_cbs *cbs;
+ gpgme_data_encoding_t encoding;
+
+#ifdef PIPE_BUF
+#define BUFFER_SIZE PIPE_BUF
+#else
+#ifdef _POSIX_PIPE_BUF
+#define BUFFER_SIZE _POSIX_PIPE_BUF
+#else
+#define BUFFER_SIZE 512
+#endif
+#endif
+ char pending[BUFFER_SIZE];
+ int pending_len;
+
+ /* File name of the data object. */
+ char *file_name;
+
+ union
+ {
+ /* For gpgme_data_new_from_fd. */
+ int fd;
+
+ /* For gpgme_data_new_from_stream. */
+ FILE *stream;
+
+ /* For gpgme_data_new_from_cbs. */
+ struct
+ {
+ gpgme_data_cbs_t cbs;
+ void *handle;
+ } user;
+
+ /* For gpgme_data_new_from_mem. */
+ struct
+ {
+ char *buffer;
+ const char *orig_buffer;
+ /* Allocated size of BUFFER. */
+ size_t size;
+ size_t length;
+ off_t offset;
+ } mem;
+
+ /* For gpgme_data_new_from_read_cb. */
+ struct
+ {
+ int (*cb) (void *, char *, size_t, size_t *);
+ void *handle;
+ } old_user;
+ } data;
+};
+
+
+gpgme_error_t _gpgme_data_new (gpgme_data_t *r_dh,
+ struct _gpgme_data_cbs *cbs);
+
+void _gpgme_data_release (gpgme_data_t dh);
+
+/* Get the file descriptor associated with DH, if possible. Otherwise
+ return -1. */
+int _gpgme_data_get_fd (gpgme_data_t dh);
+
+#endif /* DATA_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/debug.c b/libtdenetwork/libgpgme-copy/gpgme/debug.c
new file mode 100644
index 000000000..3351059e1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/debug.c
@@ -0,0 +1,221 @@
+/* debug.c - helpful output in desperate situations
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <ctype.h>
+#ifndef HAVE_DOSISH_SYSTEM
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+#endif
+#include <assert.h>
+
+#include "util.h"
+#include "sema.h"
+
+
+/* Lock to serialize initialization of the debug output subsystem and
+ output of actual debug messages. */
+DEFINE_STATIC_LOCK (debug_lock);
+
+/* The amount of detail requested by the user, per environment
+ variable GPGME_DEBUG. */
+static int debug_level;
+
+/* The output stream for the debug messages. */
+static FILE *errfp;
+
+
+/* Remove leading and trailing white spaces. */
+static char *
+trim_spaces (char *str)
+{
+ char *string, *p, *mark;
+
+ string = str;
+ /* Find first non space character. */
+ for (p = string; *p && isspace (*(unsigned char *) p); p++)
+ ;
+ /* Move characters. */
+ for (mark = NULL; (*string = *p); string++, p++)
+ if (isspace (*(unsigned char *) p))
+ {
+ if (!mark)
+ mark = string;
+ }
+ else
+ mark = NULL;
+ if (mark)
+ *mark = '\0'; /* Remove trailing spaces. */
+
+ return str;
+}
+
+
+static void
+debug_init (void)
+{
+ static int initialized;
+
+ LOCK (debug_lock);
+ if (!initialized)
+ {
+ gpgme_error_t err;
+ char *e;
+ const char *s1, *s2;;
+
+ err = _gpgme_getenv ("GPGME_DEBUG", &e);
+ if (err)
+ {
+ UNLOCK (debug_lock);
+ return;
+ }
+
+ initialized = 1;
+ errfp = stderr;
+ if (e)
+ {
+ debug_level = atoi (e);
+ s1 = strchr (e, PATHSEP_C);
+ if (s1)
+ {
+#ifndef HAVE_DOSISH_SYSTEM
+ if (getuid () == geteuid ())
+ {
+#endif
+ char *p;
+ FILE *fp;
+
+ s1++;
+ if (!(s2 = strchr (s1, PATHSEP_C)))
+ s2 = s1 + strlen (s1);
+ p = malloc (s2 - s1 + 1);
+ if (p)
+ {
+ memcpy (p, s1, s2 - s1);
+ p[s2-s1] = 0;
+ trim_spaces (p);
+ fp = fopen (p,"a");
+ if (fp)
+ {
+ setvbuf (fp, NULL, _IOLBF, 0);
+ errfp = fp;
+ }
+ free (p);
+ }
+#ifndef HAVE_DOSISH_SYSTEM
+ }
+#endif
+ }
+ free (e);
+ }
+
+ if (debug_level > 0)
+ fprintf (errfp, "gpgme_debug: level=%d\n", debug_level);
+ }
+ UNLOCK (debug_lock);
+}
+
+
+/* Log the formatted string FORMAT at debug level LEVEL or higher. */
+void
+_gpgme_debug (int level, const char *format, ...)
+{
+ va_list arg_ptr;
+
+ debug_init ();
+ if (debug_level < level)
+ return;
+
+ va_start (arg_ptr, format);
+ LOCK (debug_lock);
+ vfprintf (errfp, format, arg_ptr);
+ va_end (arg_ptr);
+ if(format && *format && format[strlen (format) - 1] != '\n')
+ putc ('\n', errfp);
+ UNLOCK (debug_lock);
+ fflush (errfp);
+}
+
+
+/* Start a new debug line in *LINE, logged at level LEVEL or higher,
+ and starting with the formatted string FORMAT. */
+void
+_gpgme_debug_begin (void **line, int level, const char *format, ...)
+{
+ va_list arg_ptr;
+
+ debug_init ();
+ if (debug_level < level)
+ {
+ /* Disable logging of this line. */
+ *line = NULL;
+ return;
+ }
+
+ va_start (arg_ptr, format);
+ vasprintf ((char **) line, format, arg_ptr);
+ va_end (arg_ptr);
+}
+
+
+/* Add the formatted string FORMAT to the debug line *LINE. */
+void
+_gpgme_debug_add (void **line, const char *format, ...)
+{
+ va_list arg_ptr;
+ char *toadd;
+ char *result;
+
+ if (!*line)
+ return;
+
+ va_start (arg_ptr, format);
+ vasprintf (&toadd, format, arg_ptr);
+ va_end (arg_ptr);
+ asprintf (&result, "%s%s", *(char **) line, toadd);
+ free (*line);
+ free (toadd);
+ *line = result;
+}
+
+
+/* Finish construction of *LINE and send it to the debug output
+ stream. */
+void
+_gpgme_debug_end (void **line)
+{
+ if (!*line)
+ return;
+
+ /* The smallest possible level is 1, so force logging here by
+ using that. */
+ _gpgme_debug (1, "%s", *line);
+ free (*line);
+ *line = NULL;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/debug.h b/libtdenetwork/libgpgme-copy/gpgme/debug.h
new file mode 100644
index 000000000..6a322634a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/debug.h
@@ -0,0 +1,127 @@
+/* debug.h - interface to debugging functions
+ Copyright (C) 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <string.h>
+
+/* Remove path components from filenames (i.e. __FILE__) for cleaner
+ logs. */
+static __inline__ const char *_gpgme_debug_srcname (const char *file);
+
+static __inline__ const char *
+_gpgme_debug_srcname (const char *file)
+{
+ const char *s = strrchr (file, '/');
+ return s? s+1:file;
+}
+
+/* Log the formatted string FORMAT at debug level LEVEL or higher. */
+void _gpgme_debug (int level, const char *format, ...);
+
+/* Start a new debug line in *LINE, logged at level LEVEL or higher,
+ and starting with the formatted string FORMAT. */
+void _gpgme_debug_begin (void **helper, int level, const char *format, ...);
+
+/* Add the formatted string FORMAT to the debug line *LINE. */
+void _gpgme_debug_add (void **helper, const char *format, ...);
+
+/* Finish construction of *LINE and send it to the debug output
+ stream. */
+void _gpgme_debug_end (void **helper);
+
+/* Indirect stringification, requires __STDC__ to work. */
+#define STRINGIFY(v) #v
+#define XSTRINGIFY(v) STRINGIFY(v)
+
+#if 0
+/* Only works in GNU. */
+#define DEBUG(fmt, arg...) \
+ _gpgme_debug (1, "%s:%s: " fmt, __FILE__, XSTRINGIFY (__LINE__) , ##arg)
+#define DEBUG_BEGIN(hlp, lvl, fmt, arg...) \
+ _gpgme_debug_begin (&(hlp), lvl, "%s:%s: " fmt, __FILE__, \
+ XSTRINGIFY (__LINE__) , ##arg)
+#define DEBUG_ADD(hlp, fmt, arg...) \
+ _gpgme_debug_add (&(hlp), fmt , ##arg)
+#define DEBUG_END(hlp, fmt, arg...) \
+ _gpgme_debug_add (&(hlp), fmt , ##arg); \
+ _gpgme_debug_end (&(hlp))
+#elif 0
+/* Only works in C99. */
+#define DEBUG0(fmt) \
+ _gpgme_debug (1, "%s:%s: " fmt, __FILE__, XSTRINGIFY (__LINE__))
+#define DEBUG(fmt, ...) \
+ _gpgme_debug (1, "%s:%s: " fmt, __FILE__, XSTRINGIFY (__LINE__), __VA_ARGS__)
+#define DEBUG_BEGIN(hlp, lvl, fmt) \
+ _gpgme_debug_begin (&(hlp), lvl, "%s:%s: " fmt, __FILE__, \
+ XSTRINGIFY (__LINE__))
+#define DEBUG_BEGINX(hlp, lvl, fmt, ...) \
+ _gpgme_debug_begin (&(hlp), lvl, "%s:%s: " fmt, __FILE__, \
+ XSTRINGIFY (__LINE__), __VA_ARGS__)
+#define DEBUG_ADD0(hlp, fmt) \
+ _gpgme_debug_add (&(hlp), fmt)
+#define DEBUG_ADD(hlp, fmt, ...) \
+ _gpgme_debug_add (&(hlp), fmt, __VA_ARGS__)
+#define DEBUG_END(hlp, fmt) \
+ _gpgme_debug_add (&(hlp), fmt); \
+ _gpgme_debug_end (&(hlp))
+#define DEBUG_ENDX(hlp, fmt, ...) \
+ _gpgme_debug_add (&(hlp), fmt, __VA_ARGS__); \
+ _gpgme_debug_end (&(hlp))
+#else
+/* This finally works everywhere, horror. */
+#define DEBUG0(fmt) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__))
+#define DEBUG1(fmt,a) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__), (a))
+#define DEBUG2(fmt,a,b) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__), (a), (b))
+#define DEBUG3(fmt,a,b,c) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__), (a), (b), (c))
+#define DEBUG4(fmt,a,b,c,d) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__), (a), (b), (c), (d))
+#define DEBUG5(fmt,a,b,c,d,e) \
+ _gpgme_debug (1, "%s:%s: " fmt, _gpgme_debug_srcname (__FILE__), \
+ XSTRINGIFY (__LINE__), (a), (b), (c), (d), (e))
+#define DEBUG_BEGIN(hlp,lvl,fmt) \
+ _gpgme_debug_begin (&(hlp), lvl, "%s:%s: " fmt, \
+ _gpgme_debug_srcname (__FILE__), XSTRINGIFY (__LINE__))
+#define DEBUG_ADD0(hlp,fmt) \
+ _gpgme_debug_add (&(hlp), fmt)
+#define DEBUG_ADD1(hlp,fmt,a) \
+ _gpgme_debug_add (&(hlp), fmt, (a))
+#define DEBUG_ADD2(hlp,fmt,a,b) \
+ _gpgme_debug_add (&(hlp), fmt, (a), (b))
+#define DEBUG_ADD3(hlp,fmt,a,b,c) \
+ _gpgme_debug_add (&(hlp), fmt, (a), (b), (c))
+#define DEBUG_END(hlp,fmt) \
+ _gpgme_debug_add (&(hlp), fmt); \
+ _gpgme_debug_end (&(hlp))
+#endif
+
+#define DEBUG_ENABLED(hlp) (!!(hlp))
+
+#endif /* DEBUG_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/decrypt-verify.c b/libtdenetwork/libgpgme-copy/gpgme/decrypt-verify.c
new file mode 100644
index 000000000..dd6a4db68
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/decrypt-verify.c
@@ -0,0 +1,103 @@
+/* decrypt-verify.c - Decrypt and verify function.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gpgme.h"
+#include "ops.h"
+
+
+static gpgme_error_t
+decrypt_verify_status_handler (void *priv, gpgme_status_code_t code,
+ char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_decrypt_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_verify_status_handler (priv, code, args);
+ return err;
+}
+
+
+static gpgme_error_t
+decrypt_verify_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_data_t cipher, gpgme_data_t plain)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_decrypt_init_result (ctx);
+ if (err)
+ return err;
+
+ err = _gpgme_op_verify_init_result (ctx);
+ if (err)
+ return err;
+
+ if (!cipher)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!plain)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ _gpgme_engine_set_status_handler (ctx->engine,
+ decrypt_verify_status_handler, ctx);
+
+ return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain);
+}
+
+
+/* Decrypt ciphertext CIPHER and make a signature verification within
+ CTX and store the resulting plaintext in PLAIN. */
+gpgme_error_t
+gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
+ gpgme_data_t plain)
+{
+ return decrypt_verify_start (ctx, 0, cipher, plain);
+}
+
+
+/* Decrypt ciphertext CIPHER and make a signature verification within
+ CTX and store the resulting plaintext in PLAIN. */
+gpgme_error_t
+gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher,
+ gpgme_data_t plain)
+{
+ gpgme_error_t err = decrypt_verify_start (ctx, 1, cipher, plain);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/decrypt.c b/libtdenetwork/libgpgme-copy/gpgme/decrypt.c
new file mode 100644
index 000000000..8d93239ed
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/decrypt.c
@@ -0,0 +1,340 @@
+/* decrypt.c - Decrypt function.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_decrypt_result result;
+
+ int okay;
+ int failed;
+
+ /* A pointer to the next pointer of the last recipient in the list.
+ This makes appending new invalid signers painless while
+ preserving the order. */
+ gpgme_recipient_t *last_recipient_p;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+
+ if (opd->result.unsupported_algorithm)
+ free (opd->result.unsupported_algorithm);
+
+ if (opd->result.file_name)
+ free (opd->result.file_name);
+}
+
+
+gpgme_decrypt_result_t
+gpgme_op_decrypt_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+static gpgme_error_t
+parse_enc_to (char *args, gpgme_recipient_t *recp)
+{
+ gpgme_recipient_t rec;
+ char *tail;
+ int i;
+
+ rec = malloc (sizeof (*rec));
+ if (!rec)
+ return gpg_error_from_errno (errno);
+
+ rec->next = NULL;
+ rec->keyid = rec->_keyid;
+ rec->status = 0;
+
+ for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
+ {
+ if (args[i] == '\0' || args[i] == ' ')
+ break;
+
+ rec->_keyid[i] = args[i];
+ }
+ rec->_keyid[i] = '\0';
+
+ args = &args[i];
+ if (*args != '\0' && *args != ' ')
+ {
+ free (rec);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ while (*args == ' ')
+ args++;
+
+ if (*args)
+ {
+ errno = 0;
+ rec->pubkey_algo = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (rec);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ }
+
+ /* FIXME: The key length is always 0 right now, so no need to parse
+ it. */
+
+ *recp = rec;
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
+ char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_passphrase_status_handler (priv, code, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_EOF:
+ /* FIXME: These error values should probably be attributed to
+ the underlying crypto engine (as error source). */
+ if (opd->failed)
+ return gpg_error (GPG_ERR_DECRYPT_FAILED);
+ else if (!opd->okay)
+ return gpg_error (GPG_ERR_NO_DATA);
+ break;
+
+ case GPGME_STATUS_DECRYPTION_OKAY:
+ opd->okay = 1;
+ break;
+
+ case GPGME_STATUS_DECRYPTION_FAILED:
+ opd->failed = 1;
+ break;
+
+ case GPGME_STATUS_ERROR:
+ /* Note that this is an informational status code which should
+ not lead to an error return unless it is something not
+ related to the backend. */
+ {
+ const char d_alg[] = "decrypt.algorithm";
+ const char u_alg[] = "Unsupported_Algorithm";
+ const char k_alg[] = "decrypt.keyusage";
+
+ if (!strncmp (args, d_alg, sizeof (d_alg) - 1))
+ {
+ args += sizeof (d_alg) - 1;
+ while (*args == ' ')
+ args++;
+
+ if (!strncmp (args, u_alg, sizeof (u_alg) - 1))
+ {
+ char *end;
+
+ args += sizeof (u_alg) - 1;
+ while (*args == ' ')
+ args++;
+
+ end = strchr (args, ' ');
+ if (end)
+ *end = '\0';
+
+ if (!(*args == '?' && *(args + 1) == '\0'))
+ {
+ opd->result.unsupported_algorithm = strdup (args);
+ if (!opd->result.unsupported_algorithm)
+ return gpg_error_from_errno (errno);
+ }
+ }
+ }
+ else if (!strncmp (args, k_alg, sizeof (k_alg) - 1))
+ {
+ args += sizeof (k_alg) - 1;
+ while (*args == ' ')
+ args++;
+
+ err = _gpgme_map_gnupg_error (args);
+ if (gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
+ opd->result.wrong_key_usage = 1;
+ }
+ }
+ break;
+
+ case GPGME_STATUS_ENC_TO:
+ err = parse_enc_to (args, opd->last_recipient_p);
+ if (err)
+ return err;
+
+ opd->last_recipient_p = &(*opd->last_recipient_p)->next;
+ break;
+
+ case GPGME_STATUS_NO_SECKEY:
+ {
+ gpgme_recipient_t rec = opd->result.recipients;
+
+ while (rec)
+ {
+ if (!strcmp (rec->keyid, args))
+ {
+ rec->status = gpg_error (GPG_ERR_NO_SECKEY);
+ break;
+ }
+ rec = rec->next;
+ }
+ /* FIXME: Is this ok? */
+ if (!rec)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ break;
+
+ case GPGME_STATUS_PLAINTEXT:
+ err = _gpgme_parse_plaintext (args, &opd->result.file_name);
+ if (err)
+ return err;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static gpgme_error_t
+decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_decrypt_status_handler (priv, code, args);
+ return err;
+}
+
+
+gpgme_error_t
+_gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->last_recipient_p = &opd->result.recipients;
+ return 0;
+}
+
+
+static gpgme_error_t
+decrypt_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_data_t cipher, gpgme_data_t plain)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_decrypt_init_result (ctx);
+ if (err)
+ return err;
+
+ if (!cipher)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!plain)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (err)
+ return err;
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
+
+ return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain);
+}
+
+
+gpgme_error_t
+gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
+ gpgme_data_t plain)
+{
+ return decrypt_start (ctx, 0, cipher, plain);
+}
+
+
+/* Decrypt ciphertext CIPHER within CTX and store the resulting
+ plaintext in PLAIN. */
+gpgme_error_t
+gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
+{
+ gpgme_error_t err = decrypt_start (ctx, 1, cipher, plain);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/delete.c b/libtdenetwork/libgpgme-copy/gpgme/delete.c
new file mode 100644
index 000000000..1f2d1a9bb
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/delete.c
@@ -0,0 +1,109 @@
+/* delete.c - Delete a key.
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+static gpgme_error_t
+delete_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ if (code == GPGME_STATUS_DELETE_PROBLEM)
+ {
+ enum delete_problem
+ {
+ DELETE_No_Problem = 0,
+ DELETE_No_Such_Key = 1,
+ DELETE_Must_Delete_Secret_Key = 2,
+ DELETE_Ambiguous_Specification = 3
+ };
+ long problem;
+ char *tail;
+
+ errno = 0;
+ problem = strtol (args, &tail, 0);
+ if (errno || (*tail && *tail != ' '))
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ switch (problem)
+ {
+ case DELETE_No_Problem:
+ break;
+
+ case DELETE_No_Such_Key:
+ return gpg_error (GPG_ERR_NO_PUBKEY);
+
+ case DELETE_Must_Delete_Secret_Key:
+ return gpg_error (GPG_ERR_CONFLICT);
+
+ case DELETE_Ambiguous_Specification:
+ return gpg_error (GPG_ERR_AMBIGUOUS_NAME);
+
+ default:
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+delete_start (gpgme_ctx_t ctx, int synchronous, const gpgme_key_t key,
+ int allow_secret)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, delete_status_handler, ctx);
+
+ return _gpgme_engine_op_delete (ctx->engine, key, allow_secret);
+}
+
+
+/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
+ keys are also deleted. */
+gpgme_error_t
+gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
+ int allow_secret)
+{
+ return delete_start (ctx, 0, key, allow_secret);
+}
+
+
+/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
+ keys are also deleted. */
+gpgme_error_t
+gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret)
+{
+ gpgme_error_t err = delete_start (ctx, 1, key, allow_secret);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/edit.c b/libtdenetwork/libgpgme-copy/gpgme/edit.c
new file mode 100644
index 000000000..7c6396770
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/edit.c
@@ -0,0 +1,177 @@
+/* edit.c - Key edit function.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ /* The user callback function and its hook value. */
+ gpgme_edit_cb_t fnc;
+ void *fnc_value;
+} *op_data_t;
+
+
+static gpgme_error_t
+edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_passphrase_status_handler (priv, status, args);
+ if (err)
+ return err;
+
+ err = _gpgme_progress_status_handler (priv, status, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ return (*opd->fnc) (opd->fnc_value, status, args, -1);
+}
+
+
+static gpgme_error_t
+command_handler (void *priv, gpgme_status_code_t status, const char *args,
+ int fd, int *processed_r)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ int processed = 0;
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_passphrase_command_handler (ctx, status, args,
+ fd, &processed);
+ if (err)
+ return err;
+ }
+
+ if (!processed)
+ {
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ /* FIXME: We expect the user to handle _all_ status codes.
+ Later, we may fix the callback interface to allow the user
+ indicate if it processed the status code or not. */
+ *processed_r = 1;
+
+ return (*opd->fnc) (opd->fnc_value, status, args, fd);
+ }
+
+ *processed_r = processed;
+ return 0;
+}
+
+
+static gpgme_error_t
+edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (!fnc || !out)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->fnc = fnc;
+ opd->fnc_value = fnc_value;
+
+ err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
+ ctx, out);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
+
+ return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
+}
+
+
+gpgme_error_t
+gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
+{
+ return edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
+}
+
+
+/* Edit the key KEY. Send status and command requests to FNC and
+ output of edit commands to OUT. */
+gpgme_error_t
+gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
+{
+ gpgme_error_t err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
+
+
+gpgme_error_t
+gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out)
+{
+ return edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
+}
+
+
+/* Edit the card for the key KEY. Send status and command requests to
+ FNC and output of edit commands to OUT. */
+gpgme_error_t
+gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
+{
+ gpgme_error_t err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/encrypt-sign.c b/libtdenetwork/libgpgme-copy/gpgme/encrypt-sign.c
new file mode 100644
index 000000000..d678ed67a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/encrypt-sign.c
@@ -0,0 +1,110 @@
+/* encrypt-sign.c - encrypt and verify functions
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+static gpgme_error_t
+encrypt_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_encrypt_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_sign_status_handler (priv, code, args);
+ return err;
+}
+
+
+static gpgme_error_t
+encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (!plain)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!cipher || !recp)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_encrypt_init_result (ctx);
+ if (err)
+ return err;
+
+ err = _gpgme_op_sign_init_result (ctx);
+ if (err)
+ return err;
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ _gpgme_engine_set_status_handler (ctx->engine,
+ encrypt_sign_status_handler, ctx);
+
+ return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, flags, plain,
+ cipher, ctx->use_armor,
+ ctx /* FIXME */);
+}
+
+
+/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
+ store the resulting ciphertext in CIPHER. Also sign the ciphertext
+ with the signers in CTX. */
+gpgme_error_t
+gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ return encrypt_sign_start (ctx, 0, recp, flags, plain, cipher);
+}
+
+
+/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
+ store the resulting ciphertext in CIPHER. Also sign the ciphertext
+ with the signers in CTX. */
+gpgme_error_t
+gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ gpgme_error_t err = encrypt_sign_start (ctx, 1, recp, flags, plain, cipher);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/encrypt.c b/libtdenetwork/libgpgme-copy/gpgme/encrypt.c
new file mode 100644
index 000000000..089c69999
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/encrypt.c
@@ -0,0 +1,222 @@
+/* encrypt.c - Encrypt function.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_encrypt_result result;
+
+ /* A pointer to the next pointer of the last invalid recipient in
+ the list. This makes appending new invalid recipients painless
+ while preserving the order. */
+ gpgme_invalid_key_t *lastp;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+ gpgme_invalid_key_t invalid_recipient = opd->result.invalid_recipients;
+
+ while (invalid_recipient)
+ {
+ gpgme_invalid_key_t next = invalid_recipient->next;
+ if (invalid_recipient->fpr)
+ free (invalid_recipient->fpr);
+ invalid_recipient = next;
+ }
+}
+
+
+gpgme_encrypt_result_t
+gpgme_op_encrypt_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL);
+ opd = hook;
+
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+gpgme_error_t
+_gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
+ char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_EOF:
+ if (opd->result.invalid_recipients)
+ return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
+ break;
+
+ case GPGME_STATUS_INV_RECP:
+ err = _gpgme_parse_inv_recp (args, opd->lastp);
+ if (err)
+ return err;
+
+ opd->lastp = &(*opd->lastp)->next;
+ break;
+
+ case GPGME_STATUS_NO_RECP:
+ /* Should not happen, because we require at least one recipient. */
+ return gpg_error (GPG_ERR_GENERAL);
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_passphrase_status_handler (priv, code, args);
+ return err;
+}
+
+
+static gpgme_error_t
+encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ return _gpgme_progress_status_handler (priv, code, args)
+ || _gpgme_encrypt_status_handler (priv, code, args);
+}
+
+
+gpgme_error_t
+_gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, sizeof (*opd),
+ release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->lastp = &opd->result.invalid_recipients;
+ return 0;
+}
+
+
+static gpgme_error_t
+encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ gpgme_error_t err;
+ int symmetric = 0;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_encrypt_init_result (ctx);
+ if (err)
+ return err;
+
+ if (!recp)
+ symmetric = 1;
+
+ if (!plain)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!cipher)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (recp && ! *recp)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (symmetric && ctx->passphrase_cb)
+ {
+ /* Symmetric encryption requires a passphrase. */
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ _gpgme_engine_set_status_handler (ctx->engine,
+ symmetric
+ ? encrypt_sym_status_handler
+ : encrypt_status_handler,
+ ctx);
+
+ return _gpgme_engine_op_encrypt (ctx->engine, recp, flags, plain, cipher,
+ ctx->use_armor);
+}
+
+
+gpgme_error_t
+gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ return encrypt_start (ctx, 0, recp, flags, plain, cipher);
+}
+
+
+/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
+ store the resulting ciphertext in CIPHER. */
+gpgme_error_t
+gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher)
+{
+ gpgme_error_t err = encrypt_start (ctx, 1, recp, flags, plain, cipher);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/engine-backend.h b/libtdenetwork/libgpgme-copy/gpgme/engine-backend.h
new file mode 100644
index 000000000..f2b978796
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/engine-backend.h
@@ -0,0 +1,110 @@
+/* engine-backend.h - A crypto backend for the engine interface.
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef ENGINE_BACKEND_H
+#define ENGINE_BACKEND_H
+
+#include "engine.h"
+
+/* FIXME: Correct check? */
+#ifdef GPGSM_PATH
+#define ENABLE_GPGSM 1
+#endif
+
+struct engine_ops
+{
+ /* Static functions. */
+
+ /* Return the default file name for the binary of this engine. */
+ const char *(*get_file_name) (void);
+
+ /* Returns a malloced string containing the version of the engine
+ with the given binary file name (or the default if FILE_NAME is
+ NULL. */
+ char *(*get_version) (const char *file_name);
+
+ /* Returns a statically allocated string containing the required
+ version. */
+ const char *(*get_req_version) (void);
+
+ gpgme_error_t (*new) (void **r_engine,
+ const char *file_name, const char *home_dir);
+
+ /* Member functions. */
+ void (*release) (void *engine);
+ gpgme_error_t (*reset) (void *engine);
+ void (*set_status_handler) (void *engine, engine_status_handler_t fnc,
+ void *fnc_value);
+ gpgme_error_t (*set_command_handler) (void *engine,
+ engine_command_handler_t fnc,
+ void *fnc_value, gpgme_data_t data);
+ gpgme_error_t (*set_colon_line_handler) (void *engine,
+ engine_colon_line_handler_t fnc,
+ void *fnc_value);
+ gpgme_error_t (*set_locale) (void *engine, int category, const char *value);
+ gpgme_error_t (*decrypt) (void *engine, gpgme_data_t ciph,
+ gpgme_data_t plain);
+ gpgme_error_t (*delete) (void *engine, gpgme_key_t key, int allow_secret);
+ gpgme_error_t (*edit) (void *engine, int type, gpgme_key_t key,
+ gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */);
+ gpgme_error_t (*encrypt) (void *engine, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph,
+ int use_armor);
+ gpgme_error_t (*encrypt_sign) (void *engine, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph,
+ int use_armor, gpgme_ctx_t ctx /* FIXME */);
+ gpgme_error_t (*export) (void *engine, const char *pattern,
+ unsigned int reserved, gpgme_data_t keydata,
+ int use_armor);
+ gpgme_error_t (*export_ext) (void *engine, const char *pattern[],
+ unsigned int reserved, gpgme_data_t keydata,
+ int use_armor);
+ gpgme_error_t (*genkey) (void *engine, gpgme_data_t help_data, int use_armor,
+ gpgme_data_t pubkey, gpgme_data_t seckey);
+ gpgme_error_t (*import) (void *engine, gpgme_data_t keydata);
+ gpgme_error_t (*keylist) (void *engine, const char *pattern,
+ int secret_only, gpgme_keylist_mode_t mode);
+ gpgme_error_t (*keylist_ext) (void *engine, const char *pattern[],
+ int secret_only, int reserved,
+ gpgme_keylist_mode_t mode);
+ gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out,
+ gpgme_sig_mode_t mode, int use_armor,
+ int use_textmode,
+ int include_certs, gpgme_ctx_t ctx /* FIXME */);
+ gpgme_error_t (*trustlist) (void *engine, const char *pattern);
+ gpgme_error_t (*verify) (void *engine, gpgme_data_t sig,
+ gpgme_data_t signed_text,
+ gpgme_data_t plaintext);
+
+ void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs);
+ void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data);
+
+ gpgme_error_t (*cancel) (void *engine);
+};
+
+
+extern struct engine_ops _gpgme_engine_ops_gpg; /* OpenPGP. */
+#ifdef ENABLE_GPGSM
+extern struct engine_ops _gpgme_engine_ops_gpgsm; /* CMS. */
+#endif
+
+#endif /* ENGINE_BACKEND_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/engine-gpgsm.c b/libtdenetwork/libgpgme-copy/gpgme/engine-gpgsm.c
new file mode 100644
index 000000000..7ad8dc6f2
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/engine-gpgsm.c
@@ -0,0 +1,1750 @@
+/* engine-gpgsm.c - GpgSM engine.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_W32_SYSTEM
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <unistd.h>
+#include <locale.h>
+#include <fcntl.h> /* FIXME */
+#include <errno.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "ops.h"
+#include "wait.h"
+#include "priv-io.h"
+#include "sema.h"
+
+#include "assuan.h"
+#include "status-table.h"
+#include "debug.h"
+
+#include "engine-backend.h"
+
+
+typedef struct
+{
+ int fd; /* FD we talk about. */
+ int server_fd; /* Server FD for this connection. */
+ int dir; /* Inbound/Outbound, maybe given implicit? */
+ void *data; /* Handler-specific data. */
+ void *tag; /* ID from the user for gpgme_remove_io_callback. */
+} iocb_data_t;
+
+
+struct engine_gpgsm
+{
+ assuan_context_t assuan_ctx;
+
+ int lc_ctype_set;
+ int lc_messages_set;
+
+ iocb_data_t status_cb;
+
+ /* Input, output etc are from the servers perspective. */
+ iocb_data_t input_cb;
+
+ iocb_data_t output_cb;
+
+ iocb_data_t message_cb;
+
+ struct
+ {
+ engine_status_handler_t fnc;
+ void *fnc_value;
+ } status;
+
+ struct
+ {
+ engine_colon_line_handler_t fnc;
+ void *fnc_value;
+ struct
+ {
+ char *line;
+ int linesize;
+ int linelen;
+ } attic;
+ int any; /* any data line seen */
+ } colon;
+
+ struct gpgme_io_cbs io_cbs;
+};
+
+typedef struct engine_gpgsm *engine_gpgsm_t;
+
+
+static char *
+gpgsm_get_version (const char *file_name)
+{
+ return _gpgme_get_program_version (file_name ? file_name
+ : _gpgme_get_gpgsm_path ());
+}
+
+
+static const char *
+gpgsm_get_req_version (void)
+{
+ return NEED_GPGSM_VERSION;
+}
+
+
+static void
+close_notify_handler (int fd, void *opaque)
+{
+ engine_gpgsm_t gpgsm = opaque;
+
+ assert (fd != -1);
+ if (gpgsm->status_cb.fd == fd)
+ {
+ if (gpgsm->status_cb.tag)
+ (*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag);
+ gpgsm->status_cb.fd = -1;
+ gpgsm->status_cb.tag = NULL;
+ }
+ else if (gpgsm->input_cb.fd == fd)
+ {
+ if (gpgsm->input_cb.tag)
+ (*gpgsm->io_cbs.remove) (gpgsm->input_cb.tag);
+ gpgsm->input_cb.fd = -1;
+ gpgsm->input_cb.tag = NULL;
+ }
+ else if (gpgsm->output_cb.fd == fd)
+ {
+ if (gpgsm->output_cb.tag)
+ (*gpgsm->io_cbs.remove) (gpgsm->output_cb.tag);
+ gpgsm->output_cb.fd = -1;
+ gpgsm->output_cb.tag = NULL;
+ }
+ else if (gpgsm->message_cb.fd == fd)
+ {
+ if (gpgsm->message_cb.tag)
+ (*gpgsm->io_cbs.remove) (gpgsm->message_cb.tag);
+ gpgsm->message_cb.fd = -1;
+ gpgsm->message_cb.tag = NULL;
+ }
+}
+
+
+static gpgme_error_t
+map_assuan_error (gpg_error_t err)
+{
+ if (!err)
+ return 0;
+
+ if (err == -1)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ /* New code will use gpg_error_t values. */
+ if (gpg_err_source (err))
+ return (gpgme_error_t) err;
+
+ /* Legacy code will use old values. */
+ switch (err)
+ {
+ case ASSUAN_No_Error:
+ return gpg_error (GPG_ERR_NO_ERROR);
+ case ASSUAN_General_Error:
+ return gpg_error (GPG_ERR_GENERAL);
+ case ASSUAN_Out_Of_Core:
+ return gpg_error (GPG_ERR_ENOMEM);
+ case ASSUAN_Invalid_Value:
+ return gpg_error (GPG_ERR_INV_VALUE);
+ case ASSUAN_Timeout:
+ return gpg_error (GPG_ERR_ETIMEDOUT);
+ case ASSUAN_Read_Error:
+ return gpg_error (GPG_ERR_GENERAL);
+ case ASSUAN_Write_Error:
+ return gpg_error (GPG_ERR_GENERAL);
+
+ case ASSUAN_Problem_Starting_Server:
+ case ASSUAN_Not_A_Server:
+ case ASSUAN_Not_A_Client:
+ case ASSUAN_Nested_Commands:
+ case ASSUAN_No_Data_Callback:
+ case ASSUAN_No_Inquire_Callback:
+ case ASSUAN_Connect_Failed:
+ case ASSUAN_Accept_Failed:
+ case ASSUAN_Invalid_Command:
+ case ASSUAN_Unknown_Command:
+ case ASSUAN_Syntax_Error:
+ case ASSUAN_Parameter_Error:
+ case ASSUAN_Parameter_Conflict:
+ case ASSUAN_No_Input:
+ case ASSUAN_No_Output:
+ case ASSUAN_No_Data_Available:
+ case ASSUAN_Too_Much_Data:
+ case ASSUAN_Inquire_Unknown:
+ case ASSUAN_Inquire_Error:
+ case ASSUAN_Invalid_Option:
+ case ASSUAN_Unexpected_tqStatus:
+ case ASSUAN_Unexpected_Data:
+ case ASSUAN_Invalid_tqStatus:
+ return gpg_error (GPG_ERR_ASSUAN);
+
+ case ASSUAN_Invalid_Response:
+ return gpg_error (GPG_ERR_INV_RESPONSE);
+
+ case ASSUAN_Not_Implemented:
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ case ASSUAN_Line_Too_Long:
+ return gpg_error (GPG_ERR_LINE_TOO_LONG);
+ case ASSUAN_Line_Not_Terminated:
+ return gpg_error (GPG_ERR_INCOMPLETE_LINE);
+ case ASSUAN_Canceled:
+ return gpg_error (GPG_ERR_CANCELED);
+
+ case ASSUAN_Unsupported_Algorithm:
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ case ASSUAN_Server_Resource_Problem:
+ return gpg_error (GPG_ERR_RESOURCE_LIMIT);
+ case ASSUAN_Server_IO_Error:
+ return gpg_error (GPG_ERR_GENERAL);
+ case ASSUAN_Server_Bug:
+ return gpg_error (GPG_ERR_BUG);
+ case ASSUAN_Invalid_Data:
+ return gpg_error (GPG_ERR_INV_DATA);
+ case ASSUAN_Invalid_Index:
+ return gpg_error (GPG_ERR_INV_INDEX);
+ case ASSUAN_Not_Confirmed:
+ return gpg_error (GPG_ERR_NOT_CONFIRMED);
+ case ASSUAN_Bad_Certificate:
+ return gpg_error (GPG_ERR_BAD_CERT);
+ case ASSUAN_Bad_Certificate_Chain:
+ return gpg_error (GPG_ERR_BAD_CERT_CHAIN);
+ case ASSUAN_Missing_Certificate:
+ return gpg_error (GPG_ERR_MISSING_CERT);
+ case ASSUAN_Bad_Signature:
+ return gpg_error (GPG_ERR_BAD_SIGNATURE);
+ case ASSUAN_No_Agent:
+ return gpg_error (GPG_ERR_NO_AGENT);
+ case ASSUAN_Agent_Error:
+ return gpg_error (GPG_ERR_AGENT);
+ case ASSUAN_No_Public_Key:
+ return gpg_error (GPG_ERR_NO_PUBKEY);
+ case ASSUAN_No_Secret_Key:
+ return gpg_error (GPG_ERR_NO_SECKEY);
+ case ASSUAN_Invalid_Name:
+ return gpg_error (GPG_ERR_INV_NAME);
+
+ case ASSUAN_Cert_Revoked:
+ return gpg_error (GPG_ERR_CERT_REVOKED);
+ case ASSUAN_No_CRL_For_Cert:
+ return gpg_error (GPG_ERR_NO_CRL_KNOWN);
+ case ASSUAN_CRL_Too_Old:
+ return gpg_error (GPG_ERR_CRL_TOO_OLD);
+ case ASSUAN_Not_Trusted:
+ return gpg_error (GPG_ERR_NOT_TRUSTED);
+
+ case ASSUAN_Card_Error:
+ return gpg_error (GPG_ERR_CARD);
+ case ASSUAN_Invalid_Card:
+ return gpg_error (GPG_ERR_INV_CARD);
+ case ASSUAN_No_PKCS15_App:
+ return gpg_error (GPG_ERR_NO_PKCS15_APP);
+ case ASSUAN_Card_Not_Present:
+ return gpg_error (GPG_ERR_CARD_NOT_PRESENT);
+ case ASSUAN_Invalid_Id:
+ return gpg_error (GPG_ERR_INV_ID);
+ default:
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+}
+
+
+static gpgme_error_t
+gpgsm_cancel (void *engine)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (gpgsm->status_cb.fd != -1)
+ _gpgme_io_close (gpgsm->status_cb.fd);
+ if (gpgsm->input_cb.fd != -1)
+ _gpgme_io_close (gpgsm->input_cb.fd);
+ if (gpgsm->output_cb.fd != -1)
+ _gpgme_io_close (gpgsm->output_cb.fd);
+ if (gpgsm->message_cb.fd != -1)
+ _gpgme_io_close (gpgsm->message_cb.fd);
+
+ if (gpgsm->assuan_ctx)
+ {
+ assuan_disconnect (gpgsm->assuan_ctx);
+ gpgsm->assuan_ctx = NULL;
+ }
+
+ return 0;
+}
+
+
+static void
+gpgsm_release (void *engine)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ if (!gpgsm)
+ return;
+
+ gpgsm_cancel (engine);
+
+ free (gpgsm->colon.attic.line);
+ free (gpgsm);
+}
+
+
+static gpgme_error_t
+gpgsm_new (void **engine, const char *file_name, const char *home_dir)
+{
+ gpgme_error_t err = 0;
+ engine_gpgsm_t gpgsm;
+ const char *argv[5];
+ int argc;
+#if !USE_DESCRIPTOR_PASSING
+ int fds[2];
+ int child_fds[4];
+#endif
+ char *dft_display = NULL;
+ char dft_ttyname[64];
+ char *dft_ttytype = NULL;
+ char *optstr;
+
+ gpgsm = calloc (1, sizeof *gpgsm);
+ if (!gpgsm)
+ return gpg_error_from_errno (errno);
+
+ gpgsm->status_cb.fd = -1;
+ gpgsm->status_cb.dir = 1;
+ gpgsm->status_cb.tag = 0;
+ gpgsm->status_cb.data = gpgsm;
+
+ gpgsm->input_cb.fd = -1;
+ gpgsm->input_cb.dir = 0;
+ gpgsm->input_cb.tag = 0;
+ gpgsm->input_cb.server_fd = -1;
+ gpgsm->output_cb.fd = -1;
+ gpgsm->output_cb.dir = 1;
+ gpgsm->output_cb.tag = 0;
+ gpgsm->output_cb.server_fd = -1;
+ gpgsm->message_cb.fd = -1;
+ gpgsm->message_cb.dir = 0;
+ gpgsm->message_cb.tag = 0;
+ gpgsm->message_cb.server_fd = -1;
+
+ gpgsm->status.fnc = 0;
+ gpgsm->colon.fnc = 0;
+ gpgsm->colon.attic.line = 0;
+ gpgsm->colon.attic.linesize = 0;
+ gpgsm->colon.attic.linelen = 0;
+ gpgsm->colon.any = 0;
+
+ gpgsm->io_cbs.add = NULL;
+ gpgsm->io_cbs.add_priv = NULL;
+ gpgsm->io_cbs.remove = NULL;
+ gpgsm->io_cbs.event = NULL;
+ gpgsm->io_cbs.event_priv = NULL;
+
+#if !USE_DESCRIPTOR_PASSING
+ if (_gpgme_io_pipe (fds, 0) < 0)
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ gpgsm->input_cb.fd = fds[1];
+ gpgsm->input_cb.server_fd = fds[0];
+
+ if (_gpgme_io_pipe (fds, 1) < 0)
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ gpgsm->output_cb.fd = fds[0];
+ gpgsm->output_cb.server_fd = fds[1];
+
+ if (_gpgme_io_pipe (fds, 0) < 0)
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ gpgsm->message_cb.fd = fds[1];
+ gpgsm->message_cb.server_fd = fds[0];
+
+ child_fds[0] = gpgsm->input_cb.server_fd;
+ child_fds[1] = gpgsm->output_cb.server_fd;
+ child_fds[2] = gpgsm->message_cb.server_fd;
+ child_fds[3] = -1;
+#endif
+
+ argc = 0;
+ argv[argc++] = "gpgsm";
+ if (home_dir)
+ {
+ argv[argc++] = "--homedir";
+ argv[argc++] = home_dir;
+ }
+ argv[argc++] = "--server";
+ argv[argc++] = NULL;
+
+#if USE_DESCRIPTOR_PASSING
+ err = assuan_pipe_connect_ext
+ (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
+ argv, NULL, NULL, NULL, 1);
+#else
+ err = assuan_pipe_connect
+ (&gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (),
+ argv, child_fds);
+#endif
+ if (err)
+ goto leave;
+
+ err = _gpgme_getenv ("DISPLAY", &dft_display);
+ if (err)
+ goto leave;
+ if (dft_display)
+ {
+ if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
+ {
+ free (dft_display);
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ free (dft_display);
+
+ err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ free (optstr);
+ if (err)
+ {
+ err = map_assuan_error (err);
+ goto leave;
+ }
+ }
+
+ if (isatty (1))
+ {
+ if (ttyname_r (1, dft_ttyname, sizeof (dft_ttyname)))
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ else
+ {
+ if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
+ {
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ free (optstr);
+ if (err)
+ {
+ err = map_assuan_error (err);
+ goto leave;
+ }
+
+ err = _gpgme_getenv ("TERM", &dft_ttytype);
+ if (err)
+ goto leave;
+ if (dft_ttytype)
+ {
+ if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
+ {
+ free (dft_ttytype);
+ err = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ free (dft_ttytype);
+
+ err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ free (optstr);
+ if (err)
+ {
+ err = map_assuan_error (err);
+ goto leave;
+ }
+ }
+ }
+ }
+
+#if !USE_DESCRIPTOR_PASSING
+ if (!err
+ && (_gpgme_io_set_close_notify (gpgsm->input_cb.fd,
+ close_notify_handler, gpgsm)
+ || _gpgme_io_set_close_notify (gpgsm->output_cb.fd,
+ close_notify_handler, gpgsm)
+ || _gpgme_io_set_close_notify (gpgsm->message_cb.fd,
+ close_notify_handler, gpgsm)))
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+#endif
+
+ leave:
+ /* Close the server ends of the pipes. Our ends are closed in
+ gpgsm_release(). */
+#if !USE_DESCRIPTOR_PASSING
+ if (gpgsm->input_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->input_cb.server_fd);
+ if (gpgsm->output_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->output_cb.server_fd);
+ if (gpgsm->message_cb.server_fd != -1)
+ _gpgme_io_close (gpgsm->message_cb.server_fd);
+#endif
+
+ if (err)
+ gpgsm_release (gpgsm);
+ else
+ *engine = gpgsm;
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_set_locale (void *engine, int category, const char *value)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+ char *optstr;
+ char *catstr;
+
+ /* FIXME: If value is NULL, we need to reset the option to default.
+ But we can't do this. So we error out here. GPGSM needs support
+ for this. */
+ if (category == LC_CTYPE)
+ {
+ catstr = "lc-ctype";
+ if (!value && gpgsm->lc_ctype_set)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (value)
+ gpgsm->lc_ctype_set = 1;
+ }
+#ifdef LC_MESSAGES
+ else if (category == LC_MESSAGES)
+ {
+ catstr = "lc-messages";
+ if (!value && gpgsm->lc_messages_set)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (value)
+ gpgsm->lc_messages_set = 1;
+ }
+#endif /* LC_MESSAGES */
+ else
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
+ err = gpg_error_from_errno (errno);
+ else
+ {
+ err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
+ NULL, NULL, NULL, NULL);
+ free (optstr);
+ if (err)
+ err = map_assuan_error (err);
+ }
+ return err;
+}
+
+
+/* Forward declaration. */
+static gpgme_status_code_t parse_status (const char *name);
+
+static gpgme_error_t
+gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
+ engine_status_handler_t status_fnc,
+ void *status_fnc_value)
+{
+ gpg_error_t err;
+ char *line;
+ size_t linelen;
+
+ err = assuan_write_line (ctx, cmd);
+ if (err)
+ return map_assuan_error (err);
+
+ do
+ {
+ err = assuan_read_line (ctx, &line, &linelen);
+ if (err)
+ return map_assuan_error (err);
+
+ if (*line == '#' || !linelen)
+ continue;
+
+ if (linelen >= 2
+ && line[0] == 'O' && line[1] == 'K'
+ && (line[2] == '\0' || line[2] == ' '))
+ return 0;
+ else if (linelen >= 4
+ && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && line[3] == ' ')
+ err = map_assuan_error (atoi (&line[4]));
+ else if (linelen >= 2
+ && line[0] == 'S' && line[1] == ' ')
+ {
+ char *rest;
+ gpgme_status_code_t r;
+
+ rest = strchr (line + 2, ' ');
+ if (!rest)
+ rest = line + linelen; /* set to an empty string */
+ else
+ *(rest++) = 0;
+
+ r = parse_status (line + 2);
+
+ if (r >= 0 && status_fnc)
+ err = status_fnc (status_fnc_value, r, rest);
+ else
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+ else
+ err = gpg_error (GPG_ERR_GENERAL);
+ }
+ while (!err);
+
+ return err;
+}
+
+
+typedef enum { INPUT_FD, OUTPUT_FD, MESSAGE_FD } fd_type_t;
+
+static void
+gpgsm_clear_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type)
+{
+#if !USE_DESCRIPTOR_PASSING
+ switch (fd_type)
+ {
+ case INPUT_FD:
+ _gpgme_io_close (gpgsm->input_cb.fd);
+ break;
+ case OUTPUT_FD:
+ _gpgme_io_close (gpgsm->output_cb.fd);
+ break;
+ case MESSAGE_FD:
+ _gpgme_io_close (gpgsm->message_cb.fd);
+ break;
+ }
+#endif
+}
+
+#define COMMANDLINELEN 40
+static gpgme_error_t
+gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt)
+{
+ gpg_error_t err = 0;
+ char line[COMMANDLINELEN];
+ char *which;
+ iocb_data_t *iocb_data;
+ int dir;
+ int fd;
+
+ switch (fd_type)
+ {
+ case INPUT_FD:
+ which = "INPUT";
+ iocb_data = &gpgsm->input_cb;
+ break;
+
+ case OUTPUT_FD:
+ which = "OUTPUT";
+ iocb_data = &gpgsm->output_cb;
+ break;
+
+ case MESSAGE_FD:
+ which = "MESSAGE";
+ iocb_data = &gpgsm->message_cb;
+ break;
+
+ default:
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
+
+ dir = iocb_data->dir;
+
+#if USE_DESCRIPTOR_PASSING
+ /* We try to short-cut the communication by giving GPGSM direct
+ access to the file descriptor, rather than using a pipe. */
+ iocb_data->server_fd = _gpgme_data_get_fd (iocb_data->data);
+ if (iocb_data->server_fd < 0)
+ {
+ int fds[2];
+
+ if (_gpgme_io_pipe (fds, 0) < 0)
+ return gpg_error_from_errno (errno);
+
+ iocb_data->fd = dir ? fds[0] : fds[1];
+ iocb_data->server_fd = dir ? fds[1] : fds[0];
+
+ if (_gpgme_io_set_close_notify (iocb_data->fd,
+ close_notify_handler, gpgsm))
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave_set_fd;
+ }
+ }
+#endif
+
+ fd = iocb_data->server_fd;
+
+#if USE_DESCRIPTOR_PASSING
+ err = assuan_sendfd (gpgsm->assuan_ctx, fd);
+ if (err)
+ goto leave_set_fd;
+
+ _gpgme_io_close (fd);
+
+ if (opt)
+ snprintf (line, COMMANDLINELEN, "%s FD %s", which, opt);
+ else
+ snprintf (line, COMMANDLINELEN, "%s FD", which);
+#else
+ if (opt)
+ snprintf (line, COMMANDLINELEN, "%s FD=%i %s", which, fd, opt);
+ else
+ snprintf (line, COMMANDLINELEN, "%s FD=%i", which, fd);
+#endif
+
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+
+#if USE_DESCRIPTOR_PASSING
+ leave_set_fd:
+ if (err)
+ {
+ _gpgme_io_close (iocb_data->fd);
+ _gpgme_io_close (iocb_data->server_fd);
+ iocb_data->fd = -1;
+ iocb_data->server_fd = -1;
+ }
+#endif
+
+ return err;
+}
+
+
+static const char *
+map_input_enc (gpgme_data_t d)
+{
+ switch (gpgme_data_get_encoding (d))
+ {
+ case GPGME_DATA_ENCODING_NONE:
+ break;
+ case GPGME_DATA_ENCODING_BINARY:
+ return "--binary";
+ case GPGME_DATA_ENCODING_BASE64:
+ return "--base64";
+ case GPGME_DATA_ENCODING_ARMOR:
+ return "--armor";
+ default:
+ break;
+ }
+ return NULL;
+}
+
+
+static int
+status_cmp (const void *ap, const void *bp)
+{
+ const struct status_table_s *a = ap;
+ const struct status_table_s *b = bp;
+
+ return strcmp (a->name, b->name);
+}
+
+
+static gpgme_status_code_t
+parse_status (const char *name)
+{
+ struct status_table_s t, *r;
+ t.name = name;
+ r = bsearch (&t, status_table, DIM(status_table) - 1,
+ sizeof t, status_cmp);
+ return r ? r->code : -1;
+}
+
+
+static gpgme_error_t
+status_handler (void *opaque, int fd)
+{
+ gpg_error_t assuan_err;
+ gpgme_error_t err = 0;
+ engine_gpgsm_t gpgsm = opaque;
+ char *line;
+ size_t linelen;
+
+ do
+ {
+ assuan_err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen);
+ if (assuan_err)
+ {
+ /* Try our best to terminate the connection friendly. */
+ /* assuan_write_line (gpgsm->assuan_ctx, "BYE"); */
+ err = map_assuan_error (assuan_err);
+ DEBUG3 ("fd %d: error from assuan (%d) getting status line : %s \n",
+ fd, assuan_err, gpg_strerror (err));
+ }
+ else if (linelen >= 3
+ && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
+ && (line[3] == '\0' || line[3] == ' '))
+ {
+ if (line[3] == ' ')
+ err = map_assuan_error (atoi (&line[4]));
+ else
+ err = gpg_error (GPG_ERR_GENERAL);
+ DEBUG2 ("fd %d: ERR line - mapped to: %s\n",
+ fd, err? gpg_strerror (err):"ok");
+ }
+ else if (linelen >= 2
+ && line[0] == 'O' && line[1] == 'K'
+ && (line[2] == '\0' || line[2] == ' '))
+ {
+ if (gpgsm->status.fnc)
+ err = gpgsm->status.fnc (gpgsm->status.fnc_value,
+ GPGME_STATUS_EOF, "");
+
+ if (!err && gpgsm->colon.fnc && gpgsm->colon.any )
+ {
+ /* We must tell a colon function about the EOF. We do
+ this only when we have seen any data lines. Note
+ that this inlined use of colon data lines will
+ eventually be changed into using a regular data
+ channel. */
+ gpgsm->colon.any = 0;
+ err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL);
+ }
+ _gpgme_io_close (gpgsm->status_cb.fd);
+ DEBUG2 ("fd %d: OK line - final status: %s\n",
+ fd, err? gpg_strerror (err):"ok");
+ return err;
+ }
+ else if (linelen > 2
+ && line[0] == 'D' && line[1] == ' '
+ && gpgsm->colon.fnc)
+ {
+ /* We are using the colon handler even for plain inline data
+ - strange name for that function but for historic reasons
+ we keep it. */
+ /* FIXME We can't use this for binary data because we
+ assume this is a string. For the current usage of colon
+ output it is correct. */
+ char *src = line + 2;
+ char *end = line + linelen;
+ char *dst;
+ char **aline = &gpgsm->colon.attic.line;
+ int *alinelen = &gpgsm->colon.attic.linelen;
+
+ if (gpgsm->colon.attic.linesize
+ < *alinelen + linelen + 1)
+ {
+ char *newline = realloc (*aline, *alinelen + linelen + 1);
+ if (!newline)
+ err = gpg_error_from_errno (errno);
+ else
+ {
+ *aline = newline;
+ gpgsm->colon.attic.linesize += linelen + 1;
+ }
+ }
+ if (!err)
+ {
+ dst = *aline + *alinelen;
+
+ while (!err && src < end)
+ {
+ if (*src == '%' && src + 2 < end)
+ {
+ /* Handle escaped characters. */
+ ++src;
+ *dst = _gpgme_hextobyte (src);
+ (*alinelen)++;
+ src += 2;
+ }
+ else
+ {
+ *dst = *src++;
+ (*alinelen)++;
+ }
+
+ if (*dst == '\n')
+ {
+ /* Terminate the pending line, pass it to the colon
+ handler and reset it. */
+
+ gpgsm->colon.any = 1;
+ if (*alinelen > 1 && *(dst - 1) == '\r')
+ dst--;
+ *dst = '\0';
+
+ /* FIXME How should we handle the return code? */
+ err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline);
+ if (!err)
+ {
+ dst = *aline;
+ *alinelen = 0;
+ }
+ }
+ else
+ dst++;
+ }
+ }
+ DEBUG2 ("fd %d: D line; final status: %s\n",
+ fd, err? gpg_strerror (err):"ok");
+ }
+ else if (linelen > 2
+ && line[0] == 'S' && line[1] == ' ')
+ {
+ char *rest;
+ gpgme_status_code_t r;
+
+ rest = strchr (line + 2, ' ');
+ if (!rest)
+ rest = line + linelen; /* set to an empty string */
+ else
+ *(rest++) = 0;
+
+ r = parse_status (line + 2);
+
+ if (r >= 0)
+ {
+ if (gpgsm->status.fnc)
+ err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
+ }
+ else
+ fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
+ DEBUG3 ("fd %d: S line (%s) - final status: %s\n",
+ fd, line+2, err? gpg_strerror (err):"ok");
+ }
+ }
+ while (!err && assuan_pending_line (gpgsm->assuan_ctx));
+
+ return err;
+}
+
+
+static gpgme_error_t
+add_io_cb (engine_gpgsm_t gpgsm, iocb_data_t *iocbd, gpgme_io_cb_t handler)
+{
+ gpgme_error_t err;
+
+ err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv,
+ iocbd->fd, iocbd->dir,
+ handler, iocbd->data, &iocbd->tag);
+ if (err)
+ return err;
+ if (!iocbd->dir)
+ /* FIXME Kludge around poll() problem. */
+ err = _gpgme_io_set_nonblocking (iocbd->fd);
+ return err;
+}
+
+
+static gpgme_error_t
+start (engine_gpgsm_t gpgsm, const char *command)
+{
+ gpgme_error_t err;
+ int fdlist[5];
+ int nfds;
+
+ /* We need to know the fd used by assuan for reads. We do this by
+ using the assumption that the first returned fd from
+ assuan_get_active_fds() is always this one. */
+ nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */,
+ fdlist, DIM (fdlist));
+ if (nfds < 1)
+ return gpg_error (GPG_ERR_GENERAL); /* FIXME */
+
+ /* We duplicate the file descriptor, so we can close it without
+ disturbing assuan. Alternatively, we could special case
+ status_fd and register/unregister it manually as needed, but this
+ increases code duplication and is more complicated as we can not
+ use the close notifications etc. */
+ gpgsm->status_cb.fd = dup (fdlist[0]);
+ if (gpgsm->status_cb.fd < 0)
+ return gpg_error_from_syserror ();
+
+ if (_gpgme_io_set_close_notify (gpgsm->status_cb.fd,
+ close_notify_handler, gpgsm))
+ {
+ close (gpgsm->status_cb.fd);
+ gpgsm->status_cb.fd = -1;
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+
+ err = add_io_cb (gpgsm, &gpgsm->status_cb, status_handler);
+ if (!err && gpgsm->input_cb.fd != -1)
+ err = add_io_cb (gpgsm, &gpgsm->input_cb, _gpgme_data_outbound_handler);
+ if (!err && gpgsm->output_cb.fd != -1)
+ err = add_io_cb (gpgsm, &gpgsm->output_cb, _gpgme_data_inbound_handler);
+ if (!err && gpgsm->message_cb.fd != -1)
+ err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler);
+
+ if (!err)
+ err = map_assuan_error (assuan_write_line (gpgsm->assuan_ctx, command));
+
+ if (!err)
+ (*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, GPGME_EVENT_START, NULL);
+
+ return err;
+}
+
+
+#if USE_DESCRIPTOR_PASSING
+static gpgme_error_t
+gpgsm_reset (void *engine)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ /* We must send a reset because we need to reset the list of
+ signers. Note that RESET does not reset OPTION commands. */
+ return gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET", NULL, NULL);
+}
+#endif
+
+
+static gpgme_error_t
+gpgsm_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ gpgsm->input_cb.data = ciph;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return gpg_error (GPG_ERR_GENERAL); /* FIXME */
+ gpgsm->output_cb.data = plain;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0);
+ if (err)
+ return gpg_error (GPG_ERR_GENERAL); /* FIXME */
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (engine, "DECRYPT");
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+ char *fpr = key->subkeys ? key->subkeys->fpr : NULL;
+ char *linep = fpr;
+ char *line;
+ int length = 8; /* "DELKEYS " */
+
+ if (!fpr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ while (*linep)
+ {
+ length++;
+ if (*linep == '%' || *linep == ' ' || *linep == '+')
+ length += 2;
+ linep++;
+ }
+ length++;
+
+ line = malloc (length);
+ if (!line)
+ return gpg_error_from_errno (errno);
+
+ strcpy (line, "DELKEYS ");
+ linep = &line[8];
+
+ while (*fpr)
+ {
+ switch (*fpr)
+ {
+ case '%':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '5';
+ break;
+ case ' ':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '0';
+ break;
+ case '+':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = 'B';
+ break;
+ default:
+ *(linep++) = *fpr;
+ break;
+ }
+ fpr++;
+ }
+ *linep = '\0';
+
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, line);
+ free (line);
+
+ return err;
+}
+
+
+static gpgme_error_t
+set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
+{
+ gpgme_error_t err = 0;
+ assuan_context_t ctx = gpgsm->assuan_ctx;
+ char *line;
+ int linelen;
+ int invalid_recipients = 0;
+ int i = 0;
+
+ linelen = 10 + 40 + 1; /* "RECIPIENT " + guess + '\0'. */
+ line = malloc (10 + 40 + 1);
+ if (!line)
+ return gpg_error_from_errno (errno);
+ strcpy (line, "RECIPIENT ");
+ while (!err && recp[i])
+ {
+ char *fpr;
+ int newlen;
+
+ if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
+ {
+ invalid_recipients++;
+ continue;
+ }
+ fpr = recp[i]->subkeys->fpr;
+
+ newlen = 11 + strlen (fpr);
+ if (linelen < newlen)
+ {
+ char *newline = realloc (line, newlen);
+ if (! newline)
+ {
+ int saved_errno = errno;
+ free (line);
+ return gpg_error_from_errno (saved_errno);
+ }
+ line = newline;
+ linelen = newlen;
+ }
+ strcpy (&line[10], fpr);
+
+ err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc,
+ gpgsm->status.fnc_value);
+ /* FIXME: This requires more work. */
+ if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
+ invalid_recipients++;
+ else if (err)
+ {
+ free (line);
+ return err;
+ }
+ i++;
+ }
+ free (line);
+ return gpg_error (invalid_recipients
+ ? GPG_ERR_UNUSABLE_PUBKEY : GPG_ERR_NO_ERROR);
+}
+
+
+static gpgme_error_t
+gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!recp)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ gpgsm->input_cb.data = plain;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ gpgsm->output_cb.data = ciph;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = set_recipients (gpgsm, recp);
+
+ if (!err)
+ err = start (gpgsm, "ENCRYPT");
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_export (void *engine, const char *pattern, unsigned int reserved,
+ gpgme_data_t keydata, int use_armor)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err = 0;
+ char *cmd;
+
+ if (!gpgsm || reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!pattern)
+ pattern = "";
+
+ cmd = malloc (7 + strlen (pattern) + 1);
+ if (!cmd)
+ return gpg_error_from_errno (errno);
+ strcpy (cmd, "EXPORT ");
+ strcpy (&cmd[7], pattern);
+
+ gpgsm->output_cb.data = keydata;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, cmd);
+ free (cmd);
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_export_ext (void *engine, const char *pattern[], unsigned int reserved,
+ gpgme_data_t keydata, int use_armor)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err = 0;
+ char *line;
+ /* Length is "EXPORT " + p + '\0'. */
+ int length = 7 + 1;
+ char *linep;
+
+ if (!gpgsm || reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (pattern && *pattern)
+ {
+ const char **pat = pattern;
+
+ while (*pat)
+ {
+ const char *patlet = *pat;
+
+ while (*patlet)
+ {
+ length++;
+ if (*patlet == '%' || *patlet == ' ' || *patlet == '+')
+ length += 2;
+ patlet++;
+ }
+ pat++;
+ length++;
+ }
+ }
+ line = malloc (length);
+ if (!line)
+ return gpg_error_from_errno (errno);
+
+ strcpy (line, "EXPORT ");
+ linep = &line[7];
+
+ if (pattern && *pattern)
+ {
+ while (*pattern)
+ {
+ const char *patlet = *pattern;
+
+ while (*patlet)
+ {
+ switch (*patlet)
+ {
+ case '%':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '5';
+ break;
+ case ' ':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '0';
+ break;
+ case '+':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = 'B';
+ break;
+ default:
+ *(linep++) = *patlet;
+ break;
+ }
+ patlet++;
+ }
+ pattern++;
+ if (*pattern)
+ *linep++ = ' ';
+ }
+ }
+ *linep = '\0';
+
+ gpgsm->output_cb.data = keydata;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, line);
+ free (line);
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_genkey (void *engine, gpgme_data_t help_data, int use_armor,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+
+ if (!gpgsm || !pubkey || seckey)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ gpgsm->input_cb.data = help_data;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ gpgsm->output_cb.data = pubkey;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, "GENKEY");
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_import (void *engine, gpgme_data_t keydata)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ gpgsm->input_cb.data = keydata;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, "IMPORT");
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_keylist (void *engine, const char *pattern, int secret_only,
+ gpgme_keylist_mode_t mode)
+{
+ engine_gpgsm_t gpgsm = engine;
+ char *line;
+ gpgme_error_t err;
+ int list_mode = 0;
+
+ if (mode & GPGME_KEYLIST_MODE_LOCAL)
+ list_mode |= 1;
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ list_mode |= 2;
+
+ if (!pattern)
+ pattern = "";
+
+ /* Always send list-mode option because RESET does not reset it. */
+ if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
+ return gpg_error_from_errno (errno);
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+ free (line);
+ if (err)
+ return err;
+
+
+ /* Always send key validation because RESET does not reset it. */
+
+ /* Use the validation mode if required. We don't check for an error
+ yet because this is a pretty fresh gpgsm features. */
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (mode & GPGME_KEYLIST_MODE_VALIDATE)?
+ "OPTION with-validation=1":
+ "OPTION with-validation=0" ,
+ NULL, NULL);
+
+
+ /* Length is "LISTSECRETKEYS " + p + '\0'. */
+ line = malloc (15 + strlen (pattern) + 1);
+ if (!line)
+ return gpg_error_from_errno (errno);
+ if (secret_only)
+ {
+ strcpy (line, "LISTSECRETKEYS ");
+ strcpy (&line[15], pattern);
+ }
+ else
+ {
+ strcpy (line, "LISTKEYS ");
+ strcpy (&line[9], pattern);
+ }
+
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, line);
+ free (line);
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
+ int reserved, gpgme_keylist_mode_t mode)
+{
+ engine_gpgsm_t gpgsm = engine;
+ char *line;
+ gpgme_error_t err;
+ /* Length is "LISTSECRETKEYS " + p + '\0'. */
+ int length = 15 + 1;
+ char *linep;
+ int any_pattern = 0;
+ int list_mode = 0;
+
+ if (reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (mode & GPGME_KEYLIST_MODE_LOCAL)
+ list_mode |= 1;
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ list_mode |= 2;
+
+ /* Always send list-mode option because RESET does not reset it. */
+ if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
+ return gpg_error_from_errno (errno);
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+ free (line);
+ if (err)
+ return err;
+
+ /* Always send key validation because RESET does not reset it. */
+ /* Use the validation mode if required. We don't check for an error
+ yet because this is a pretty fresh gpgsm features. */
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (mode & GPGME_KEYLIST_MODE_VALIDATE)?
+ "OPTION with-validation=1":
+ "OPTION with-validation=0" ,
+ NULL, NULL);
+
+
+ if (pattern && *pattern)
+ {
+ const char **pat = pattern;
+
+ while (*pat)
+ {
+ const char *patlet = *pat;
+
+ while (*patlet)
+ {
+ length++;
+ if (*patlet == '%' || *patlet == ' ' || *patlet == '+')
+ length += 2;
+ patlet++;
+ }
+ pat++;
+ length++;
+ }
+ }
+ line = malloc (length);
+ if (!line)
+ return gpg_error_from_errno (errno);
+ if (secret_only)
+ {
+ strcpy (line, "LISTSECRETKEYS ");
+ linep = &line[15];
+ }
+ else
+ {
+ strcpy (line, "LISTKEYS ");
+ linep = &line[9];
+ }
+
+ if (pattern && *pattern)
+ {
+ while (*pattern)
+ {
+ const char *patlet = *pattern;
+
+ while (*patlet)
+ {
+ switch (*patlet)
+ {
+ case '%':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '5';
+ break;
+ case ' ':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = '0';
+ break;
+ case '+':
+ *(linep++) = '%';
+ *(linep++) = '2';
+ *(linep++) = 'B';
+ break;
+ default:
+ *(linep++) = *patlet;
+ break;
+ }
+ patlet++;
+ }
+ any_pattern = 1;
+ *linep++ = ' ';
+ pattern++;
+ }
+ }
+ if (any_pattern)
+ linep--;
+ *linep = '\0';
+
+ gpgsm_clear_fd (gpgsm, INPUT_FD);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, line);
+ free (line);
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
+ gpgme_sig_mode_t mode, int use_armor, int use_textmode,
+ int include_certs, gpgme_ctx_t ctx /* FIXME */)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+ char *assuan_cmd;
+ int i;
+ gpgme_key_t key;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* FIXME: This does not work as RESET does not reset it so we can't
+ revert back to default. */
+ if (include_certs != GPGME_INCLUDE_CERTS_DEFAULT)
+ {
+ /* FIXME: Make sure that if we run multiple operations, that we
+ can reset any previously set value in case the default is
+ requested. */
+
+ if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0)
+ return gpg_error_from_errno (errno);
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, assuan_cmd,
+ NULL, NULL);
+ free (assuan_cmd);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
+ {
+ const char *s = key->subkeys ? key->subkeys->fpr : NULL;
+ if (s && strlen (s) < 80)
+ {
+ char buf[100];
+
+ strcpy (stpcpy (buf, "SIGNER "), s);
+ err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, buf,
+ NULL, NULL);
+ }
+ else
+ err = gpg_error (GPG_ERR_INV_VALUE);
+ gpgme_key_unref (key);
+ if (err)
+ return err;
+ }
+
+ gpgsm->input_cb.data = in;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ gpgsm->output_cb.data = out;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+
+ err = start (gpgsm, mode == GPGME_SIG_MODE_DETACH
+ ? "SIGN --detached" : "SIGN");
+ return err;
+}
+
+
+static gpgme_error_t
+gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
+ gpgme_data_t plaintext)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgme_error_t err;
+
+ if (!gpgsm)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ gpgsm->input_cb.data = sig;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_input_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ if (plaintext)
+ {
+ /* Normal or cleartext signature. */
+ gpgsm->output_cb.data = plaintext;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0);
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+ }
+ else
+ {
+ /* Detached signature. */
+ gpgsm->message_cb.data = signed_text;
+ err = gpgsm_set_fd (gpgsm, MESSAGE_FD, 0);
+ gpgsm_clear_fd (gpgsm, OUTPUT_FD);
+ }
+
+ if (!err)
+ err = start (gpgsm, "VERIFY");
+
+ return err;
+}
+
+
+static void
+gpgsm_set_status_handler (void *engine, engine_status_handler_t fnc,
+ void *fnc_value)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ gpgsm->status.fnc = fnc;
+ gpgsm->status.fnc_value = fnc_value;
+}
+
+
+static gpgme_error_t
+gpgsm_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
+ void *fnc_value)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ gpgsm->colon.fnc = fnc;
+ gpgsm->colon.fnc_value = fnc_value;
+ gpgsm->colon.any = 0;
+ return 0;
+}
+
+
+static void
+gpgsm_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
+{
+ engine_gpgsm_t gpgsm = engine;
+ gpgsm->io_cbs = *io_cbs;
+}
+
+
+static void
+gpgsm_io_event (void *engine, gpgme_event_io_t type, void *type_data)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ if (gpgsm->io_cbs.event)
+ (*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, type, type_data);
+}
+
+
+struct engine_ops _gpgme_engine_ops_gpgsm =
+ {
+ /* Static functions. */
+ _gpgme_get_gpgsm_path,
+ gpgsm_get_version,
+ gpgsm_get_req_version,
+ gpgsm_new,
+
+ /* Member functions. */
+ gpgsm_release,
+#if USE_DESCRIPTOR_PASSING
+ gpgsm_reset,
+#else
+ NULL, /* reset */
+#endif
+ gpgsm_set_status_handler,
+ NULL, /* set_command_handler */
+ gpgsm_set_colon_line_handler,
+ gpgsm_set_locale,
+ gpgsm_decrypt,
+ gpgsm_delete,
+ NULL, /* edit */
+ gpgsm_encrypt,
+ NULL, /* encrypt_sign */
+ gpgsm_export,
+ gpgsm_export_ext,
+ gpgsm_genkey,
+ gpgsm_import,
+ gpgsm_keylist,
+ gpgsm_keylist_ext,
+ gpgsm_sign,
+ NULL, /* trustlist */
+ gpgsm_verify,
+ gpgsm_set_io_cbs,
+ gpgsm_io_event,
+ gpgsm_cancel
+ };
+
+#endif /*!HAVE_W32_SYSTEM*/
diff --git a/libtdenetwork/libgpgme-copy/gpgme/engine.c b/libtdenetwork/libgpgme-copy/gpgme/engine.c
new file mode 100644
index 000000000..ae5bc8674
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/engine.c
@@ -0,0 +1,744 @@
+/* engine.c - GPGME engine support.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "sema.h"
+#include "ops.h"
+
+#include "engine.h"
+#include "engine-backend.h"
+
+
+struct engine
+{
+ struct engine_ops *ops;
+ void *engine;
+};
+
+
+static struct engine_ops *engine_ops[] =
+ {
+ &_gpgme_engine_ops_gpg, /* OpenPGP. */
+#ifdef ENABLE_GPGSM
+ &_gpgme_engine_ops_gpgsm /* CMS. */
+#else
+ NULL
+#endif
+ };
+
+
+/* The engine info. */
+static gpgme_engine_info_t engine_info;
+DEFINE_STATIC_LOCK (engine_info_lock);
+
+
+/* Get the file name of the engine for PROTOCOL. */
+static const char *
+engine_get_file_name (gpgme_protocol_t proto)
+{
+ if (proto > DIM (engine_ops))
+ return NULL;
+
+ if (engine_ops[proto] && engine_ops[proto]->get_file_name)
+ return (*engine_ops[proto]->get_file_name) ();
+ else
+ return NULL;
+}
+
+
+/* Get a malloced string containing the version number of the engine
+ for PROTOCOL. */
+static char *
+engine_get_version (gpgme_protocol_t proto, const char *file_name)
+{
+ if (proto > DIM (engine_ops))
+ return NULL;
+
+ if (engine_ops[proto] && engine_ops[proto]->get_version)
+ return (*engine_ops[proto]->get_version) (file_name);
+ else
+ return NULL;
+}
+
+
+/* Get the required version number of the engine for PROTOCOL. */
+static const char *
+engine_get_req_version (gpgme_protocol_t proto)
+{
+ if (proto > DIM (engine_ops))
+ return NULL;
+
+ if (engine_ops[proto] && engine_ops[proto]->get_req_version)
+ return (*engine_ops[proto]->get_req_version) ();
+ else
+ return NULL;
+}
+
+
+/* Verify the version requirement for the engine for PROTOCOL. */
+gpgme_error_t
+gpgme_engine_check_version (gpgme_protocol_t proto)
+{
+ gpgme_error_t err;
+ gpgme_engine_info_t info;
+ int result;
+
+ LOCK (engine_info_lock);
+ info = engine_info;
+ if (!info)
+ {
+ /* Make sure it is initialized. */
+ UNLOCK (engine_info_lock);
+ err = gpgme_get_engine_info (&info);
+ if (err)
+ return err;
+
+ LOCK (engine_info_lock);
+ }
+
+ while (info && info->protocol != proto)
+ info = info->next;
+
+ if (!info)
+ result = 0;
+ else
+ result = _gpgme_compare_versions (info->version,
+ info->req_version);
+
+ UNLOCK (engine_info_lock);
+ return result ? 0 : gpg_error (GPG_ERR_INV_ENGINE);
+}
+
+
+/* Release the engine info INFO. */
+void
+_gpgme_engine_info_release (gpgme_engine_info_t info)
+{
+ while (info)
+ {
+ gpgme_engine_info_t next_info = info->next;
+
+ assert (info->file_name);
+ free (info->file_name);
+ if (info->home_dir)
+ free (info->home_dir);
+ if (info->version)
+ free (info->version);
+ free (info);
+ info = next_info;
+ }
+}
+
+
+/* Get the information about the configured and installed engines. A
+ pointer to the first engine in the statically allocated linked list
+ is returned in *INFO. If an error occurs, it is returned. The
+ returned data is valid until the next gpgme_set_engine_info. */
+gpgme_error_t
+gpgme_get_engine_info (gpgme_engine_info_t *info)
+{
+ LOCK (engine_info_lock);
+ if (!engine_info)
+ {
+ gpgme_engine_info_t *lastp = &engine_info;
+ gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
+ GPGME_PROTOCOL_CMS };
+ unsigned int proto;
+
+ for (proto = 0; proto < DIM (proto_list); proto++)
+ {
+ const char *ofile_name = engine_get_file_name (proto_list[proto]);
+ char *file_name;
+
+ if (!ofile_name)
+ continue;
+
+ file_name = strdup (ofile_name);
+
+ *lastp = malloc (sizeof (*engine_info));
+ if (!*lastp || !file_name)
+ {
+ int saved_errno = errno;
+
+ _gpgme_engine_info_release (engine_info);
+ engine_info = NULL;
+
+ if (file_name)
+ free (file_name);
+
+ UNLOCK (engine_info_lock);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ (*lastp)->protocol = proto_list[proto];
+ (*lastp)->file_name = file_name;
+ (*lastp)->home_dir = NULL;
+ (*lastp)->version = engine_get_version (proto_list[proto], NULL);
+ (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
+ (*lastp)->next = NULL;
+ lastp = &(*lastp)->next;
+ }
+ }
+
+ *info = engine_info;
+ UNLOCK (engine_info_lock);
+ return 0;
+}
+
+
+/* Get a deep copy of the engine info and return it in INFO. */
+gpgme_error_t
+_gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
+{
+ gpgme_error_t err = 0;
+ gpgme_engine_info_t info;
+ gpgme_engine_info_t new_info;
+ gpgme_engine_info_t *lastp;
+
+ LOCK (engine_info_lock);
+ info = engine_info;
+ if (!info)
+ {
+ /* Make sure it is initialized. */
+ UNLOCK (engine_info_lock);
+ err = gpgme_get_engine_info (&info);
+ if (err)
+ return err;
+
+ LOCK (engine_info_lock);
+ }
+
+ new_info = NULL;
+ lastp = &new_info;
+
+ while (info)
+ {
+ char *file_name;
+ char *home_dir;
+ char *version;
+
+ assert (info->file_name);
+ file_name = strdup (info->file_name);
+
+ if (info->home_dir)
+ {
+ home_dir = strdup (info->home_dir);
+ if (!home_dir)
+ err = gpg_error_from_errno (errno);
+ }
+ else
+ home_dir = NULL;
+
+ if (info->version)
+ {
+ version = strdup (info->version);
+ if (!version)
+ err = gpg_error_from_errno (errno);
+ }
+ else
+ version = NULL;
+
+ *lastp = malloc (sizeof (*engine_info));
+ if (!*lastp || !file_name || err)
+ {
+ int saved_errno = errno;
+
+ _gpgme_engine_info_release (new_info);
+
+ if (file_name)
+ free (file_name);
+ if (home_dir)
+ free (home_dir);
+ if (version)
+ free (version);
+
+ UNLOCK (engine_info_lock);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ (*lastp)->protocol = info->protocol;
+ (*lastp)->file_name = file_name;
+ (*lastp)->home_dir = home_dir;
+ (*lastp)->version = version;
+ (*lastp)->req_version = info->req_version;
+ (*lastp)->next = NULL;
+ lastp = &(*lastp)->next;
+
+ info = info->next;
+ }
+
+ *r_info = new_info;
+ UNLOCK (engine_info_lock);
+ return 0;
+}
+
+
+/* Set the engine info for the info list INFO, protocol PROTO, to the
+ file name FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t
+_gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
+ const char *file_name, const char *home_dir)
+{
+ char *new_file_name;
+ char *new_home_dir;
+
+ /* FIXME: Use some PROTO_MAX definition. */
+ if (proto > DIM (engine_ops))
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ while (info && info->protocol != proto)
+ info = info->next;
+
+ if (!info)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ /* Prepare new members. */
+ if (file_name)
+ new_file_name = strdup (file_name);
+ else
+ {
+ const char *ofile_name = engine_get_file_name (proto);
+ assert (ofile_name);
+ new_file_name = strdup (ofile_name);
+ }
+ if (!new_file_name)
+ return gpg_error_from_errno (errno);
+
+ if (home_dir)
+ {
+ new_home_dir = strdup (home_dir);
+ if (!new_home_dir)
+ {
+ free (new_file_name);
+ return gpg_error_from_errno (errno);
+ }
+ }
+ else
+ new_home_dir = NULL;
+
+ /* Remove the old members. */
+ assert (info->file_name);
+ free (info->file_name);
+ if (info->home_dir)
+ free (info->home_dir);
+ if (info->version)
+ free (info->version);
+
+ /* Install the new members. */
+ info->file_name = new_file_name;
+ info->home_dir = new_home_dir;
+ info->version = engine_get_version (proto, new_file_name);
+
+ return 0;
+}
+
+
+/* Set the default engine info for the protocol PROTO to the file name
+ FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t
+gpgme_set_engine_info (gpgme_protocol_t proto,
+ const char *file_name, const char *home_dir)
+{
+ gpgme_error_t err;
+ gpgme_engine_info_t info;
+
+ LOCK (engine_info_lock);
+ info = engine_info;
+ if (!info)
+ {
+ /* Make sure it is initialized. */
+ UNLOCK (engine_info_lock);
+ err = gpgme_get_engine_info (&info);
+ if (err)
+ return err;
+
+ LOCK (engine_info_lock);
+ }
+
+ err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
+ UNLOCK (engine_info_lock);
+ return err;
+}
+
+
+gpgme_error_t
+_gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
+{
+ engine_t engine;
+
+ if (!info->file_name || !info->version)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ engine = calloc (1, sizeof *engine);
+ if (!engine)
+ return gpg_error_from_errno (errno);
+
+ engine->ops = engine_ops[info->protocol];
+ if (engine->ops->new)
+ {
+ gpgme_error_t err;
+ err = (*engine->ops->new) (&engine->engine,
+ info->file_name, info->home_dir);
+ if (err)
+ {
+ free (engine);
+ return err;
+ }
+ }
+ else
+ engine->engine = NULL;
+
+ *r_engine = engine;
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_engine_reset (engine_t engine)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->reset)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->reset) (engine->engine);
+}
+
+
+void
+_gpgme_engine_release (engine_t engine)
+{
+ if (!engine)
+ return;
+
+ if (engine->ops->release)
+ (*engine->ops->release) (engine->engine);
+ free (engine);
+}
+
+
+void
+_gpgme_engine_set_status_handler (engine_t engine,
+ engine_status_handler_t fnc, void *fnc_value)
+{
+ if (!engine)
+ return;
+
+ if (engine->ops->set_status_handler)
+ (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
+}
+
+
+gpgme_error_t
+_gpgme_engine_set_command_handler (engine_t engine,
+ engine_command_handler_t fnc,
+ void *fnc_value,
+ gpgme_data_t linked_data)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->set_command_handler)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->set_command_handler) (engine->engine,
+ fnc, fnc_value, linked_data);
+}
+
+gpgme_error_t
+_gpgme_engine_set_colon_line_handler (engine_t engine,
+ engine_colon_line_handler_t fnc,
+ void *fnc_value)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->set_colon_line_handler)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->set_colon_line_handler) (engine->engine,
+ fnc, fnc_value);
+}
+
+gpgme_error_t
+_gpgme_engine_set_locale (engine_t engine, int category,
+ const char *value)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->set_locale)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->set_locale) (engine->engine, category, value);
+}
+
+gpgme_error_t
+_gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
+ gpgme_data_t plain)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->decrypt)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->decrypt) (engine->engine, ciph, plain);
+}
+
+gpgme_error_t
+_gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
+ int allow_secret)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->delete)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->delete) (engine->engine, key, allow_secret);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
+ gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->edit)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->encrypt)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
+ use_armor);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph,
+ int use_armor, gpgme_ctx_t ctx /* FIXME */)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->encrypt_sign)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
+ plain, ciph, use_armor, ctx);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_export (engine_t engine, const char *pattern,
+ unsigned int reserved, gpgme_data_t keydata,
+ int use_armor)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->export)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->export) (engine->engine, pattern, reserved,
+ keydata, use_armor);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
+ unsigned int reserved, gpgme_data_t keydata,
+ int use_armor)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->export_ext)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
+ keydata, use_armor);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
+ int use_armor, gpgme_data_t pubkey,
+ gpgme_data_t seckey)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->genkey)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
+ pubkey, seckey);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->import)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->import) (engine->engine, keydata);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_keylist (engine_t engine, const char *pattern,
+ int secret_only, gpgme_keylist_mode_t mode)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->keylist)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
+ int secret_only, int reserved,
+ gpgme_keylist_mode_t mode)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->keylist_ext)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
+ reserved, mode);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
+ gpgme_sig_mode_t mode, int use_armor,
+ int use_textmode, int include_certs,
+ gpgme_ctx_t ctx /* FIXME */)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->sign)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
+ use_textmode, include_certs, ctx);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->trustlist)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->trustlist) (engine->engine, pattern);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
+ gpgme_data_t signed_text, gpgme_data_t plaintext)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->verify)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
+}
+
+
+void
+_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
+{
+ if (!engine)
+ return;
+
+ (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
+}
+
+
+void
+_gpgme_engine_io_event (engine_t engine,
+ gpgme_event_io_t type, void *type_data)
+{
+ if (!engine)
+ return;
+
+ (*engine->ops->io_event) (engine->engine, type, type_data);
+}
+
+
+gpgme_error_t
+_gpgme_engine_cancel (engine_t engine)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->cancel)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->cancel) (engine->engine);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/engine.h b/libtdenetwork/libgpgme-copy/gpgme/engine.h
new file mode 100644
index 000000000..079c215a1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/engine.h
@@ -0,0 +1,133 @@
+/* engine.h - GPGME engine interface.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include "gpgme.h"
+
+struct engine;
+typedef struct engine *engine_t;
+
+typedef gpgme_error_t (*engine_status_handler_t) (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+typedef gpgme_error_t (*engine_colon_line_handler_t) (void *priv, char *line);
+typedef gpgme_error_t (*engine_command_handler_t) (void *priv,
+ gpgme_status_code_t code,
+ const char *keyword,
+ int fd, int *processed);
+
+/* Get a deep copy of the engine info and return it in INFO. */
+gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);
+
+/* Release the engine info INFO. */
+void _gpgme_engine_info_release (gpgme_engine_info_t info);
+
+/* Set the engine info for the info list INFO, protocol PROTO, to the
+ file name FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t _gpgme_set_engine_info (gpgme_engine_info_t info,
+ gpgme_protocol_t praoto,
+ const char *file_name,
+ const char *home_dir);
+
+
+gpgme_error_t _gpgme_engine_new (gpgme_engine_info_t info,
+ engine_t *r_engine);
+gpgme_error_t _gpgme_engine_reset (engine_t engine);
+
+gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
+ const char *value);
+
+void _gpgme_engine_release (engine_t engine);
+void _gpgme_engine_set_status_handler (engine_t engine,
+ engine_status_handler_t fnc,
+ void *fnc_value);
+gpgme_error_t _gpgme_engine_set_command_handler (engine_t engine,
+ engine_command_handler_t fnc,
+ void *fnc_value,
+ gpgme_data_t data);
+gpgme_error_t
+_gpgme_engine_set_colon_line_handler (engine_t engine,
+ engine_colon_line_handler_t fnc,
+ void *fnc_value);
+gpgme_error_t _gpgme_engine_op_decrypt (engine_t engine,
+ gpgme_data_t ciph,
+ gpgme_data_t plain);
+gpgme_error_t _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
+ int allow_secret);
+gpgme_error_t _gpgme_engine_op_edit (engine_t engine, int type,
+ gpgme_key_t key, gpgme_data_t out,
+ gpgme_ctx_t ctx /* FIXME */);
+gpgme_error_t _gpgme_engine_op_encrypt (engine_t engine,
+ gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph,
+ int use_armor);
+gpgme_error_t _gpgme_engine_op_encrypt_sign (engine_t engine,
+ gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain,
+ gpgme_data_t ciph,
+ int use_armor,
+ gpgme_ctx_t ctx /* FIXME */);
+gpgme_error_t _gpgme_engine_op_export (engine_t engine, const char *pattern,
+ unsigned int reserved,
+ gpgme_data_t keydata, int use_armor);
+gpgme_error_t _gpgme_engine_op_export_ext (engine_t engine,
+ const char *pattern[],
+ unsigned int reserved,
+ gpgme_data_t keydata,
+ int use_armor);
+gpgme_error_t _gpgme_engine_op_genkey (engine_t engine,
+ gpgme_data_t help_data,
+ int use_armor, gpgme_data_t pubkey,
+ gpgme_data_t seckey);
+gpgme_error_t _gpgme_engine_op_import (engine_t engine,
+ gpgme_data_t keydata);
+gpgme_error_t _gpgme_engine_op_keylist (engine_t engine,
+ const char *pattern,
+ int secret_only,
+ gpgme_keylist_mode_t mode);
+gpgme_error_t _gpgme_engine_op_keylist_ext (engine_t engine,
+ const char *pattern[],
+ int secret_only,
+ int reserved,
+ gpgme_keylist_mode_t mode);
+gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in,
+ gpgme_data_t out, gpgme_sig_mode_t mode,
+ int use_armor, int use_textmode,
+ int include_certs,
+ gpgme_ctx_t ctx /* FIXME */);
+gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine,
+ const char *pattern);
+gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
+ gpgme_data_t signed_text,
+ gpgme_data_t plaintext);
+
+void _gpgme_engine_set_io_cbs (engine_t engine,
+ gpgme_io_cbs_t io_cbs);
+void _gpgme_engine_io_event (engine_t engine,
+ gpgme_event_io_t type, void *type_data);
+
+gpgme_error_t _gpgme_engine_cancel (engine_t engine);
+
+#endif /* ENGINE_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/error.c b/libtdenetwork/libgpgme-copy/gpgme/error.c
new file mode 100644
index 000000000..f0ea4929d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/error.c
@@ -0,0 +1,92 @@
+/* error.c - Error handling for GPGME.
+ Copyright (C) 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gpgme.h>
+
+/* Return a pointer to a string containing a description of the error
+ code in the error value ERR. */
+const char *
+gpgme_strerror (gpgme_error_t err)
+{
+ return gpg_strerror (err);
+}
+
+
+/* Return the error string for ERR in the user-supplied buffer BUF of
+ size BUFLEN. This function is, in contrast to gpg_strerror,
+ thread-safe if a thread-safe strerror_r() function is provided by
+ the system. If the function succeeds, 0 is returned and BUF
+ contains the string describing the error. If the buffer was not
+ large enough, ERANGE is returned and BUF contains as much of the
+ beginning of the error string as fits into the buffer. */
+int
+gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen)
+{
+ return gpg_strerror_r (err, buf, buflen);
+}
+
+
+/* Return a pointer to a string containing a description of the error
+ source in the error value ERR. */
+const char *
+gpgme_strsource (gpgme_error_t err)
+{
+ return gpg_strsource (err);
+}
+
+
+/* Retrieve the error code for the system error ERR. This returns
+ GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
+ this). */
+gpgme_err_code_t
+gpgme_err_code_from_errno (int err)
+{
+ return gpg_err_code_from_errno (err);
+}
+
+
+/* Retrieve the system error for the error code CODE. This returns 0
+ if CODE is not a system error code. */
+int
+gpgme_err_code_to_errno (gpgme_err_code_t code)
+{
+ return gpg_err_code_from_errno (code);
+}
+
+
+/* Return an error value with the error source SOURCE and the system
+ error ERR. */
+gpgme_error_t
+gpgme_err_make_from_errno (gpg_err_source_t source, int err)
+{
+ return gpg_err_make_from_errno (source, err);
+}
+
+
+/* Return an error value with the system error ERR. */
+gpgme_err_code_t
+gpgme_error_from_errno (int err)
+{
+ return gpgme_error (gpg_err_code_from_errno (err));
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/export.c b/libtdenetwork/libgpgme-copy/gpgme/export.c
new file mode 100644
index 000000000..176ec66c4
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/export.c
@@ -0,0 +1,117 @@
+/* export.c - Export a key.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+static gpgme_error_t
+export_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ return 0;
+}
+
+
+static gpgme_error_t
+export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
+ unsigned int reserved, gpgme_data_t keydata)
+{
+ gpgme_error_t err;
+
+ if (!keydata)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
+
+ return _gpgme_engine_op_export (ctx->engine, pattern, reserved, keydata,
+ ctx->use_armor);
+}
+
+
+/* Export the keys listed in RECP into KEYDATA. */
+gpgme_error_t
+gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
+ unsigned int reserved, gpgme_data_t keydata)
+{
+ return export_start (ctx, 0, pattern, reserved, keydata);
+}
+
+
+/* Export the keys listed in RECP into KEYDATA. */
+gpgme_error_t
+gpgme_op_export (gpgme_ctx_t ctx, const char *pattern, unsigned int reserved,
+ gpgme_data_t keydata)
+{
+ gpgme_error_t err = export_start (ctx, 1, pattern, reserved, keydata);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
+
+
+static gpgme_error_t
+export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
+ unsigned int reserved, gpgme_data_t keydata)
+{
+ gpgme_error_t err;
+
+ if (!keydata)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
+
+ return _gpgme_engine_op_export_ext (ctx->engine, pattern, reserved, keydata,
+ ctx->use_armor);
+}
+
+
+/* Export the keys listed in RECP into KEYDATA. */
+gpgme_error_t
+gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
+ unsigned int reserved, gpgme_data_t keydata)
+{
+ return export_ext_start (ctx, 0, pattern, reserved, keydata);
+}
+
+
+/* Export the keys listed in RECP into KEYDATA. */
+gpgme_error_t
+gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
+ unsigned int reserved, gpgme_data_t keydata)
+{
+ gpgme_error_t err = export_ext_start (ctx, 1, pattern, reserved, keydata);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/fakes.c b/libtdenetwork/libgpgme-copy/gpgme/fakes.c
new file mode 100644
index 000000000..44d5940f1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/fakes.c
@@ -0,0 +1,24 @@
+#include <config.h>
+
+/** How can this work? The prototypes are not defined anywhere for code using those functions.... */
+
+#ifndef HAVE_STPCPY
+#include "stpcpy.c"
+#endif
+
+/*#ifndef HAVE_ISASCII
+#include "isascii.c"
+#endif*/
+
+#ifndef HAVE_PUTC_UNLOCKED
+#ifndef __FreeBSD__
+#include "putc_unlocked.c"
+#endif
+#endif
+
+#ifndef HAVE_MEMRCHR
+#include "memrchr.c"
+#endif
+
+
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/funopen.c b/libtdenetwork/libgpgme-copy/gpgme/funopen.c
new file mode 100644
index 000000000..67b6fc2b7
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/funopen.c
@@ -0,0 +1,43 @@
+/* funopen.c - Replacement for funopen.
+ Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_FOPENCOOKIE
+FILE *
+funopen(const void *cookie, cookie_read_function_t *readfn,
+ cookie_write_function_t *writefn,
+ cookie_seek_function_t *seekfn,
+ cookie_close_function_t *closefn)
+{
+ cookie_io_functions_t io = { read: readfn, write: writefn,
+ seek: seekfn, close: closefn };
+
+ return fopencookie ((void *) cookie,
+ readfn ? (writefn ? "rw" : "r")
+ : (writefn ? "w" : ""), io);
+}
+#else
+#error No known way to implement funopen.
+#endif
diff --git a/libtdenetwork/libgpgme-copy/gpgme/genkey.c b/libtdenetwork/libgpgme-copy/gpgme/genkey.c
new file mode 100644
index 000000000..daaeb2848
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/genkey.c
@@ -0,0 +1,206 @@
+/* genkey.c - Key generation.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_genkey_result result;
+
+ /* The key parameters passed to the crypto engine. */
+ gpgme_data_t key_parameter;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+
+ if (opd->result.fpr)
+ free (opd->result.fpr);
+ if (opd->key_parameter)
+ gpgme_data_release (opd->key_parameter);
+}
+
+
+gpgme_genkey_result_t
+gpgme_op_genkey_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+static gpgme_error_t
+genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ /* Pipe the status code through the progress status handler. */
+ err = _gpgme_progress_status_handler (ctx, code, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_KEY_CREATED:
+ if (args && *args)
+ {
+ if (*args == 'B' || *args == 'P')
+ opd->result.primary = 1;
+ if (*args == 'B' || *args == 'S')
+ opd->result.sub = 1;
+ if (args[1] == ' ')
+ {
+ if (opd->result.fpr)
+ free (opd->result.fpr);
+ opd->result.fpr = strdup (&args[2]);
+ if (!opd->result.fpr)
+ return gpg_error_from_errno (errno);
+ }
+ }
+ break;
+
+ case GPGME_STATUS_EOF:
+ /* FIXME: Should return some more useful error value. */
+ if (!opd->result.primary && !opd->result.sub)
+ return gpg_error (GPG_ERR_GENERAL);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+get_key_parameter (const char *parms, gpgme_data_t *key_parameter)
+{
+ const char *content;
+ const char *attrib;
+ const char *endtag;
+
+ /* Extract the key parameter from the XML structure. */
+ parms = strstr (parms, "<GnupgKeyParms ");
+ if (!parms)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ content = strchr (parms, '>');
+ if (!content)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ content++;
+
+ attrib = strstr (parms, "format=\"internal\"");
+ if (!attrib || attrib >= content)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ endtag = strstr (content, "</GnupgKeyParms>");
+ /* FIXME: Check that there are no control statements inside. */
+ while (content[0] == '\n'
+ || (content[0] == '\r' && content[1] == '\n'))
+ content++;
+
+ return gpgme_data_new_from_mem (key_parameter, content,
+ endtag - content, 1);
+}
+
+
+static gpgme_error_t
+genkey_start (gpgme_ctx_t ctx, int synchronous, const char *parms,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ err = get_key_parameter (parms, &opd->key_parameter);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+
+ return _gpgme_engine_op_genkey (ctx->engine, opd->key_parameter,
+ ctx->use_armor, pubkey, seckey);
+}
+
+
+/* Generate a new keypair and add it to the keyring. PUBKEY and
+ SECKEY should be null for now. PARMS specifies what keys should be
+ generated. */
+gpgme_error_t
+gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ return genkey_start (ctx, 0, parms, pubkey, seckey);
+}
+
+
+/* Generate a new keypair and add it to the keyring. PUBKEY and
+ SECKEY should be null for now. PARMS specifies what keys should be
+ generated. */
+gpgme_error_t
+gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey,
+ gpgme_data_t seckey)
+{
+ gpgme_error_t err;
+
+ err = genkey_start (ctx, 1, parms, pubkey, seckey);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/get-env.c b/libtdenetwork/libgpgme-copy/gpgme/get-env.c
new file mode 100644
index 000000000..b5884048e
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/get-env.c
@@ -0,0 +1,59 @@
+/* get_env.c - A getenv() replacement.
+ Copyright (C) 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "util.h"
+
+
+#if defined(HAVE_THREAD_SAFE_GETENV) || !defined (HAVE_GETENV_R)
+/* We prefer using getenv() if it is thread-safe. */
+
+/* Retrieve the environment variable NAME and return a copy of it in a
+ malloc()'ed buffer in *VALUE. If the environment variable is not
+ set, return NULL in *VALUE. */
+gpgme_error_t
+_gpgme_getenv (const char *name, char **value)
+{
+ char *env_value;
+
+ env_value = getenv (name);
+ if (!env_value)
+ *value = NULL;
+ else
+ {
+ *value = strdup (env_value);
+ if (!*value)
+ return gpg_error_from_errno (errno);
+ }
+ return 0;
+}
+
+#else
+
+/* FIXME: Implement this when we have the specification for it. */
+#error Use of getenv_r not implemented.
+
+#endif
diff --git a/libtdenetwork/libgpgme-copy/gpgme/gpgme.c b/libtdenetwork/libgpgme-copy/gpgme/gpgme.c
new file mode 100644
index 000000000..9a2f90b8d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/gpgme.c
@@ -0,0 +1,582 @@
+/* gpgme.c - GnuPG Made Easy.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <locale.h>
+
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+#include "wait.h"
+
+
+/* The default locale. */
+DEFINE_STATIC_LOCK (def_lc_lock);
+static char *def_lc_ctype;
+static char *def_lc_messages;
+
+
+/* Create a new context as an environment for GPGME crypto
+ operations. */
+gpgme_error_t
+gpgme_new (gpgme_ctx_t *r_ctx)
+{
+ gpgme_ctx_t ctx;
+
+ ctx = calloc (1, sizeof *ctx);
+ if (!ctx)
+ return gpg_error_from_errno (errno);
+
+ _gpgme_engine_info_copy (&ctx->engine_info);
+ if (!ctx->engine_info)
+ {
+ free (ctx);
+ return gpg_error_from_errno (errno);
+ }
+
+ ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL;
+ ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
+ ctx->protocol = GPGME_PROTOCOL_OpenPGP;
+ _gpgme_fd_table_init (&ctx->fdt);
+
+ LOCK (def_lc_lock);
+ if (def_lc_ctype)
+ {
+ ctx->lc_ctype = strdup (def_lc_ctype);
+ if (!ctx->lc_ctype)
+ {
+ UNLOCK (def_lc_lock);
+ _gpgme_engine_info_release (ctx->engine_info);
+ free (ctx);
+ return gpg_error_from_errno (errno);
+ }
+ }
+ else
+ def_lc_ctype = NULL;
+
+ if (def_lc_messages)
+ {
+ ctx->lc_messages = strdup (def_lc_messages);
+ if (!ctx->lc_messages)
+ {
+ UNLOCK (def_lc_lock);
+ if (ctx->lc_ctype)
+ free (ctx->lc_ctype);
+ _gpgme_engine_info_release (ctx->engine_info);
+ free (ctx);
+ return gpg_error_from_errno (errno);
+ }
+ }
+ else
+ def_lc_messages = NULL;
+ UNLOCK (def_lc_lock);
+
+ *r_ctx = ctx;
+ return 0;
+}
+
+
+/* Cancel a pending asynchronous operation. */
+gpgme_error_t
+gpgme_cancel (gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_engine_cancel (ctx->engine);
+ if (err)
+ return err;
+
+ err = gpg_error (GPG_ERR_CANCELED);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+
+ return 0;
+}
+
+/* Release all resources associated with the given context. */
+void
+gpgme_release (gpgme_ctx_t ctx)
+{
+ _gpgme_engine_release (ctx->engine);
+ _gpgme_fd_table_deinit (&ctx->fdt);
+ _gpgme_release_result (ctx);
+ gpgme_signers_clear (ctx);
+ if (ctx->signers)
+ free (ctx->signers);
+ if (ctx->lc_ctype)
+ free (ctx->lc_ctype);
+ if (ctx->lc_messages)
+ free (ctx->lc_messages);
+ _gpgme_engine_info_release (ctx->engine_info);
+ free (ctx);
+}
+
+
+void
+_gpgme_release_result (gpgme_ctx_t ctx)
+{
+ struct ctx_op_data *data = ctx->op_data;
+
+ while (data)
+ {
+ struct ctx_op_data *next_data = data->next;
+ if (data->cleanup)
+ (*data->cleanup) (data->hook);
+ free (data);
+ data = next_data;
+ }
+ ctx->op_data = NULL;
+}
+
+
+gpgme_error_t
+gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
+{
+ if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (ctx->protocol != protocol)
+ {
+ /* Shut down the engine when switching protocols. */
+ if (ctx->engine)
+ {
+ _gpgme_engine_release (ctx->engine);
+ ctx->engine = NULL;
+ }
+
+ ctx->protocol = protocol;
+ }
+ return 0;
+}
+
+
+gpgme_protocol_t
+gpgme_get_protocol (gpgme_ctx_t ctx)
+{
+ return ctx->protocol;
+}
+
+
+const char *
+gpgme_get_protocol_name (gpgme_protocol_t protocol)
+{
+ switch (protocol)
+ {
+ case GPGME_PROTOCOL_OpenPGP:
+ return "OpenPGP";
+
+ case GPGME_PROTOCOL_CMS:
+ return "CMS";
+
+ default:
+ return NULL;
+ }
+}
+
+/* Enable or disable the use of an ascii armor for all output. */
+void
+gpgme_set_armor (gpgme_ctx_t ctx, int yes)
+{
+ ctx->use_armor = yes;
+}
+
+
+/* Return the state of the armor flag. */
+int
+gpgme_get_armor (gpgme_ctx_t ctx)
+{
+ return ctx->use_armor;
+}
+
+
+/* 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 that the MUA does some preparations so that textmode
+ is not needed anymore. */
+void
+gpgme_set_textmode (gpgme_ctx_t ctx, int yes)
+{
+ ctx->use_textmode = yes;
+}
+
+/* Return the state of the textmode flag. */
+int
+gpgme_get_textmode (gpgme_ctx_t ctx)
+{
+ return ctx->use_textmode;
+}
+
+
+/* Set the number of certifications to include in an S/MIME message.
+ The default is GPGME_INCLUDE_CERTS_DEFAULT. -1 means all certs,
+ and -2 means all certs except the root cert. */
+void
+gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs)
+{
+ if (nr_of_certs == GPGME_INCLUDE_CERTS_DEFAULT)
+ ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
+ else if (nr_of_certs < -2)
+ ctx->include_certs = -2;
+ else
+ ctx->include_certs = nr_of_certs;
+}
+
+
+/* Get the number of certifications to include in an S/MIME
+ message. */
+int
+gpgme_get_include_certs (gpgme_ctx_t ctx)
+{
+ return ctx->include_certs;
+}
+
+
+/* This function changes the default behaviour of the keylisting
+ functions. MODE is a bitwise-OR of the GPGME_KEYLIST_* flags. The
+ default mode is GPGME_KEYLIST_MODE_LOCAL. */
+gpgme_error_t
+gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
+{
+ ctx->keylist_mode = mode;
+ return 0;
+}
+
+/* This function returns the default behaviour of the keylisting
+ functions. */
+gpgme_keylist_mode_t
+gpgme_get_keylist_mode (gpgme_ctx_t ctx)
+{
+ return ctx->keylist_mode;
+}
+
+
+/* This function sets a callback function to be used to pass a
+ passphrase to gpg. */
+void
+gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb,
+ void *cb_value)
+{
+ ctx->passphrase_cb = cb;
+ ctx->passphrase_cb_value = cb_value;
+}
+
+
+/* This function returns the callback function to be used to pass a
+ passphrase to the crypto engine. */
+void
+gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *r_cb,
+ void **r_cb_value)
+{
+ if (r_cb)
+ *r_cb = ctx->passphrase_cb;
+ if (r_cb_value)
+ *r_cb_value = ctx->passphrase_cb_value;
+}
+
+
+/* This function sets a callback function to be used as a progress
+ indicator. */
+void
+gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb, void *cb_value)
+{
+ ctx->progress_cb = cb;
+ ctx->progress_cb_value = cb_value;
+}
+
+
+/* This function returns the callback function to be used as a
+ progress indicator. */
+void
+gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb,
+ void **r_cb_value)
+{
+ if (r_cb)
+ *r_cb = ctx->progress_cb;
+ if (r_cb_value)
+ *r_cb_value = ctx->progress_cb_value;
+}
+
+
+/* Set the I/O callback functions for CTX to IO_CBS. */
+void
+gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
+{
+ if (io_cbs)
+ ctx->io_cbs = *io_cbs;
+ else
+ {
+ ctx->io_cbs.add = NULL;
+ ctx->io_cbs.add_priv = NULL;
+ ctx->io_cbs.remove = NULL;
+ ctx->io_cbs.event = NULL;
+ ctx->io_cbs.event_priv = NULL;
+ }
+}
+
+
+/* This function returns the callback function for I/O. */
+void
+gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
+{
+ *io_cbs = ctx->io_cbs;
+}
+
+
+/* This function sets the locale for the context CTX, or the default
+ locale if CTX is a null pointer. */
+gpgme_error_t
+gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
+{
+ int failed = 0;
+ char *new_lc_ctype = NULL;
+ char *new_lc_messages = NULL;
+
+#define PREPARE_ONE_LOCALE(lcat, ucat) \
+ if (!failed && value \
+ && (category == LC_ALL || category == LC_ ## ucat)) \
+ { \
+ new_lc_ ## lcat = strdup (value); \
+ if (!new_lc_ ## lcat) \
+ failed = 1; \
+ }
+
+ PREPARE_ONE_LOCALE (ctype, CTYPE);
+#ifdef LC_MESSAGES
+ PREPARE_ONE_LOCALE (messages, MESSAGES);
+#endif
+
+ if (failed)
+ {
+ int saved_errno = errno;
+
+ if (new_lc_ctype)
+ free (new_lc_ctype);
+ if (new_lc_messages)
+ free (new_lc_messages);
+
+ return gpg_error_from_errno (saved_errno);
+ }
+
+#define SET_ONE_LOCALE(lcat, ucat) \
+ if (category == LC_ALL || category == LC_ ## ucat) \
+ { \
+ if (ctx) \
+ { \
+ if (ctx->lc_ ## lcat) \
+ free (ctx->lc_ ## lcat); \
+ ctx->lc_ ## lcat = new_lc_ ## lcat; \
+ } \
+ else \
+ { \
+ if (def_lc_ ## lcat) \
+ free (def_lc_ ## lcat); \
+ def_lc_ ## lcat = new_lc_ ## lcat; \
+ } \
+ }
+
+ if (!ctx)
+ LOCK (def_lc_lock);
+ SET_ONE_LOCALE (ctype, CTYPE);
+#ifdef LC_MESSAGES
+ SET_ONE_LOCALE (messages, MESSAGES);
+#endif
+ if (!ctx)
+ UNLOCK (def_lc_lock);
+
+ return 0;
+}
+
+
+/* Get the information about the configured engines. A pointer to the
+ first engine in the statically allocated linked list is returned.
+ The returned data is valid until the next gpgme_ctx_set_engine_info. */
+gpgme_engine_info_t
+gpgme_ctx_get_engine_info (gpgme_ctx_t ctx)
+{
+ return ctx->engine_info;
+}
+
+
+/* Set the engine info for the context CTX, protocol PROTO, to the
+ file name FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t
+gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,
+ const char *file_name, const char *home_dir)
+{
+ /* Shut down the engine when changing engine info. */
+ if (ctx->engine)
+ {
+ _gpgme_engine_release (ctx->engine);
+ ctx->engine = NULL;
+ }
+ return _gpgme_set_engine_info (ctx->engine_info, proto,
+ file_name, home_dir);
+}
+
+
+/* Clear all notation data from the context. */
+void
+gpgme_sig_notation_clear (gpgme_ctx_t ctx)
+{
+ gpgme_sig_notation_t notation;
+
+ if (!ctx)
+ return;
+
+ notation = ctx->sig_notations;
+ while (notation)
+ {
+ gpgme_sig_notation_t next_notation = notation->next;
+ _gpgme_sig_notation_free (notation);
+ notation = next_notation;
+ }
+}
+
+
+/* Add the human-readable notation data with name NAME and value VALUE
+ to the context CTX, using the flags FLAGS. If NAME is NULL, then
+ VALUE should be a policy URL. The flag
+ GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
+ data, and false for policy URLs. */
+gpgme_error_t
+gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
+ const char *value, gpgme_sig_notation_flags_t flags)
+{
+ gpgme_error_t err;
+ gpgme_sig_notation_t notation;
+ gpgme_sig_notation_t *lastp;
+
+ if (!ctx)
+ gpg_error (GPG_ERR_INV_VALUE);
+
+ if (name)
+ flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
+ else
+ flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE;
+
+ err = _gpgme_sig_notation_create (&notation, name, name ? strlen (name) : 0,
+ value, value ? strlen (value) : 0, flags);
+ if (err)
+ return err;
+
+ lastp = &ctx->sig_notations;
+ while (*lastp)
+ lastp = &(*lastp)->next;
+
+ *lastp = notation;
+ return 0;
+}
+
+
+/* Get the sig notations for this context. */
+gpgme_sig_notation_t
+gpgme_sig_notation_get (gpgme_ctx_t ctx)
+{
+ if (!ctx)
+ return NULL;
+
+ return ctx->sig_notations;
+}
+
+
+const char *
+gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
+{
+ switch (algo)
+ {
+ case GPGME_PK_RSA:
+ return "RSA";
+
+ case GPGME_PK_RSA_E:
+ return "RSA-E";
+
+ case GPGME_PK_RSA_S:
+ return "RSA-S";
+
+ case GPGME_PK_ELG_E:
+ return "ELG-E";
+
+ case GPGME_PK_DSA:
+ return "DSA";
+
+ case GPGME_PK_ELG:
+ return "ELG";
+
+ default:
+ return NULL;
+ }
+}
+
+
+const char *
+gpgme_hash_algo_name (gpgme_hash_algo_t algo)
+{
+ switch (algo)
+ {
+ case GPGME_MD_MD5:
+ return "MD5";
+
+ case GPGME_MD_SHA1:
+ return "SHA1";
+
+ case GPGME_MD_RMD160:
+ return "RIPEMD160";
+
+ case GPGME_MD_MD2:
+ return "MD2";
+
+ case GPGME_MD_TIGER:
+ return "TIGER192";
+
+ case GPGME_MD_HAVAL:
+ return "HAVAL";
+
+ case GPGME_MD_SHA256:
+ return "SHA256";
+
+ case GPGME_MD_SHA384:
+ return "SHA384";
+
+ case GPGME_MD_SHA512:
+ return "SHA512";
+
+ case GPGME_MD_MD4:
+ return "MD4";
+
+ case GPGME_MD_CRC32:
+ return "CRC32";
+
+ case GPGME_MD_CRC32_RFC1510:
+ return "CRC32RFC1510";
+
+ case GPGME_MD_CRC24_RFC2440:
+ return "CRC24RFC2440";
+
+ default:
+ return NULL;
+ }
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/gpgme.h b/libtdenetwork/libgpgme-copy/gpgme/gpgme.h
new file mode 100644
index 000000000..f6f31ae2a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/gpgme.h
@@ -0,0 +1,1706 @@
+/* gpgme.h - Public interface to GnuPG Made Easy.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef GPGME_H
+#define GPGME_H
+
+#ifdef __GNUC__
+#define _GPGME_INLINE __inline__
+#elif __STDC_VERSION__ >= 199901L
+#define _GPGME_INLINE inline
+#else
+#define _GPGME_INLINE
+#endif
+
+/* Include stdio.h for the FILE type definition. */
+#include <stdio.h>
+
+#ifdef _MSC_VER
+ typedef long off_t;
+ typedef long ssize_t;
+#else
+# include <sys/types.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#if 0 /* just to make Emacs auto-indent happy */
+}
+#endif
+#endif /* __cplusplus */
+
+#include <gpg-error.h>
+
+
+/* Check for compiler features. */
+#if __GNUC__
+#define _GPGME_GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+#if _GPGME_GCC_VERSION > 30100
+#define _GPGME_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+#endif
+
+#ifndef _GPGME_DEPRECATED
+#define _GPGME_DEPRECATED
+#endif
+
+
+/* The version of this header should match the one of the library. Do
+ not use this symbol in your application, use gpgme_check_version
+ instead. The purpose of this macro is to let autoconf (using the
+ AM_PATH_GPGME macro) check that this header matches the installed
+ library. Warning: Do not edit the next line. configure will do
+ that for you! */
+#define GPGME_VERSION "1.1.4"
+
+
+
+/* Some opaque data types used by GPGME. */
+
+/* The context holds some global state and configration options, as
+ well as the results of a crypto operation. */
+struct gpgme_context;
+typedef struct gpgme_context *gpgme_ctx_t;
+
+/* The data object is used by GPGME to exchange arbitrary data. */
+struct gpgme_data;
+typedef struct gpgme_data *gpgme_data_t;
+
+
+/* Wrappers for the libgpg-error library. */
+
+typedef gpg_error_t gpgme_error_t;
+typedef gpg_err_code_t gpgme_err_code_t;
+typedef gpg_err_source_t gpgme_err_source_t;
+
+
+static _GPGME_INLINE gpgme_error_t
+gpgme_err_make (gpgme_err_source_t source, gpgme_err_code_t code)
+{
+ return gpg_err_make (source, code);
+}
+
+
+/* The user can define GPGME_ERR_SOURCE_DEFAULT before including this
+ file to specify a default source for gpgme_error. */
+#ifndef GPGME_ERR_SOURCE_DEFAULT
+#define GPGME_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
+#endif
+
+static _GPGME_INLINE gpgme_error_t
+gpgme_error (gpgme_err_code_t code)
+{
+ return gpgme_err_make (GPGME_ERR_SOURCE_DEFAULT, code);
+}
+
+
+static _GPGME_INLINE gpgme_err_code_t
+gpgme_err_code (gpgme_error_t err)
+{
+ return gpg_err_code (err);
+}
+
+
+static _GPGME_INLINE gpgme_err_source_t
+gpgme_err_source (gpgme_error_t err)
+{
+ return gpg_err_source (err);
+}
+
+
+/* Return a pointer to a string containing a description of the error
+ code in the error value ERR. This function is not thread safe. */
+const char *gpgme_strerror (gpgme_error_t err);
+
+/* Return the error string for ERR in the user-supplied buffer BUF of
+ size BUFLEN. This function is, in contrast to gpg_strerror,
+ thread-safe if a thread-safe strerror_r() function is provided by
+ the system. If the function succeeds, 0 is returned and BUF
+ contains the string describing the error. If the buffer was not
+ large enough, ERANGE is returned and BUF contains as much of the
+ beginning of the error string as fits into the buffer. */
+int gpgme_strerror_r (gpg_error_t err, char *buf, size_t buflen);
+
+
+/* Return a pointer to a string containing a description of the error
+ source in the error value ERR. */
+const char *gpgme_strsource (gpgme_error_t err);
+
+
+/* Retrieve the error code for the system error ERR. This returns
+ GPG_ERR_UNKNOWN_ERRNO if the system error is not mapped (report
+ this). */
+gpgme_err_code_t gpgme_err_code_from_errno (int err);
+
+
+/* Retrieve the system error for the error code CODE. This returns 0
+ if CODE is not a system error code. */
+int gpgme_err_code_to_errno (gpgme_err_code_t code);
+
+
+/* Return an error value with the error source SOURCE and the system
+ error ERR. */
+gpgme_error_t gpgme_err_make_from_errno (gpgme_err_source_t source, int err);
+
+
+/* Return an error value with the system error ERR. */
+gpgme_err_code_t gpgme_error_from_errno (int err);
+
+
+/* The possible encoding mode of gpgme_data_t objects. */
+typedef enum
+ {
+ GPGME_DATA_ENCODING_NONE = 0, /* Not specified. */
+ GPGME_DATA_ENCODING_BINARY = 1,
+ GPGME_DATA_ENCODING_BASE64 = 2,
+ GPGME_DATA_ENCODING_ARMOR = 3 /* Either PEM or OpenPGP Armor. */
+ }
+gpgme_data_encoding_t;
+
+
+/* Public key algorithms from libgcrypt. */
+typedef enum
+ {
+ GPGME_PK_RSA = 1,
+ GPGME_PK_RSA_E = 2,
+ GPGME_PK_RSA_S = 3,
+ GPGME_PK_ELG_E = 16,
+ GPGME_PK_DSA = 17,
+ GPGME_PK_ELG = 20
+ }
+gpgme_pubkey_algo_t;
+
+
+/* Hash algorithms from libgcrypt. */
+typedef enum
+ {
+ GPGME_MD_NONE = 0,
+ GPGME_MD_MD5 = 1,
+ GPGME_MD_SHA1 = 2,
+ GPGME_MD_RMD160 = 3,
+ GPGME_MD_MD2 = 5,
+ GPGME_MD_TIGER = 6, /* TIGER/192. */
+ GPGME_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
+ GPGME_MD_SHA256 = 8,
+ GPGME_MD_SHA384 = 9,
+ GPGME_MD_SHA512 = 10,
+ GPGME_MD_MD4 = 301,
+ GPGME_MD_CRC32 = 302,
+ GPGME_MD_CRC32_RFC1510 = 303,
+ GPGME_MD_CRC24_RFC2440 = 304
+ }
+gpgme_hash_algo_t;
+
+
+/* The possible signature stati. Deprecated, use error value in sig
+ status. */
+typedef enum
+ {
+ GPGME_SIG_STAT_NONE = 0,
+ GPGME_SIG_STAT_GOOD = 1,
+ GPGME_SIG_STAT_BAD = 2,
+ GPGME_SIG_STAT_NOKEY = 3,
+ GPGME_SIG_STAT_NOSIG = 4,
+ GPGME_SIG_STAT_ERROR = 5,
+ GPGME_SIG_STAT_DIFF = 6,
+ GPGME_SIG_STAT_GOOD_EXP = 7,
+ GPGME_SIG_STAT_GOOD_EXPKEY = 8
+ }
+_gpgme_sig_stat_t;
+typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED;
+
+
+/* The available signature modes. */
+typedef enum
+ {
+ GPGME_SIG_MODE_NORMAL = 0,
+ GPGME_SIG_MODE_DETACH = 1,
+ GPGME_SIG_MODE_CLEAR = 2
+ }
+gpgme_sig_mode_t;
+
+
+/* The available key and signature attributes. Deprecated, use the
+ individual result structures instead. */
+typedef enum
+ {
+ GPGME_ATTR_KEYID = 1,
+ GPGME_ATTR_FPR = 2,
+ GPGME_ATTR_ALGO = 3,
+ GPGME_ATTR_LEN = 4,
+ GPGME_ATTR_CREATED = 5,
+ GPGME_ATTR_EXPIRE = 6,
+ GPGME_ATTR_OTRUST = 7,
+ GPGME_ATTR_USERID = 8,
+ GPGME_ATTR_NAME = 9,
+ GPGME_ATTR_EMAIL = 10,
+ GPGME_ATTR_COMMENT = 11,
+ GPGME_ATTR_VALIDITY = 12,
+ GPGME_ATTR_LEVEL = 13,
+ GPGME_ATTR_TYPE = 14,
+ GPGME_ATTR_IS_SECRET = 15,
+ GPGME_ATTR_KEY_REVOKED = 16,
+ GPGME_ATTR_KEY_INVALID = 17,
+ GPGME_ATTR_UID_REVOKED = 18,
+ GPGME_ATTR_UID_INVALID = 19,
+ GPGME_ATTR_KEY_CAPS = 20,
+ GPGME_ATTR_CAN_ENCRYPT = 21,
+ GPGME_ATTR_CAN_SIGN = 22,
+ GPGME_ATTR_CAN_CERTIFY = 23,
+ GPGME_ATTR_KEY_EXPIRED = 24,
+ GPGME_ATTR_KEY_DISABLED = 25,
+ GPGME_ATTR_SERIAL = 26,
+ GPGME_ATTR_ISSUER = 27,
+ GPGME_ATTR_CHAINID = 28,
+ GPGME_ATTR_SIG_STATUS = 29,
+ GPGME_ATTR_ERRTOK = 30,
+ GPGME_ATTR_SIG_SUMMARY = 31,
+ GPGME_ATTR_SIG_CLASS = 32
+ }
+_gpgme_attr_t;
+typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED;
+
+
+/* The available validities for a trust item or key. */
+typedef enum
+ {
+ GPGME_VALIDITY_UNKNOWN = 0,
+ GPGME_VALIDITY_UNDEFINED = 1,
+ GPGME_VALIDITY_NEVER = 2,
+ GPGME_VALIDITY_MARGINAL = 3,
+ GPGME_VALIDITY_FULL = 4,
+ GPGME_VALIDITY_ULTIMATE = 5
+ }
+gpgme_validity_t;
+
+
+/* The available protocols. */
+typedef enum
+ {
+ GPGME_PROTOCOL_OpenPGP = 0, /* The default mode. */
+ GPGME_PROTOCOL_CMS = 1
+ }
+gpgme_protocol_t;
+
+
+/* The available keylist mode flags. */
+#define GPGME_KEYLIST_MODE_LOCAL 1
+#define GPGME_KEYLIST_MODE_EXTERN 2
+#define GPGME_KEYLIST_MODE_SIGS 4
+#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
+#define GPGME_KEYLIST_MODE_VALIDATE 256
+
+typedef unsigned int gpgme_keylist_mode_t;
+
+
+/* Signature notations. */
+
+/* The available signature notation flags. */
+#define GPGME_SIG_NOTATION_HUMAN_READABLE 1
+#define GPGME_SIG_NOTATION_CRITICAL 2
+
+typedef unsigned int gpgme_sig_notation_flags_t;
+
+struct _gpgme_sig_notation
+{
+ struct _gpgme_sig_notation *next;
+
+ /* If NAME is a null pointer, then VALUE contains a policy URL
+ rather than a notation. */
+ char *name;
+
+ /* The value of the notation data. */
+ char *value;
+
+ /* The length of the name of the notation data. */
+ int name_len;
+
+ /* The length of the value of the notation data. */
+ int value_len;
+
+ /* The accumulated flags. */
+ gpgme_sig_notation_flags_t flags;
+
+ /* Notation data is human-readable. */
+ unsigned int human_readable : 1;
+
+ /* Notation data is critical. */
+ unsigned int critical : 1;
+
+ /* Internal to GPGME, do not use. */
+ int _unused : 30;
+};
+typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;
+
+
+/* The possible stati for the edit operation. */
+typedef enum
+ {
+ GPGME_STATUS_EOF,
+ /* mkstatus processing starts here */
+ GPGME_STATUS_ENTER,
+ GPGME_STATUS_LEAVE,
+ GPGME_STATUS_ABORT,
+
+ GPGME_STATUS_GOODSIG,
+ GPGME_STATUS_BADSIG,
+ GPGME_STATUS_ERRSIG,
+
+ GPGME_STATUS_BADARMOR,
+
+ GPGME_STATUS_RSA_OR_IDEA,
+ GPGME_STATUS_KEYEXPIRED,
+ GPGME_STATUS_KEYREVOKED,
+
+ GPGME_STATUS_TRUST_UNDEFINED,
+ GPGME_STATUS_TRUST_NEVER,
+ GPGME_STATUS_TRUST_MARGINAL,
+ GPGME_STATUS_TRUST_FULLY,
+ GPGME_STATUS_TRUST_ULTIMATE,
+
+ GPGME_STATUS_SHM_INFO,
+ GPGME_STATUS_SHM_GET,
+ GPGME_STATUS_SHM_GET_BOOL,
+ GPGME_STATUS_SHM_GET_HIDDEN,
+
+ GPGME_STATUS_NEED_PASSPHRASE,
+ GPGME_STATUS_VALIDSIG,
+ GPGME_STATUS_SIG_ID,
+ GPGME_STATUS_ENC_TO,
+ GPGME_STATUS_NODATA,
+ GPGME_STATUS_BAD_PASSPHRASE,
+ GPGME_STATUS_NO_PUBKEY,
+ GPGME_STATUS_NO_SECKEY,
+ GPGME_STATUS_NEED_PASSPHRASE_SYM,
+ GPGME_STATUS_DECRYPTION_FAILED,
+ GPGME_STATUS_DECRYPTION_OKAY,
+ GPGME_STATUS_MISSING_PASSPHRASE,
+ GPGME_STATUS_GOOD_PASSPHRASE,
+ GPGME_STATUS_GOODMDC,
+ GPGME_STATUS_BADMDC,
+ GPGME_STATUS_ERRMDC,
+ GPGME_STATUS_IMPORTED,
+ GPGME_STATUS_IMPORT_OK,
+ GPGME_STATUS_IMPORT_PROBLEM,
+ GPGME_STATUS_IMPORT_RES,
+ GPGME_STATUS_FILE_START,
+ GPGME_STATUS_FILE_DONE,
+ GPGME_STATUS_FILE_ERROR,
+
+ GPGME_STATUS_BEGIN_DECRYPTION,
+ GPGME_STATUS_END_DECRYPTION,
+ GPGME_STATUS_BEGIN_ENCRYPTION,
+ GPGME_STATUS_END_ENCRYPTION,
+
+ GPGME_STATUS_DELETE_PROBLEM,
+ GPGME_STATUS_GET_BOOL,
+ GPGME_STATUS_GET_LINE,
+ GPGME_STATUS_GET_HIDDEN,
+ GPGME_STATUS_GOT_IT,
+ GPGME_STATUS_PROGRESS,
+ GPGME_STATUS_SIG_CREATED,
+ GPGME_STATUS_SESSION_KEY,
+ GPGME_STATUS_NOTATION_NAME,
+ GPGME_STATUS_NOTATION_DATA,
+ GPGME_STATUS_POLICY_URL,
+ GPGME_STATUS_BEGIN_STREAM,
+ GPGME_STATUS_END_STREAM,
+ GPGME_STATUS_KEY_CREATED,
+ GPGME_STATUS_USERID_HINT,
+ GPGME_STATUS_UNEXPECTED,
+ GPGME_STATUS_INV_RECP,
+ GPGME_STATUS_NO_RECP,
+ GPGME_STATUS_ALREADY_SIGNED,
+ GPGME_STATUS_SIGEXPIRED,
+ GPGME_STATUS_EXPSIG,
+ GPGME_STATUS_EXPKEYSIG,
+ GPGME_STATUS_TRUNCATED,
+ GPGME_STATUS_ERROR,
+ GPGME_STATUS_NEWSIG,
+ GPGME_STATUS_REVKEYSIG,
+ GPGME_STATUS_SIG_SUBPACKET,
+ GPGME_STATUS_NEED_PASSPHRASE_PIN,
+ GPGME_STATUS_SC_OP_FAILURE,
+ GPGME_STATUS_SC_OP_SUCCESS,
+ GPGME_STATUS_CARDCTRL,
+ GPGME_STATUS_BACKUP_KEY_CREATED,
+ GPGME_STATUS_PKA_TRUST_BAD,
+ GPGME_STATUS_PKA_TRUST_GOOD,
+
+ GPGME_STATUS_PLAINTEXT
+ }
+gpgme_status_code_t;
+
+
+/* The engine information structure. */
+struct _gpgme_engine_info
+{
+ struct _gpgme_engine_info *next;
+
+ /* The protocol ID. */
+ gpgme_protocol_t protocol;
+
+ /* The file name of the engine binary. */
+ char *file_name;
+
+ /* The version string of the installed engine. */
+ char *version;
+
+ /* The minimum version required for GPGME. */
+ const char *req_version;
+
+ /* The home directory used, or NULL if default. */
+ char *home_dir;
+};
+typedef struct _gpgme_engine_info *gpgme_engine_info_t;
+
+
+/* A subkey from a key. */
+struct _gpgme_subkey
+{
+ struct _gpgme_subkey *next;
+
+ /* True if subkey is revoked. */
+ unsigned int revoked : 1;
+
+ /* True if subkey is expired. */
+ unsigned int expired : 1;
+
+ /* True if subkey is disabled. */
+ unsigned int disabled : 1;
+
+ /* True if subkey is invalid. */
+ unsigned int invalid : 1;
+
+ /* True if subkey can be used for encryption. */
+ unsigned int can_encrypt : 1;
+
+ /* True if subkey can be used for signing. */
+ unsigned int can_sign : 1;
+
+ /* True if subkey can be used for certification. */
+ unsigned int can_certify : 1;
+
+ /* True if subkey is secret. */
+ unsigned int secret : 1;
+
+ /* True if subkey can be used for authentication. */
+ unsigned int can_authenticate : 1;
+
+ /* True if subkey is qualified for signatures according to German law. */
+ unsigned int is_qualified : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 22;
+
+ /* Public key algorithm supported by this subkey. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* Length of the subkey. */
+ unsigned int length;
+
+ /* The key ID of the subkey. */
+ char *keyid;
+
+ /* Internal to GPGME, do not use. */
+ char _keyid[16 + 1];
+
+ /* The fingerprint of the subkey in hex digit form. */
+ char *fpr;
+
+ /* The creation timestamp, -1 if invalid, 0 if not available. */
+ long int timestamp;
+
+ /* The expiration timestamp, 0 if the subkey does not expire. */
+ long int expires;
+};
+typedef struct _gpgme_subkey *gpgme_subkey_t;
+
+
+/* A signature on a user ID. */
+struct _gpgme_key_sig
+{
+ struct _gpgme_key_sig *next;
+
+ /* True if the signature is a revocation signature. */
+ unsigned int revoked : 1;
+
+ /* True if the signature is expired. */
+ unsigned int expired : 1;
+
+ /* True if the signature is invalid. */
+ unsigned int invalid : 1;
+
+ /* True if the signature should be exported. */
+ unsigned int exportable : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 28;
+
+ /* The public key algorithm used to create the signature. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The key ID of key used to create the signature. */
+ char *keyid;
+
+ /* Internal to GPGME, do not use. */
+ char _keyid[16 + 1];
+
+ /* The creation timestamp, -1 if invalid, 0 if not available. */
+ long int timestamp;
+
+ /* The expiration timestamp, 0 if the subkey does not expire. */
+ long int expires;
+
+ /* Same as in gpgme_signature_t. */
+ gpgme_error_t status;
+
+#ifdef __cplusplus
+ unsigned int _obsolete_class _GPGME_DEPRECATED;
+#else
+ /* Must be set to SIG_CLASS below. */
+ unsigned int class _GPGME_DEPRECATED;
+#endif
+
+ /* The user ID string. */
+ char *uid;
+
+ /* The name part of the user ID. */
+ char *name;
+
+ /* The email part of the user ID. */
+ char *email;
+
+ /* The comment part of the user ID. */
+ char *comment;
+
+ /* Crypto backend specific signature class. */
+ unsigned int sig_class;
+
+ /* Notation data and policy URLs. */
+ gpgme_sig_notation_t notations;
+
+ /* Internal to GPGME, do not use. */
+ gpgme_sig_notation_t _last_notation;
+};
+typedef struct _gpgme_key_sig *gpgme_key_sig_t;
+
+
+/* An user ID from a key. */
+struct _gpgme_user_id
+{
+ struct _gpgme_user_id *next;
+
+ /* True if the user ID is revoked. */
+ unsigned int revoked : 1;
+
+ /* True if the user ID is invalid. */
+ unsigned int invalid : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 30;
+
+ /* The validity of the user ID. */
+ gpgme_validity_t validity;
+
+ /* The user ID string. */
+ char *uid;
+
+ /* The name part of the user ID. */
+ char *name;
+
+ /* The email part of the user ID. */
+ char *email;
+
+ /* The comment part of the user ID. */
+ char *comment;
+
+ /* The signatures of the user ID. */
+ gpgme_key_sig_t signatures;
+
+ /* Internal to GPGME, do not use. */
+ gpgme_key_sig_t _last_keysig;
+};
+typedef struct _gpgme_user_id *gpgme_user_id_t;
+
+
+/* A key from the keyring. */
+struct _gpgme_key
+{
+ /* Internal to GPGME, do not use. */
+ unsigned int _refs;
+
+ /* True if key is revoked. */
+ unsigned int revoked : 1;
+
+ /* True if key is expired. */
+ unsigned int expired : 1;
+
+ /* True if key is disabled. */
+ unsigned int disabled : 1;
+
+ /* True if key is invalid. */
+ unsigned int invalid : 1;
+
+ /* True if key can be used for encryption. */
+ unsigned int can_encrypt : 1;
+
+ /* True if key can be used for signing. */
+ unsigned int can_sign : 1;
+
+ /* True if key can be used for certification. */
+ unsigned int can_certify : 1;
+
+ /* True if key is secret. */
+ unsigned int secret : 1;
+
+ /* True if key can be used for authentication. */
+ unsigned int can_authenticate : 1;
+
+ /* True if subkey is qualified for signatures according to German law. */
+ unsigned int is_qualified : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 22;
+
+ /* This is the protocol supported by this key. */
+ gpgme_protocol_t protocol;
+
+ /* If protocol is GPGME_PROTOCOL_CMS, this string contains the
+ issuer serial. */
+ char *issuer_serial;
+
+ /* If protocol is GPGME_PROTOCOL_CMS, this string contains the
+ issuer name. */
+ char *issuer_name;
+
+ /* If protocol is GPGME_PROTOCOL_CMS, this string contains the chain
+ ID. */
+ char *chain_id;
+
+ /* If protocol is GPGME_PROTOCOL_OpenPGP, this field contains the
+ owner trust. */
+ gpgme_validity_t owner_trust;
+
+ /* The subkeys of the key. */
+ gpgme_subkey_t subkeys;
+
+ /* The user IDs of the key. */
+ gpgme_user_id_t uids;
+
+ /* Internal to GPGME, do not use. */
+ gpgme_subkey_t _last_subkey;
+
+ /* Internal to GPGME, do not use. */
+ gpgme_user_id_t _last_uid;
+
+ /* The keylist mode that was active when listing the key. */
+ gpgme_keylist_mode_t keylist_mode;
+};
+typedef struct _gpgme_key *gpgme_key_t;
+
+
+
+/* Types for callback functions. */
+
+/* Request a passphrase from the user. */
+typedef gpgme_error_t (*gpgme_passphrase_cb_t) (void *hook,
+ const char *uid_hint,
+ const char *passphrase_info,
+ int prev_was_bad, int fd);
+
+/* Inform the user about progress made. */
+typedef void (*gpgme_progress_cb_t) (void *opaque, const char *what,
+ int type, int current, int total);
+
+/* Interact with the user about an edit operation. */
+typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
+ gpgme_status_code_t status,
+ const char *args, int fd);
+
+
+/* Context management functions. */
+
+/* Create a new context and return it in CTX. */
+gpgme_error_t gpgme_new (gpgme_ctx_t *ctx);
+
+/* Release the context CTX. */
+void gpgme_release (gpgme_ctx_t ctx);
+
+/* Set the protocol to be used by CTX to PROTO. */
+gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto);
+
+/* Get the protocol used with CTX */
+gpgme_protocol_t gpgme_get_protocol (gpgme_ctx_t ctx);
+
+/* Get the string describing protocol PROTO, or NULL if invalid. */
+const char *gpgme_get_protocol_name (gpgme_protocol_t proto);
+
+/* If YES is non-zero, enable armor mode in CTX, disable it otherwise. */
+void gpgme_set_armor (gpgme_ctx_t ctx, int yes);
+
+/* Return non-zero if armor mode is set in CTX. */
+int gpgme_get_armor (gpgme_ctx_t ctx);
+
+/* If YES is non-zero, enable text mode in CTX, disable it otherwise. */
+void gpgme_set_textmode (gpgme_ctx_t ctx, int yes);
+
+/* Return non-zero if text mode is set in CTX. */
+int gpgme_get_textmode (gpgme_ctx_t ctx);
+
+/* Use whatever the default of the backend crypto engine is. */
+#define GPGME_INCLUDE_CERTS_DEFAULT -256
+
+/* Include up to NR_OF_CERTS certificates in an S/MIME message. */
+void gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs);
+
+/* Return the number of certs to include in an S/MIME message. */
+int gpgme_get_include_certs (gpgme_ctx_t ctx);
+
+/* Set keylist mode in CTX to MODE. */
+gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t ctx,
+ gpgme_keylist_mode_t mode);
+
+/* Get keylist mode in CTX. */
+gpgme_keylist_mode_t gpgme_get_keylist_mode (gpgme_ctx_t ctx);
+
+/* Set the passphrase callback function in CTX to CB. HOOK_VALUE is
+ passed as first argument to the passphrase callback function. */
+void gpgme_set_passphrase_cb (gpgme_ctx_t ctx,
+ gpgme_passphrase_cb_t cb, void *hook_value);
+
+/* Get the current passphrase callback function in *CB and the current
+ hook value in *HOOK_VALUE. */
+void gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *cb,
+ void **hook_value);
+
+/* Set the progress callback function in CTX to CB. HOOK_VALUE is
+ passed as first argument to the progress callback function. */
+void gpgme_set_progress_cb (gpgme_ctx_t c, gpgme_progress_cb_t cb,
+ void *hook_value);
+
+/* Get the current progress callback function in *CB and the current
+ hook value in *HOOK_VALUE. */
+void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
+ void **hook_value);
+
+/* This function sets the locale for the context CTX, or the default
+ locale if CTX is a null pointer. */
+gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category,
+ const char *value);
+
+/* Get the information about the configured engines. A pointer to the
+ first engine in the statically allocated linked list is returned.
+ The returned data is valid until the next gpgme_ctx_set_engine_info. */
+gpgme_engine_info_t gpgme_ctx_get_engine_info (gpgme_ctx_t ctx);
+
+/* Set the engine info for the context CTX, protocol PROTO, to the
+ file name FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
+ gpgme_protocol_t proto,
+ const char *file_name,
+ const char *home_dir);
+
+
+/* Return a statically allocated string with the name of the public
+ key algorithm ALGO, or NULL if that name is not known. */
+const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo);
+
+/* Return a statically allocated string with the name of the hash
+ algorithm ALGO, or NULL if that name is not known. */
+const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo);
+
+
+/* Delete all signers from CTX. */
+void gpgme_signers_clear (gpgme_ctx_t ctx);
+
+/* Add KEY to list of signers in CTX. */
+gpgme_error_t gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key);
+
+/* Return the SETQth signer's key in CTX. */
+gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq);
+
+/* Retrieve the signature status of signature IDX in CTX after a
+ successful verify operation in R_STAT (if non-null). The creation
+ time stamp of the signature is returned in R_CREATED (if non-null).
+ The function returns a string containing the fingerprint.
+ Deprecated, use verify result directly. */
+const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
+ _gpgme_sig_stat_t *r_stat,
+ time_t *r_created) _GPGME_DEPRECATED;
+
+/* Retrieve certain attributes of a signature. IDX is the index
+ number of the signature after a successful verify operation. WHAT
+ is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
+ one. WHATIDX is to be passed as 0 for most attributes . */
+unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx,
+ _gpgme_attr_t what, int whatidx)
+ _GPGME_DEPRECATED;
+const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx,
+ _gpgme_attr_t what, int whatidx)
+ _GPGME_DEPRECATED;
+
+
+/* Get the key used to create signature IDX in CTX and return it in
+ R_KEY. */
+gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
+ _GPGME_DEPRECATED;
+
+
+/* Clear all notation data from the context. */
+void gpgme_sig_notation_clear (gpgme_ctx_t ctx);
+
+/* Add the human-readable notation data with name NAME and value VALUE
+ to the context CTX, using the flags FLAGS. If NAME is NULL, then
+ VALUE should be a policy URL. The flag
+ GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
+ data, and false for policy URLs. */
+gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
+ const char *value,
+ gpgme_sig_notation_flags_t flags);
+
+/* Get the sig notations for this context. */
+gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx);
+
+
+/* Run control. */
+
+/* The type of an I/O callback function. */
+typedef gpgme_error_t (*gpgme_io_cb_t) (void *data, int fd);
+
+/* The type of a function that can register FNC as the I/O callback
+ function for the file descriptor FD with direction dir (0: for writing,
+ 1: for reading). FNC_DATA should be passed as DATA to FNC. The
+ function should return a TAG suitable for the corresponding
+ gpgme_remove_io_cb_t, and an error value. */
+typedef gpgme_error_t (*gpgme_register_io_cb_t) (void *data, int fd, int dir,
+ gpgme_io_cb_t fnc,
+ void *fnc_data, void **tag);
+
+/* The type of a function that can remove a previously registered I/O
+ callback function given TAG as returned by the register
+ function. */
+typedef void (*gpgme_remove_io_cb_t) (void *tag);
+
+typedef enum
+ {
+ GPGME_EVENT_START,
+ GPGME_EVENT_DONE,
+ GPGME_EVENT_NEXT_KEY,
+ GPGME_EVENT_NEXT_TRUSTITEM
+ }
+gpgme_event_io_t;
+
+/* The type of a function that is called when a context finished an
+ operation. */
+typedef void (*gpgme_event_io_cb_t) (void *data, gpgme_event_io_t type,
+ void *type_data);
+
+struct gpgme_io_cbs
+{
+ gpgme_register_io_cb_t add;
+ void *add_priv;
+ gpgme_remove_io_cb_t remove;
+ gpgme_event_io_cb_t event;
+ void *event_priv;
+};
+typedef struct gpgme_io_cbs *gpgme_io_cbs_t;
+
+/* Set the I/O callback functions in CTX to IO_CBS. */
+void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
+
+/* Get the current I/O callback functions. */
+void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
+
+/* Process the pending operation and, if HANG is non-zero, wait for
+ the pending operation to finish. */
+gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang);
+
+
+/* Functions to handle data objects. */
+
+/* Read up to SIZE bytes into buffer BUFFER from the data object with
+ the handle HANDLE. Return the number of characters read, 0 on EOF
+ and -1 on error. If an error occurs, errno is set. */
+typedef ssize_t (*gpgme_data_read_cb_t) (void *handle, void *buffer,
+ size_t size);
+
+/* Write up to SIZE bytes from buffer BUFFER to the data object with
+ the handle HANDLE. Return the number of characters written, or -1
+ on error. If an error occurs, errno is set. */
+typedef ssize_t (*gpgme_data_write_cb_t) (void *handle, const void *buffer,
+ size_t size);
+
+/* Set the current position from where the next read or write starts
+ in the data object with the handle HANDLE to OFFSET, relativ to
+ WHENCE. */
+typedef off_t (*gpgme_data_seek_cb_t) (void *handle, off_t offset, int whence);
+
+/* Close the data object with the handle DL. */
+typedef void (*gpgme_data_release_cb_t) (void *handle);
+
+struct gpgme_data_cbs
+{
+ gpgme_data_read_cb_t read;
+ gpgme_data_write_cb_t write;
+ gpgme_data_seek_cb_t seek;
+ gpgme_data_release_cb_t release;
+};
+typedef struct gpgme_data_cbs *gpgme_data_cbs_t;
+
+/* Read up to SIZE bytes into buffer BUFFER from the data object with
+ the handle DH. Return the number of characters read, 0 on EOF and
+ -1 on error. If an error occurs, errno is set. */
+ssize_t gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size);
+
+/* Write up to SIZE bytes from buffer BUFFER to the data object with
+ the handle DH. Return the number of characters written, or -1 on
+ error. If an error occurs, errno is set. */
+ssize_t gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size);
+
+/* Set the current position from where the next read or write starts
+ in the data object with the handle DH to OFFSET, relativ to
+ WHENCE. */
+off_t gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence);
+
+/* Create a new data buffer and return it in R_DH. */
+gpgme_error_t gpgme_data_new (gpgme_data_t *r_dh);
+
+/* Destroy the data buffer DH. */
+void gpgme_data_release (gpgme_data_t dh);
+
+/* Create a new data buffer filled with SIZE bytes starting from
+ BUFFER. If COPY is zero, copying is delayed until necessary, and
+ the data is taken from the original location when needed. */
+gpgme_error_t gpgme_data_new_from_mem (gpgme_data_t *r_dh,
+ const char *buffer, size_t size,
+ int copy);
+
+/* Destroy the data buffer DH and return a pointer to its content.
+ The memory has be to released with gpgme_free() by the user. It's
+ size is returned in R_LEN. */
+char *gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len);
+
+/* Release the memory returned by gpgme_data_release_and_get_mem(). */
+void gpgme_free (void *buffer);
+
+gpgme_error_t gpgme_data_new_from_cbs (gpgme_data_t *dh,
+ gpgme_data_cbs_t cbs,
+ void *handle);
+
+gpgme_error_t gpgme_data_new_from_fd (gpgme_data_t *dh, int fd);
+
+gpgme_error_t gpgme_data_new_from_stream (gpgme_data_t *dh, FILE *stream);
+
+/* Return the encoding attribute of the data buffer DH */
+gpgme_data_encoding_t gpgme_data_get_encoding (gpgme_data_t dh);
+
+/* Set the encoding attribute of data buffer DH to ENC */
+gpgme_error_t gpgme_data_set_encoding (gpgme_data_t dh,
+ gpgme_data_encoding_t enc);
+
+/* Get the file name associated with the data object with handle DH, or
+ NULL if there is none. */
+char *gpgme_data_get_file_name (gpgme_data_t dh);
+
+/* Set the file name associated with the data object with handle DH to
+ FILE_NAME. */
+gpgme_error_t gpgme_data_set_file_name (gpgme_data_t dh,
+ const char *file_name);
+
+
+/* Create a new data buffer which retrieves the data from the callback
+ function READ_CB. Deprecated, please use gpgme_data_new_from_cbs
+ instead. */
+gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
+ int (*read_cb) (void*,char *,
+ size_t,size_t*),
+ void *read_cb_value)
+ _GPGME_DEPRECATED;
+
+/* Create a new data buffer filled with the content of file FNAME.
+ COPY must be non-zero. For delayed read, please use
+ gpgme_data_new_from_fd or gpgme_data_new_from stream instead. */
+gpgme_error_t gpgme_data_new_from_file (gpgme_data_t *r_dh,
+ const char *fname,
+ int copy);
+
+/* Create a new data buffer filled with LENGTH bytes starting from
+ OFFSET within the file FNAME or stream FP (exactly one must be
+ non-zero). */
+gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh,
+ const char *fname, FILE *fp,
+ off_t offset, size_t length);
+
+/* Reset the read pointer in DH. Deprecated, please use
+ gpgme_data_seek instead. */
+gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED;
+
+
+/* Key and trust functions. */
+
+/* Get the key with the fingerprint FPR from the crypto backend. If
+ SECRET is true, get the secret key. */
+gpgme_error_t gpgme_get_key (gpgme_ctx_t ctx, const char *fpr,
+ gpgme_key_t *r_key, int secret);
+
+/* Acquire a reference to KEY. */
+void gpgme_key_ref (gpgme_key_t key);
+
+/* Release a reference to KEY. If this was the last one the key is
+ destroyed. */
+void gpgme_key_unref (gpgme_key_t key);
+void gpgme_key_release (gpgme_key_t key);
+
+/* Return the value of the attribute WHAT of KEY, which has to be
+ representable by a string. IDX specifies the sub key or user ID
+ for attributes related to sub keys or user IDs. Deprecated, use
+ key structure directly instead. */
+const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+/* Return the value of the attribute WHAT of KEY, which has to be
+ representable by an unsigned integer. IDX specifies the sub key or
+ user ID for attributes related to sub keys or user IDs.
+ Deprecated, use key structure directly instead. */
+unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+/* Return the value of the attribute WHAT of a signature on user ID
+ UID_IDX in KEY, which has to be representable by a string. IDX
+ specifies the signature. Deprecated, use key structure directly
+ instead. */
+const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
+ _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+/* Return the value of the attribute WHAT of a signature on user ID
+ UID_IDX in KEY, which has to be representable by an unsigned
+ integer string. IDX specifies the signature. Deprecated, use key
+ structure directly instead. */
+unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx,
+ _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+
+/* Crypto Operations. */
+
+/* Cancel a pending asynchronous operation. */
+gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx);
+
+
+struct _gpgme_invalid_key
+{
+ struct _gpgme_invalid_key *next;
+ char *fpr;
+ gpgme_error_t reason;
+};
+typedef struct _gpgme_invalid_key *gpgme_invalid_key_t;
+
+
+/* Encryption. */
+struct _gpgme_op_encrypt_result
+{
+ /* The list of invalid recipients. */
+ gpgme_invalid_key_t invalid_recipients;
+};
+typedef struct _gpgme_op_encrypt_result *gpgme_encrypt_result_t;
+
+/* Retrieve a pointer to the result of the encrypt operation. */
+gpgme_encrypt_result_t gpgme_op_encrypt_result (gpgme_ctx_t ctx);
+
+/* The valid encryption flags. */
+typedef enum
+ {
+ GPGME_ENCRYPT_ALWAYS_TRUST = 1
+ }
+gpgme_encrypt_flags_t;
+
+/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
+ store the resulting ciphertext in CIPHER. */
+gpgme_error_t gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher);
+gpgme_error_t gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher);
+
+/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
+ store the resulting ciphertext in CIPHER. Also sign the ciphertext
+ with the signers in CTX. */
+gpgme_error_t gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx,
+ gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain,
+ gpgme_data_t cipher);
+gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t cipher);
+
+
+/* Decryption. */
+
+struct _gpgme_recipient
+{
+ struct _gpgme_recipient *next;
+
+ /* The key ID of key for which the text was encrypted. */
+ char *keyid;
+
+ /* Internal to GPGME, do not use. */
+ char _keyid[16 + 1];
+
+ /* The public key algorithm of the recipient key. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The status of the recipient. */
+ gpgme_error_t status;
+};
+typedef struct _gpgme_recipient *gpgme_recipient_t;
+
+struct _gpgme_op_decrypt_result
+{
+ char *unsupported_algorithm;
+
+ /* Key should not have been used for encryption. */
+ unsigned int wrong_key_usage : 1;
+
+ /* Internal to GPGME, do not use. */
+ int _unused : 31;
+
+ gpgme_recipient_t recipients;
+
+ /* The original file name of the plaintext message, if
+ available. */
+ char *file_name;
+};
+typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t;
+
+/* Retrieve a pointer to the result of the decrypt operation. */
+gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx);
+
+/* Decrypt ciphertext CIPHER within CTX and store the resulting
+ plaintext in PLAIN. */
+gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
+ gpgme_data_t plain);
+gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx,
+ gpgme_data_t cipher, gpgme_data_t plain);
+
+/* Decrypt ciphertext CIPHER and make a signature verification within
+ CTX and store the resulting plaintext in PLAIN. */
+gpgme_error_t gpgme_op_decrypt_verify_start (gpgme_ctx_t ctx,
+ gpgme_data_t cipher,
+ gpgme_data_t plain);
+gpgme_error_t gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher,
+ gpgme_data_t plain);
+
+
+/* Signing. */
+struct _gpgme_new_signature
+{
+ struct _gpgme_new_signature *next;
+
+ /* The type of the signature. */
+ gpgme_sig_mode_t type;
+
+ /* The public key algorithm used to create the signature. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The hash algorithm used to create the signature. */
+ gpgme_hash_algo_t hash_algo;
+
+ /* Internal to GPGME, do not use. Must be set to the same value as
+ CLASS below. */
+ unsigned long _obsolete_class;
+
+ /* Signature creation time. */
+ long int timestamp;
+
+ /* The fingerprint of the signature. */
+ char *fpr;
+
+#ifdef __cplusplus
+ unsigned int _obsolete_class_2;
+#else
+ /* Must be set to SIG_CLASS below. */
+ unsigned int class _GPGME_DEPRECATED;
+#endif
+
+ /* Crypto backend specific signature class. */
+ unsigned int sig_class;
+};
+typedef struct _gpgme_new_signature *gpgme_new_signature_t;
+
+struct _gpgme_op_sign_result
+{
+ /* The list of invalid signers. */
+ gpgme_invalid_key_t invalid_signers;
+ gpgme_new_signature_t signatures;
+};
+typedef struct _gpgme_op_sign_result *gpgme_sign_result_t;
+
+/* Retrieve a pointer to the result of the signing operation. */
+gpgme_sign_result_t gpgme_op_sign_result (gpgme_ctx_t ctx);
+
+/* Sign the plaintext PLAIN and store the signature in SIG. */
+gpgme_error_t gpgme_op_sign_start (gpgme_ctx_t ctx,
+ gpgme_data_t plain, gpgme_data_t sig,
+ gpgme_sig_mode_t mode);
+gpgme_error_t gpgme_op_sign (gpgme_ctx_t ctx,
+ gpgme_data_t plain, gpgme_data_t sig,
+ gpgme_sig_mode_t mode);
+
+
+/* Verify. */
+
+/* Flags used for the SUMMARY field in a gpgme_signature_t. */
+typedef enum
+ {
+ GPGME_SIGSUM_VALID = 0x0001, /* The signature is fully valid. */
+ GPGME_SIGSUM_GREEN = 0x0002, /* The signature is good. */
+ GPGME_SIGSUM_RED = 0x0004, /* The signature is bad. */
+ GPGME_SIGSUM_KEY_REVOKED = 0x0010, /* One key has been revoked. */
+ GPGME_SIGSUM_KEY_EXPIRED = 0x0020, /* One key has expired. */
+ GPGME_SIGSUM_SIG_EXPIRED = 0x0040, /* The signature has expired. */
+ GPGME_SIGSUM_KEY_MISSING = 0x0080, /* Can't verify: key missing. */
+ GPGME_SIGSUM_CRL_MISSING = 0x0100, /* CRL not available. */
+ GPGME_SIGSUM_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */
+ GPGME_SIGSUM_BAD_POLICY = 0x0400, /* A policy was not met. */
+ GPGME_SIGSUM_SYS_ERROR = 0x0800 /* A system error occured. */
+ }
+gpgme_sigsum_t;
+
+struct _gpgme_signature
+{
+ struct _gpgme_signature *next;
+
+ /* A summary of the signature status. */
+ gpgme_sigsum_t summary;
+
+ /* The fingerprint or key ID of the signature. */
+ char *fpr;
+
+ /* The status of the signature. */
+ gpgme_error_t status;
+
+ /* Notation data and policy URLs. */
+ gpgme_sig_notation_t notations;
+
+ /* Signature creation time. */
+ unsigned long timestamp;
+
+ /* Signature exipration time or 0. */
+ unsigned long exp_timestamp;
+
+ /* Key should not have been used for signing. */
+ unsigned int wrong_key_usage : 1;
+
+ /* PKA status: 0 = not available, 1 = bad, 2 = okay, 3 = RFU. */
+ unsigned int pka_trust : 2;
+
+ /* Internal to GPGME, do not use. */
+ int _unused : 29;
+
+ gpgme_validity_t validity;
+ gpgme_error_t validity_reason;
+
+ /* The public key algorithm used to create the signature. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The hash algorithm used to create the signature. */
+ gpgme_hash_algo_t hash_algo;
+
+ /* The mailbox from the PKA information or NULL. */
+ char *pka_address;
+};
+typedef struct _gpgme_signature *gpgme_signature_t;
+
+struct _gpgme_op_verify_result
+{
+ gpgme_signature_t signatures;
+
+ /* The original file name of the plaintext message, if
+ available. */
+ char *file_name;
+};
+typedef struct _gpgme_op_verify_result *gpgme_verify_result_t;
+
+/* Retrieve a pointer to the result of the verify operation. */
+gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx);
+
+/* Verify within CTX that SIG is a valid signature for TEXT. */
+gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
+ gpgme_data_t signed_text,
+ gpgme_data_t plaintext);
+gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig,
+ gpgme_data_t signed_text,
+ gpgme_data_t plaintext);
+
+
+/* Import. */
+
+/* The key was new. */
+#define GPGME_IMPORT_NEW 1
+
+/* The key contained new user IDs. */
+#define GPGME_IMPORT_UID 2
+
+/* The key contained new signatures. */
+#define GPGME_IMPORT_SIG 4
+
+/* The key contained new sub keys. */
+#define GPGME_IMPORT_SUBKEY 8
+
+/* The key contained a secret key. */
+#define GPGME_IMPORT_SECRET 16
+
+
+struct _gpgme_import_status
+{
+ struct _gpgme_import_status *next;
+
+ /* Fingerprint. */
+ char *fpr;
+
+ /* If a problem occured, the reason why the key could not be
+ imported. Otherwise GPGME_No_Error. */
+ gpgme_error_t result;
+
+ /* The result of the import, the GPGME_IMPORT_* values bit-wise
+ ORed. 0 means the key was already known and no new components
+ have been added. */
+ unsigned int status;
+};
+typedef struct _gpgme_import_status *gpgme_import_status_t;
+
+/* Import. */
+struct _gpgme_op_import_result
+{
+ /* Number of considered keys. */
+ int considered;
+
+ /* Keys without user ID. */
+ int no_user_id;
+
+ /* Imported keys. */
+ int imported;
+
+ /* Imported RSA keys. */
+ int imported_rsa;
+
+ /* Unchanged keys. */
+ int unchanged;
+
+ /* Number of new user ids. */
+ int new_user_ids;
+
+ /* Number of new sub keys. */
+ int new_sub_keys;
+
+ /* Number of new signatures. */
+ int new_signatures;
+
+ /* Number of new revocations. */
+ int new_revocations;
+
+ /* Number of secret keys read. */
+ int secret_read;
+
+ /* Number of secret keys imported. */
+ int secret_imported;
+
+ /* Number of secret keys unchanged. */
+ int secret_unchanged;
+
+ /* Number of new keys skipped. */
+ int skipped_new_keys;
+
+ /* Number of keys not imported. */
+ int not_imported;
+
+ /* List of keys for which an import was attempted. */
+ gpgme_import_status_t imports;
+};
+typedef struct _gpgme_op_import_result *gpgme_import_result_t;
+
+/* Retrieve a pointer to the result of the import operation. */
+gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx);
+
+/* Import the key in KEYDATA into the keyring. */
+gpgme_error_t gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata);
+gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata);
+gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata,
+ int *nr) _GPGME_DEPRECATED;
+
+
+/* Export the keys found by PATTERN into KEYDATA. */
+gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
+ unsigned int reserved,
+ gpgme_data_t keydata);
+gpgme_error_t gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
+ unsigned int reserved, gpgme_data_t keydata);
+
+gpgme_error_t gpgme_op_export_ext_start (gpgme_ctx_t ctx,
+ const char *pattern[],
+ unsigned int reserved,
+ gpgme_data_t keydata);
+gpgme_error_t gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
+ unsigned int reserved,
+ gpgme_data_t keydata);
+
+
+/* Key generation. */
+struct _gpgme_op_genkey_result
+{
+ /* A primary key was generated. */
+ unsigned int primary : 1;
+
+ /* A sub key was generated. */
+ unsigned int sub : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 30;
+
+ /* The fingerprint of the generated key. */
+ char *fpr;
+};
+typedef struct _gpgme_op_genkey_result *gpgme_genkey_result_t;
+
+/* Generate a new keypair and add it to the keyring. PUBKEY and
+ SECKEY should be null for now. PARMS specifies what keys should be
+ generated. */
+gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
+ gpgme_data_t pubkey, gpgme_data_t seckey);
+gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms,
+ gpgme_data_t pubkey, gpgme_data_t seckey);
+
+/* Retrieve a pointer to the result of the genkey operation. */
+gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx);
+
+
+/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
+ keys are also deleted. */
+gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
+ int allow_secret);
+gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key,
+ int allow_secret);
+
+
+/* Edit the key KEY. Send status and command requests to FNC and
+ output of edit commands to OUT. */
+gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out);
+gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out);
+
+/* Edit the card for the key KEY. Send status and command requests to
+ FNC and output of edit commands to OUT. */
+gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out);
+gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out);
+
+
+/* Key management functions. */
+struct _gpgme_op_keylist_result
+{
+ unsigned int truncated : 1;
+
+ /* Internal to GPGME, do not use. */
+ unsigned int _unused : 31;
+};
+typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t;
+
+/* Retrieve a pointer to the result of the key listing operation. */
+gpgme_keylist_result_t gpgme_op_keylist_result (gpgme_ctx_t ctx);
+
+/* Start a keylist operation within CTX, searching for keys which
+ match PATTERN. If SECRET_ONLY is true, only secret keys are
+ returned. */
+gpgme_error_t gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern,
+ int secret_only);
+gpgme_error_t gpgme_op_keylist_ext_start (gpgme_ctx_t ctx,
+ const char *pattern[],
+ int secret_only, int reserved);
+
+/* Return the next key from the keylist in R_KEY. */
+gpgme_error_t gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key);
+
+/* Terminate a pending keylist operation within CTX. */
+gpgme_error_t gpgme_op_keylist_end (gpgme_ctx_t ctx);
+
+
+/* Trust items and operations. */
+
+struct _gpgme_trust_item
+{
+ /* Internal to GPGME, do not use. */
+ unsigned int _refs;
+
+ /* The key ID to which the trust item belongs. */
+ char *keyid;
+
+ /* Internal to GPGME, do not use. */
+ char _keyid[16 + 1];
+
+ /* The type of the trust item, 1 refers to a key, 2 to a user ID. */
+ int type;
+
+ /* The trust level. */
+ int level;
+
+ /* The owner trust if TYPE is 1. */
+ char *owner_trust;
+
+ /* Internal to GPGME, do not use. */
+ char _owner_trust[2];
+
+ /* The calculated validity. */
+ char *validity;
+
+ /* Internal to GPGME, do not use. */
+ char _validity[2];
+
+ /* The user name if TYPE is 2. */
+ char *name;
+};
+typedef struct _gpgme_trust_item *gpgme_trust_item_t;
+
+/* Start a trustlist operation within CTX, searching for trust items
+ which match PATTERN. */
+gpgme_error_t gpgme_op_trustlist_start (gpgme_ctx_t ctx,
+ const char *pattern, int max_level);
+
+/* Return the next trust item from the trustlist in R_ITEM. */
+gpgme_error_t gpgme_op_trustlist_next (gpgme_ctx_t ctx,
+ gpgme_trust_item_t *r_item);
+
+/* Terminate a pending trustlist operation within CTX. */
+gpgme_error_t gpgme_op_trustlist_end (gpgme_ctx_t ctx);
+
+/* Acquire a reference to ITEM. */
+void gpgme_trust_item_ref (gpgme_trust_item_t item);
+
+/* Release a reference to ITEM. If this was the last one the trust
+ item is destroyed. */
+void gpgme_trust_item_unref (gpgme_trust_item_t item);
+
+/* Release the trust item ITEM. Deprecated, use
+ gpgme_trust_item_unref. */
+void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED;
+
+/* Return the value of the attribute WHAT of ITEM, which has to be
+ representable by a string. Deprecated, use trust item structure
+ directly. */
+const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item,
+ _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+/* Return the value of the attribute WHAT of KEY, which has to be
+ representable by an integer. IDX specifies a running index if the
+ attribute appears more than once in the key. Deprecated, use trust
+ item structure directly. */
+int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
+ const void *reserved, int idx)
+ _GPGME_DEPRECATED;
+
+
+/* Various functions. */
+
+/* Check that the library fulfills the version requirement. */
+const char *gpgme_check_version (const char *req_version);
+
+/* Get the information about the configured and installed engines. A
+ pointer to the first engine in the statically allocated linked list
+ is returned in *INFO. If an error occurs, it is returned. The
+ returned data is valid until the next gpgme_set_engine_info. */
+gpgme_error_t gpgme_get_engine_info (gpgme_engine_info_t *engine_info);
+
+/* Set the default engine info for the protocol PROTO to the file name
+ FILE_NAME and the home directory HOME_DIR. */
+gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto,
+ const char *file_name,
+ const char *home_dir);
+
+
+/* Engine support functions. */
+
+/* Verify that the engine implementing PROTO is installed and
+ available. */
+gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto);
+
+
+/* Deprecated types. */
+typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED;
+typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED;
+typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED;
+typedef gpgme_data_encoding_t GpgmeDataEncoding _GPGME_DEPRECATED;
+typedef gpgme_pubkey_algo_t GpgmePubKeyAlgo _GPGME_DEPRECATED;
+typedef gpgme_hash_algo_t GpgmeHashAlgo _GPGME_DEPRECATED;
+typedef gpgme_sig_stat_t GpgmeSigStat _GPGME_DEPRECATED;
+typedef gpgme_sig_mode_t GpgmeSigMode _GPGME_DEPRECATED;
+typedef gpgme_attr_t GpgmeAttr _GPGME_DEPRECATED;
+typedef gpgme_validity_t GpgmeValidity _GPGME_DEPRECATED;
+typedef gpgme_protocol_t GpgmeProtocol _GPGME_DEPRECATED;
+typedef gpgme_engine_info_t GpgmeEngineInfo _GPGME_DEPRECATED;
+typedef gpgme_subkey_t GpgmeSubkey _GPGME_DEPRECATED;
+typedef gpgme_key_sig_t GpgmeKeySig _GPGME_DEPRECATED;
+typedef gpgme_user_id_t GpgmeUserID _GPGME_DEPRECATED;
+typedef gpgme_key_t GpgmeKey _GPGME_DEPRECATED;
+typedef gpgme_passphrase_cb_t GpgmePassphraseCb _GPGME_DEPRECATED;
+typedef gpgme_progress_cb_t GpgmeProgressCb _GPGME_DEPRECATED;
+typedef gpgme_io_cb_t GpgmeIOCb _GPGME_DEPRECATED;
+typedef gpgme_register_io_cb_t GpgmeRegisterIOCb _GPGME_DEPRECATED;
+typedef gpgme_remove_io_cb_t GpgmeRemoveIOCb _GPGME_DEPRECATED;
+typedef gpgme_event_io_t GpgmeEventIO _GPGME_DEPRECATED;
+typedef gpgme_event_io_cb_t GpgmeEventIOCb _GPGME_DEPRECATED;
+#define GpgmeIOCbs gpgme_io_cbs
+typedef gpgme_data_read_cb_t GpgmeDataReadCb _GPGME_DEPRECATED;
+typedef gpgme_data_write_cb_t GpgmeDataWriteCb _GPGME_DEPRECATED;
+typedef gpgme_data_seek_cb_t GpgmeDataSeekCb _GPGME_DEPRECATED;
+typedef gpgme_data_release_cb_t GpgmeDataReleaseCb _GPGME_DEPRECATED;
+#define GpgmeDataCbs gpgme_data_cbs
+typedef gpgme_encrypt_result_t GpgmeEncryptResult _GPGME_DEPRECATED;
+typedef gpgme_sig_notation_t GpgmeSigNotation _GPGME_DEPRECATED;
+typedef gpgme_signature_t GpgmeSignature _GPGME_DEPRECATED;
+typedef gpgme_verify_result_t GpgmeVerifyResult _GPGME_DEPRECATED;
+typedef gpgme_import_status_t GpgmeImportqStatus _GPGME_DEPRECATED;
+typedef gpgme_import_result_t GpgmeImportResult _GPGME_DEPRECATED;
+typedef gpgme_genkey_result_t GpgmeGenKeyResult _GPGME_DEPRECATED;
+typedef gpgme_trust_item_t GpgmeTrustItem _GPGME_DEPRECATED;
+typedef gpgme_status_code_t GpgmeStatusCode _GPGME_DEPRECATED;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GPGME_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/import.c b/libtdenetwork/libgpgme-copy/gpgme/import.c
new file mode 100644
index 000000000..03967f745
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/import.c
@@ -0,0 +1,273 @@
+/* import.c - Import a key.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_import_result result;
+
+ /* A pointer to the next pointer of the last import status in the
+ list. This makes appending new imports painless while preserving
+ the order. */
+ gpgme_import_status_t *lastp;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+ gpgme_import_status_t import = opd->result.imports;
+
+ while (import)
+ {
+ gpgme_import_status_t next = import->next;
+ free (import->fpr);
+ free (import);
+ import = next;
+ }
+}
+
+
+gpgme_import_result_t
+gpgme_op_import_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+static gpgme_error_t
+parse_import (char *args, gpgme_import_status_t *import_status, int problem)
+{
+ gpgme_import_status_t import;
+ char *tail;
+ long int nr;
+
+ import = malloc (sizeof (*import));
+ if (!import)
+ return gpg_error_from_errno (errno);
+ import->next = NULL;
+
+ errno = 0;
+ nr = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (import);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ args = tail;
+
+ if (problem)
+ {
+ switch (nr)
+ {
+ case 0:
+ case 4:
+ default:
+ import->result = gpg_error (GPG_ERR_GENERAL);
+ break;
+
+ case 1:
+ import->result = gpg_error (GPG_ERR_BAD_CERT);
+ break;
+
+ case 2:
+ import->result = gpg_error (GPG_ERR_MISSING_CERT);
+ break;
+
+ case 3:
+ import->result = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
+ break;
+ }
+ import->status = 0;
+ }
+ else
+ {
+ import->result = gpg_error (GPG_ERR_NO_ERROR);
+ import->status = nr;
+ }
+
+ while (*args == ' ')
+ args++;
+ tail = strchr (args, ' ');
+ if (tail)
+ *tail = '\0';
+
+ import->fpr = strdup (args);
+ if (!import->fpr)
+ {
+ int saved_errno = errno;
+ free (import);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ *import_status = import;
+ return 0;
+}
+
+
+
+gpgme_error_t
+parse_import_res (char *args, gpgme_import_result_t result)
+{
+ char *tail;
+
+ errno = 0;
+
+#define PARSE_NEXT(x) \
+ (x) = strtol (args, &tail, 0); \
+ if (errno || args == tail || *tail != ' ') \
+ /* The crypto backend does not behave. */ \
+ return gpg_error (GPG_ERR_INV_ENGINE); \
+ args = tail;
+
+ PARSE_NEXT (result->considered);
+ PARSE_NEXT (result->no_user_id);
+ PARSE_NEXT (result->imported);
+ PARSE_NEXT (result->imported_rsa);
+ PARSE_NEXT (result->unchanged);
+ PARSE_NEXT (result->new_user_ids);
+ PARSE_NEXT (result->new_sub_keys);
+ PARSE_NEXT (result->new_signatures);
+ PARSE_NEXT (result->new_revocations);
+ PARSE_NEXT (result->secret_read);
+ PARSE_NEXT (result->secret_imported);
+ PARSE_NEXT (result->secret_unchanged);
+ PARSE_NEXT (result->skipped_new_keys);
+ PARSE_NEXT (result->not_imported);
+
+ return 0;
+}
+
+
+static gpgme_error_t
+import_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_IMPORT_OK:
+ case GPGME_STATUS_IMPORT_PROBLEM:
+ err = parse_import (args, opd->lastp,
+ code == GPGME_STATUS_IMPORT_OK ? 0 : 1);
+ if (err)
+ return err;
+
+ opd->lastp = &(*opd->lastp)->next;
+ break;
+
+ case GPGME_STATUS_IMPORT_RES:
+ err = parse_import_res (args, &opd->result);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+_gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+ opd->lastp = &opd->result.imports;
+
+ if (!keydata)
+ return gpg_error (GPG_ERR_NO_DATA);
+
+ _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
+
+ return _gpgme_engine_op_import (ctx->engine, keydata);
+}
+
+
+gpgme_error_t
+gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata)
+{
+ return _gpgme_op_import_start (ctx, 0, keydata);
+}
+
+
+/* Import the key in KEYDATA into the keyring. */
+gpgme_error_t
+gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata)
+{
+ gpgme_error_t err = _gpgme_op_import_start (ctx, 1, keydata);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
+
+
+gpgme_error_t
+gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr)
+{
+ gpgme_error_t err = gpgme_op_import (ctx, keydata);
+ if (!err && nr)
+ {
+ gpgme_import_result_t result = gpgme_op_import_result (ctx);
+ *nr = result->considered;
+ }
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/io.h b/libtdenetwork/libgpgme-copy/gpgme/io.h
new file mode 100644
index 000000000..47b748f8b
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/io.h
@@ -0,0 +1,65 @@
+/* io.h - Interface to the I/O functions.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003 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 General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GPGME; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef IO_H
+#define IO_H
+
+/* A single file descriptor passed to spawn. For child fds, dup_to
+ specifies the fd it should become in the child. */
+struct spawn_fd_item_s
+{
+ int fd;
+ int dup_to;
+};
+
+struct io_select_fd_s
+{
+ int fd;
+ int for_read;
+ int for_write;
+ int signaled;
+ int frozen;
+ void *opaque;
+};
+
+/* These function are either defined in posix-io.c or w32-io.c. */
+void _gpgme_io_subsystem_init (void);
+int _gpgme_io_read (int fd, void *buffer, size_t count);
+int _gpgme_io_write (int fd, const void *buffer, size_t count);
+int _gpgme_io_pipe (int filedes[2], int inherit_idx);
+int _gpgme_io_close (int fd);
+int _gpgme_io_set_close_notify (int fd, void (*handler) (int, void *),
+ void *value);
+int _gpgme_io_set_nonblocking (int fd);
+
+/* Spawn the executable PATH with ARGV as arguments, after forking
+ close all fds in FD_PARENT_LIST in the parent and close or dup all
+ fds in FD_CHILD_LIST in the child. */
+int _gpgme_io_spawn (const char *path, char **argv,
+ struct spawn_fd_item_s *fd_child_list,
+ struct spawn_fd_item_s *fd_parent_list);
+int _gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal);
+int _gpgme_io_kill (int pid, int hard);
+int _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock);
+
+#endif /* IO_H */
+
+
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/isascii.c b/libtdenetwork/libgpgme-copy/gpgme/isascii.c
new file mode 100644
index 000000000..d2d73de72
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/isascii.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991,92,93,95,96,97,98,99,2001,2002,2004
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library 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.
+
+ The GNU C Library 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+int
+isascii (int c)
+{
+ return (((c) & ~0x7f) == 0);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/key.c b/libtdenetwork/libgpgme-copy/gpgme/key.c
new file mode 100644
index 000000000..d411e572d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/key.c
@@ -0,0 +1,722 @@
+/* key.c - Key objects.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "util.h"
+#include "ops.h"
+#include "sema.h"
+
+
+/* Protects all reference counters in keys. All other accesses to a
+ key are read only. */
+DEFINE_STATIC_LOCK (key_ref_lock);
+
+
+/* Create a new key. */
+gpgme_error_t
+_gpgme_key_new (gpgme_key_t *r_key)
+{
+ gpgme_key_t key;
+
+ key = calloc (1, sizeof *key);
+ if (!key)
+ return gpg_error_from_errno (errno);
+ key->_refs = 1;
+
+ *r_key = key;
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_key_add_subkey (gpgme_key_t key, gpgme_subkey_t *r_subkey)
+{
+ gpgme_subkey_t subkey;
+
+ subkey = calloc (1, sizeof *subkey);
+ if (!subkey)
+ return gpg_error_from_errno (errno);
+ subkey->keyid = subkey->_keyid;
+ subkey->_keyid[16] = '\0';
+
+ if (!key->subkeys)
+ key->subkeys = subkey;
+ if (key->_last_subkey)
+ key->_last_subkey->next = subkey;
+ key->_last_subkey = subkey;
+
+ *r_subkey = subkey;
+ return 0;
+}
+
+
+static char *
+set_user_id_part (char *tail, const char *buf, size_t len)
+{
+ while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t'))
+ len--;
+ for (; len; len--)
+ *tail++ = *buf++;
+ *tail++ = 0;
+ return tail;
+}
+
+
+static void
+parse_user_id (char *src, char **name, char **email,
+ char **comment, char *tail)
+{
+ const char *start = NULL;
+ int in_name = 0;
+ int in_email = 0;
+ int in_comment = 0;
+
+ while (*src)
+ {
+ if (in_email)
+ {
+ if (*src == '<')
+ /* Not legal but anyway. */
+ in_email++;
+ else if (*src == '>')
+ {
+ if (!--in_email && !*email)
+ {
+ *email = tail;
+ tail = set_user_id_part (tail, start, src - start);
+ }
+ }
+ }
+ else if (in_comment)
+ {
+ if (*src == '(')
+ in_comment++;
+ else if (*src == ')')
+ {
+ if (!--in_comment && !*comment)
+ {
+ *comment = tail;
+ tail = set_user_id_part (tail, start, src - start);
+ }
+ }
+ }
+ else if (*src == '<')
+ {
+ if (in_name)
+ {
+ if (!*name)
+ {
+ *name = tail;
+ tail = set_user_id_part (tail, start, src - start);
+ }
+ in_name = 0;
+ }
+ in_email = 1;
+ start = src + 1;
+ }
+ else if (*src == '(')
+ {
+ if (in_name)
+ {
+ if (!*name)
+ {
+ *name = tail;
+ tail = set_user_id_part (tail, start, src - start);
+ }
+ in_name = 0;
+ }
+ in_comment = 1;
+ start = src + 1;
+ }
+ else if (!in_name && *src != ' ' && *src != '\t')
+ {
+ in_name = 1;
+ start = src;
+ }
+ src++;
+ }
+
+ if (in_name)
+ {
+ if (!*name)
+ {
+ *name = tail;
+ tail = set_user_id_part (tail, start, src - start);
+ }
+ }
+
+ /* Let unused parts point to an EOS. */
+ tail--;
+ if (!*name)
+ *name = tail;
+ if (!*email)
+ *email = tail;
+ if (!*comment)
+ *comment = tail;
+}
+
+
+static void
+parse_x509_user_id (char *src, char **name, char **email,
+ char **comment, char *tail)
+{
+ if (*src == '<' && src[strlen (src) - 1] == '>')
+ *email = src;
+
+ /* Let unused parts point to an EOS. */
+ tail--;
+ if (!*name)
+ *name = tail;
+ if (!*email)
+ *email = tail;
+ if (!*comment)
+ *comment = tail;
+}
+
+
+/* Take a name from the --with-colon listing, remove certain escape
+ sequences sequences and put it into the list of UIDs. */
+gpgme_error_t
+_gpgme_key_append_name (gpgme_key_t key, char *src)
+{
+ gpgme_user_id_t uid;
+ char *dst;
+ int src_len = strlen (src);
+
+ assert (key);
+ /* We can malloc a buffer of the same length, because the converted
+ string will never be larger. Actually we allocate it twice the
+ size, so that we are able to store the parsed stuff there too. */
+ uid = malloc (sizeof (*uid) + 2 * src_len + 3);
+ if (!uid)
+ return gpg_error_from_errno (errno);
+ memset (uid, 0, sizeof *uid);
+
+ uid->uid = ((char *) uid) + sizeof (*uid);
+ dst = uid->uid;
+ _gpgme_decode_c_string (src, &dst, src_len + 1);
+
+ dst += strlen (dst) + 1;
+ if (key->protocol == GPGME_PROTOCOL_CMS)
+ parse_x509_user_id (uid->uid, &uid->name, &uid->email,
+ &uid->comment, dst);
+ else
+ parse_user_id (uid->uid, &uid->name, &uid->email,
+ &uid->comment, dst);
+
+ if (!key->uids)
+ key->uids = uid;
+ if (key->_last_uid)
+ key->_last_uid->next = uid;
+ key->_last_uid = uid;
+
+ return 0;
+}
+
+
+gpgme_key_sig_t
+_gpgme_key_add_sig (gpgme_key_t key, char *src)
+{
+ int src_len = src ? strlen (src) : 0;
+ gpgme_user_id_t uid;
+ gpgme_key_sig_t sig;
+
+ assert (key); /* XXX */
+
+ uid = key->_last_uid;
+ assert (uid); /* XXX */
+
+ /* We can malloc a buffer of the same length, because the converted
+ string will never be larger. Actually we allocate it twice the
+ size, so that we are able to store the parsed stuff there too. */
+ sig = malloc (sizeof (*sig) + 2 * src_len + 3);
+ if (!sig)
+ return NULL;
+ memset (sig, 0, sizeof *sig);
+
+ sig->keyid = sig->_keyid;
+ sig->_keyid[16] = '\0';
+ sig->uid = ((char *) sig) + sizeof (*sig);
+
+ if (src)
+ {
+ char *dst = sig->uid;
+ _gpgme_decode_c_string (src, &dst, src_len + 1);
+ dst += strlen (dst) + 1;
+ if (key->protocol == GPGME_PROTOCOL_CMS)
+ parse_x509_user_id (sig->uid, &sig->name, &sig->email,
+ &sig->comment, dst);
+ else
+ parse_user_id (sig->uid, &sig->name, &sig->email,
+ &sig->comment, dst);
+ }
+
+ if (!uid->signatures)
+ uid->signatures = sig;
+ if (uid->_last_keysig)
+ uid->_last_keysig->next = sig;
+ uid->_last_keysig = sig;
+
+ return sig;
+}
+
+
+/* Acquire a reference to KEY. */
+void
+gpgme_key_ref (gpgme_key_t key)
+{
+ LOCK (key_ref_lock);
+ key->_refs++;
+ UNLOCK (key_ref_lock);
+}
+
+
+/* gpgme_key_unref releases the key object. Note, that this function
+ may not do an actual release if there are other shallow copies of
+ the objects. You have to call this function for every newly
+ created key object as well as for every gpgme_key_ref() done on the
+ key object. */
+void
+gpgme_key_unref (gpgme_key_t key)
+{
+ gpgme_user_id_t uid;
+ gpgme_subkey_t subkey;
+
+ if (!key)
+ return;
+
+ LOCK (key_ref_lock);
+ assert (key->_refs > 0);
+ if (--key->_refs)
+ {
+ UNLOCK (key_ref_lock);
+ return;
+ }
+ UNLOCK (key_ref_lock);
+
+ subkey = key->subkeys;
+ while (subkey)
+ {
+ gpgme_subkey_t next = subkey->next;
+ if (subkey->fpr)
+ free (subkey->fpr);
+ free (subkey);
+ subkey = next;
+ }
+
+ uid = key->uids;
+ while (uid)
+ {
+ gpgme_user_id_t next_uid = uid->next;
+ gpgme_key_sig_t keysig = uid->signatures;
+
+ while (keysig)
+ {
+ gpgme_key_sig_t next_keysig = keysig->next;
+ gpgme_sig_notation_t notation = keysig->notations;
+
+ while (notation)
+ {
+ gpgme_sig_notation_t next_notation = notation->next;
+
+ _gpgme_sig_notation_free (notation);
+ notation = next_notation;
+ }
+
+ free (keysig);
+ keysig = next_keysig;
+ }
+ free (uid);
+ uid = next_uid;
+ }
+
+ if (key->issuer_serial)
+ free (key->issuer_serial);
+ if (key->issuer_name)
+ free (key->issuer_name);
+
+ if (key->chain_id)
+ free (key->chain_id);
+
+ free (key);
+}
+
+
+/* Compatibility interfaces. */
+
+void
+gpgme_key_release (gpgme_key_t key)
+{
+ gpgme_key_unref (key);
+}
+
+
+static const char *
+otrust_to_string (int otrust)
+{
+ switch (otrust)
+ {
+ case GPGME_VALIDITY_NEVER:
+ return "n";
+
+ case GPGME_VALIDITY_MARGINAL:
+ return "m";
+
+ case GPGME_VALIDITY_FULL:
+ return "f";
+
+ case GPGME_VALIDITY_ULTIMATE:
+ return "u";
+
+ default:
+ return "?";
+ }
+}
+
+
+static const char *
+validity_to_string (int validity)
+{
+ switch (validity)
+ {
+ case GPGME_VALIDITY_UNDEFINED:
+ return "q";
+
+ case GPGME_VALIDITY_NEVER:
+ return "n";
+
+ case GPGME_VALIDITY_MARGINAL:
+ return "m";
+
+ case GPGME_VALIDITY_FULL:
+ return "f";
+
+ case GPGME_VALIDITY_ULTIMATE:
+ return "u";
+
+ case GPGME_VALIDITY_UNKNOWN:
+ default:
+ return "?";
+ }
+}
+
+
+static const char *
+capabilities_to_string (gpgme_subkey_t subkey)
+{
+ static const char *const strings[8] =
+ {
+ "",
+ "c",
+ "s",
+ "sc",
+ "e",
+ "ec",
+ "es",
+ "esc"
+ };
+ return strings[(!!subkey->can_encrypt << 2)
+ | (!!subkey->can_sign << 1)
+ | (!!subkey->can_certify)];
+}
+
+
+/* Return the value of the attribute WHAT of ITEM, which has to be
+ representable by a string. */
+const char *
+gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ gpgme_subkey_t subkey;
+ gpgme_user_id_t uid;
+ int i;
+
+ if (!key || reserved || idx < 0)
+ return NULL;
+
+ /* Select IDXth subkey. */
+ subkey = key->subkeys;
+ for (i = 0; i < idx; i++)
+ {
+ subkey = subkey->next;
+ if (!subkey)
+ break;
+ }
+
+ /* Select the IDXth user ID. */
+ uid = key->uids;
+ for (i = 0; i < idx; i++)
+ {
+ uid = uid->next;
+ if (!uid)
+ break;
+ }
+
+ switch (what)
+ {
+ case GPGME_ATTR_KEYID:
+ return subkey ? subkey->keyid : NULL;
+
+ case GPGME_ATTR_FPR:
+ return subkey ? subkey->fpr : NULL;
+
+ case GPGME_ATTR_ALGO:
+ return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
+
+ case GPGME_ATTR_TYPE:
+ return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
+
+ case GPGME_ATTR_OTRUST:
+ return otrust_to_string (key->owner_trust);
+
+ case GPGME_ATTR_USERID:
+ return uid ? uid->uid : NULL;
+
+ case GPGME_ATTR_NAME:
+ return uid ? uid->name : NULL;
+
+ case GPGME_ATTR_EMAIL:
+ return uid ? uid->email : NULL;
+
+ case GPGME_ATTR_COMMENT:
+ return uid ? uid->comment : NULL;
+
+ case GPGME_ATTR_VALIDITY:
+ return uid ? validity_to_string (uid->validity) : NULL;
+
+ case GPGME_ATTR_KEY_CAPS:
+ return subkey ? capabilities_to_string (subkey) : NULL;
+
+ case GPGME_ATTR_SERIAL:
+ return key->issuer_serial;
+
+ case GPGME_ATTR_ISSUER:
+ return idx ? NULL : key->issuer_name;
+
+ case GPGME_ATTR_CHAINID:
+ return key->chain_id;
+
+ default:
+ return NULL;
+ }
+}
+
+
+unsigned long
+gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ gpgme_subkey_t subkey;
+ gpgme_user_id_t uid;
+ int i;
+
+ if (!key || reserved || idx < 0)
+ return 0;
+
+ /* Select IDXth subkey. */
+ subkey = key->subkeys;
+ for (i = 0; i < idx; i++)
+ {
+ subkey = subkey->next;
+ if (!subkey)
+ break;
+ }
+
+ /* Select the IDXth user ID. */
+ uid = key->uids;
+ for (i = 0; i < idx; i++)
+ {
+ uid = uid->next;
+ if (!uid)
+ break;
+ }
+
+ switch (what)
+ {
+ case GPGME_ATTR_ALGO:
+ return subkey ? (unsigned long) subkey->pubkey_algo : 0;
+
+ case GPGME_ATTR_LEN:
+ return subkey ? (unsigned long) subkey->length : 0;
+
+ case GPGME_ATTR_TYPE:
+ return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
+
+ case GPGME_ATTR_CREATED:
+ return (subkey && subkey->timestamp >= 0)
+ ? (unsigned long) subkey->timestamp : 0;
+
+ case GPGME_ATTR_EXPIRE:
+ return (subkey && subkey->expires >= 0)
+ ? (unsigned long) subkey->expires : 0;
+
+ case GPGME_ATTR_VALIDITY:
+ return uid ? uid->validity : 0;
+
+ case GPGME_ATTR_OTRUST:
+ return key->owner_trust;
+
+ case GPGME_ATTR_IS_SECRET:
+ return !!key->secret;
+
+ case GPGME_ATTR_KEY_REVOKED:
+ return subkey ? subkey->revoked : 0;
+
+ case GPGME_ATTR_KEY_INVALID:
+ return subkey ? subkey->invalid : 0;
+
+ case GPGME_ATTR_KEY_EXPIRED:
+ return subkey ? subkey->expired : 0;
+
+ case GPGME_ATTR_KEY_DISABLED:
+ return subkey ? subkey->disabled : 0;
+
+ case GPGME_ATTR_UID_REVOKED:
+ return uid ? uid->revoked : 0;
+
+ case GPGME_ATTR_UID_INVALID:
+ return uid ? uid->invalid : 0;
+
+ case GPGME_ATTR_CAN_ENCRYPT:
+ return key->can_encrypt;
+
+ case GPGME_ATTR_CAN_SIGN:
+ return key->can_sign;
+
+ case GPGME_ATTR_CAN_CERTIFY:
+ return key->can_certify;
+
+ default:
+ return 0;
+ }
+}
+
+
+static gpgme_key_sig_t
+get_keysig (gpgme_key_t key, int uid_idx, int idx)
+{
+ gpgme_user_id_t uid;
+ gpgme_key_sig_t sig;
+
+ if (!key || uid_idx < 0 || idx < 0)
+ return NULL;
+
+ uid = key->uids;
+ while (uid && uid_idx > 0)
+ {
+ uid = uid->next;
+ uid_idx--;
+ }
+ if (!uid)
+ return NULL;
+
+ sig = uid->signatures;
+ while (sig && idx > 0)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ return sig;
+}
+
+
+const char *
+gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
+ _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
+
+ if (!certsig || reserved)
+ return NULL;
+
+ switch (what)
+ {
+ case GPGME_ATTR_KEYID:
+ return certsig->keyid;
+
+ case GPGME_ATTR_ALGO:
+ return gpgme_pubkey_algo_name (certsig->pubkey_algo);
+
+ case GPGME_ATTR_USERID:
+ return certsig->uid;
+
+ case GPGME_ATTR_NAME:
+ return certsig->name;
+
+ case GPGME_ATTR_EMAIL:
+ return certsig->email;
+
+ case GPGME_ATTR_COMMENT:
+ return certsig->comment;
+
+ default:
+ return NULL;
+ }
+}
+
+
+unsigned long
+gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx, _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ gpgme_key_sig_t certsig = get_keysig (key, uid_idx, idx);
+
+ if (!certsig || reserved)
+ return 0;
+
+ switch (what)
+ {
+ case GPGME_ATTR_ALGO:
+ return (unsigned long) certsig->pubkey_algo;
+
+ case GPGME_ATTR_CREATED:
+ return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
+
+ case GPGME_ATTR_EXPIRE:
+ return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
+
+ case GPGME_ATTR_KEY_REVOKED:
+ return certsig->revoked;
+
+ case GPGME_ATTR_KEY_INVALID:
+ return certsig->invalid;
+
+ case GPGME_ATTR_KEY_EXPIRED:
+ return certsig->expired;
+
+ case GPGME_ATTR_SIG_CLASS:
+ return certsig->sig_class;
+
+ case GPGME_ATTR_SIG_STATUS:
+ return certsig->status;
+
+ default:
+ return 0;
+ }
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/keylist.c b/libtdenetwork/libgpgme-copy/gpgme/keylist.c
new file mode 100644
index 000000000..442409bef
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/keylist.c
@@ -0,0 +1,980 @@
+/* keylist.c - Listing keys.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+#include "debug.h"
+
+
+struct key_queue_item_s
+{
+ struct key_queue_item_s *next;
+ gpgme_key_t key;
+};
+
+typedef struct
+{
+ struct _gpgme_op_keylist_result result;
+
+ gpgme_key_t tmp_key;
+
+ /* This points to the last uid in tmp_key. */
+ gpgme_user_id_t tmp_uid;
+
+ /* This points to the last sig in tmp_uid. */
+ gpgme_key_sig_t tmp_keysig;
+
+ /* Something new is available. */
+ int key_cond;
+ struct key_queue_item_s *key_queue;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+ struct key_queue_item_s *key = opd->key_queue;
+
+ if (opd->tmp_key)
+ gpgme_key_unref (opd->tmp_key);
+
+ /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
+ so we do not need to release them here. */
+
+ while (key)
+ {
+ struct key_queue_item_s *next = key->next;
+
+ gpgme_key_unref (key->key);
+ key = next;
+ }
+}
+
+
+gpgme_keylist_result_t
+gpgme_op_keylist_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+static gpgme_error_t
+keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_TRUNCATED:
+ opd->result.truncated = 1;
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static void
+set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
+{
+ while (*src && !isdigit (*src))
+ {
+ switch (*src)
+ {
+ case 'e':
+ subkey->expired = 1;
+ break;
+
+ case 'r':
+ subkey->revoked = 1;
+ break;
+
+ case 'd':
+ /* Note that gpg 1.3 won't print that anymore but only uses
+ the capabilities field. */
+ subkey->disabled = 1;
+ break;
+
+ case 'i':
+ subkey->invalid = 1;
+ break;
+ }
+ src++;
+ }
+}
+
+
+static void
+set_mainkey_trust_info (gpgme_key_t key, const char *src)
+{
+ /* First set the trust info of the main key (the first subkey). */
+ set_subkey_trust_info (key->subkeys, src);
+
+ /* Now set the summarized trust info. */
+ while (*src && !isdigit (*src))
+ {
+ switch (*src)
+ {
+ case 'e':
+ key->expired = 1;
+ break;
+
+ case 'r':
+ key->revoked = 1;
+ break;
+
+ case 'd':
+ /* Note that gpg 1.3 won't print that anymore but only uses
+ the capabilities field. However, it is still used for
+ external key listings. */
+ key->disabled = 1;
+ break;
+
+ case 'i':
+ key->invalid = 1;
+ break;
+ }
+ src++;
+ }
+}
+
+
+static void
+set_userid_flags (gpgme_key_t key, const char *src)
+{
+ gpgme_user_id_t uid = key->_last_uid;
+
+ assert (uid);
+ /* Look at letters and stop at the first digit. */
+ while (*src && !isdigit (*src))
+ {
+ switch (*src)
+ {
+ case 'r':
+ uid->revoked = 1;
+ break;
+
+ case 'i':
+ uid->invalid = 1;
+ break;
+
+ case 'n':
+ uid->validity = GPGME_VALIDITY_NEVER;
+ break;
+
+ case 'm':
+ uid->validity = GPGME_VALIDITY_MARGINAL;
+ break;
+
+ case 'f':
+ uid->validity = GPGME_VALIDITY_FULL;
+ break;
+
+ case 'u':
+ uid->validity = GPGME_VALIDITY_ULTIMATE;
+ break;
+ }
+ src++;
+ }
+}
+
+
+static void
+set_subkey_capability (gpgme_subkey_t subkey, const char *src)
+{
+ while (*src)
+ {
+ switch (*src)
+ {
+ case 'e':
+ subkey->can_encrypt = 1;
+ break;
+
+ case 's':
+ subkey->can_sign = 1;
+ break;
+
+ case 'c':
+ subkey->can_certify = 1;
+ break;
+
+ case 'a':
+ subkey->can_authenticate = 1;
+ break;
+
+ case 'q':
+ subkey->is_qualified = 1;
+ break;
+
+ case 'd':
+ subkey->disabled = 1;
+ break;
+ }
+ src++;
+ }
+}
+
+
+static void
+set_mainkey_capability (gpgme_key_t key, const char *src)
+{
+ /* First set the capabilities of the main key (the first subkey). */
+ set_subkey_capability (key->subkeys, src);
+
+ while (*src)
+ {
+ switch (*src)
+ {
+ case 'd':
+ case 'D':
+ /* Note, that this flag is also set using the key validity
+ field for backward compatibility with gpg 1.2. We use d
+ and D, so that a future gpg version will be able to
+ disable certain subkeys. Currently it is expected that
+ gpg sets this for the primary key. */
+ key->disabled = 1;
+ break;
+
+ case 'e':
+ case 'E':
+ key->can_encrypt = 1;
+ break;
+
+ case 's':
+ case 'S':
+ key->can_sign = 1;
+ break;
+
+ case 'c':
+ case 'C':
+ key->can_certify = 1;
+ break;
+
+ case 'a':
+ case 'A':
+ key->can_authenticate = 1;
+ break;
+
+ case 'q':
+ case 'Q':
+ key->is_qualified = 1;
+ break;
+ }
+ src++;
+ }
+}
+
+
+static void
+set_ownertrust (gpgme_key_t key, const char *src)
+{
+ /* Look at letters and stop at the first digit. */
+ while (*src && !isdigit (*src))
+ {
+ switch (*src)
+ {
+ case 'n':
+ key->owner_trust = GPGME_VALIDITY_NEVER;
+ break;
+
+ case 'm':
+ key->owner_trust = GPGME_VALIDITY_MARGINAL;
+ break;
+
+ case 'f':
+ key->owner_trust = GPGME_VALIDITY_FULL;
+ break;
+
+ case 'u':
+ key->owner_trust = GPGME_VALIDITY_ULTIMATE;
+ break;
+
+ default:
+ key->owner_trust = GPGME_VALIDITY_UNKNOWN;
+ break;
+ }
+ src++;
+ }
+}
+
+
+/* We have read an entire key into tmp_key and should now finish it.
+ It is assumed that this releases tmp_key. */
+static void
+finish_key (gpgme_ctx_t ctx, op_data_t opd)
+{
+ gpgme_key_t key = opd->tmp_key;
+
+ opd->tmp_key = NULL;
+ opd->tmp_uid = NULL;
+ opd->tmp_keysig = NULL;
+
+ if (key)
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
+}
+
+
+/* Note: We are allowed to modify LINE. */
+static gpgme_error_t
+keylist_colon_handler (void *priv, char *line)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ enum
+ {
+ RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
+ RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
+ }
+ rectype = RT_NONE;
+#define NR_FIELDS 16
+ char *field[NR_FIELDS];
+ int fields = 0;
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+ gpgme_key_t key;
+ gpgme_subkey_t subkey = NULL;
+ gpgme_key_sig_t keysig = NULL;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ key = opd->tmp_key;
+
+ DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
+ ctx, key, line ? line : "(null)");
+
+ if (!line)
+ {
+ /* End Of File. */
+ finish_key (ctx, opd);
+ return 0;
+ }
+
+ while (line && fields < NR_FIELDS)
+ {
+ field[fields++] = line;
+ line = strchr (line, ':');
+ if (line)
+ *(line++) = '\0';
+ }
+
+ if (!strcmp (field[0], "sig"))
+ rectype = RT_SIG;
+ else if (!strcmp (field[0], "rev"))
+ rectype = RT_REV;
+ else if (!strcmp (field[0], "pub"))
+ rectype = RT_PUB;
+ else if (!strcmp (field[0], "sec"))
+ rectype = RT_SEC;
+ else if (!strcmp (field[0], "crt"))
+ rectype = RT_CRT;
+ else if (!strcmp (field[0], "crs"))
+ rectype = RT_CRS;
+ else if (!strcmp (field[0], "fpr") && key)
+ rectype = RT_FPR;
+ else if (!strcmp (field[0], "uid") && key)
+ rectype = RT_UID;
+ else if (!strcmp (field[0], "sub") && key)
+ rectype = RT_SUB;
+ else if (!strcmp (field[0], "ssb") && key)
+ rectype = RT_SSB;
+ else if (!strcmp (field[0], "spk") && key)
+ rectype = RT_SPK;
+ else
+ rectype = RT_NONE;
+
+ /* Only look at signatures immediately following a user ID. For
+ this, clear the user ID pointer when encountering anything but a
+ signature. */
+ if (rectype != RT_SIG && rectype != RT_REV)
+ opd->tmp_uid = NULL;
+
+ /* Only look at subpackets immediately following a signature. For
+ this, clear the signature pointer when encountering anything but
+ a subpacket. */
+ if (rectype != RT_SPK)
+ opd->tmp_keysig = NULL;
+
+ switch (rectype)
+ {
+ case RT_PUB:
+ case RT_SEC:
+ case RT_CRT:
+ case RT_CRS:
+ /* Start a new keyblock. */
+ err = _gpgme_key_new (&key);
+ if (err)
+ return err;
+ key->keylist_mode = ctx->keylist_mode;
+ err = _gpgme_key_add_subkey (key, &subkey);
+ if (err)
+ {
+ gpgme_key_unref (key);
+ return err;
+ }
+
+ if (rectype == RT_SEC || rectype == RT_CRS)
+ key->secret = subkey->secret = 1;
+ if (rectype == RT_CRT || rectype == RT_CRS)
+ key->protocol = GPGME_PROTOCOL_CMS;
+ finish_key (ctx, opd);
+ opd->tmp_key = key;
+
+ /* Field 2 has the trust info. */
+ if (fields >= 2)
+ set_mainkey_trust_info (key, field[1]);
+
+ /* Field 3 has the key length. */
+ if (fields >= 3)
+ {
+ int i = atoi (field[2]);
+ /* Ignore invalid values. */
+ if (i > 1)
+ subkey->length = i;
+ }
+
+ /* Field 4 has the public key algorithm. */
+ if (fields >= 4)
+ {
+ int i = atoi (field[3]);
+ if (i >= 1 && i < 128)
+ subkey->pubkey_algo = i;
+ }
+
+ /* Field 5 has the long keyid. Allow short key IDs for the
+ output of an external keyserver listing. */
+ if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
+ strcpy (subkey->_keyid, field[4]);
+
+ /* Field 6 has the timestamp (seconds). */
+ if (fields >= 6)
+ subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
+
+ /* Field 7 has the expiration time (seconds). */
+ if (fields >= 7)
+ subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
+
+ /* Field 8 has the X.509 serial number. */
+ if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
+ {
+ key->issuer_serial = strdup (field[7]);
+ if (!key->issuer_serial)
+ return gpg_error_from_errno (errno);
+ }
+
+ /* Field 9 has the ownertrust. */
+ if (fields >= 9)
+ set_ownertrust (key, field[8]);
+
+ /* Field 10 is not used for gpg due to --fixed-list-mode option
+ but GPGSM stores the issuer name. */
+ if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
+ if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
+ return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
+
+ /* Field 11 has the signature class. */
+
+ /* Field 12 has the capabilities. */
+ if (fields >= 12)
+ set_mainkey_capability (key, field[11]);
+
+ /* Field 15 carries special flags of a secret key. We reset the
+ SECRET flag of a subkey here if the key is actually only a
+ stub. The SECRET flag of the key will be true even then. */
+ if (fields >= 15 && key->secret)
+ if (*field[14] == '#')
+ subkey->secret = 0;
+ break;
+
+ case RT_SUB:
+ case RT_SSB:
+ /* Start a new subkey. */
+ err = _gpgme_key_add_subkey (key, &subkey);
+ if (err)
+ return err;
+
+ if (rectype == RT_SSB)
+ subkey->secret = 1;
+
+ /* Field 2 has the trust info. */
+ if (fields >= 2)
+ set_subkey_trust_info (subkey, field[1]);
+
+ /* Field 3 has the key length. */
+ if (fields >= 3)
+ {
+ int i = atoi (field[2]);
+ /* Ignore invalid values. */
+ if (i > 1)
+ subkey->length = i;
+ }
+
+ /* Field 4 has the public key algorithm. */
+ if (fields >= 4)
+ {
+ int i = atoi (field[3]);
+ if (i >= 1 && i < 128)
+ subkey->pubkey_algo = i;
+ }
+
+ /* Field 5 has the long keyid. */
+ if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
+ strcpy (subkey->_keyid, field[4]);
+
+ /* Field 6 has the timestamp (seconds). */
+ if (fields >= 6)
+ subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
+
+ /* Field 7 has the expiration time (seconds). */
+ if (fields >= 7)
+ subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
+
+ /* Field 8 is reserved (LID). */
+ /* Field 9 has the ownertrust. */
+ /* Field 10, the user ID, is n/a for a subkey. */
+
+ /* Field 11 has the signature class. */
+
+ /* Field 12 has the capabilities. */
+ if (fields >= 12)
+ set_subkey_capability (subkey, field[11]);
+
+ /* Field 15 carries special flags of a secret key. */
+ if (fields >= 15 && key->secret)
+ if (*field[14] == '#')
+ subkey->secret = 0;
+ break;
+
+ case RT_UID:
+ /* Field 2 has the trust info, and field 10 has the user ID. */
+ if (fields >= 10)
+ {
+ if (_gpgme_key_append_name (key, field[9]))
+ return gpg_error_from_errno (GPG_ERR_ENOMEM); /* FIXME */
+ else
+ {
+ if (field[1])
+ set_userid_flags (key, field[1]);
+ opd->tmp_uid = key->_last_uid;
+ }
+ }
+ break;
+
+ case RT_FPR:
+ /* Field 10 has the fingerprint (take only the first one). */
+ if (fields >= 10 && field[9] && *field[9])
+ {
+ /* Need to apply it to the last subkey because all subkeys
+ do have fingerprints. */
+ subkey = key->_last_subkey;
+ if (!subkey->fpr)
+ {
+ subkey->fpr = strdup (field[9]);
+ if (!subkey->fpr)
+ return gpg_error_from_errno (errno);
+ }
+ }
+
+ /* Field 13 has the gpgsm chain ID (take only the first one). */
+ if (fields >= 13 && !key->chain_id && *field[12])
+ {
+ key->chain_id = strdup (field[12]);
+ if (!key->chain_id)
+ return gpg_error_from_errno (errno);
+ }
+ break;
+
+ case RT_SIG:
+ case RT_REV:
+ if (!opd->tmp_uid)
+ return 0;
+
+ /* Start a new (revoked) signature. */
+ assert (opd->tmp_uid == key->_last_uid);
+ keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
+ if (!keysig)
+ return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
+
+ /* Field 2 has the calculated trust ('!', '-', '?', '%'). */
+ if (fields >= 2)
+ switch (field[1][0])
+ {
+ case '!':
+ keysig->status = gpg_error (GPG_ERR_NO_ERROR);
+ break;
+
+ case '-':
+ keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
+ break;
+
+ case '?':
+ keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
+ break;
+
+ case '%':
+ keysig->status = gpg_error (GPG_ERR_GENERAL);
+ break;
+
+ default:
+ keysig->status = gpg_error (GPG_ERR_NO_ERROR);
+ break;
+ }
+
+ /* Field 4 has the public key algorithm. */
+ if (fields >= 4)
+ {
+ int i = atoi (field[3]);
+ if (i >= 1 && i < 128)
+ keysig->pubkey_algo = i;
+ }
+
+ /* Field 5 has the long keyid. */
+ if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
+ strcpy (keysig->_keyid, field[4]);
+
+ /* Field 6 has the timestamp (seconds). */
+ if (fields >= 6)
+ keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
+
+ /* Field 7 has the expiration time (seconds). */
+ if (fields >= 7)
+ keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
+
+ /* Field 11 has the signature class (eg, 0x30 means revoked). */
+ if (fields >= 11)
+ if (field[10][0] && field[10][1])
+ {
+ int sig_class = _gpgme_hextobyte (field[10]);
+ if (sig_class >= 0)
+ {
+ keysig->sig_class = sig_class;
+ keysig->class = keysig->sig_class;
+ if (sig_class == 0x30)
+ keysig->revoked = 1;
+ }
+ if (field[10][2] == 'x')
+ keysig->exportable = 1;
+ }
+
+ opd->tmp_keysig = keysig;
+ break;
+
+ case RT_SPK:
+ if (!opd->tmp_keysig)
+ return 0;
+ assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
+
+ if (fields >= 4)
+ {
+ /* Field 2 has the subpacket type. */
+ int type = atoi (field[1]);
+
+ /* Field 3 has the flags. */
+ int flags = atoi (field[2]);
+
+ /* Field 4 has the length. */
+ int len = atoi (field[3]);
+
+ /* Field 5 has the data. */
+ char *data = field[4];
+
+ /* Type 20: Notation data. */
+ /* Type 26: Policy URL. */
+ if (type == 20 || type == 26)
+ {
+ gpgme_sig_notation_t notation;
+
+ keysig = opd->tmp_keysig;
+
+ /* At this time, any error is serious. */
+ err = _gpgme_parse_notation (&notation, type, flags, len, data);
+ if (err)
+ return err;
+
+ /* Add a new notation. FIXME: Could be factored out. */
+ if (!keysig->notations)
+ keysig->notations = notation;
+ if (keysig->_last_notation)
+ keysig->_last_notation->next = notation;
+ keysig->_last_notation = notation;
+ }
+ }
+
+ case RT_NONE:
+ /* Unknown record. */
+ break;
+ }
+ return 0;
+}
+
+
+void
+_gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
+{
+ gpgme_error_t err;
+ gpgme_ctx_t ctx = (gpgme_ctx_t) data;
+ gpgme_key_t key = (gpgme_key_t) type_data;
+ void *hook;
+ op_data_t opd;
+ struct key_queue_item_s *q, *q2;
+
+ assert (type == GPGME_EVENT_NEXT_KEY);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return;
+
+ q = malloc (sizeof *q);
+ if (!q)
+ {
+ gpgme_key_unref (key);
+ /* FIXME return GPGME_Out_Of_Core; */
+ return;
+ }
+ q->key = key;
+ q->next = NULL;
+ /* FIXME: Use a tail pointer? */
+ if (!(q2 = opd->key_queue))
+ opd->key_queue = q;
+ else
+ {
+ for (; q2->next; q2 = q2->next)
+ ;
+ q2->next = q;
+ }
+ opd->key_cond = 1;
+}
+
+
+/* Start a keylist operation within CTX, searching for keys which
+ match PATTERN. If SECRET_ONLY is true, only secret keys are
+ returned. */
+gpgme_error_t
+gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, 2);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
+
+ err = _gpgme_engine_set_colon_line_handler (ctx->engine,
+ keylist_colon_handler, ctx);
+ if (err)
+ return err;
+
+ return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
+ ctx->keylist_mode);
+}
+
+
+/* Start a keylist operation within CTX, searching for keys which
+ match PATTERN. If SECRET_ONLY is true, only secret keys are
+ returned. */
+gpgme_error_t
+gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
+ int secret_only, int reserved)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, 2);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
+ err = _gpgme_engine_set_colon_line_handler (ctx->engine,
+ keylist_colon_handler, ctx);
+ if (err)
+ return err;
+
+ return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
+ reserved, ctx->keylist_mode);
+}
+
+
+/* Return the next key from the keylist in R_KEY. */
+gpgme_error_t
+gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
+{
+ gpgme_error_t err;
+ struct key_queue_item_s *queue_item;
+ void *hook;
+ op_data_t opd;
+
+ if (!ctx || !r_key)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ *r_key = NULL;
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+ if (opd == NULL)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!opd->key_queue)
+ {
+ err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
+ if (err)
+ return err;
+
+ if (!opd->key_cond)
+ return gpg_error (GPG_ERR_EOF);
+
+ opd->key_cond = 0;
+ assert (opd->key_queue);
+ }
+ queue_item = opd->key_queue;
+ opd->key_queue = queue_item->next;
+ if (!opd->key_queue)
+ opd->key_cond = 0;
+
+ *r_key = queue_item->key;
+ free (queue_item);
+ return 0;
+}
+
+
+/* Terminate a pending keylist operation within CTX. */
+gpgme_error_t
+gpgme_op_keylist_end (gpgme_ctx_t ctx)
+{
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ return 0;
+}
+
+
+/* Get the key with the fingerprint FPR from the crypto backend. If
+ SECRET is true, get the secret key. */
+gpgme_error_t
+gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
+ int secret)
+{
+ gpgme_ctx_t listctx;
+ gpgme_error_t err;
+ gpgme_key_t key;
+
+ if (!ctx || !r_key || !fpr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (strlen (fpr) < 8) /* We have at least a key ID. */
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* FIXME: We use our own context because we have to avoid the user's
+ I/O callback handlers. */
+ err = gpgme_new (&listctx);
+ if (err)
+ return err;
+ {
+ gpgme_protocol_t proto;
+ gpgme_engine_info_t info;
+
+ /* Clone the relevant state. */
+ proto = gpgme_get_protocol (ctx);
+ gpgme_set_protocol (listctx, proto);
+ gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
+ info = gpgme_ctx_get_engine_info (ctx);
+ while (info && info->protocol != proto)
+ info = info->next;
+ if (info)
+ gpgme_ctx_set_engine_info (listctx, proto,
+ info->file_name, info->home_dir);
+ }
+
+ err = gpgme_op_keylist_start (listctx, fpr, secret);
+ if (!err)
+ err = gpgme_op_keylist_next (listctx, r_key);
+ if (!err)
+ {
+ err = gpgme_op_keylist_next (listctx, &key);
+ if (gpgme_err_code (err) == GPG_ERR_EOF)
+ err = gpg_error (GPG_ERR_NO_ERROR);
+ else
+ {
+ if (!err)
+ {
+ gpgme_key_unref (key);
+ err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
+ }
+ gpgme_key_unref (*r_key);
+ }
+ }
+ gpgme_release (listctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/libgpgme.vers b/libtdenetwork/libgpgme-copy/gpgme/libgpgme.vers
new file mode 100644
index 000000000..11571b9e5
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/libgpgme.vers
@@ -0,0 +1,167 @@
+# libgpgme.vers - List of symbols to export.
+# Copyright (C) 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+#-------------------------------------------------------
+# Please remember to add new functions also to gpgme.def
+#-------------------------------------------------------
+
+GPGME_1.1 {
+ global:
+ gpgme_set_engine_info;
+
+ gpgme_ctx_get_engine_info;
+ gpgme_ctx_set_engine_info;
+
+ gpgme_data_set_file_name;
+ gpgme_data_get_file_name;
+
+ gpgme_sig_notation_clear;
+ gpgme_sig_notation_add;
+ gpgme_sig_notation_get;
+
+ gpgme_free;
+};
+
+
+GPGME_1.0 {
+ global:
+ gpgme_check_version;
+ gpgme_get_engine_info;
+ gpgme_engine_check_version;
+
+ gpgme_err_code_from_errno;
+ gpgme_err_code_to_errno;
+ gpgme_err_make_from_errno;
+ gpgme_error_from_errno;
+ gpgme_strerror;
+ gpgme_strerror_r;
+ gpgme_strsource;
+
+ gpgme_data_get_encoding;
+ gpgme_data_new;
+ gpgme_data_new_from_cbs;
+ gpgme_data_new_from_fd;
+ gpgme_data_new_from_file;
+ gpgme_data_new_from_filepart;
+ gpgme_data_new_from_mem;
+ gpgme_data_new_from_stream;
+ gpgme_data_read;
+ gpgme_data_release;
+ gpgme_data_release_and_get_mem;
+ gpgme_data_seek;
+ gpgme_data_set_encoding;
+ gpgme_data_write;
+
+ gpgme_get_protocol_name;
+ gpgme_hash_algo_name;
+ gpgme_pubkey_algo_name;
+
+ gpgme_new;
+ gpgme_get_armor;
+ gpgme_get_include_certs;
+ gpgme_get_io_cbs;
+ gpgme_get_keylist_mode;
+ gpgme_get_passphrase_cb;
+ gpgme_get_progress_cb;
+ gpgme_get_protocol;
+ gpgme_get_textmode;
+ gpgme_release;
+ gpgme_set_armor;
+ gpgme_set_include_certs;
+ gpgme_set_io_cbs;
+ gpgme_set_keylist_mode;
+ gpgme_set_locale;
+ gpgme_set_passphrase_cb;
+ gpgme_set_progress_cb;
+ gpgme_set_protocol;
+ gpgme_set_textmode;
+ gpgme_signers_add;
+ gpgme_signers_clear;
+ gpgme_signers_enum;
+
+ gpgme_key_ref;
+ gpgme_key_unref;
+ gpgme_key_release;
+
+ gpgme_trust_item_ref;
+ gpgme_trust_item_unref;
+
+ gpgme_cancel;
+ gpgme_op_card_edit;
+ gpgme_op_card_edit_start;
+ gpgme_op_decrypt;
+ gpgme_op_decrypt_result;
+ gpgme_op_decrypt_start;
+ gpgme_op_decrypt_verify;
+ gpgme_op_decrypt_verify_start;
+ gpgme_op_delete;
+ gpgme_op_delete_start;
+ gpgme_op_edit;
+ gpgme_op_edit_start;
+ gpgme_op_encrypt;
+ gpgme_op_encrypt_result;
+ gpgme_op_encrypt_sign;
+ gpgme_op_encrypt_sign_start;
+ gpgme_op_encrypt_start;
+ gpgme_op_export;
+ gpgme_op_export_ext;
+ gpgme_op_export_ext_start;
+ gpgme_op_export_start;
+ gpgme_op_genkey;
+ gpgme_op_genkey_result;
+ gpgme_op_genkey_start;
+ gpgme_get_key;
+ gpgme_op_import;
+ gpgme_op_import_result;
+ gpgme_op_import_start;
+ gpgme_op_keylist_end;
+ gpgme_op_keylist_ext_start;
+ gpgme_op_keylist_next;
+ gpgme_op_keylist_result;
+ gpgme_op_keylist_start;
+ gpgme_op_sign;
+ gpgme_op_sign_result;
+ gpgme_op_sign_start;
+ gpgme_op_trustlist_end;
+ gpgme_op_trustlist_next;
+ gpgme_op_trustlist_start;
+ gpgme_op_verify;
+ gpgme_op_verify_result;
+ gpgme_op_verify_start;
+ gpgme_wait;
+
+ gpgme_data_new_with_read_cb;
+ gpgme_data_rewind;
+ gpgme_get_sig_status;
+ gpgme_get_sig_string_attr;
+ gpgme_get_sig_ulong_attr;
+ gpgme_get_sig_key;
+ gpgme_key_get_string_attr;
+ gpgme_key_get_ulong_attr;
+ gpgme_key_sig_get_string_attr;
+ gpgme_key_sig_get_ulong_attr;
+ gpgme_op_import_ext;
+ gpgme_trust_item_get_int_attr;
+ gpgme_trust_item_get_string_attr;
+ gpgme_trust_item_release;
+
+ local:
+ *;
+
+};
diff --git a/libtdenetwork/libgpgme-copy/gpgme/memrchr.c b/libtdenetwork/libgpgme-copy/gpgme/memrchr.c
new file mode 100644
index 000000000..4f91ef2bd
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/memrchr.c
@@ -0,0 +1,210 @@
+/* memrchr -- find the last occurrence of a byte in a memory block
+ Copyright (C) 1991, 93, 96, 97, 99, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
+ with help from Dan Sahlin (dan@sics.se) and
+ commentary by Jim Blandy (jimb@ai.mit.edu);
+ adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
+ and implemented by Roland McGrath (roland@ai.mit.edu).
+
+ The GNU C Library 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.
+
+ The GNU C Library 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA. */
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef __ptr_t
+#if defined __cplusplus || (defined __STDC__ && __STDC__)
+# define __ptr_t void *
+#else /* Not C++ or ANSI C. */
+# define __ptr_t char *
+#endif /* C++ or ANSI C. */
+
+#if defined _LIBC
+# include <string.h>
+# include <memcopy.h>
+#else
+# define reg_char char
+#endif
+
+#if defined HAVE_LIMITS_H || defined _LIBC
+# include <limits.h>
+#endif
+
+#define LONG_MAX_32_BITS 2147483647
+
+#ifndef LONG_MAX
+# define LONG_MAX LONG_MAX_32_BITS
+#endif
+
+#include <sys/types.h>
+
+#undef __memrchr
+#undef memrchr
+
+#ifndef weak_alias
+# define __memrchr memrchr
+#endif
+
+/* Search no more than N bytes of S for C. */
+__ptr_t
+__memrchr (s, c_in, n)
+ const __ptr_t s;
+ int c_in;
+ size_t n;
+{
+ const unsigned char *char_ptr;
+ const unsigned long int *longword_ptr;
+ unsigned long int longword, magic_bits, charmask;
+ unsigned reg_char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the last few characters by reading one character at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s + n;
+ n > 0 && ((unsigned long int) char_ptr
+ & (sizeof (longword) - 1)) != 0;
+ --n)
+ if (*--char_ptr == c)
+ return (__ptr_t) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to 8-byte longwords. */
+
+ longword_ptr = (const unsigned long int *) char_ptr;
+
+ /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
+ the "holes." Note that there is a hole just to the left of
+ each byte, with an extra at the end:
+
+ bits: 01111110 11111110 11111110 11111111
+ bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+ The 1-bits make sure that carries propagate to the next 0-bit.
+ The 0-bits provide holes for carries to fall into. */
+
+ if (sizeof (longword) != 4 && sizeof (longword) != 8)
+ abort ();
+
+#if LONG_MAX <= LONG_MAX_32_BITS
+ magic_bits = 0x7efefeff;
+#else
+ magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff;
+#endif
+
+ /* Set up a longword, each of whose bytes is C. */
+ charmask = c | (c << 8);
+ charmask |= charmask << 16;
+#if LONG_MAX > LONG_MAX_32_BITS
+ charmask |= charmask << 32;
+#endif
+
+ /* Instead of the traditional loop which tests each character,
+ we will test a longword at a time. The tricky part is testing
+ if *any of the four* bytes in the longword in question are zero. */
+ while (n >= sizeof (longword))
+ {
+ /* We tentatively exit the loop if adding MAGIC_BITS to
+ LONGWORD fails to change any of the hole bits of LONGWORD.
+
+ 1) Is this safe? Will it catch all the zero bytes?
+ Suppose there is a byte with all zeros. Any carry bits
+ propagating from its left will fall into the hole at its
+ least significant bit and stop. Since there will be no
+ carry from its most significant bit, the LSB of the
+ byte to the left will be unchanged, and the zero will be
+ detected.
+
+ 2) Is this worthwhile? Will it ignore everything except
+ zero bytes? Suppose every byte of LONGWORD has a bit set
+ somewhere. There will be a carry into bit 8. If bit 8
+ is set, this will carry into bit 16. If bit 8 is clear,
+ one of bits 9-15 must be set, so there will be a carry
+ into bit 16. Similarly, there will be a carry into bit
+ 24. If one of bits 24-30 is set, there will be a carry
+ into bit 31, so all of the hole bits will be changed.
+
+ The one misfire occurs when bits 24-30 are clear and bit
+ 31 is set; in this case, the hole at bit 31 is not
+ changed. If we had access to the processor carry flag,
+ we could close this loophole by putting the fourth hole
+ at bit 32!
+
+ So it ignores everything except 128's, when they're aligned
+ properly.
+
+ 3) But wait! Aren't we looking for C, not zero?
+ Good point. So what we do is XOR LONGWORD with a longword,
+ each of whose bytes is C. This turns each byte that is C
+ into a zero. */
+
+ longword = *--longword_ptr ^ charmask;
+
+ /* Add MAGIC_BITS to LONGWORD. */
+ if ((((longword + magic_bits)
+
+ /* Set those bits that were unchanged by the addition. */
+ ^ ~longword)
+
+ /* Look at only the hole bits. If any of the hole bits
+ are unchanged, most likely one of the bytes was a
+ zero. */
+ & ~magic_bits) != 0)
+ {
+ /* Which of the bytes was C? If none of them were, it was
+ a misfire; continue the search. */
+
+ const unsigned char *cp = (const unsigned char *) longword_ptr;
+
+#if LONG_MAX > 2147483647
+ if (cp[7] == c)
+ return (__ptr_t) &cp[7];
+ if (cp[6] == c)
+ return (__ptr_t) &cp[6];
+ if (cp[5] == c)
+ return (__ptr_t) &cp[5];
+ if (cp[4] == c)
+ return (__ptr_t) &cp[4];
+#endif
+ if (cp[3] == c)
+ return (__ptr_t) &cp[3];
+ if (cp[2] == c)
+ return (__ptr_t) &cp[2];
+ if (cp[1] == c)
+ return (__ptr_t) &cp[1];
+ if (cp[0] == c)
+ return (__ptr_t) cp;
+ }
+
+ n -= sizeof (longword);
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ while (n-- > 0)
+ {
+ if (*--char_ptr == c)
+ return (__ptr_t) char_ptr;
+ }
+
+ return 0;
+}
+#ifdef weak_alias
+weak_alias (__memrchr, memrchr)
+#endif
diff --git a/libtdenetwork/libgpgme-copy/gpgme/mkstatus b/libtdenetwork/libgpgme-copy/gpgme/mkstatus
new file mode 100755
index 000000000..2c6420178
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/mkstatus
@@ -0,0 +1,52 @@
+#!/bin/sh
+# mkstatus - Extract error strings from rungpg.h
+# and create a lookup table
+# Copyright (C) 2000 Werner Koch (dd9jn)
+# Copyright (C) 2001 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 General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+# resetting collate is important, so that the bsearch works properly
+LC_ALL=C
+LC_COLLATE=C
+export LC_ALL LC_COLLATE
+
+cat <<EOF
+/* Generated automatically by mkstatus */
+/* Do not edit! */
+
+struct status_table_s {
+ const char *name;
+ gpgme_status_code_t code;
+};
+
+static struct status_table_s status_table[] =
+{
+EOF
+
+awk '
+/GPGME_STATUS_ENTER/ { okay = 1 }
+!okay { next }
+/}/ { exit 0 }
+/GPGME_STATUS_[A-Za-z_]*/ { sub (/,/, "", $1); printf " { \"%s\", %s },\n", substr($1,14), $1 }
+' | sort
+
+cat <<EOF
+ {NULL, 0}
+};
+
+EOF
diff --git a/libtdenetwork/libgpgme-copy/gpgme/op-support.c b/libtdenetwork/libgpgme-copy/gpgme/op-support.c
new file mode 100644
index 000000000..87e47f42b
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/op-support.c
@@ -0,0 +1,280 @@
+/* op-support.c
+ Copyright (C) 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <locale.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+gpgme_error_t
+_gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook,
+ int size, void (*cleanup) (void *))
+{
+ struct ctx_op_data *data = ctx->op_data;
+ while (data && data->type != type)
+ data = data->next;
+ if (!data)
+ {
+ if (size < 0)
+ {
+ *hook = NULL;
+ return 0;
+ }
+
+ data = calloc (1, sizeof (struct ctx_op_data) + size);
+ if (!data)
+ return gpg_error_from_errno (errno);
+ data->next = ctx->op_data;
+ data->type = type;
+ data->cleanup = cleanup;
+ data->hook = (void *) (((char *) data) + sizeof (struct ctx_op_data));
+ ctx->op_data = data;
+ }
+ *hook = data->hook;
+ return 0;
+}
+
+
+/* type is: 0: asynchronous operation (use global or user event loop).
+ 1: synchronous operation (always use private event loop).
+ 2: asynchronous private operation (use private or user
+ event loop). */
+gpgme_error_t
+_gpgme_op_reset (gpgme_ctx_t ctx, int type)
+{
+ gpgme_error_t err = 0;
+ struct gpgme_io_cbs io_cbs;
+
+ _gpgme_release_result (ctx);
+
+ if (ctx->engine)
+ {
+ /* Attempt to reset an existing engine. */
+
+ err = _gpgme_engine_reset (ctx->engine);
+ if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
+ {
+ _gpgme_engine_release (ctx->engine);
+ ctx->engine = NULL;
+ }
+ }
+
+ if (!ctx->engine)
+ {
+ gpgme_engine_info_t info;
+ info = ctx->engine_info;
+ while (info && info->protocol != ctx->protocol)
+ info = info->next;
+
+ if (!info)
+ return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ /* Create an engine object. */
+ err = _gpgme_engine_new (info, &ctx->engine);
+ if (err)
+ return err;
+ }
+
+ err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype);
+#ifdef LC_MESSAGES
+ if (!err)
+ err = _gpgme_engine_set_locale (ctx->engine,
+ LC_MESSAGES, ctx->lc_messages);
+#endif
+
+ if (err)
+ {
+ _gpgme_engine_release (ctx->engine);
+ ctx->engine = NULL;
+ return err;
+ }
+
+ if (type == 1 || (type == 2 && !ctx->io_cbs.add))
+ {
+ /* Use private event loop. */
+ io_cbs.add = _gpgme_add_io_cb;
+ io_cbs.add_priv = ctx;
+ io_cbs.remove = _gpgme_remove_io_cb;
+ io_cbs.event = _gpgme_wait_private_event_cb;
+ io_cbs.event_priv = ctx;
+ }
+ else if (! ctx->io_cbs.add)
+ {
+ /* Use global event loop. */
+ io_cbs.add = _gpgme_add_io_cb;
+ io_cbs.add_priv = ctx;
+ io_cbs.remove = _gpgme_remove_io_cb;
+ io_cbs.event = _gpgme_wait_global_event_cb;
+ io_cbs.event_priv = ctx;
+ }
+ else
+ {
+ /* Use user event loop. */
+ io_cbs.add = _gpgme_wait_user_add_io_cb;
+ io_cbs.add_priv = ctx;
+ io_cbs.remove = _gpgme_wait_user_remove_io_cb;
+ io_cbs.event = _gpgme_wait_user_event_cb;
+ io_cbs.event_priv = ctx;
+ }
+ _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
+ return err;
+}
+
+
+/* Parse the INV_RECP status line in ARGS and return the result in
+ KEY. */
+gpgme_error_t
+_gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
+{
+ gpgme_invalid_key_t inv_key;
+ char *tail;
+ long int reason;
+
+ inv_key = malloc (sizeof (*inv_key));
+ if (!inv_key)
+ return gpg_error_from_errno (errno);
+ inv_key->next = NULL;
+ errno = 0;
+ reason = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (inv_key);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ switch (reason)
+ {
+ default:
+ case 0:
+ inv_key->reason = gpg_error (GPG_ERR_GENERAL);
+ break;
+
+ case 1:
+ inv_key->reason = gpg_error (GPG_ERR_NO_PUBKEY);
+ break;
+
+ case 2:
+ inv_key->reason = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
+ break;
+
+ case 3:
+ inv_key->reason = gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ break;
+
+ case 4:
+ inv_key->reason = gpg_error (GPG_ERR_CERT_REVOKED);
+ break;
+
+ case 5:
+ inv_key->reason = gpg_error (GPG_ERR_CERT_EXPIRED);
+ break;
+
+ case 6:
+ inv_key->reason = gpg_error (GPG_ERR_NO_CRL_KNOWN);
+ break;
+
+ case 7:
+ inv_key->reason = gpg_error (GPG_ERR_CRL_TOO_OLD);
+ break;
+
+ case 8:
+ inv_key->reason = gpg_error (GPG_ERR_NO_POLICY_MATCH);
+ break;
+
+ case 9:
+ inv_key->reason = gpg_error (GPG_ERR_NO_SECKEY);
+ break;
+
+ case 10:
+ inv_key->reason = gpg_error (GPG_ERR_PUBKEY_NOT_TRUSTED);
+ break;
+ }
+
+ while (*tail == ' ')
+ tail++;
+ if (*tail)
+ {
+ inv_key->fpr = strdup (tail);
+ if (!inv_key->fpr)
+ {
+ int saved_errno = errno;
+ free (inv_key);
+ return gpg_error_from_errno (saved_errno);
+ }
+ }
+ else
+ inv_key->fpr = NULL;
+
+ *key = inv_key;
+ return 0;
+}
+
+
+/* Parse the PLAINTEXT status line in ARGS and return the result in
+ FILENAMEP. */
+gpgme_error_t
+_gpgme_parse_plaintext (char *args, char **filenamep)
+{
+ char *tail;
+
+ while (*args == ' ')
+ args++;
+ if (*args == '\0')
+ return 0;
+
+ /* First argument is file type. */
+ while (*args != ' ' && *args != '\0')
+ args++;
+ while (*args == ' ')
+ args++;
+ if (*args == '\0')
+ return 0;
+
+ /* Second argument is the timestamp. */
+ while (*args != ' ' && *args != '\0')
+ args++;
+ while (*args == ' ')
+ args++;
+ if (*args == '\0')
+ return 0;
+
+ tail = args;
+ while (*tail != ' ' && *tail != '\0')
+ tail++;
+ *tail = '\0';
+ if (filenamep && *args != '\0')
+ {
+ char *filename = strdup (args);
+ if (!filename)
+ return gpg_error_from_errno (errno);
+
+ *filenamep = filename;
+ }
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/ops.h b/libtdenetwork/libgpgme-copy/gpgme/ops.h
new file mode 100644
index 000000000..fd857dd56
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/ops.h
@@ -0,0 +1,169 @@
+/* ops.h - Internal operation support.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef OPS_H
+#define OPS_H
+
+#include "gpgme.h"
+#include "context.h"
+
+
+/* From gpgme.c. */
+void _gpgme_release_result (gpgme_ctx_t ctx);
+
+
+/* From wait.c. */
+gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx);
+gpgme_error_t _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond);
+
+
+/* From data.c. */
+gpgme_error_t _gpgme_data_inbound_handler (void *opaque, int fd);
+gpgme_error_t _gpgme_data_outbound_handler (void *opaque, int fd);
+
+
+/* From op-support.c. */
+
+/* Find or create the op data object of type TYPE. */
+gpgme_error_t _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type,
+ void **hook, int size,
+ void (*cleanup) (void *));
+
+/* Prepare a new operation on CTX. */
+gpgme_error_t _gpgme_op_reset (gpgme_ctx_t ctx, int synchronous);
+
+/* Parse the INV_RECP status line in ARGS and return the result in
+ KEY. */
+gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key);
+
+/* Parse the PLAINTEXT status line in ARGS and return the result in
+ FILENAMEP. */
+gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep);
+
+
+
+/* From verify.c. */
+gpgme_error_t _gpgme_op_verify_init_result (gpgme_ctx_t ctx);
+gpgme_error_t _gpgme_verify_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+
+
+/* From decrypt.c. */
+gpgme_error_t _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx);
+gpgme_error_t _gpgme_decrypt_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+
+
+/* From sign.c. */
+
+/* Create an initial op data object for signing. Needs to be called
+ once before calling _gpgme_sign_status_handler. */
+gpgme_error_t _gpgme_op_sign_init_result (gpgme_ctx_t ctx);
+
+/* Process a status line for signing operations. */
+gpgme_error_t _gpgme_sign_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+
+
+/* From encrypt.c. */
+
+/* Create an initial op data object for encrypt. Needs to be called
+ once before calling _gpgme_encrypt_status_handler. */
+gpgme_error_t _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx);
+
+/* Process a status line for encryption operations. */
+gpgme_error_t _gpgme_encrypt_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+
+
+/* From passphrase.c. */
+gpgme_error_t _gpgme_passphrase_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+gpgme_error_t _gpgme_passphrase_command_handler (void *opaque,
+ gpgme_status_code_t code,
+ const char *key, int fd,
+ int *processed);
+
+
+/* From progress.c. */
+gpgme_error_t _gpgme_progress_status_handler (void *priv,
+ gpgme_status_code_t code,
+ char *args);
+
+
+/* From key.c. */
+gpgme_error_t _gpgme_key_new (gpgme_key_t *r_key);
+gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key,
+ gpgme_subkey_t *r_subkey);
+gpgme_error_t _gpgme_key_append_name (gpgme_key_t key, char *src);
+gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src);
+
+
+/* From keylist.c. */
+void _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data);
+
+
+/* From trust-item.c. */
+
+/* Create a new trust item. */
+gpgme_error_t _gpgme_trust_item_new (gpgme_trust_item_t *r_item);
+
+
+/* From trustlist.c. */
+void _gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data);
+
+
+/* From version.c. */
+
+/* Return true if MY_VERSION is at least RETQ_VERSION, and false
+ otherwise. */
+int _gpgme_compare_versions (const char *my_version,
+ const char *req_version);
+char *_gpgme_get_program_version (const char *const path);
+
+
+/* From sig-notation.c. */
+
+/* Create a new, empty signature notation data object. */
+gpgme_error_t _gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
+ const char *name, int name_len,
+ const char *value, int value_len,
+ gpgme_sig_notation_flags_t flags);
+
+/* Free the signature notation object and all associated resources.
+ The object must already be removed from any linked list as the next
+ pointer is ignored. */
+void _gpgme_sig_notation_free (gpgme_sig_notation_t notation);
+
+/* Parse a notation or policy URL subpacket. If the packet type is
+ not known, return no error but NULL in NOTATION. */
+gpgme_error_t _gpgme_parse_notation (gpgme_sig_notation_t *notationp,
+ int type, int pkflags, int len,
+ char *data);
+
+#endif /* OPS_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/passphrase.c b/libtdenetwork/libgpgme-copy/gpgme/passphrase.c
new file mode 100644
index 000000000..a07cb8d4d
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/passphrase.c
@@ -0,0 +1,153 @@
+/* passphrase.c - Passphrase callback.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ int no_passphrase;
+ char *uid_hint;
+ char *passphrase_info;
+ int bad_passphrase;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+
+ if (opd->passphrase_info)
+ free (opd->passphrase_info);
+ if (opd->uid_hint)
+ free (opd->uid_hint);
+}
+
+
+gpgme_error_t
+_gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
+ char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_USERID_HINT:
+ if (opd->uid_hint)
+ free (opd->uid_hint);
+ if (!(opd->uid_hint = strdup (args)))
+ return gpg_error_from_errno (errno);
+ break;
+
+ case GPGME_STATUS_BAD_PASSPHRASE:
+ opd->bad_passphrase++;
+ opd->no_passphrase = 0;
+ break;
+
+ case GPGME_STATUS_GOOD_PASSPHRASE:
+ opd->bad_passphrase = 0;
+ opd->no_passphrase = 0;
+ break;
+
+ case GPGME_STATUS_NEED_PASSPHRASE:
+ case GPGME_STATUS_NEED_PASSPHRASE_SYM:
+ case GPGME_STATUS_NEED_PASSPHRASE_PIN:
+ if (opd->passphrase_info)
+ free (opd->passphrase_info);
+ opd->passphrase_info = strdup (args);
+ if (!opd->passphrase_info)
+ return gpg_error_from_errno (errno);
+ break;
+
+ case GPGME_STATUS_MISSING_PASSPHRASE:
+ opd->no_passphrase = 1;
+ break;
+
+ case GPGME_STATUS_EOF:
+ if (opd->no_passphrase || opd->bad_passphrase)
+ return gpg_error (GPG_ERR_BAD_PASSPHRASE);
+ break;
+
+ default:
+ /* Ignore all other codes. */
+ break;
+ }
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
+ const char *key, int fd, int *processed)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ assert (ctx->passphrase_cb);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ if (code == GPGME_STATUS_GET_HIDDEN
+ && (!strcmp (key, "passphrase.enter")
+ || !strcmp (key, "passphrase.pin.ask")))
+ {
+ if (processed)
+ *processed = 1;
+
+ err = ctx->passphrase_cb (ctx->passphrase_cb_value,
+ opd->uid_hint, opd->passphrase_info,
+ opd->bad_passphrase, fd);
+
+ /* Reset bad passphrase flag, in case it is correct now. */
+ opd->bad_passphrase = 0;
+
+ return err;
+ }
+
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/posix-io.c b/libtdenetwork/libgpgme-copy/gpgme/posix-io.c
new file mode 100644
index 000000000..7f3b80e70
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/posix-io.c
@@ -0,0 +1,497 @@
+/* posix-io.c - Posix I/O functions
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "util.h"
+#include "priv-io.h"
+#include "sema.h"
+#include "ath.h"
+#include "debug.h"
+
+
+void
+_gpgme_io_subsystem_init (void)
+{
+ struct sigaction act;
+
+ sigaction (SIGPIPE, NULL, &act);
+ if (act.sa_handler == SIG_DFL)
+ {
+ act.sa_handler = SIG_IGN;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction (SIGPIPE, &act, NULL);
+ }
+}
+
+
+/* Write the printable version of FD to the buffer BUF of length
+ BUFLEN. The printable version is the representation on the command
+ line that the child process expects. */
+int
+_gpgme_io_fd2str (char *buf, int buflen, int fd)
+{
+ return snprintf (buf, buflen, "%d", fd);
+}
+
+
+static struct
+{
+ void (*handler) (int,void*);
+ void *value;
+} notify_table[256];
+
+int
+_gpgme_io_read (int fd, void *buffer, size_t count)
+{
+ int nread;
+ int saved_errno;
+
+ DEBUG2 ("fd %d: about to read %d bytes\n", fd, (int) count);
+ do
+ {
+ nread = _gpgme_ath_read (fd, buffer, count);
+ }
+ while (nread == -1 && errno == EINTR);
+ saved_errno = errno;
+ DEBUG2 ("fd %d: got %d bytes\n", fd, nread);
+ if (nread > 0)
+ _gpgme_debug (2, "fd %d: got `%.*s'\n", fd, nread, buffer);
+ errno = saved_errno;
+ return nread;
+}
+
+
+int
+_gpgme_io_write (int fd, const void *buffer, size_t count)
+{
+ int saved_errno;
+ int nwritten;
+
+ DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int) count);
+ _gpgme_debug (2, "fd %d: write `%.*s'\n", fd, (int) count, buffer);
+ do
+ {
+ nwritten = _gpgme_ath_write (fd, buffer, count);
+ }
+ while (nwritten == -1 && errno == EINTR);
+ saved_errno = errno;
+ DEBUG2 ("fd %d: wrote %d bytes\n", fd, (int) nwritten);
+ errno = saved_errno;
+ return nwritten;
+}
+
+
+int
+_gpgme_io_pipe (int filedes[2], int inherit_idx)
+{
+ int saved_errno;
+ int err;
+
+ err = pipe (filedes);
+ if (err < 0)
+ return err;
+ /* FIXME: Should get the old flags first. */
+ err = fcntl (filedes[1 - inherit_idx], F_SETFD, FD_CLOEXEC);
+ saved_errno = errno;
+ if (err < 0)
+ {
+ close (filedes[0]);
+ close (filedes[1]);
+ }
+ errno = saved_errno;
+ return err;
+}
+
+
+int
+_gpgme_io_close (int fd)
+{
+ if (fd == -1)
+ return -1;
+ /* First call the notify handler. */
+ DEBUG1 ("closing fd %d", fd);
+ if (fd >= 0 && fd < (int) DIM (notify_table))
+ {
+ if (notify_table[fd].handler)
+ {
+ notify_table[fd].handler (fd, notify_table[fd].value);
+ notify_table[fd].handler = NULL;
+ notify_table[fd].value = NULL;
+ }
+ }
+ /* Then do the close. */
+ return close (fd);
+}
+
+
+int
+_gpgme_io_set_close_notify (int fd, void (*handler)(int, void*), void *value)
+{
+ assert (fd != -1);
+
+ if (fd < 0 || fd >= (int) DIM (notify_table))
+ return -1;
+ DEBUG1 ("set notification for fd %d", fd);
+ notify_table[fd].handler = handler;
+ notify_table[fd].value = value;
+ return 0;
+}
+
+
+int
+_gpgme_io_set_nonblocking (int fd)
+{
+ int flags;
+
+ flags = fcntl (fd, F_GETFL, 0);
+ if (flags == -1)
+ return -1;
+ flags |= O_NONBLOCK;
+ return fcntl (fd, F_SETFL, flags);
+}
+
+
+static int
+_gpgme_io_waitpid (int pid, int hang, int *r_status, int *r_signal)
+{
+ int status;
+
+ *r_status = 0;
+ *r_signal = 0;
+ if (_gpgme_ath_waitpid (pid, &status, hang? 0 : WNOHANG) == pid)
+ {
+ if (WIFSIGNALED (status))
+ {
+ *r_status = 4; /* Need some value here. */
+ *r_signal = WTERMSIG (status);
+ }
+ else if (WIFEXITED (status))
+ *r_status = WEXITSTATUS (status);
+ else
+ *r_status = 4; /* Oops. */
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Returns 0 on success, -1 on error. */
+int
+_gpgme_io_spawn (const char *path, char **argv,
+ struct spawn_fd_item_s *fd_child_list,
+ struct spawn_fd_item_s *fd_parent_list)
+{
+ pid_t pid;
+ int i;
+ int status, signo;
+
+ pid = fork ();
+ if (pid == -1)
+ return -1;
+
+ if (!pid)
+ {
+ /* Intermediate child to prevent zombie processes. */
+ if ((pid = fork ()) == 0)
+ {
+ /* Child. */
+ int duped_stdin = 0;
+ int duped_stderr = 0;
+
+ /* First close all fds which will not be duped. */
+ for (i=0; fd_child_list[i].fd != -1; i++)
+ if (fd_child_list[i].dup_to == -1)
+ close (fd_child_list[i].fd);
+
+ /* And now dup and close the rest. */
+ for (i=0; fd_child_list[i].fd != -1; i++)
+ {
+ if (fd_child_list[i].dup_to != -1)
+ {
+ if (dup2 (fd_child_list[i].fd,
+ fd_child_list[i].dup_to) == -1)
+ {
+ DEBUG1 ("dup2 failed in child: %s\n", strerror (errno));
+ _exit (8);
+ }
+ if (fd_child_list[i].dup_to == 0)
+ duped_stdin=1;
+ if (fd_child_list[i].dup_to == 2)
+ duped_stderr=1;
+ close (fd_child_list[i].fd);
+ }
+ }
+
+ if (!duped_stdin || !duped_stderr)
+ {
+ int fd = open ("/dev/null", O_RDWR);
+ if (fd == -1)
+ {
+ DEBUG1 ("can't open `/dev/null': %s\n", strerror (errno));
+ _exit (8);
+ }
+ /* Make sure that the process has a connected stdin. */
+ if (!duped_stdin)
+ {
+ if (dup2 (fd, 0) == -1)
+ {
+ DEBUG1("dup2(/dev/null, 0) failed: %s\n",
+ strerror (errno));
+ _exit (8);
+ }
+ }
+ if (!duped_stderr)
+ if (dup2 (fd, 2) == -1)
+ {
+ DEBUG1 ("dup2(dev/null, 2) failed: %s\n",
+ strerror (errno));
+ _exit (8);
+ }
+ close (fd);
+ }
+
+ execv ( path, argv );
+ /* Hmm: in that case we could write a special status code to the
+ status-pipe. */
+ DEBUG1 ("exec of `%s' failed\n", path);
+ _exit (8);
+ } /* End child. */
+ if (pid == -1)
+ _exit (1);
+ else
+ _exit (0);
+ }
+
+ _gpgme_io_waitpid (pid, 1, &status, &signo);
+ if (status)
+ return -1;
+
+ /* .dup_to is not used in the parent list. */
+ for (i = 0; fd_parent_list[i].fd != -1; i++)
+ _gpgme_io_close (fd_parent_list[i].fd);
+
+ return 0;
+}
+
+
+/*
+ * Select on the list of fds.
+ * Returns: -1 = error
+ * 0 = timeout or nothing to select
+ * >0 = number of signaled fds
+ */
+int
+_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
+{
+ fd_set readfds;
+ fd_set writefds;
+ unsigned int i;
+ int any, max_fd, n, count;
+ struct timeval timeout = { 1, 0 }; /* Use a 1s timeout. */
+ void *dbg_help = NULL;
+
+ FD_ZERO (&readfds);
+ FD_ZERO (&writefds);
+ max_fd = 0;
+ if (nonblock)
+ timeout.tv_sec = 0;
+
+ DEBUG_BEGIN (dbg_help, 3, "gpgme:select on [ ");
+ any = 0;
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd == -1)
+ continue;
+ if (fds[i].frozen)
+ DEBUG_ADD1 (dbg_help, "f%d ", fds[i].fd);
+ else if (fds[i].for_read)
+ {
+ assert (!FD_ISSET (fds[i].fd, &readfds));
+ FD_SET (fds[i].fd, &readfds);
+ if (fds[i].fd > max_fd)
+ max_fd = fds[i].fd;
+ DEBUG_ADD1 (dbg_help, "r%d ", fds[i].fd);
+ any = 1;
+ }
+ else if (fds[i].for_write)
+ {
+ assert (!FD_ISSET (fds[i].fd, &writefds));
+ FD_SET (fds[i].fd, &writefds);
+ if (fds[i].fd > max_fd)
+ max_fd = fds[i].fd;
+ DEBUG_ADD1 (dbg_help, "w%d ", fds[i].fd);
+ any = 1;
+ }
+ fds[i].signaled = 0;
+ }
+ DEBUG_END (dbg_help, "]");
+ if (!any)
+ return 0;
+
+ do
+ {
+ count = _gpgme_ath_select (max_fd + 1, &readfds, &writefds, NULL,
+ &timeout);
+ }
+ while (count < 0 && errno == EINTR);
+ if (count < 0)
+ {
+ int saved_errno = errno;
+ DEBUG1 ("_gpgme_io_select failed: %s\n", strerror (errno));
+ errno = saved_errno;
+ return -1; /* error */
+ }
+
+ DEBUG_BEGIN (dbg_help, 3, "select OK [ ");
+ if (DEBUG_ENABLED (dbg_help))
+ {
+ for (i = 0; i <= max_fd; i++)
+ {
+ if (FD_ISSET (i, &readfds))
+ DEBUG_ADD1 (dbg_help, "r%d ", i);
+ if (FD_ISSET (i, &writefds))
+ DEBUG_ADD1 (dbg_help, "w%d ", i);
+ }
+ DEBUG_END (dbg_help, "]");
+ }
+
+ /* n is used to optimize it a little bit. */
+ for (n = count, i = 0; i < nfds && n; i++)
+ {
+ if (fds[i].fd == -1)
+ ;
+ else if (fds[i].for_read)
+ {
+ if (FD_ISSET (fds[i].fd, &readfds))
+ {
+ fds[i].signaled = 1;
+ n--;
+ }
+ }
+ else if (fds[i].for_write)
+ {
+ if (FD_ISSET (fds[i].fd, &writefds))
+ {
+ fds[i].signaled = 1;
+ n--;
+ }
+ }
+ }
+ return count;
+}
+
+
+int
+_gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags)
+{
+ int nread;
+ int saved_errno;
+ struct iovec *iov;
+
+ nread = 0;
+ iov = msg->msg_iov;
+ while (iov < msg->msg_iov + msg->msg_iovlen)
+ {
+ nread += iov->iov_len;
+ iov++;
+ }
+
+ DEBUG2 ("fd %d: about to receive %d bytes\n",
+ fd, (int) nread);
+ do
+ {
+ nread = _gpgme_ath_recvmsg (fd, msg, flags);
+ }
+ while (nread == -1 && errno == EINTR);
+ saved_errno = errno;
+ DEBUG2 ("fd %d: got %d bytes\n", fd, nread);
+ if (nread > 0)
+ {
+ int nr = nread;
+
+ iov = msg->msg_iov;
+ while (nr > 0)
+ {
+ int len = nr > iov->iov_len ? iov->iov_len : nr;
+ _gpgme_debug (2, "fd %d: got `%.*s'\n", fd, len,
+ msg->msg_iov->iov_base);
+ iov++;
+ nr -= len;
+ }
+ }
+ errno = saved_errno;
+ return nread;
+}
+
+
+int
+_gpgme_io_sendmsg (int fd, const struct msghdr *msg, int flags)
+{
+ int saved_errno;
+ int nwritten;
+ struct iovec *iov;
+
+ nwritten = 0;
+ iov = msg->msg_iov;
+ while (iov < msg->msg_iov + msg->msg_iovlen)
+ {
+ nwritten += iov->iov_len;
+ iov++;
+ }
+
+ DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int) nwritten);
+ iov = msg->msg_iov;
+ while (nwritten > 0)
+ {
+ int len = nwritten > iov->iov_len ? iov->iov_len : nwritten;
+ _gpgme_debug (2, "fd %d: write `%.*s'\n", fd, len,
+ msg->msg_iov->iov_base);
+ iov++;
+ nwritten -= len;
+ }
+
+ do
+ {
+ nwritten = _gpgme_ath_sendmsg (fd, msg, flags);
+ }
+ while (nwritten == -1 && errno == EINTR);
+ saved_errno = errno;
+ DEBUG2 ("fd %d: wrote %d bytes\n", fd, (int) nwritten);
+ errno = saved_errno;
+ return nwritten;
+}
+
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/posix-sema.c b/libtdenetwork/libgpgme-copy/gpgme/posix-sema.c
new file mode 100644
index 000000000..477f07872
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/posix-sema.c
@@ -0,0 +1,62 @@
+/* posix-sema.c
+ Copyright (C) 2001 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "util.h"
+#include "sema.h"
+#include "ath.h"
+
+void
+_gpgme_sema_subsystem_init ()
+{
+}
+
+void
+_gpgme_sema_cs_enter (struct critsect_s *s)
+{
+ _gpgme_ath_mutex_lock (&s->private);
+}
+
+void
+_gpgme_sema_cs_leave (struct critsect_s *s)
+{
+ _gpgme_ath_mutex_unlock (&s->private);
+}
+
+void
+_gpgme_sema_cs_destroy (struct critsect_s *s)
+{
+ _gpgme_ath_mutex_destroy (&s->private);
+ s->private = NULL;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/posix-util.c b/libtdenetwork/libgpgme-copy/gpgme/posix-util.c
new file mode 100644
index 000000000..ecb597617
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/posix-util.c
@@ -0,0 +1,57 @@
+/* posix-util.c - Utility functions for Posix
+ Copyright (C) 2001 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "util.h"
+
+const char *
+_gpgme_get_gpg_path (void)
+{
+#ifdef GPG_PATH
+ return GPG_PATH;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+_gpgme_get_gpgsm_path (void)
+{
+#ifdef GPGSM_PATH
+ return GPGSM_PATH;
+#else
+ return NULL;
+#endif
+}
+
+/* See w32-util.c */
+int
+_gpgme_get_conf_int (const char *key, int *value)
+{
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/priv-io.h b/libtdenetwork/libgpgme-copy/gpgme/priv-io.h
new file mode 100644
index 000000000..9a908570f
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/priv-io.h
@@ -0,0 +1,67 @@
+/* priv-io.h - Interface to the private I/O functions.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef IO_H
+#define IO_H
+
+
+/* A single file descriptor passed to spawn. For child fds, dup_to
+ specifies the fd it should become in the child. */
+struct spawn_fd_item_s
+{
+ int fd;
+ int dup_to;
+};
+
+struct io_select_fd_s
+{
+ int fd;
+ int for_read;
+ int for_write;
+ int signaled;
+ int frozen;
+ void *opaque;
+};
+
+/* These function are either defined in posix-io.c or w32-io.c. */
+void _gpgme_io_subsystem_init (void);
+int _gpgme_io_read (int fd, void *buffer, size_t count);
+int _gpgme_io_write (int fd, const void *buffer, size_t count);
+int _gpgme_io_pipe (int filedes[2], int inherit_idx);
+int _gpgme_io_close (int fd);
+int _gpgme_io_set_close_notify (int fd, void (*handler) (int, void *),
+ void *value);
+int _gpgme_io_set_nonblocking (int fd);
+
+/* Spawn the executable PATH with ARGV as arguments, after forking
+ close all fds in FD_PARENT_LIST in the parent and close or dup all
+ fds in FD_CHILD_LIST in the child. */
+int _gpgme_io_spawn (const char *path, char **argv,
+ struct spawn_fd_item_s *fd_child_list,
+ struct spawn_fd_item_s *fd_parent_list);
+int _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock);
+
+/* Write the printable version of FD to the buffer BUF of length
+ BUFLEN. The printable version is the representation on the command
+ line that the child process expects. */
+int _gpgme_io_fd2str (char *buf, int buflen, int fd);
+
+#endif /* IO_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/progress.c b/libtdenetwork/libgpgme-copy/gpgme/progress.c
new file mode 100644
index 000000000..cdc87eb8a
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/progress.c
@@ -0,0 +1,81 @@
+/* progress.c - status handler for progress status
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "util.h"
+#include "context.h"
+
+
+gpgme_error_t
+_gpgme_progress_status_handler (void *priv, gpgme_status_code_t code,
+ char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ char *p;
+ char *args_cpy;
+ int type = 0;
+ int current = 0;
+ int total = 0;
+
+ if (code != GPGME_STATUS_PROGRESS || !*args || !ctx->progress_cb)
+ return 0;
+
+ args_cpy = strdup (args);
+ if (!args_cpy)
+ return gpg_error_from_errno (errno);
+
+ p = strchr (args_cpy, ' ');
+ if (p)
+ {
+ *p++ = 0;
+ if (*p)
+ {
+ type = *(unsigned char *)p;
+ p = strchr (p+1, ' ');
+ if (p)
+ {
+ *p++ = 0;
+ if (*p)
+ {
+ current = atoi (p);
+ p = strchr (p+1, ' ');
+ if (p)
+ {
+ *p++ = 0;
+ total = atoi (p);
+ }
+ }
+ }
+ }
+ }
+
+ if (type != 'X')
+ ctx->progress_cb (ctx->progress_cb_value, args_cpy, type, current, total);
+
+ free (args_cpy);
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/putc_unlocked.c b/libtdenetwork/libgpgme-copy/gpgme/putc_unlocked.c
new file mode 100644
index 000000000..a11d1ceab
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/putc_unlocked.c
@@ -0,0 +1,31 @@
+/* putc_unlocked.c - Replacement for putc_unlocked.
+ Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+int
+putc_unlocked (int c, FILE *stream)
+{
+ return putc (c, stream);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/rungpg.c b/libtdenetwork/libgpgme-copy/gpgme/rungpg.c
new file mode 100644
index 000000000..d09cdf3b6
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/rungpg.c
@@ -0,0 +1,2111 @@
+/* rungpg.c - Gpg Engine.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <locale.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "ops.h"
+#include "wait.h"
+#include "context.h" /*temp hack until we have GpmeData methods to do I/O */
+#include "priv-io.h"
+#include "sema.h"
+#include "debug.h"
+
+#include "status-table.h"
+#include "engine-backend.h"
+
+
+/* This type is used to build a list of gpg arguments and data
+ sources/sinks. */
+struct arg_and_data_s
+{
+ struct arg_and_data_s *next;
+ gpgme_data_t data; /* If this is not NULL, use arg below. */
+ int inbound; /* True if this is used for reading from gpg. */
+ int dup_to;
+ int print_fd; /* Print the fd number and not the special form of it. */
+ char arg[1]; /* Used if data above is not used. */
+};
+
+
+struct fd_data_map_s
+{
+ gpgme_data_t data;
+ int inbound; /* true if this is used for reading from gpg */
+ int dup_to;
+ int fd; /* the fd to use */
+ int peer_fd; /* the outher side of the pipe */
+ void *tag;
+};
+
+
+typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
+
+struct engine_gpg
+{
+ char *file_name;
+
+ char *lc_messages;
+ char *lc_ctype;
+
+ struct arg_and_data_s *arglist;
+ struct arg_and_data_s **argtail;
+
+ struct
+ {
+ int fd[2];
+ size_t bufsize;
+ char *buffer;
+ size_t readpos;
+ int eof;
+ engine_status_handler_t fnc;
+ void *fnc_value;
+ void *tag;
+ } status;
+
+ /* This is a kludge - see the comment at colon_line_handler. */
+ struct
+ {
+ int fd[2];
+ size_t bufsize;
+ char *buffer;
+ size_t readpos;
+ int eof;
+ engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
+ void *fnc_value;
+ void *tag;
+ colon_preprocessor_t preprocess_fnc;
+ } colon;
+
+ char **argv;
+ struct fd_data_map_s *fd_data_map;
+
+ /* stuff needed for interactive (command) mode */
+ struct
+ {
+ int used;
+ int fd;
+ void *cb_data;
+ int idx; /* Index in fd_data_map */
+ gpgme_status_code_t code; /* last code */
+ char *keyword; /* what has been requested (malloced) */
+ engine_command_handler_t fnc;
+ void *fnc_value;
+ /* The kludges never end. This is used to couple command handlers
+ with output data in edit key mode. */
+ gpgme_data_t linked_data;
+ int linked_idx;
+ } cmd;
+
+ struct gpgme_io_cbs io_cbs;
+};
+
+typedef struct engine_gpg *engine_gpg_t;
+
+
+static void
+gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
+{
+ engine_gpg_t gpg = engine;
+
+ if (gpg->io_cbs.event)
+ (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
+}
+
+
+static void
+close_notify_handler (int fd, void *opaque)
+{
+ engine_gpg_t gpg = opaque;
+ assert (fd != -1);
+
+ if (gpg->status.fd[0] == fd)
+ {
+ if (gpg->status.tag)
+ (*gpg->io_cbs.remove) (gpg->status.tag);
+ gpg->status.fd[0] = -1;
+ }
+ else if (gpg->status.fd[1] == fd)
+ gpg->status.fd[1] = -1;
+ else if (gpg->colon.fd[0] == fd)
+ {
+ if (gpg->colon.tag)
+ (*gpg->io_cbs.remove) (gpg->colon.tag);
+ gpg->colon.fd[0] = -1;
+ }
+ else if (gpg->colon.fd[1] == fd)
+ gpg->colon.fd[1] = -1;
+ else if (gpg->fd_data_map)
+ {
+ int i;
+
+ for (i = 0; gpg->fd_data_map[i].data; i++)
+ {
+ if (gpg->fd_data_map[i].fd == fd)
+ {
+ if (gpg->fd_data_map[i].tag)
+ (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
+ gpg->fd_data_map[i].fd = -1;
+ break;
+ }
+ if (gpg->fd_data_map[i].peer_fd == fd)
+ {
+ gpg->fd_data_map[i].peer_fd = -1;
+ break;
+ }
+ }
+ }
+}
+
+/* If FRONT is true, push at the front of the list. Use this for
+ options added late in the process. */
+static gpgme_error_t
+add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
+{
+ struct arg_and_data_s *a;
+
+ assert (gpg);
+ assert (arg);
+
+ a = malloc (sizeof *a + strlen (arg));
+ if (!a)
+ return gpg_error_from_errno (errno);
+
+ a->data = NULL;
+ a->dup_to = -1;
+ strcpy (a->arg, arg);
+ if (front)
+ {
+ a->next = gpg->arglist;
+ if (!gpg->arglist)
+ {
+ /* If this is the first argument, we need to update the tail
+ pointer. */
+ gpg->argtail = &a->next;
+ }
+ gpg->arglist = a;
+ }
+ else
+ {
+ a->next = NULL;
+ *gpg->argtail = a;
+ gpg->argtail = &a->next;
+ }
+
+ return 0;
+}
+
+static gpgme_error_t
+add_arg (engine_gpg_t gpg, const char *arg)
+{
+ return add_arg_ext (gpg, arg, 0);
+}
+
+static gpgme_error_t
+add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
+{
+ struct arg_and_data_s *a;
+
+ assert (gpg);
+ assert (data);
+
+ a = malloc (sizeof *a - 1);
+ if (!a)
+ return gpg_error_from_errno (errno);
+ a->next = NULL;
+ a->data = data;
+ a->inbound = inbound;
+ if (dup_to == -2)
+ {
+ a->print_fd = 1;
+ a->dup_to = -1;
+ }
+ else
+ {
+ a->print_fd = 0;
+ a->dup_to = dup_to;
+ }
+ *gpg->argtail = a;
+ gpg->argtail = &a->next;
+ return 0;
+}
+
+
+static char *
+gpg_get_version (const char *file_name)
+{
+ return _gpgme_get_program_version (file_name ? file_name
+ : _gpgme_get_gpg_path ());
+}
+
+
+static const char *
+gpg_get_req_version (void)
+{
+ return NEED_GPG_VERSION;
+}
+
+
+static void
+free_argv (char **argv)
+{
+ int i;
+
+ for (i = 0; argv[i]; i++)
+ free (argv[i]);
+ free (argv);
+}
+
+
+static void
+free_fd_data_map (struct fd_data_map_s *fd_data_map)
+{
+ int i;
+
+ if (!fd_data_map)
+ return;
+
+ for (i = 0; fd_data_map[i].data; i++)
+ {
+ if (fd_data_map[i].fd != -1)
+ _gpgme_io_close (fd_data_map[i].fd);
+ if (fd_data_map[i].peer_fd != -1)
+ _gpgme_io_close (fd_data_map[i].peer_fd);
+ /* Don't release data because this is only a reference. */
+ }
+ free (fd_data_map);
+}
+
+
+static gpgme_error_t
+gpg_cancel (void *engine)
+{
+ engine_gpg_t gpg = engine;
+
+ if (!gpg)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (gpg->status.fd[0] != -1)
+ _gpgme_io_close (gpg->status.fd[0]);
+ if (gpg->status.fd[1] != -1)
+ _gpgme_io_close (gpg->status.fd[1]);
+ if (gpg->colon.fd[0] != -1)
+ _gpgme_io_close (gpg->colon.fd[0]);
+ if (gpg->colon.fd[1] != -1)
+ _gpgme_io_close (gpg->colon.fd[1]);
+ if (gpg->fd_data_map)
+ {
+ free_fd_data_map (gpg->fd_data_map);
+ gpg->fd_data_map = NULL;
+ }
+ if (gpg->cmd.fd != -1)
+ _gpgme_io_close (gpg->cmd.fd);
+
+ return 0;
+}
+
+static void
+gpg_release (void *engine)
+{
+ engine_gpg_t gpg = engine;
+
+ if (!gpg)
+ return;
+
+ gpg_cancel (engine);
+
+ if (gpg->file_name)
+ free (gpg->file_name);
+
+ if (gpg->lc_messages)
+ free (gpg->lc_messages);
+ if (gpg->lc_ctype)
+ free (gpg->lc_ctype);
+
+ while (gpg->arglist)
+ {
+ struct arg_and_data_s *next = gpg->arglist->next;
+
+ if (gpg->arglist)
+ free (gpg->arglist);
+ gpg->arglist = next;
+ }
+
+ if (gpg->status.buffer)
+ free (gpg->status.buffer);
+ if (gpg->colon.buffer)
+ free (gpg->colon.buffer);
+ if (gpg->argv)
+ free_argv (gpg->argv);
+ if (gpg->cmd.keyword)
+ free (gpg->cmd.keyword);
+
+ free (gpg);
+}
+
+
+static gpgme_error_t
+gpg_new (void **engine, const char *file_name, const char *home_dir)
+{
+ engine_gpg_t gpg;
+ gpgme_error_t rc = 0;
+ char *dft_display = NULL;
+ char dft_ttyname[64];
+ char *dft_ttytype = NULL;
+
+ gpg = calloc (1, sizeof *gpg);
+ if (!gpg)
+ return gpg_error_from_errno (errno);
+
+ if (file_name)
+ {
+ gpg->file_name = strdup (file_name);
+ if (!gpg->file_name)
+ {
+ rc = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ }
+
+ gpg->argtail = &gpg->arglist;
+ gpg->status.fd[0] = -1;
+ gpg->status.fd[1] = -1;
+ gpg->colon.fd[0] = -1;
+ gpg->colon.fd[1] = -1;
+ gpg->cmd.fd = -1;
+ gpg->cmd.idx = -1;
+ gpg->cmd.linked_data = NULL;
+ gpg->cmd.linked_idx = -1;
+
+ /* Allocate the read buffer for the status pipe. */
+ gpg->status.bufsize = 1024;
+ gpg->status.readpos = 0;
+ gpg->status.buffer = malloc (gpg->status.bufsize);
+ if (!gpg->status.buffer)
+ {
+ rc = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ /* In any case we need a status pipe - create it right here and
+ don't handle it with our generic gpgme_data_t mechanism. */
+ if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
+ {
+ rc = gpg_error_from_errno (errno);
+ goto leave;
+ }
+ if (_gpgme_io_set_close_notify (gpg->status.fd[0],
+ close_notify_handler, gpg)
+ || _gpgme_io_set_close_notify (gpg->status.fd[1],
+ close_notify_handler, gpg))
+ {
+ rc = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
+ gpg->status.eof = 0;
+
+ if (home_dir)
+ {
+ rc = add_arg (gpg, "--homedir");
+ if (!rc)
+ rc = add_arg (gpg, home_dir);
+ if (rc)
+ goto leave;
+ }
+
+ rc = add_arg (gpg, "--status-fd");
+ if (rc)
+ goto leave;
+
+ {
+ char buf[25];
+ _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
+ rc = add_arg (gpg, buf);
+ if (rc)
+ goto leave;
+ }
+
+ rc = add_arg (gpg, "--no-tty");
+ if (!rc)
+ rc = add_arg (gpg, "--charset");
+ if (!rc)
+ rc = add_arg (gpg, "utf8");
+ if (!rc)
+ rc = add_arg (gpg, "--enable-progress-filter");
+ if (rc)
+ goto leave;
+
+ rc = _gpgme_getenv ("DISPLAY", &dft_display);
+ if (dft_display)
+ {
+ rc = add_arg (gpg, "--display");
+ if (!rc)
+ rc = add_arg (gpg, dft_display);
+
+ free (dft_display);
+ }
+ if (rc)
+ goto leave;
+
+ if (isatty (1))
+ {
+ if (ttyname_r (1, dft_ttyname, sizeof (dft_ttyname)))
+ rc = gpg_error_from_errno (errno);
+ else
+ {
+ rc = add_arg (gpg, "--ttyname");
+ if (!rc)
+ rc = add_arg (gpg, dft_ttyname);
+ if (!rc)
+ {
+ rc = _gpgme_getenv ("TERM", &dft_ttytype);
+ if (!rc)
+ goto leave;
+
+ rc = add_arg (gpg, "--ttytype");
+ if (!rc)
+ rc = add_arg (gpg, dft_ttytype);
+
+ free (dft_ttytype);
+ }
+ }
+ if (rc)
+ goto leave;
+ }
+
+ leave:
+ if (rc)
+ gpg_release (gpg);
+ else
+ *engine = gpg;
+ return rc;
+}
+
+
+static gpgme_error_t
+gpg_set_locale (void *engine, int category, const char *value)
+{
+ engine_gpg_t gpg = engine;
+
+ if (category == LC_CTYPE)
+ {
+ if (gpg->lc_ctype)
+ {
+ free (gpg->lc_ctype);
+ gpg->lc_ctype = NULL;
+ }
+ if (value)
+ {
+ gpg->lc_ctype = strdup (value);
+ if (!gpg->lc_ctype)
+ return gpg_error_from_syserror ();
+ }
+ }
+#ifdef LC_MESSAGES
+ else if (category == LC_MESSAGES)
+ {
+ if (gpg->lc_messages)
+ {
+ free (gpg->lc_messages);
+ gpg->lc_messages = NULL;
+ }
+ if (value)
+ {
+ gpg->lc_messages = strdup (value);
+ if (!gpg->lc_messages)
+ return gpg_error_from_syserror ();
+ }
+ }
+#endif /* LC_MESSAGES */
+ else
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ return 0;
+}
+
+
+/* Note, that the status_handler is allowed to modifiy the args
+ value. */
+static void
+gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
+ void *fnc_value)
+{
+ engine_gpg_t gpg = engine;
+
+ gpg->status.fnc = fnc;
+ gpg->status.fnc_value = fnc_value;
+}
+
+/* Kludge to process --with-colon output. */
+static gpgme_error_t
+gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
+ void *fnc_value)
+{
+ engine_gpg_t gpg = engine;
+
+ gpg->colon.bufsize = 1024;
+ gpg->colon.readpos = 0;
+ gpg->colon.buffer = malloc (gpg->colon.bufsize);
+ if (!gpg->colon.buffer)
+ return gpg_error_from_errno (errno);
+
+ if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
+ {
+ int saved_errno = errno;
+ free (gpg->colon.buffer);
+ gpg->colon.buffer = NULL;
+ return gpg_error_from_errno (saved_errno);
+ }
+ if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
+ || _gpgme_io_set_close_notify (gpg->colon.fd[1],
+ close_notify_handler, gpg))
+ return gpg_error (GPG_ERR_GENERAL);
+ gpg->colon.eof = 0;
+ gpg->colon.fnc = fnc;
+ gpg->colon.fnc_value = fnc_value;
+ return 0;
+}
+
+
+static gpgme_error_t
+command_handler (void *opaque, int fd)
+{
+ gpgme_error_t err;
+ engine_gpg_t gpg = (engine_gpg_t) opaque;
+ int processed = 0;
+
+ assert (gpg->cmd.used);
+ assert (gpg->cmd.code);
+ assert (gpg->cmd.fnc);
+
+ err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
+ &processed);
+ if (err)
+ return err;
+
+ /* We always need to send at least a newline character. */
+ if (!processed)
+ _gpgme_io_write (fd, "\n", 1);
+
+ gpg->cmd.code = 0;
+ /* And sleep again until read_status will wake us up again. */
+ /* XXX We must check if there are any more fds active after removing
+ this one. */
+ (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
+ gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
+ gpg->fd_data_map[gpg->cmd.idx].fd = -1;
+
+ return 0;
+}
+
+
+
+/* The Fnc will be called to get a value for one of the commands with
+ a key KEY. If the Code pssed to FNC is 0, the function may release
+ resources associated with the returned value from another call. To
+ match such a second call to a first call, the returned value from
+ the first call is passed as keyword. */
+static gpgme_error_t
+gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
+ void *fnc_value, gpgme_data_t linked_data)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t rc;
+
+ rc = add_arg (gpg, "--command-fd");
+ if (rc)
+ return rc;
+
+ /* This is a hack. We don't have a real data object. The only
+ thing that matters is that we use something unique, so we use the
+ address of the cmd structure in the gpg object. */
+ rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
+ if (rc)
+ return rc;
+
+ gpg->cmd.fnc = fnc;
+ gpg->cmd.cb_data = (void *) &gpg->cmd;
+ gpg->cmd.fnc_value = fnc_value;
+ gpg->cmd.linked_data = linked_data;
+ gpg->cmd.used = 1;
+ return 0;
+}
+
+
+static gpgme_error_t
+build_argv (engine_gpg_t gpg)
+{
+ gpgme_error_t err;
+ struct arg_and_data_s *a;
+ struct fd_data_map_s *fd_data_map;
+ size_t datac=0, argc=0;
+ char **argv;
+ int need_special = 0;
+ int use_agent = 0;
+ char *p;
+
+ /* We don't want to use the agent with a malformed environment
+ variable. This is only a very basic test but sufficient to make
+ our life in the regression tests easier. */
+ err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
+ if (err)
+ return err;
+ use_agent = (p && strchr (p, ':'));
+ if (p)
+ free (p);
+
+ if (gpg->argv)
+ {
+ free_argv (gpg->argv);
+ gpg->argv = NULL;
+ }
+ if (gpg->fd_data_map)
+ {
+ free_fd_data_map (gpg->fd_data_map);
+ gpg->fd_data_map = NULL;
+ }
+
+ argc++; /* For argv[0]. */
+ for (a = gpg->arglist; a; a = a->next)
+ {
+ argc++;
+ if (a->data)
+ {
+ /*fprintf (stderr, "build_argv: data\n" );*/
+ datac++;
+ if (a->dup_to == -1 && !a->print_fd)
+ need_special = 1;
+ }
+ else
+ {
+ /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
+ }
+ }
+ if (need_special)
+ argc++;
+ if (use_agent)
+ argc++;
+ if (!gpg->cmd.used)
+ argc++; /* --batch */
+ argc += 1; /* --no-sk-comment */
+
+ argv = calloc (argc + 1, sizeof *argv);
+ if (!argv)
+ return gpg_error_from_errno (errno);
+ fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
+ if (!fd_data_map)
+ {
+ int saved_errno = errno;
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ argc = datac = 0;
+ argv[argc] = strdup ("gpg"); /* argv[0] */
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ if (need_special)
+ {
+ argv[argc] = strdup ("--enable-special-filenames");
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ }
+ if (use_agent)
+ {
+ argv[argc] = strdup ("--use-agent");
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ }
+ if (!gpg->cmd.used)
+ {
+ argv[argc] = strdup ("--batch");
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ }
+ argv[argc] = strdup ("--no-sk-comment");
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ for (a = gpg->arglist; a; a = a->next)
+ {
+ if (a->data)
+ {
+ /* Create a pipe to pass it down to gpg. */
+ fd_data_map[datac].inbound = a->inbound;
+
+ /* Create a pipe. */
+ {
+ int fds[2];
+
+ if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
+ == -1)
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error (saved_errno);
+ }
+ if (_gpgme_io_set_close_notify (fds[0],
+ close_notify_handler, gpg)
+ || _gpgme_io_set_close_notify (fds[1],
+ close_notify_handler,
+ gpg))
+ {
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ /* If the data_type is FD, we have to do a dup2 here. */
+ if (fd_data_map[datac].inbound)
+ {
+ fd_data_map[datac].fd = fds[0];
+ fd_data_map[datac].peer_fd = fds[1];
+ }
+ else
+ {
+ fd_data_map[datac].fd = fds[1];
+ fd_data_map[datac].peer_fd = fds[0];
+ }
+ }
+
+ /* Hack to get hands on the fd later. */
+ if (gpg->cmd.used)
+ {
+ if (gpg->cmd.cb_data == a->data)
+ {
+ assert (gpg->cmd.idx == -1);
+ gpg->cmd.idx = datac;
+ }
+ else if (gpg->cmd.linked_data == a->data)
+ {
+ assert (gpg->cmd.linked_idx == -1);
+ gpg->cmd.linked_idx = datac;
+ }
+ }
+
+ fd_data_map[datac].data = a->data;
+ fd_data_map[datac].dup_to = a->dup_to;
+ if (a->dup_to == -1)
+ {
+ char *ptr;
+ int buflen = 25;
+
+ argv[argc] = malloc (buflen);
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+
+ ptr = argv[argc];
+ if (!a->print_fd)
+ {
+ *(ptr++) = '-';
+ *(ptr++) = '&';
+ buflen -= 2;
+ }
+
+ _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
+ argc++;
+ }
+ datac++;
+ }
+ else
+ {
+ argv[argc] = strdup (a->arg);
+ if (!argv[argc])
+ {
+ int saved_errno = errno;
+ free (fd_data_map);
+ free_argv (argv);
+ return gpg_error_from_errno (saved_errno);
+ }
+ argc++;
+ }
+ }
+
+ gpg->argv = argv;
+ gpg->fd_data_map = fd_data_map;
+ return 0;
+}
+
+
+static gpgme_error_t
+add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
+ void **tag)
+{
+ gpgme_error_t err;
+
+ err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
+ if (err)
+ return err;
+ if (!dir)
+ /* FIXME Kludge around poll() problem. */
+ err = _gpgme_io_set_nonblocking (fd);
+ return err;
+}
+
+
+static int
+status_cmp (const void *ap, const void *bp)
+{
+ const struct status_table_s *a = ap;
+ const struct status_table_s *b = bp;
+
+ return strcmp (a->name, b->name);
+}
+
+
+/* Handle the status output of GnuPG. This function does read entire
+ lines and passes them as C strings to the callback function (we can
+ use C Strings because the status output is always UTF-8 encoded).
+ Of course we have to buffer the lines to cope with long lines
+ e.g. with a large user ID. Note: We can optimize this to only cope
+ with status line code we know about and skip all other stuff
+ without buffering (i.e. without extending the buffer). */
+static gpgme_error_t
+read_status (engine_gpg_t gpg)
+{
+ char *p;
+ int nread;
+ size_t bufsize = gpg->status.bufsize;
+ char *buffer = gpg->status.buffer;
+ size_t readpos = gpg->status.readpos;
+
+ assert (buffer);
+ if (bufsize - readpos < 256)
+ {
+ /* Need more room for the read. */
+ bufsize += 1024;
+ buffer = realloc (buffer, bufsize);
+ if (!buffer)
+ return gpg_error_from_errno (errno);
+ }
+
+ nread = _gpgme_io_read (gpg->status.fd[0],
+ buffer + readpos, bufsize-readpos);
+ if (nread == -1)
+ return gpg_error_from_errno (errno);
+
+ if (!nread)
+ {
+ gpg->status.eof = 1;
+ if (gpg->status.fnc)
+ {
+ gpgme_error_t err;
+ err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
+ if (err)
+ return err;
+ }
+ return 0;
+ }
+
+ while (nread > 0)
+ {
+ for (p = buffer + readpos; nread; nread--, p++)
+ {
+ if (*p == '\n')
+ {
+ /* (we require that the last line is terminated by a LF) */
+ if (p > buffer && p[-1] == '\r')
+ p[-1] = 0;
+ *p = 0;
+ if (!strncmp (buffer, "[GNUPG:] ", 9)
+ && buffer[9] >= 'A' && buffer[9] <= 'Z')
+ {
+ struct status_table_s t, *r;
+ char *rest;
+
+ rest = strchr (buffer + 9, ' ');
+ if (!rest)
+ rest = p; /* Set to an empty string. */
+ else
+ *rest++ = 0;
+
+ t.name = buffer+9;
+ /* (the status table has one extra element) */
+ r = bsearch (&t, status_table, DIM(status_table) - 1,
+ sizeof t, status_cmp);
+ if (r)
+ {
+ if (gpg->cmd.used
+ && (r->code == GPGME_STATUS_GET_BOOL
+ || r->code == GPGME_STATUS_GET_LINE
+ || r->code == GPGME_STATUS_GET_HIDDEN))
+ {
+ gpg->cmd.code = r->code;
+ if (gpg->cmd.keyword)
+ free (gpg->cmd.keyword);
+ gpg->cmd.keyword = strdup (rest);
+ if (!gpg->cmd.keyword)
+ return gpg_error_from_errno (errno);
+ /* This should be the last thing we have
+ received and the next thing will be that
+ the command handler does its action. */
+ if (nread > 1)
+ DEBUG0 ("ERROR, unexpected data in read_status");
+
+ add_io_cb (gpg, gpg->cmd.fd, 0,
+ command_handler, gpg,
+ &gpg->fd_data_map[gpg->cmd.idx].tag);
+ gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
+ gpg->cmd.fd = -1;
+ }
+ else if (gpg->status.fnc)
+ {
+ gpgme_error_t err;
+ err = gpg->status.fnc (gpg->status.fnc_value,
+ r->code, rest);
+ if (err)
+ return err;
+ }
+
+ if (r->code == GPGME_STATUS_END_STREAM)
+ {
+ if (gpg->cmd.used)
+ {
+ /* Before we can actually add the
+ command fd, we might have to flush
+ the linked output data pipe. */
+ if (gpg->cmd.linked_idx != -1
+ && gpg->fd_data_map[gpg->cmd.linked_idx].fd
+ != -1)
+ {
+ struct io_select_fd_s fds;
+ fds.fd =
+ gpg->fd_data_map[gpg->cmd.linked_idx].fd;
+ fds.for_read = 1;
+ fds.for_write = 0;
+ fds.frozen = 0;
+ fds.opaque = NULL;
+ do
+ {
+ fds.signaled = 0;
+ _gpgme_io_select (&fds, 1, 1);
+ if (fds.signaled)
+ _gpgme_data_inbound_handler
+ (gpg->cmd.linked_data, fds.fd);
+ }
+ while (fds.signaled);
+ }
+
+ /* XXX We must check if there are any
+ more fds active after removing this
+ one. */
+ (*gpg->io_cbs.remove)
+ (gpg->fd_data_map[gpg->cmd.idx].tag);
+ gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
+ gpg->fd_data_map[gpg->cmd.idx].fd = -1;
+ }
+ }
+ }
+ }
+ /* To reuse the buffer for the next line we have to
+ shift the remaining data to the buffer start and
+ restart the loop Hmmm: We can optimize this function
+ by looking forward in the buffer to see whether a
+ second complete line is available and in this case
+ avoid the memmove for this line. */
+ nread--; p++;
+ if (nread)
+ memmove (buffer, p, nread);
+ readpos = 0;
+ break; /* the for loop */
+ }
+ else
+ readpos++;
+ }
+ }
+
+ /* Update the gpg object. */
+ gpg->status.bufsize = bufsize;
+ gpg->status.buffer = buffer;
+ gpg->status.readpos = readpos;
+ return 0;
+}
+
+
+static gpgme_error_t
+status_handler (void *opaque, int fd)
+{
+ engine_gpg_t gpg = opaque;
+ int err;
+
+ assert (fd == gpg->status.fd[0]);
+ err = read_status (gpg);
+ if (err)
+ return err;
+ if (gpg->status.eof)
+ _gpgme_io_close (fd);
+ return 0;
+}
+
+
+static gpgme_error_t
+read_colon_line (engine_gpg_t gpg)
+{
+ char *p;
+ int nread;
+ size_t bufsize = gpg->colon.bufsize;
+ char *buffer = gpg->colon.buffer;
+ size_t readpos = gpg->colon.readpos;
+
+ assert (buffer);
+ if (bufsize - readpos < 256)
+ {
+ /* Need more room for the read. */
+ bufsize += 1024;
+ buffer = realloc (buffer, bufsize);
+ if (!buffer)
+ return gpg_error_from_errno (errno);
+ }
+
+ nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
+ if (nread == -1)
+ return gpg_error_from_errno (errno);
+
+ if (!nread)
+ {
+ gpg->colon.eof = 1;
+ assert (gpg->colon.fnc);
+ gpg->colon.fnc (gpg->colon.fnc_value, NULL);
+ return 0;
+ }
+
+ while (nread > 0)
+ {
+ for (p = buffer + readpos; nread; nread--, p++)
+ {
+ if ( *p == '\n' )
+ {
+ /* (we require that the last line is terminated by a LF)
+ and we skip empty lines. Note: we use UTF8 encoding
+ and escaping of special characters. We require at
+ least one colon to cope with some other printed
+ information. */
+ *p = 0;
+ if (*buffer && strchr (buffer, ':'))
+ {
+ char *line = NULL;
+
+ if (gpg->colon.preprocess_fnc)
+ {
+ gpgme_error_t err;
+
+ err = gpg->colon.preprocess_fnc (buffer, &line);
+ if (err)
+ return err;
+ }
+
+ assert (gpg->colon.fnc);
+ gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
+ if (line)
+ free (line);
+ }
+
+ /* To reuse the buffer for the next line we have to
+ shift the remaining data to the buffer start and
+ restart the loop Hmmm: We can optimize this function
+ by looking forward in the buffer to see whether a
+ second complete line is available and in this case
+ avoid the memmove for this line. */
+ nread--; p++;
+ if (nread)
+ memmove (buffer, p, nread);
+ readpos = 0;
+ break; /* The for loop. */
+ }
+ else
+ readpos++;
+ }
+ }
+
+ /* Update the gpg object. */
+ gpg->colon.bufsize = bufsize;
+ gpg->colon.buffer = buffer;
+ gpg->colon.readpos = readpos;
+ return 0;
+}
+
+
+/* This colonline handler thing is not the clean way to do it. It
+ might be better to enhance the gpgme_data_t object to act as a wrapper
+ for a callback. Same goes for the status thing. For now we use
+ this thing here because it is easier to implement. */
+static gpgme_error_t
+colon_line_handler (void *opaque, int fd)
+{
+ engine_gpg_t gpg = opaque;
+ gpgme_error_t rc = 0;
+
+ assert (fd == gpg->colon.fd[0]);
+ rc = read_colon_line (gpg);
+ if (rc)
+ return rc;
+ if (gpg->colon.eof)
+ _gpgme_io_close (fd);
+ return 0;
+}
+
+
+static gpgme_error_t
+start (engine_gpg_t gpg)
+{
+ gpgme_error_t rc;
+ int saved_errno;
+ int i, n;
+ int status;
+ struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
+
+ if (!gpg)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!gpg->file_name && !_gpgme_get_gpg_path ())
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ if (gpg->lc_ctype)
+ {
+ rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
+ if (!rc)
+ rc = add_arg_ext (gpg, "--lc-ctype", 1);
+ if (rc)
+ return rc;
+ }
+
+ if (gpg->lc_messages)
+ {
+ rc = add_arg_ext (gpg, gpg->lc_messages, 1);
+ if (!rc)
+ rc = add_arg_ext (gpg, "--lc-messages", 1);
+ if (rc)
+ return rc;
+ }
+
+ rc = build_argv (gpg);
+ if (rc)
+ return rc;
+
+ n = 3; /* status_fd, colon_fd and end of list */
+ for (i = 0; gpg->fd_data_map[i].data; i++)
+ n++;
+ fd_child_list = calloc (n + n, sizeof *fd_child_list);
+ if (!fd_child_list)
+ return gpg_error_from_errno (errno);
+ fd_parent_list = fd_child_list + n;
+
+ /* build the fd list for the child */
+ n = 0;
+ if (gpg->colon.fnc)
+ {
+ fd_child_list[n].fd = gpg->colon.fd[1];
+ fd_child_list[n].dup_to = 1; /* dup to stdout */
+ n++;
+ }
+ for (i = 0; gpg->fd_data_map[i].data; i++)
+ {
+ if (gpg->fd_data_map[i].dup_to != -1)
+ {
+ fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
+ fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
+ n++;
+ }
+ }
+ fd_child_list[n].fd = -1;
+ fd_child_list[n].dup_to = -1;
+
+ /* Build the fd list for the parent. */
+ n = 0;
+ if (gpg->status.fd[1] != -1)
+ {
+ fd_parent_list[n].fd = gpg->status.fd[1];
+ fd_parent_list[n].dup_to = -1;
+ n++;
+ }
+ if (gpg->colon.fd[1] != -1)
+ {
+ fd_parent_list[n].fd = gpg->colon.fd[1];
+ fd_parent_list[n].dup_to = -1;
+ n++;
+ }
+ for (i = 0; gpg->fd_data_map[i].data; i++)
+ {
+ fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
+ fd_parent_list[n].dup_to = -1;
+ n++;
+ }
+ fd_parent_list[n].fd = -1;
+ fd_parent_list[n].dup_to = -1;
+
+ status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
+ _gpgme_get_gpg_path (),
+ gpg->argv, fd_child_list, fd_parent_list);
+ saved_errno = errno;
+ free (fd_child_list);
+ if (status == -1)
+ return gpg_error_from_errno (saved_errno);
+
+ /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
+
+ rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
+ &gpg->status.tag);
+ if (rc)
+ /* FIXME: kill the child */
+ return rc;
+
+ if (gpg->colon.fnc)
+ {
+ assert (gpg->colon.fd[0] != -1);
+ rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
+ &gpg->colon.tag);
+ if (rc)
+ /* FIXME: kill the child */
+ return rc;
+ }
+
+ for (i = 0; gpg->fd_data_map[i].data; i++)
+ {
+ if (gpg->cmd.used && i == gpg->cmd.idx)
+ {
+ /* Park the cmd fd. */
+ gpg->cmd.fd = gpg->fd_data_map[i].fd;
+ gpg->fd_data_map[i].fd = -1;
+ }
+ else
+ {
+ rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
+ gpg->fd_data_map[i].inbound,
+ gpg->fd_data_map[i].inbound
+ ? _gpgme_data_inbound_handler
+ : _gpgme_data_outbound_handler,
+ gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
+
+ if (rc)
+ /* FIXME: kill the child */
+ return rc;
+ }
+ }
+
+ (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
+
+ /* fixme: check what data we can release here */
+ return 0;
+}
+
+
+static gpgme_error_t
+gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--decrypt");
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_arg (gpg, "--output");
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_data (gpg, plain, 1, 1);
+ if (!err)
+ err = add_data (gpg, ciph, 0, 0);
+
+ if (!err)
+ start (gpg);
+ return err;
+}
+
+static gpgme_error_t
+gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
+ : "--delete-key");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ {
+ if (!key->subkeys || !key->subkeys->fpr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ else
+ err = add_arg (gpg, key->subkeys->fpr);
+ }
+
+ if (!err)
+ start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
+{
+ gpgme_error_t err = 0;
+ int i;
+ gpgme_key_t key;
+
+ for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
+ {
+ const char *s = key->subkeys ? key->subkeys->keyid : NULL;
+ if (s)
+ {
+ if (!err)
+ err = add_arg (gpg, "-u");
+ if (!err)
+ err = add_arg (gpg, s);
+ }
+ gpgme_key_unref (key);
+ if (err) break;
+ }
+ return err;
+}
+
+
+static gpgme_error_t
+append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
+{
+ gpgme_error_t err = 0;
+ gpgme_sig_notation_t notation;
+
+ notation = gpgme_sig_notation_get (ctx);
+
+ while (!err && notation)
+ {
+ if (notation->name
+ && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
+ err = gpg_error (GPG_ERR_INV_VALUE);
+ else if (notation->name)
+ {
+ char *arg;
+
+ /* Maximum space needed is one byte for the "critical" flag,
+ the name, one byte for '=', the value, and a terminating
+ '\0'. */
+
+ arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
+ if (!arg)
+ err = gpg_error_from_errno (errno);
+
+ if (!err)
+ {
+ char *argp = arg;
+
+ if (notation->critical)
+ *(argp++) = '!';
+
+ memcpy (argp, notation->name, notation->name_len);
+ argp += notation->name_len;
+
+ *(argp++) = '=';
+
+ /* We know that notation->name is '\0' terminated. */
+ strcpy (argp, notation->value);
+ }
+
+ if (!err)
+ err = add_arg (gpg, "--sig-notation");
+ if (!err)
+ err = add_arg (gpg, arg);
+
+ if (arg)
+ free (arg);
+ }
+ else
+ {
+ /* This is a policy URL. */
+
+ char *value;
+
+ if (notation->critical)
+ {
+ value = malloc (1 + notation->value_len + 1);
+ if (!value)
+ err = gpg_error_from_errno (errno);
+ else
+ {
+ value[0] = '!';
+ /* We know that notation->value is '\0' terminated. */
+ strcpy (&value[1], notation->value);
+ }
+ }
+ else
+ value = notation->value;
+
+ if (!err)
+ err = add_arg (gpg, "--sig-policy-url");
+ if (!err)
+ err = add_arg (gpg, value);
+
+ if (value != notation->value)
+ free (value);
+ }
+
+ notation = notation->next;
+ }
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
+ gpgme_ctx_t ctx /* FIXME */)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--with-colons");
+ if (!err)
+ err = append_args_from_signers (gpg, ctx);
+ if (!err)
+ err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
+ if (!err)
+ err = add_data (gpg, out, 1, 1);
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err && type == 0)
+ {
+ const char *s = key->subkeys ? key->subkeys->fpr : NULL;
+ if (!s)
+ err = gpg_error (GPG_ERR_INV_VALUE);
+ else
+ err = add_arg (gpg, s);
+ }
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
+{
+ gpgme_error_t err = 0;
+ int i = 0;
+
+ while (recp[i])
+ {
+ if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
+ err = gpg_error (GPG_ERR_INV_VALUE);
+ if (!err)
+ err = add_arg (gpg, "-r");
+ if (!err)
+ err = add_arg (gpg, recp[i]->subkeys->fpr);
+ if (err)
+ break;
+ i++;
+ }
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
+ gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+ int symmetric = !recp;
+
+ err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
+
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+
+ if (!symmetric)
+ {
+ /* If we know that all recipients are valid (full or ultimate trust)
+ we can suppress further checks. */
+ if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
+ err = add_arg (gpg, "--always-trust");
+
+ if (!err)
+ err = append_args_from_recipients (gpg, recp);
+ }
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_arg (gpg, "--output");
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_data (gpg, ciph, 1, 1);
+ if (gpgme_data_get_file_name (plain))
+ {
+ if (!err)
+ err = add_arg (gpg, "--set-filename");
+ if (!err)
+ err = add_arg (gpg, gpgme_data_get_file_name (plain));
+ }
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, plain, 0, 0);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
+ gpgme_encrypt_flags_t flags, gpgme_data_t plain,
+ gpgme_data_t ciph, int use_armor,
+ gpgme_ctx_t ctx /* FIXME */)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--encrypt");
+ if (!err)
+ err = add_arg (gpg, "--sign");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+
+ /* If we know that all recipients are valid (full or ultimate trust)
+ we can suppress further checks. */
+ if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
+ err = add_arg (gpg, "--always-trust");
+
+ if (!err)
+ err = append_args_from_recipients (gpg, recp);
+
+ if (!err)
+ err = append_args_from_signers (gpg, ctx);
+ if (!err)
+ err = append_args_from_sig_notations (gpg, ctx);
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_arg (gpg, "--output");
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_data (gpg, ciph, 1, 1);
+ if (gpgme_data_get_file_name (plain))
+ {
+ if (!err)
+ err = add_arg (gpg, "--set-filename");
+ if (!err)
+ err = add_arg (gpg, gpgme_data_get_file_name (plain));
+ }
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, plain, 0, 0);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_export (void *engine, const char *pattern, unsigned int reserved,
+ gpgme_data_t keydata, int use_armor)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = add_arg (gpg, "--export");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+ if (!err)
+ err = add_data (gpg, keydata, 1, 1);
+ if (!err)
+ err = add_arg (gpg, "--");
+
+ if (!err && pattern && *pattern)
+ err = add_arg (gpg, pattern);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved,
+ gpgme_data_t keydata, int use_armor)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = add_arg (gpg, "--export");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+ if (!err)
+ err = add_data (gpg, keydata, 1, 1);
+ if (!err)
+ err = add_arg (gpg, "--");
+
+ if (pattern)
+ {
+ while (!err && *pattern && **pattern)
+ err = add_arg (gpg, *(pattern++));
+ }
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (!gpg)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* We need a special mechanism to get the fd of a pipe here, so that
+ we can use this for the %pubring and %secring parameters. We
+ don't have this yet, so we implement only the adding to the
+ standard keyrings. */
+ if (pubkey || seckey)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ err = add_arg (gpg, "--gen-key");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+ if (!err)
+ err = add_data (gpg, help_data, 0, 0);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_import (void *engine, gpgme_data_t keydata)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--import");
+ if (!err)
+ err = add_data (gpg, keydata, 0, 0);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+/* The output for external keylistings in GnuPG is different from all
+ the other key listings. We catch this here with a special
+ preprocessor that reformats the colon handler lines. */
+static gpgme_error_t
+gpg_keylist_preprocess (char *line, char **r_line)
+{
+ enum
+ {
+ RT_NONE, RT_INFO, RT_PUB, RT_UID
+ }
+ rectype = RT_NONE;
+#define NR_FIELDS 16
+ char *field[NR_FIELDS];
+ int fields = 0;
+
+ *r_line = NULL;
+
+ while (line && fields < NR_FIELDS)
+ {
+ field[fields++] = line;
+ line = strchr (line, ':');
+ if (line)
+ *(line++) = '\0';
+ }
+
+ if (!strcmp (field[0], "info"))
+ rectype = RT_INFO;
+ else if (!strcmp (field[0], "pub"))
+ rectype = RT_PUB;
+ else if (!strcmp (field[0], "uid"))
+ rectype = RT_UID;
+ else
+ rectype = RT_NONE;
+
+ switch (rectype)
+ {
+ case RT_INFO:
+ /* FIXME: Eventually, check the version number at least. */
+ return 0;
+
+ case RT_PUB:
+ if (fields < 7)
+ return 0;
+
+ /* The format is:
+
+ pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
+
+ as defined in 5.2. Machine Readable Indexes of the OpenPGP
+ HTTP Keyserver Protocol (draft).
+
+ We want:
+ pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
+ */
+
+ if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
+ field[6], field[3], field[2], field[1],
+ field[4], field[5]) < 0)
+ return gpg_error_from_errno (errno);
+ return 0;
+
+ case RT_UID:
+ /* The format is:
+
+ uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
+
+ as defined in 5.2. Machine Readable Indexes of the OpenPGP
+ HTTP Keyserver Protocol (draft).
+
+ We want:
+ uid:o<flags>::::<creatdate>:<expdate>:::<uid>:
+ */
+
+ if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
+ field[4], field[2], field[3], field[1]) < 0)
+ return gpg_error_from_errno (errno);
+ return 0;
+
+ case RT_NONE:
+ /* Unknown record. */
+ break;
+ }
+ return 0;
+
+}
+
+
+static gpgme_error_t
+gpg_keylist (void *engine, const char *pattern, int secret_only,
+ gpgme_keylist_mode_t mode)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ {
+ if ((mode & GPGME_KEYLIST_MODE_LOCAL)
+ || secret_only)
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+ }
+
+ err = add_arg (gpg, "--with-colons");
+ if (!err)
+ err = add_arg (gpg, "--fixed-list-mode");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
+ && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
+ {
+ err = add_arg (gpg, "--list-options");
+ if (!err)
+ err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
+ }
+ if (!err)
+ {
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ {
+ err = add_arg (gpg, "--search-keys");
+ gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
+ }
+ else
+ {
+ err = add_arg (gpg, secret_only ? "--list-secret-keys"
+ : ((mode & GPGME_KEYLIST_MODE_SIGS)
+ ? "--check-sigs" : "--list-keys"));
+ }
+ }
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err && pattern && *pattern)
+ err = add_arg (gpg, pattern);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
+ int reserved, gpgme_keylist_mode_t mode)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (reserved)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = add_arg (gpg, "--with-colons");
+ if (!err)
+ err = add_arg (gpg, "--fixed-list-mode");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
+ && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
+ {
+ err = add_arg (gpg, "--list-options");
+ if (!err)
+ err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
+ }
+ if (!err)
+ err = add_arg (gpg, secret_only ? "--list-secret-keys"
+ : ((mode & GPGME_KEYLIST_MODE_SIGS)
+ ? "--check-sigs" : "--list-keys"));
+ if (!err)
+ err = add_arg (gpg, "--");
+
+ if (pattern)
+ {
+ while (!err && *pattern && **pattern)
+ err = add_arg (gpg, *(pattern++));
+ }
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
+ gpgme_sig_mode_t mode, int use_armor, int use_textmode,
+ int include_certs, gpgme_ctx_t ctx /* FIXME */)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ if (mode == GPGME_SIG_MODE_CLEAR)
+ err = add_arg (gpg, "--clearsign");
+ else
+ {
+ err = add_arg (gpg, "--sign");
+ if (!err && mode == GPGME_SIG_MODE_DETACH)
+ err = add_arg (gpg, "--detach");
+ if (!err && use_armor)
+ err = add_arg (gpg, "--armor");
+ if (!err && use_textmode)
+ err = add_arg (gpg, "--textmode");
+ }
+
+ if (!err)
+ err = append_args_from_signers (gpg, ctx);
+ if (!err)
+ err = append_args_from_sig_notations (gpg, ctx);
+
+ if (gpgme_data_get_file_name (in))
+ {
+ if (!err)
+ err = add_arg (gpg, "--set-filename");
+ if (!err)
+ err = add_arg (gpg, gpgme_data_get_file_name (in));
+ }
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_data (gpg, in, 0, 0);
+ if (!err)
+ err = add_data (gpg, out, 1, 1);
+
+ if (!err)
+ start (gpg);
+
+ return err;
+}
+
+static gpgme_error_t
+gpg_trustlist (void *engine, const char *pattern)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--with-colons");
+ if (!err)
+ err = add_arg (gpg, "--list-trust-path");
+
+ /* Tell the gpg object about the data. */
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, pattern);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
+ gpgme_data_t plaintext)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err = 0;
+
+ if (plaintext)
+ {
+ /* Normal or cleartext signature. */
+
+ err = add_arg (gpg, "--output");
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, sig, 0, 0);
+ if (!err)
+ err = add_data (gpg, plaintext, 1, 1);
+ }
+ else
+ {
+ err = add_arg (gpg, "--verify");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_data (gpg, sig, -1, 0);
+ if (signed_text)
+ {
+ if (!err)
+ err = add_arg (gpg, "-");
+ if (!err)
+ err = add_data (gpg, signed_text, 0, 0);
+ }
+ }
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static void
+gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
+{
+ engine_gpg_t gpg = engine;
+
+ gpg->io_cbs = *io_cbs;
+}
+
+
+struct engine_ops _gpgme_engine_ops_gpg =
+ {
+ /* Static functions. */
+ _gpgme_get_gpg_path,
+ gpg_get_version,
+ gpg_get_req_version,
+ gpg_new,
+
+ /* Member functions. */
+ gpg_release,
+ NULL, /* reset */
+ gpg_set_status_handler,
+ gpg_set_command_handler,
+ gpg_set_colon_line_handler,
+ gpg_set_locale,
+ gpg_decrypt,
+ gpg_delete,
+ gpg_edit,
+ gpg_encrypt,
+ gpg_encrypt_sign,
+ gpg_export,
+ gpg_export_ext,
+ gpg_genkey,
+ gpg_import,
+ gpg_keylist,
+ gpg_keylist_ext,
+ gpg_sign,
+ gpg_trustlist,
+ gpg_verify,
+ gpg_set_io_cbs,
+ gpg_io_event,
+ gpg_cancel
+ };
diff --git a/libtdenetwork/libgpgme-copy/gpgme/sema.h b/libtdenetwork/libgpgme-copy/gpgme/sema.h
new file mode 100644
index 000000000..640bb7156
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/sema.h
@@ -0,0 +1,67 @@
+/* sema.h - Definitions for semaphores.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef SEMA_H
+#define SEMA_H
+
+struct critsect_s
+{
+ const char *name;
+ void *private;
+};
+
+#define DEFINE_GLOBAL_LOCK(name) \
+ struct critsect_s name = { #name, NULL }
+#define DEFINE_STATIC_LOCK(name) \
+ static struct critsect_s name = { #name, NULL }
+
+#define DECLARE_LOCK(name) \
+ struct critsect_s name
+#define INIT_LOCK(a) \
+ do \
+ { \
+ (a).name = #a; \
+ (a).private = NULL; \
+ } \
+ while (0)
+#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name))
+
+
+#define LOCK(name) \
+ do \
+ { \
+ _gpgme_sema_cs_enter (&(name)); \
+ } \
+ while (0)
+
+#define UNLOCK(name) \
+ do \
+ { \
+ _gpgme_sema_cs_leave (&(name)); \
+ } \
+ while (0)
+
+void _gpgme_sema_subsystem_init (void);
+void _gpgme_sema_cs_enter (struct critsect_s *s);
+void _gpgme_sema_cs_leave (struct critsect_s *s);
+void _gpgme_sema_cs_destroy (struct critsect_s *s);
+
+#endif /* SEMA_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/sig-notation.c b/libtdenetwork/libgpgme-copy/gpgme/sig-notation.c
new file mode 100644
index 000000000..a5558ece8
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/sig-notation.c
@@ -0,0 +1,260 @@
+/* sig-notation.c - Signature notation data support.
+ Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+
+
+/* Free the signature notation object and all associated resources.
+ The object must already be removed from any linked list as the next
+ pointer is ignored. */
+void
+_gpgme_sig_notation_free (gpgme_sig_notation_t notation)
+{
+ if (notation->name)
+ free (notation->name);
+
+ if (notation->value)
+ free (notation->value);
+
+ free (notation);
+}
+
+
+/* Set the flags of NOTATION to FLAGS. */
+static void
+sig_notation_set_flags (gpgme_sig_notation_t notation,
+ gpgme_sig_notation_flags_t flags)
+{
+ /* We copy the flags into individual bits to make them easier
+ accessible individually for the user. */
+ notation->human_readable = flags & GPGME_SIG_NOTATION_HUMAN_READABLE ? 1 : 0;
+ notation->critical = flags & GPGME_SIG_NOTATION_CRITICAL ? 1 : 0;
+
+ notation->flags = flags;
+}
+
+
+/* Create a new, empty signature notation data object. */
+gpgme_error_t
+_gpgme_sig_notation_create (gpgme_sig_notation_t *notationp,
+ const char *name, int name_len,
+ const char *value, int value_len,
+ gpgme_sig_notation_flags_t flags)
+{
+ gpgme_error_t err = 0;
+ gpgme_sig_notation_t notation;
+
+ /* Currently, we require all notations to be human-readable. */
+ if (name && !(flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ notation = calloc (1, sizeof (*notation));
+ if (!notation)
+ return gpg_error_from_errno (errno);
+
+ /* This is critical. We want to reliably identify policy URLs by
+ using a NULL pointer for NAME. So all notations must have a NAME
+ string, even if it is empty. */
+ if (name)
+ {
+ /* We add a trailing '\0' for stringification in the good
+ case. */
+ notation->name = malloc (name_len + 1);
+ if (!notation->name)
+ {
+ err = gpg_error_from_errno (errno);
+ goto err;
+ }
+
+ memcpy (notation->name, name, name_len);
+ notation->name[name_len] = '\0';
+ notation->name_len = name_len;
+ }
+
+ if (value)
+ {
+ /* We add a trailing '\0' for stringification in the good
+ case. */
+ notation->value = malloc (value_len + 1);
+ if (!notation->value)
+ {
+ err = gpg_error_from_errno (errno);
+ goto err;
+ }
+
+ memcpy (notation->value, value, value_len);
+ notation->value[value_len] = '\0';
+ notation->value_len = value_len;
+ }
+
+ sig_notation_set_flags (notation, flags);
+
+ *notationp = notation;
+ return 0;
+
+ err:
+ _gpgme_sig_notation_free (notation);
+ return err;
+}
+
+
+/* GnuPG subpacket flags. */
+
+/* This subpacket data is part of the hashed data. */
+#define GNUPG_SPK_HASHED 0x01
+
+/* This subpacket is marked critical. */
+#define GNUPG_SPK_CRITICAL 0x02
+
+/* Parse a notation or policy URL subpacket. If the packet type is
+ not known, return no error but NULL in NOTATION. */
+gpgme_error_t
+_gpgme_parse_notation (gpgme_sig_notation_t *notationp,
+ int type, int pkflags, int len, char *data)
+{
+ gpgme_error_t err;
+ char *name = NULL;
+ int name_len = 0;
+ char *value = NULL;
+ int value_len = 0;
+ gpgme_sig_notation_flags_t flags = 0;
+ char *decoded_data;
+ unsigned char *bdata;
+
+ /* Type 20: Notation data. */
+ /* Type 26: Policy URL. */
+ if (type != 20 && type != 26)
+ {
+ *notationp = NULL;
+ return 0;
+ }
+
+ /* A few simple sanity checks. */
+ if (len > strlen (data))
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ /* See below for the format of a notation subpacket. It has at
+ least four octets of flags and two times two octets of length
+ information. */
+ if (type == 20 && len < 4 + 2 + 2)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ err = _gpgme_decode_percent_string (data, &decoded_data, 0, 1);
+ if (err)
+ return err;
+ bdata = (unsigned char *) decoded_data;
+
+ /* Flags common to notation data and policy URL. */
+ if (pkflags & GNUPG_SPK_CRITICAL)
+ flags |= GPGME_SIG_NOTATION_CRITICAL;
+
+ /* This information is relevant in parsing multi-octet numbers below:
+
+ 3.1. Scalar numbers
+
+ Scalar numbers are unsigned, and are always stored in big-endian
+ format. Using n[k] to refer to the kth octet being interpreted,
+ the value of a two-octet scalar is ((n[0] << 8) + n[1]). The
+ value of a four-octet scalar is ((n[0] << 24) + (n[1] << 16) +
+ (n[2] << 8) + n[3]).
+
+ From RFC2440: OpenPGP Message Format. Copyright (C) The Internet
+ Society (1998). All Rights Reserved. */
+#define RFC2440_GET_WORD(chr) ((((int)((unsigned char *)(chr))[0]) << 8) \
+ + ((int)((unsigned char *)(chr))[1]))
+
+ if (type == 20)
+ {
+ /* 5.2.3.15. Notation Data
+
+ (4 octets of flags, 2 octets of name length (M),
+ 2 octets of value length (N), M octets of name data,
+ N octets of value data)
+
+ [...] The "flags" field holds four octets of flags.
+ All undefined flags MUST be zero. Defined flags are:
+
+ First octet: 0x80 = human-readable. [...]
+ Other octets: none.
+
+ From RFC2440: OpenPGP Message Format. Copyright (C) The
+ Internet Society (1998). All Rights Reserved. */
+
+ int chr;
+
+ /* First octet of flags. */
+#define RFC2440_SPK20_FLAG1_HUMAN_READABLE 0x80
+
+ chr = *bdata;
+ bdata++;
+
+ if (chr & RFC2440_SPK20_FLAG1_HUMAN_READABLE)
+ flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
+
+ /* The second, third and four octet of flags are unused. */
+ bdata++;
+ bdata++;
+ bdata++;
+
+ name_len = RFC2440_GET_WORD (bdata);
+ bdata += 2;
+
+ value_len = RFC2440_GET_WORD (bdata);
+ bdata += 2;
+
+ /* Small sanity check. */
+ if (4 + 2 + 2 + name_len + value_len > len)
+ {
+ free (decoded_data);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ name = (char *) bdata;
+ bdata += name_len;
+
+ value = (char *) bdata;
+ }
+ else
+ {
+ /* Type is 26. */
+
+ /* NAME is NULL, name_len is 0. */
+
+ value = (char *) bdata;
+ value_len = strlen (value);
+ }
+
+ err = _gpgme_sig_notation_create (notationp, name, name_len,
+ value, value_len, flags);
+
+ free (decoded_data);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/sign.c b/libtdenetwork/libgpgme-copy/gpgme/sign.c
new file mode 100644
index 000000000..f766c0437
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/sign.c
@@ -0,0 +1,328 @@
+/* sign.c - Signing function.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "ops.h"
+#include "util.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_sign_result result;
+
+ /* A pointer to the next pointer of the last invalid signer in
+ the list. This makes appending new invalid signers painless
+ while preserving the order. */
+ gpgme_invalid_key_t *last_signer_p;
+
+ /* Likewise for signature information. */
+ gpgme_new_signature_t *last_sig_p;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+ gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers;
+ gpgme_new_signature_t sig = opd->result.signatures;
+
+ while (invalid_signer)
+ {
+ gpgme_invalid_key_t next = invalid_signer->next;
+ if (invalid_signer->fpr)
+ free (invalid_signer->fpr);
+ free (invalid_signer);
+ invalid_signer = next;
+ }
+
+ while (sig)
+ {
+ gpgme_new_signature_t next = sig->next;
+ free (sig->fpr);
+ free (sig);
+ sig = next;
+ }
+}
+
+
+gpgme_sign_result_t
+gpgme_op_sign_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+static gpgme_error_t
+parse_sig_created (char *args, gpgme_new_signature_t *sigp)
+{
+ gpgme_new_signature_t sig;
+ char *tail;
+
+ sig = malloc (sizeof (*sig));
+ if (!sig)
+ return gpg_error_from_errno (errno);
+
+ sig->next = NULL;
+ switch (*args)
+ {
+ case 'S':
+ sig->type = GPGME_SIG_MODE_NORMAL;
+ break;
+
+ case 'D':
+ sig->type = GPGME_SIG_MODE_DETACH;
+ break;
+
+ case 'C':
+ sig->type = GPGME_SIG_MODE_CLEAR;
+ break;
+
+ default:
+ /* The backend engine is not behaving. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ args++;
+ if (*args != ' ')
+ {
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ errno = 0;
+ sig->pubkey_algo = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ args = tail;
+
+ sig->hash_algo = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ args = tail;
+
+ sig->sig_class = strtol (args, &tail, 0);
+ sig->class = sig->sig_class;
+ sig->_obsolete_class = sig->sig_class;
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ args = tail;
+
+ sig->timestamp = _gpgme_parse_timestamp (args, &tail);
+ if (sig->timestamp == -1 || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ args = tail;
+ while (*args == ' ')
+ args++;
+
+ if (!*args)
+ {
+ /* The crypto backend does not behave. */
+ free (sig);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ tail = strchr (args, ' ');
+ if (tail)
+ *tail = '\0';
+
+ sig->fpr = strdup (args);
+ if (!sig->fpr)
+ {
+ int saved_errno = errno;
+ free (sig);
+ return gpg_error_from_errno (saved_errno);
+ }
+ *sigp = sig;
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_passphrase_status_handler (priv, code, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_SIG_CREATED:
+ err = parse_sig_created (args, opd->last_sig_p);
+ if (err)
+ return err;
+
+ opd->last_sig_p = &(*opd->last_sig_p)->next;
+ break;
+
+ case GPGME_STATUS_INV_RECP:
+ err = _gpgme_parse_inv_recp (args, opd->last_signer_p);
+ if (err)
+ return err;
+
+ opd->last_signer_p = &(*opd->last_signer_p)->next;
+ break;
+
+ case GPGME_STATUS_EOF:
+ if (opd->result.invalid_signers)
+ return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
+ break;
+
+ default:
+ break;
+ }
+ return err;
+}
+
+
+static gpgme_error_t
+sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_sign_status_handler (priv, code, args);
+ return err;
+}
+
+
+gpgme_error_t
+_gpgme_op_sign_init_result (gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+ opd->last_signer_p = &opd->result.invalid_signers;
+ opd->last_sig_p = &opd->result.signatures;
+ return 0;
+}
+
+
+static gpgme_error_t
+sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
+ gpgme_data_t sig, gpgme_sig_mode_t mode)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_sign_init_result (ctx);
+ if (err)
+ return err;
+
+ if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
+ && mode != GPGME_SIG_MODE_CLEAR)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!plain)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!sig)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
+ ctx);
+
+ return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor,
+ ctx->use_textmode, ctx->include_certs,
+ ctx /* FIXME */);
+}
+
+
+/* Sign the plaintext PLAIN and store the signature in SIG. */
+gpgme_error_t
+gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
+ gpgme_sig_mode_t mode)
+{
+ return sign_start (ctx, 0, plain, sig, mode);
+}
+
+
+/* Sign the plaintext PLAIN and store the signature in SIG. */
+gpgme_error_t
+gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
+ gpgme_sig_mode_t mode)
+{
+ gpgme_error_t err = sign_start (ctx, 1, plain, sig, mode);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/signers.c b/libtdenetwork/libgpgme-copy/gpgme/signers.c
new file mode 100644
index 000000000..e60d2dd35
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/signers.c
@@ -0,0 +1,95 @@
+/* signers.c - Maintain signer sets.
+ Copyright (C) 2001 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "util.h"
+#include "context.h"
+
+
+/* Delete all signers from CTX. */
+void
+gpgme_signers_clear (gpgme_ctx_t ctx)
+{
+ unsigned int i;
+
+ if (!ctx || !ctx->signers)
+ return;
+
+ for (i = 0; i < ctx->signers_len; i++)
+ {
+ assert (ctx->signers[i]);
+ gpgme_key_unref (ctx->signers[i]);
+ ctx->signers[i] = NULL;
+ }
+ ctx->signers_len = 0;
+}
+
+/* Add KEY to list of signers in CTX. */
+gpgme_error_t
+gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key)
+{
+ if (!ctx || !key)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (ctx->signers_len == ctx->signers_size)
+ {
+ gpgme_key_t *newarr;
+ int n = ctx->signers_size + 5;
+ int j;
+
+ newarr = realloc (ctx->signers, n * sizeof (*newarr));
+ if (!newarr)
+ return gpg_error_from_errno (errno);
+ for (j = ctx->signers_size; j < n; j++)
+ newarr[j] = NULL;
+ ctx->signers = newarr;
+ ctx->signers_size = n;
+ }
+
+ gpgme_key_ref (key);
+ ctx->signers[ctx->signers_len++] = key;
+ return 0;
+}
+
+
+/* Return the SETQth signer's key in CTX with one reference. */
+gpgme_key_t
+gpgme_signers_enum (const gpgme_ctx_t ctx, int seq)
+{
+ unsigned int seqno;
+
+ if (!ctx || seq < 0)
+ return NULL;
+
+ seqno = (unsigned int) seq;
+ if (seqno >= ctx->signers_len)
+ return NULL;
+ gpgme_key_ref (ctx->signers[seqno]);
+ return ctx->signers[seqno];
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/status-table.h b/libtdenetwork/libgpgme-copy/gpgme/status-table.h
new file mode 100644
index 000000000..e2ae5c3b6
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/status-table.h
@@ -0,0 +1,94 @@
+/* Generated automatically by mkstatus */
+/* Do not edit! */
+
+struct status_table_s {
+ const char *name;
+ gpgme_status_code_t code;
+};
+
+static struct status_table_s status_table[] =
+{
+ { "ABORT", GPGME_STATUS_ABORT },
+ { "ALREADY_SIGNED", GPGME_STATUS_ALREADY_SIGNED },
+ { "BACKUP_KEY_CREATED", GPGME_STATUS_BACKUP_KEY_CREATED },
+ { "BADARMOR", GPGME_STATUS_BADARMOR },
+ { "BADMDC", GPGME_STATUS_BADMDC },
+ { "BADSIG", GPGME_STATUS_BADSIG },
+ { "BAD_PASSPHRASE", GPGME_STATUS_BAD_PASSPHRASE },
+ { "BEGIN_DECRYPTION", GPGME_STATUS_BEGIN_DECRYPTION },
+ { "BEGIN_ENCRYPTION", GPGME_STATUS_BEGIN_ENCRYPTION },
+ { "BEGIN_STREAM", GPGME_STATUS_BEGIN_STREAM },
+ { "CARDCTRL", GPGME_STATUS_CARDCTRL },
+ { "DECRYPTION_FAILED", GPGME_STATUS_DECRYPTION_FAILED },
+ { "DECRYPTION_OKAY", GPGME_STATUS_DECRYPTION_OKAY },
+ { "DELETE_PROBLEM", GPGME_STATUS_DELETE_PROBLEM },
+ { "ENC_TO", GPGME_STATUS_ENC_TO },
+ { "END_DECRYPTION", GPGME_STATUS_END_DECRYPTION },
+ { "END_ENCRYPTION", GPGME_STATUS_END_ENCRYPTION },
+ { "END_STREAM", GPGME_STATUS_END_STREAM },
+ { "ENTER", GPGME_STATUS_ENTER },
+ { "ERRMDC", GPGME_STATUS_ERRMDC },
+ { "ERROR", GPGME_STATUS_ERROR },
+ { "ERRSIG", GPGME_STATUS_ERRSIG },
+ { "EXPKEYSIG", GPGME_STATUS_EXPKEYSIG },
+ { "EXPSIG", GPGME_STATUS_EXPSIG },
+ { "FILE_DONE", GPGME_STATUS_FILE_DONE },
+ { "FILE_ERROR", GPGME_STATUS_FILE_ERROR },
+ { "FILE_START", GPGME_STATUS_FILE_START },
+ { "GET_BOOL", GPGME_STATUS_GET_BOOL },
+ { "GET_HIDDEN", GPGME_STATUS_GET_HIDDEN },
+ { "GET_LINE", GPGME_STATUS_GET_LINE },
+ { "GOODMDC", GPGME_STATUS_GOODMDC },
+ { "GOODSIG", GPGME_STATUS_GOODSIG },
+ { "GOOD_PASSPHRASE", GPGME_STATUS_GOOD_PASSPHRASE },
+ { "GOT_IT", GPGME_STATUS_GOT_IT },
+ { "IMPORTED", GPGME_STATUS_IMPORTED },
+ { "IMPORT_OK", GPGME_STATUS_IMPORT_OK },
+ { "IMPORT_PROBLEM", GPGME_STATUS_IMPORT_PROBLEM },
+ { "IMPORT_RES", GPGME_STATUS_IMPORT_RES },
+ { "INV_RECP", GPGME_STATUS_INV_RECP },
+ { "KEYEXPIRED", GPGME_STATUS_KEYEXPIRED },
+ { "KEYREVOKED", GPGME_STATUS_KEYREVOKED },
+ { "KEY_CREATED", GPGME_STATUS_KEY_CREATED },
+ { "LEAVE", GPGME_STATUS_LEAVE },
+ { "MISSING_PASSPHRASE", GPGME_STATUS_MISSING_PASSPHRASE },
+ { "NEED_PASSPHRASE", GPGME_STATUS_NEED_PASSPHRASE },
+ { "NEED_PASSPHRASE_PIN", GPGME_STATUS_NEED_PASSPHRASE_PIN },
+ { "NEED_PASSPHRASE_SYM", GPGME_STATUS_NEED_PASSPHRASE_SYM },
+ { "NEWSIG", GPGME_STATUS_NEWSIG },
+ { "NODATA", GPGME_STATUS_NODATA },
+ { "NOTATION_DATA", GPGME_STATUS_NOTATION_DATA },
+ { "NOTATION_NAME", GPGME_STATUS_NOTATION_NAME },
+ { "NO_PUBKEY", GPGME_STATUS_NO_PUBKEY },
+ { "NO_RECP", GPGME_STATUS_NO_RECP },
+ { "NO_SECKEY", GPGME_STATUS_NO_SECKEY },
+ { "PKA_TRUST_BAD", GPGME_STATUS_PKA_TRUST_BAD },
+ { "PKA_TRUST_GOOD", GPGME_STATUS_PKA_TRUST_GOOD },
+ { "PLAINTEXT", GPGME_STATUS_PLAINTEXT },
+ { "POLICY_URL", GPGME_STATUS_POLICY_URL },
+ { "PROGRESS", GPGME_STATUS_PROGRESS },
+ { "REVKEYSIG", GPGME_STATUS_REVKEYSIG },
+ { "RSA_OR_IDEA", GPGME_STATUS_RSA_OR_IDEA },
+ { "SC_OP_FAILURE", GPGME_STATUS_SC_OP_FAILURE },
+ { "SC_OP_SUCCESS", GPGME_STATUS_SC_OP_SUCCESS },
+ { "SESSION_KEY", GPGME_STATUS_SESSION_KEY },
+ { "SHM_GET", GPGME_STATUS_SHM_GET },
+ { "SHM_GET_BOOL", GPGME_STATUS_SHM_GET_BOOL },
+ { "SHM_GET_HIDDEN", GPGME_STATUS_SHM_GET_HIDDEN },
+ { "SHM_INFO", GPGME_STATUS_SHM_INFO },
+ { "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED },
+ { "SIG_CREATED", GPGME_STATUS_SIG_CREATED },
+ { "SIG_ID", GPGME_STATUS_SIG_ID },
+ { "SIG_SUBPACKET", GPGME_STATUS_SIG_SUBPACKET },
+ { "TRUNCATED", GPGME_STATUS_TRUNCATED },
+ { "TRUST_FULLY", GPGME_STATUS_TRUST_FULLY },
+ { "TRUST_MARGINAL", GPGME_STATUS_TRUST_MARGINAL },
+ { "TRUST_NEVER", GPGME_STATUS_TRUST_NEVER },
+ { "TRUST_ULTIMATE", GPGME_STATUS_TRUST_ULTIMATE },
+ { "TRUST_UNDEFINED", GPGME_STATUS_TRUST_UNDEFINED },
+ { "UNEXPECTED", GPGME_STATUS_UNEXPECTED },
+ { "USERID_HINT", GPGME_STATUS_USERID_HINT },
+ { "VALIDSIG", GPGME_STATUS_VALIDSIG },
+ {NULL, 0}
+};
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/stpcpy.c b/libtdenetwork/libgpgme-copy/gpgme/stpcpy.c
new file mode 100644
index 000000000..4e9fc10a0
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/stpcpy.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1992, 1995, 1997, 2002, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library 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.
+
+ The GNU C Library 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#undef __stpcpy
+#undef stpcpy
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
+char *
+__stpcpy (dest, src)
+ char *dest;
+ const char *src;
+{
+ register char *d = dest;
+ register const char *s = src;
+
+ do
+ *d++ = *s;
+ while (*s++ != '\0');
+
+ return d - 1;
+}
+#ifdef libc_hidden_def
+libc_hidden_def (__stpcpy)
+#endif
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
+#ifdef libc_hidden_builtin_def
+libc_hidden_builtin_def (stpcpy)
+#endif
diff --git a/libtdenetwork/libgpgme-copy/gpgme/trust-item.c b/libtdenetwork/libgpgme-copy/gpgme/trust-item.c
new file mode 100644
index 000000000..84d7e659f
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/trust-item.c
@@ -0,0 +1,171 @@
+/* trust-item.c - Trust item objects.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "util.h"
+#include "ops.h"
+#include "sema.h"
+
+
+/* Protects all reference counters in trust items. All other accesses
+ to a trust item are either read only or happen before the trust
+ item is available to the user. */
+DEFINE_STATIC_LOCK (trust_item_ref_lock);
+
+
+/* Create a new trust item. */
+gpgme_error_t
+_gpgme_trust_item_new (gpgme_trust_item_t *r_item)
+{
+ gpgme_trust_item_t item;
+
+ item = calloc (1, sizeof *item);
+ if (!item)
+ return gpg_error_from_errno (errno);
+ item->_refs = 1;
+ item->keyid = item->_keyid;
+ item->_keyid[16] = '\0';
+ item->owner_trust = item->_owner_trust;
+ item->_owner_trust[1] = '\0';
+ item->validity = item->_validity;
+ item->_validity[1] = '\0';
+ *r_item = item;
+ return 0;
+}
+
+
+/* Acquire a reference to ITEM. */
+void
+gpgme_trust_item_ref (gpgme_trust_item_t item)
+{
+ LOCK (trust_item_ref_lock);
+ item->_refs++;
+ UNLOCK (trust_item_ref_lock);
+}
+
+
+/* gpgme_trust_item_unref releases the trust item object. Note that
+ this function may not do an actual release if there are other
+ shallow copies of the object. You have to call this function for
+ every newly created trust item object as well as for every
+ gpgme_trust_item_ref() done on the trust item object. */
+void
+gpgme_trust_item_unref (gpgme_trust_item_t item)
+{
+ LOCK (trust_item_ref_lock);
+ assert (item->_refs > 0);
+ if (--item->_refs)
+ {
+ UNLOCK (trust_item_ref_lock);
+ return;
+ }
+ UNLOCK (trust_item_ref_lock);
+
+ if (item->name)
+ free (item->name);
+ free (item);
+}
+
+
+/* Compatibility interfaces. */
+void
+gpgme_trust_item_release (gpgme_trust_item_t item)
+{
+ gpgme_trust_item_unref (item);
+}
+
+/* Return the value of the attribute WHAT of ITEM, which has to be
+ representable by a string. */
+const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item,
+ _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ const char *val = NULL;
+
+ if (!item)
+ return NULL;
+ if (reserved)
+ return NULL;
+ if (idx)
+ return NULL;
+
+ switch (what)
+ {
+ case GPGME_ATTR_KEYID:
+ val = item->keyid;
+ break;
+
+ case GPGME_ATTR_OTRUST:
+ val = item->owner_trust;
+ break;
+
+ case GPGME_ATTR_VALIDITY:
+ val = item->validity;
+ break;
+
+ case GPGME_ATTR_USERID:
+ val = item->name;
+ break;
+
+ default:
+ break;
+ }
+ return val;
+}
+
+
+/* Return the value of the attribute WHAT of KEY, which has to be
+ representable by an integer. IDX specifies a running index if the
+ attribute appears more than once in the key. */
+int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
+ const void *reserved, int idx)
+{
+ int val = 0;
+
+ if (!item)
+ return 0;
+ if (reserved)
+ return 0;
+ if (idx)
+ return 0;
+
+ switch (what)
+ {
+ case GPGME_ATTR_LEVEL:
+ val = item->level;
+ break;
+
+ case GPGME_ATTR_TYPE:
+ val = item->type;
+ break;
+
+ default:
+ break;
+ }
+ return val;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/trustlist.c b/libtdenetwork/libgpgme-copy/gpgme/trustlist.c
new file mode 100644
index 000000000..664e67cd7
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/trustlist.c
@@ -0,0 +1,248 @@
+/* trustlist.c - Trust item listing.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+
+
+struct trust_queue_item_s
+{
+ struct trust_queue_item_s *next;
+ gpgme_trust_item_t item;
+};
+
+typedef struct
+{
+ /* Something new is available. */
+ int trust_cond;
+ struct trust_queue_item_s *trust_queue;
+} *op_data_t;
+
+
+
+static gpgme_error_t
+trustlist_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ return 0;
+}
+
+
+/* This handler is used to parse the output of --list-trust-path:
+ Format:
+ level:keyid:type:recno:ot:val:mc:cc:name:
+ With TYPE = U for a user ID
+ K for a key
+ The RECNO is either the one of the dir record or the one of the uid
+ record. OT is the the usual trust letter and only availabel on K
+ lines. VAL is the calcualted validity MC is the marginal trust
+ counter and only available on U lines CC is the same for the
+ complete count NAME ist the username and only printed on U
+ lines. */
+static gpgme_error_t
+trustlist_colon_handler (void *priv, char *line)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ char *p, *pend;
+ int field = 0;
+ gpgme_trust_item_t item = NULL;
+
+ if (!line)
+ return 0; /* EOF */
+
+ for (p = line; p; p = pend)
+ {
+ field++;
+ pend = strchr (p, ':');
+ if (pend)
+ *pend++ = 0;
+
+ switch (field)
+ {
+ case 1: /* level */
+ err = _gpgme_trust_item_new (&item);
+ if (err)
+ return err;
+ item->level = atoi (p);
+ break;
+ case 2: /* long keyid */
+ if (strlen (p) == DIM(item->keyid) - 1)
+ strcpy (item->keyid, p);
+ break;
+ case 3: /* type */
+ item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
+ break;
+ case 5: /* owner trust */
+ item->_owner_trust[0] = *p;
+ break;
+ case 6: /* validity */
+ item->_validity[0] = *p;
+ break;
+ case 9: /* user ID */
+ item->name = strdup (p);
+ if (!item->name)
+ {
+ int saved_errno = errno;
+ gpgme_trust_item_unref (item);
+ return gpg_error_from_errno (saved_errno);
+ }
+ break;
+ }
+ }
+
+ if (item)
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
+ return 0;
+}
+
+
+void
+_gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) data;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ gpgme_trust_item_t item = (gpgme_trust_item_t) type_data;
+ struct trust_queue_item_s *q, *q2;
+
+ assert (type == GPGME_EVENT_NEXT_TRUSTITEM);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return;
+
+ q = malloc (sizeof *q);
+ if (!q)
+ {
+ gpgme_trust_item_unref (item);
+ /* FIXME: GPGME_Out_Of_Core; */
+ return;
+ }
+ q->item = item;
+ q->next = NULL;
+ /* FIXME: Use a tail pointer */
+ q2 = opd->trust_queue;
+ if (!q2)
+ opd->trust_queue = q;
+ else
+ {
+ while (q2->next)
+ q2 = q2->next;
+ q2->next = q;
+ }
+ /* FIXME: unlock queue */
+ opd->trust_cond = 1;
+}
+
+
+gpgme_error_t
+gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
+{
+ gpgme_error_t err = 0;
+ void *hook;
+ op_data_t opd;
+
+ if (!pattern || !*pattern)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_reset (ctx, 2);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
+ sizeof (*opd), NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine,
+ trustlist_status_handler, ctx);
+ err = _gpgme_engine_set_colon_line_handler (ctx->engine,
+ trustlist_colon_handler, ctx);
+ if (err)
+ return err;
+
+ return _gpgme_engine_op_trustlist (ctx->engine, pattern);
+}
+
+
+gpgme_error_t
+gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ struct trust_queue_item_s *q;
+
+ if (!r_item)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ *r_item = NULL;
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+ if (opd == NULL)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!opd->trust_queue)
+ {
+ err = _gpgme_wait_on_condition (ctx, &opd->trust_cond);
+ if (err)
+ return err;
+ if (!opd->trust_cond)
+ return gpg_error (GPG_ERR_EOF);
+ opd->trust_cond = 0;
+ assert (opd->trust_queue);
+ }
+ q = opd->trust_queue;
+ opd->trust_queue = q->next;
+
+ *r_item = q->item;
+ free (q);
+ return 0;
+}
+
+
+/* Terminate a pending trustlist operation within CTX. */
+gpgme_error_t
+gpgme_op_trustlist_end (gpgme_ctx_t ctx)
+{
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ return 0;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/util.h b/libtdenetwork/libgpgme-copy/gpgme/util.h
new file mode 100644
index 000000000..05fd69d56
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/util.h
@@ -0,0 +1,106 @@
+/* util.h
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "gpgme.h"
+
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+
+
+/*-- {posix,w32}-util.c --*/
+const char *_gpgme_get_gpg_path (void);
+const char *_gpgme_get_gpgsm_path (void);
+int _gpgme_get_conf_int (const char *key, int *value);
+
+
+/*-- replacement functions in <funcname>.c --*/
+#ifdef HAVE_CONFIG_H
+
+#ifndef HAVE_STPCPY
+static _GPGME_INLINE char *
+_gpgme_stpcpy (char *a, const char *b)
+{
+ while (*b)
+ *a++ = *b++;
+ *a = 0;
+ return a;
+}
+#define stpcpy(a,b) _gpgme_stpcpy ((a), (b))
+#endif /*!HAVE_STPCPY*/
+
+#if !HAVE_VASPRINTF
+#include <stdarg.h>
+int vasprintf (char **result, const char *format, va_list args);
+int asprintf (char **result, const char *format, ...);
+#endif
+
+#ifndef HAVE_TTYNAME_R
+int ttyname_r (int fd, char *buf, size_t buflen);
+#endif
+#endif
+
+
+/*-- conversion.c --*/
+/* 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);
+
+/* 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);
+
+/* 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);
+
+
+/* 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);
+
+
+gpgme_error_t _gpgme_map_gnupg_error (char *err);
+
+
+/* Retrieve the environment variable NAME and return a copy of it in a
+ malloc()'ed buffer in *VALUE. If the environment variable is not
+ set, return NULL in *VALUE. */
+gpgme_error_t _gpgme_getenv (const char *name, char **value);
+
+#endif /* UTIL_H */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/vasprintf.c b/libtdenetwork/libgpgme-copy/gpgme/vasprintf.c
new file mode 100644
index 000000000..b41d2ff91
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/vasprintf.c
@@ -0,0 +1,192 @@
+/* Like vsprintf but provides a pointer to malloc'd storage, which must
+ be freed by the caller.
+ Copyright (C) 1994, 2002 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+
+#ifndef va_copy /* According to POSIX, va_copy is a macro. */
+#if defined (__GNUC__) && defined (__PPC__) \
+ && (defined (_CALL_SYSV) || defined (_WIN32))
+#define va_copy(d, s) (*(d) = *(s))
+#elif defined (MUST_COPY_VA_BYVAL)
+#define va_copy(d, s) ((d) = (s))
+#else
+#define va_copy(d, s) memcpy ((d), (s), sizeof (va_list))
+#endif
+#endif
+
+
+#ifdef TEST
+int global_total_width;
+#endif
+
+static int int_vasprintf (char **, const char *, va_list *);
+
+static int
+int_vasprintf (result, format, args)
+ char **result;
+ const char *format;
+ va_list *args;
+{
+ const char *p = format;
+ /* Add one to make sure that it is never zero, which might cause malloc
+ to return NULL. */
+ int total_width = strlen (format) + 1;
+ va_list ap;
+
+ va_copy (ap, *args);
+
+ while (*p != '\0')
+ {
+ if (*p++ == '%')
+ {
+ while (strchr ("-+ #0", *p))
+ ++p;
+ if (*p == '*')
+ {
+ ++p;
+ total_width += abs (va_arg (ap, int));
+ }
+ else
+ total_width += strtoul (p, (char **) &p, 10);
+ if (*p == '.')
+ {
+ ++p;
+ if (*p == '*')
+ {
+ ++p;
+ total_width += abs (va_arg (ap, int));
+ }
+ else
+ total_width += strtoul (p, (char **) &p, 10);
+ }
+ while (strchr ("hlL", *p))
+ ++p;
+ /* Should be big enough for any format specifier except %s and floats. */
+ total_width += 30;
+ switch (*p)
+ {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'c':
+ (void) va_arg (ap, int);
+ break;
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ (void) va_arg (ap, double);
+ /* Since an ieee double can have an exponent of 307, we'll
+ make the buffer wide enough to cover the gross case. */
+ total_width += 307;
+ break;
+ case 's':
+ {
+ char *tmp = va_arg (ap, char *);
+ if (tmp)
+ total_width += strlen (tmp);
+ else /* in case the vsprintf does prints a text */
+ total_width += 25; /* e.g. "(null pointer reference)" */
+ }
+ break;
+ case 'p':
+ case 'n':
+ (void) va_arg (ap, char *);
+ break;
+ }
+ p++;
+ }
+ }
+#ifdef TEST
+ global_total_width = total_width;
+#endif
+ *result = malloc (total_width);
+ if (*result != NULL)
+ return vsprintf (*result, format, *args);
+ else
+ return 0;
+}
+
+int
+vasprintf (result, format, args)
+ char **result;
+ const char *format;
+#if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
+ _BSD_VA_LIST_ args;
+#else
+ va_list args;
+#endif
+{
+ return int_vasprintf (result, format, &args);
+}
+
+
+int
+asprintf (char **buf, const char *fmt, ...)
+{
+ int status;
+ va_list ap;
+
+ va_start (ap, fmt);
+ status = vasprintf (buf, fmt, ap);
+ va_end (ap);
+ return status;
+}
+
+
+#ifdef TEST
+void
+checkit (const char* format, ...)
+{
+ va_list args;
+ char *result;
+
+ va_start (args, format);
+ vasprintf (&result, format, args);
+ if (strlen (result) < global_total_width)
+ printf ("PASS: ");
+ else
+ printf ("FAIL: ");
+ printf ("%d %s\n", global_total_width, result);
+}
+
+int
+main (void)
+{
+ checkit ("%d", 0x12345678);
+ checkit ("%200d", 5);
+ checkit ("%.300d", 6);
+ checkit ("%100.150d", 7);
+ checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
+777777777777777777333333333333366666666666622222222222777777777777733333");
+ checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
+}
+#endif /* TEST */
diff --git a/libtdenetwork/libgpgme-copy/gpgme/verify.c b/libtdenetwork/libgpgme-copy/gpgme/verify.c
new file mode 100644
index 000000000..4000a61c7
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/verify.c
@@ -0,0 +1,992 @@
+/* verify.c - Signature verification.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "gpgme.h"
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ struct _gpgme_op_verify_result result;
+
+ gpgme_signature_t current_sig;
+ int did_prepare_new_sig;
+ int only_newsig_seen;
+ int plaintext_seen;
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+ gpgme_signature_t sig = opd->result.signatures;
+
+ while (sig)
+ {
+ gpgme_signature_t next = sig->next;
+ gpgme_sig_notation_t notation = sig->notations;
+
+ while (notation)
+ {
+ gpgme_sig_notation_t next_nota = notation->next;
+
+ _gpgme_sig_notation_free (notation);
+ notation = next_nota;
+ }
+
+ if (sig->fpr)
+ free (sig->fpr);
+ if (sig->pka_address)
+ free (sig->pka_address);
+ free (sig);
+ sig = next;
+ }
+
+ if (opd->result.file_name)
+ free (opd->result.file_name);
+}
+
+
+gpgme_verify_result_t
+gpgme_op_verify_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+ gpgme_error_t err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
+ opd = hook;
+ if (err || !opd)
+ return NULL;
+
+ return &opd->result;
+}
+
+
+/* Build a summary vector from RESULT. */
+static void
+calc_sig_summary (gpgme_signature_t sig)
+{
+ unsigned long sum = 0;
+
+ /* Calculate the red/green flag. */
+ if (sig->validity == GPGME_VALIDITY_FULL
+ || sig->validity == GPGME_VALIDITY_ULTIMATE)
+ {
+ if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
+ || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
+ || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
+ sum |= GPGME_SIGSUM_GREEN;
+ }
+ else if (sig->validity == GPGME_VALIDITY_NEVER)
+ {
+ if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
+ || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
+ || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
+ sum |= GPGME_SIGSUM_RED;
+ }
+ else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
+ sum |= GPGME_SIGSUM_RED;
+
+
+ /* FIXME: handle the case when key and message are expired. */
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_SIG_EXPIRED:
+ sum |= GPGME_SIGSUM_SIG_EXPIRED;
+ break;
+
+ case GPG_ERR_KEY_EXPIRED:
+ sum |= GPGME_SIGSUM_KEY_EXPIRED;
+ break;
+
+ case GPG_ERR_NO_PUBKEY:
+ sum |= GPGME_SIGSUM_KEY_MISSING;
+ break;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ case GPG_ERR_NO_ERROR:
+ break;
+
+ default:
+ sum |= GPGME_SIGSUM_SYS_ERROR;
+ break;
+ }
+
+ /* Now look at the certain reason codes. */
+ switch (gpg_err_code (sig->validity_reason))
+ {
+ case GPG_ERR_CRL_TOO_OLD:
+ if (sig->validity == GPGME_VALIDITY_UNKNOWN)
+ sum |= GPGME_SIGSUM_CRL_TOO_OLD;
+ break;
+
+ case GPG_ERR_CERT_REVOKED:
+ sum |= GPGME_SIGSUM_KEY_REVOKED;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Check other flags. */
+ if (sig->wrong_key_usage)
+ sum |= GPGME_SIGSUM_BAD_POLICY;
+
+ /* Set the valid flag when the signature is unquestionable
+ valid. */
+ if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
+ sum |= GPGME_SIGSUM_VALID;
+
+ sig->summary = sum;
+}
+
+
+static gpgme_error_t
+prepare_new_sig (op_data_t opd)
+{
+ gpgme_signature_t sig;
+
+ if (opd->only_newsig_seen && opd->current_sig)
+ {
+ /* We have only seen the NEWSIG status and nothing else - we
+ better skip this signature therefore and reuse it for the
+ next possible signature. */
+ sig = opd->current_sig;
+ memset (sig, 0, sizeof *sig);
+ assert (opd->result.signatures == sig);
+ }
+ else
+ {
+ sig = calloc (1, sizeof (*sig));
+ if (!sig)
+ return gpg_error_from_errno (errno);
+ if (!opd->result.signatures)
+ opd->result.signatures = sig;
+ if (opd->current_sig)
+ opd->current_sig->next = sig;
+ opd->current_sig = sig;
+ }
+ opd->did_prepare_new_sig = 1;
+ opd->only_newsig_seen = 0;
+ return 0;
+}
+
+static gpgme_error_t
+parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
+{
+ gpgme_signature_t sig;
+ char *end = strchr (args, ' ');
+ char *tail;
+
+ if (end)
+ {
+ *end = '\0';
+ end++;
+ }
+
+ if (!opd->did_prepare_new_sig)
+ {
+ gpg_error_t err;
+
+ err = prepare_new_sig (opd);
+ if (err)
+ return err;
+ }
+ assert (opd->did_prepare_new_sig);
+ opd->did_prepare_new_sig = 0;
+
+ assert (opd->current_sig);
+ sig = opd->current_sig;
+
+ /* FIXME: We should set the source of the state. */
+ switch (code)
+ {
+ case GPGME_STATUS_GOODSIG:
+ sig->status = gpg_error (GPG_ERR_NO_ERROR);
+ break;
+
+ case GPGME_STATUS_EXPSIG:
+ sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
+ break;
+
+ case GPGME_STATUS_EXPKEYSIG:
+ sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
+ break;
+
+ case GPGME_STATUS_BADSIG:
+ sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
+ break;
+
+ case GPGME_STATUS_REVKEYSIG:
+ sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
+ break;
+
+ case GPGME_STATUS_ERRSIG:
+ /* Parse the pubkey algo. */
+ if (!end)
+ goto parse_err_sig_fail;
+ errno = 0;
+ sig->pubkey_algo = strtol (end, &tail, 0);
+ if (errno || end == tail || *tail != ' ')
+ goto parse_err_sig_fail;
+ end = tail;
+ while (*end == ' ')
+ end++;
+
+ /* Parse the hash algo. */
+ if (!*end)
+ goto parse_err_sig_fail;
+ errno = 0;
+ sig->hash_algo = strtol (end, &tail, 0);
+ if (errno || end == tail || *tail != ' ')
+ goto parse_err_sig_fail;
+ end = tail;
+ while (*end == ' ')
+ end++;
+
+ /* Skip the sig class. */
+ end = strchr (end, ' ');
+ if (!end)
+ goto parse_err_sig_fail;
+ while (*end == ' ')
+ end++;
+
+ /* Parse the timestamp. */
+ sig->timestamp = _gpgme_parse_timestamp (end, &tail);
+ if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ end = tail;
+ while (*end == ' ')
+ end++;
+
+ /* Parse the return code. */
+ if (end[0] && (!end[1] || end[1] == ' '))
+ {
+ switch (end[0])
+ {
+ case '4':
+ sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ break;
+
+ case '9':
+ sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
+ break;
+
+ default:
+ sig->status = gpg_error (GPG_ERR_GENERAL);
+ }
+ }
+ else
+ goto parse_err_sig_fail;
+
+ goto parse_err_sig_ok;
+
+ parse_err_sig_fail:
+ sig->status = gpg_error (GPG_ERR_GENERAL);
+ parse_err_sig_ok:
+ break;
+
+ default:
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+
+ if (*args)
+ {
+ sig->fpr = strdup (args);
+ if (!sig->fpr)
+ return gpg_error_from_errno (errno);
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+parse_valid_sig (gpgme_signature_t sig, char *args)
+{
+ char *end = strchr (args, ' ');
+ if (end)
+ {
+ *end = '\0';
+ end++;
+ }
+
+ if (!*args)
+ /* We require at least the fingerprint. */
+ return gpg_error (GPG_ERR_GENERAL);
+
+ if (sig->fpr)
+ free (sig->fpr);
+ sig->fpr = strdup (args);
+ if (!sig->fpr)
+ return gpg_error_from_errno (errno);
+
+ /* Skip the creation date. */
+ end = strchr (end, ' ');
+ if (end)
+ {
+ char *tail;
+
+ sig->timestamp = _gpgme_parse_timestamp (end, &tail);
+ if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ end = tail;
+
+ sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
+ if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ end = tail;
+
+ while (*end == ' ')
+ end++;
+ /* Skip the signature version. */
+ end = strchr (end, ' ');
+ if (end)
+ {
+ while (*end == ' ')
+ end++;
+
+ /* Skip the reserved field. */
+ end = strchr (end, ' ');
+ if (end)
+ {
+ /* Parse the pubkey algo. */
+ errno = 0;
+ sig->pubkey_algo = strtol (end, &tail, 0);
+ if (errno || end == tail || *tail != ' ')
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ end = tail;
+
+ while (*end == ' ')
+ end++;
+
+ if (*end)
+ {
+ /* Parse the hash algo. */
+
+ errno = 0;
+ sig->hash_algo = strtol (end, &tail, 0);
+ if (errno || end == tail || *tail != ' ')
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ end = tail;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+ gpgme_sig_notation_t *lastp = &sig->notations;
+ gpgme_sig_notation_t notation = sig->notations;
+ char *end = strchr (args, ' ');
+
+ if (end)
+ *end = '\0';
+
+ if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
+ {
+ /* FIXME: We could keep a pointer to the last notation in the list. */
+ while (notation && notation->value)
+ {
+ lastp = &notation->next;
+ notation = notation->next;
+ }
+
+ if (notation)
+ /* There is another notation name without data for the
+ previous one. The crypto backend misbehaves. */
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
+ if (err)
+ return err;
+
+ if (code == GPGME_STATUS_NOTATION_NAME)
+ {
+ err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
+ if (err)
+ {
+ _gpgme_sig_notation_free (notation);
+ return err;
+ }
+
+ notation->name_len = strlen (notation->name);
+
+ /* FIXME: For now we fake the human-readable flag. The
+ critical flag can not be reported as it is not
+ provided. */
+ notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
+ notation->human_readable = 1;
+ }
+ else
+ {
+ /* This is a policy URL. */
+
+ err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
+ if (err)
+ {
+ _gpgme_sig_notation_free (notation);
+ return err;
+ }
+
+ notation->value_len = strlen (notation->value);
+ }
+ *lastp = notation;
+ }
+ else if (code == GPGME_STATUS_NOTATION_DATA)
+ {
+ int len = strlen (args) + 1;
+ char *dest;
+
+ /* FIXME: We could keep a pointer to the last notation in the list. */
+ while (notation && notation->next)
+ {
+ lastp = &notation->next;
+ notation = notation->next;
+ }
+
+ if (!notation || !notation->name)
+ /* There is notation data without a previous notation
+ name. The crypto backend misbehaves. */
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ if (!notation->value)
+ {
+ dest = notation->value = malloc (len);
+ if (!dest)
+ return gpg_error_from_errno (errno);
+ }
+ else
+ {
+ int cur_len = strlen (notation->value);
+ dest = realloc (notation->value, len + strlen (notation->value));
+ if (!dest)
+ return gpg_error_from_errno (errno);
+ notation->value = dest;
+ dest += cur_len;
+ }
+
+ err = _gpgme_decode_percent_string (args, &dest, len, 0);
+ if (err)
+ return err;
+
+ notation->value_len += strlen (dest);
+ }
+ else
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ return 0;
+}
+
+
+static gpgme_error_t
+parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
+{
+ char *end = strchr (args, ' ');
+
+ if (end)
+ *end = '\0';
+
+ switch (code)
+ {
+ case GPGME_STATUS_TRUST_UNDEFINED:
+ default:
+ sig->validity = GPGME_VALIDITY_UNKNOWN;
+ break;
+
+ case GPGME_STATUS_TRUST_NEVER:
+ sig->validity = GPGME_VALIDITY_NEVER;
+ break;
+
+ case GPGME_STATUS_TRUST_MARGINAL:
+ sig->validity = GPGME_VALIDITY_MARGINAL;
+ break;
+
+ case GPGME_STATUS_TRUST_FULLY:
+ case GPGME_STATUS_TRUST_ULTIMATE:
+ sig->validity = GPGME_VALIDITY_FULL;
+ break;
+ }
+
+ if (*args)
+ sig->validity_reason = _gpgme_map_gnupg_error (args);
+ else
+ sig->validity_reason = 0;
+
+ return 0;
+}
+
+
+/* Parse an error status line and if SET_STATUS is true update the
+ result status as appropriate. With SET_STATUS being false, only
+ check for an error. */
+static gpgme_error_t
+parse_error (gpgme_signature_t sig, char *args, int set_status)
+{
+ gpgme_error_t err;
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ return gpg_error (GPG_ERR_INV_ENGINE);
+
+ err = _gpgme_map_gnupg_error (which);
+
+ if (!strcmp (where, "proc_pkt.plaintext")
+ && gpg_err_code (err) == GPG_ERR_BAD_DATA)
+ {
+ /* This indicates a double plaintext. The only solid way to
+ handle this is by failing the oepration. */
+ return gpg_error (GPG_ERR_BAD_DATA);
+ }
+ else if (!set_status)
+ ;
+ else if (!strcmp (where, "verify.findkey"))
+ sig->status = err;
+ else if (!strcmp (where, "verify.keyusage")
+ && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
+ sig->wrong_key_usage = 1;
+
+ return 0;
+}
+
+
+gpgme_error_t
+_gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ gpgme_signature_t sig;
+ char *end;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ sig = opd->current_sig;
+
+ switch (code)
+ {
+ case GPGME_STATUS_NEWSIG:
+ if (sig)
+ calc_sig_summary (sig);
+ err = prepare_new_sig (opd);
+ opd->only_newsig_seen = 1;
+ return err;
+
+ case GPGME_STATUS_GOODSIG:
+ case GPGME_STATUS_EXPSIG:
+ case GPGME_STATUS_EXPKEYSIG:
+ case GPGME_STATUS_BADSIG:
+ case GPGME_STATUS_ERRSIG:
+ case GPGME_STATUS_REVKEYSIG:
+ if (sig && !opd->did_prepare_new_sig)
+ calc_sig_summary (sig);
+ opd->only_newsig_seen = 0;
+ return parse_new_sig (opd, code, args);
+
+ case GPGME_STATUS_VALIDSIG:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_valid_sig (sig, args)
+ : gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_NODATA:
+ opd->only_newsig_seen = 0;
+ if (!sig)
+ return gpg_error (GPG_ERR_NO_DATA);
+ sig->status = gpg_error (GPG_ERR_NO_DATA);
+ break;
+
+ case GPGME_STATUS_UNEXPECTED:
+ opd->only_newsig_seen = 0;
+ if (!sig)
+ return gpg_error (GPG_ERR_GENERAL);
+ sig->status = gpg_error (GPG_ERR_NO_DATA);
+ break;
+
+ case GPGME_STATUS_NOTATION_NAME:
+ case GPGME_STATUS_NOTATION_DATA:
+ case GPGME_STATUS_POLICY_URL:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_notation (sig, code, args)
+ : gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_TRUST_UNDEFINED:
+ case GPGME_STATUS_TRUST_NEVER:
+ case GPGME_STATUS_TRUST_MARGINAL:
+ case GPGME_STATUS_TRUST_FULLY:
+ case GPGME_STATUS_TRUST_ULTIMATE:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_trust (sig, code, args)
+ : gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_PKA_TRUST_BAD:
+ case GPGME_STATUS_PKA_TRUST_GOOD:
+ opd->only_newsig_seen = 0;
+ /* Check that we only get one of these status codes per
+ signature; if not the crypto backend misbehaves. */
+ if (!sig || sig->pka_trust || sig->pka_address)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
+ end = strchr (args, ' ');
+ if (end)
+ *end = 0;
+ sig->pka_address = strdup (args);
+ break;
+
+ case GPGME_STATUS_ERROR:
+ opd->only_newsig_seen = 0;
+ /* Some error stati are informational, so we don't return an
+ error code if we are not ready to process this status. */
+ return parse_error (sig, args, !!sig );
+
+ case GPGME_STATUS_EOF:
+ if (sig && !opd->did_prepare_new_sig)
+ calc_sig_summary (sig);
+ if (opd->only_newsig_seen && sig)
+ {
+ gpgme_signature_t sig2;
+ /* The last signature has no valid information - remove it
+ from the list. */
+ assert (!sig->next);
+ if (sig == opd->result.signatures)
+ opd->result.signatures = NULL;
+ else
+ {
+ for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
+ if (sig2->next == sig)
+ {
+ sig2->next = NULL;
+ break;
+ }
+ }
+ /* Note that there is no need to release the members of SIG
+ because we won't be here if they have been set. */
+ free (sig);
+ opd->current_sig = NULL;
+ }
+ opd->only_newsig_seen = 0;
+ break;
+
+ case GPGME_STATUS_PLAINTEXT:
+ if (++opd->plaintext_seen > 1)
+ return gpg_error (GPG_ERR_BAD_DATA);
+ err = _gpgme_parse_plaintext (args, &opd->result.file_name);
+ if (err)
+ return err;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static gpgme_error_t
+verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_verify_status_handler (priv, code, args);
+ return err;
+}
+
+
+gpgme_error_t
+_gpgme_op_verify_init_result (gpgme_ctx_t ctx)
+{
+ void *hook;
+ op_data_t opd;
+
+ return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
+ sizeof (*opd), release_op_data);
+}
+
+
+static gpgme_error_t
+verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
+ gpgme_data_t signed_text, gpgme_data_t plaintext)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_verify_init_result (ctx);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
+
+ if (!sig)
+ return gpg_error (GPG_ERR_NO_DATA);
+ if (!signed_text && !plaintext)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
+}
+
+
+/* Decrypt ciphertext CIPHER and make a signature verification within
+ CTX and store the resulting plaintext in PLAIN. */
+gpgme_error_t
+gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
+ gpgme_data_t signed_text, gpgme_data_t plaintext)
+{
+ return verify_start (ctx, 0, sig, signed_text, plaintext);
+}
+
+
+/* Decrypt ciphertext CIPHER and make a signature verification within
+ CTX and store the resulting plaintext in PLAIN. */
+gpgme_error_t
+gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
+ gpgme_data_t plaintext)
+{
+ gpgme_error_t err;
+
+ err = verify_start (ctx, 1, sig, signed_text, plaintext);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
+
+
+/* Compatibility interfaces. */
+
+/* Get the key used to create signature IDX in CTX and return it in
+ R_KEY. */
+gpgme_error_t
+gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
+{
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return gpg_error (GPG_ERR_EOF);
+
+ return gpgme_get_key (ctx, sig->fpr, r_key, 0);
+}
+
+
+/* Retrieve the signature status of signature IDX in CTX after a
+ successful verify operation in R_STAT (if non-null). The creation
+ time stamp of the signature is returned in R_CREATED (if non-null).
+ The function returns a string containing the fingerprint. */
+const char *
+gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
+ _gpgme_sig_stat_t *r_stat, time_t *r_created)
+{
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return NULL;
+
+ if (r_stat)
+ {
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_NO_ERROR:
+ *r_stat = GPGME_SIG_STAT_GOOD;
+ break;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ *r_stat = GPGME_SIG_STAT_BAD;
+ break;
+
+ case GPG_ERR_NO_PUBKEY:
+ *r_stat = GPGME_SIG_STAT_NOKEY;
+ break;
+
+ case GPG_ERR_NO_DATA:
+ *r_stat = GPGME_SIG_STAT_NOSIG;
+ break;
+
+ case GPG_ERR_SIG_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXP;
+ break;
+
+ case GPG_ERR_KEY_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
+ break;
+
+ default:
+ *r_stat = GPGME_SIG_STAT_ERROR;
+ break;
+ }
+ }
+ if (r_created)
+ *r_created = sig->timestamp;
+ return sig->fpr;
+}
+
+
+/* Retrieve certain attributes of a signature. IDX is the index
+ number of the signature after a successful verify operation. WHAT
+ is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
+ one. WHATIDX is to be passed as 0 for most attributes . */
+unsigned long
+gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
+ _gpgme_attr_t what, int whatidx)
+{
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return 0;
+
+ switch (what)
+ {
+ case GPGME_ATTR_CREATED:
+ return sig->timestamp;
+
+ case GPGME_ATTR_EXPIRE:
+ return sig->exp_timestamp;
+
+ case GPGME_ATTR_VALIDITY:
+ return (unsigned long) sig->validity;
+
+ case GPGME_ATTR_SIG_STATUS:
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_NO_ERROR:
+ return GPGME_SIG_STAT_GOOD;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ return GPGME_SIG_STAT_BAD;
+
+ case GPG_ERR_NO_PUBKEY:
+ return GPGME_SIG_STAT_NOKEY;
+
+ case GPG_ERR_NO_DATA:
+ return GPGME_SIG_STAT_NOSIG;
+
+ case GPG_ERR_SIG_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXP;
+
+ case GPG_ERR_KEY_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXPKEY;
+
+ default:
+ return GPGME_SIG_STAT_ERROR;
+ }
+
+ case GPGME_ATTR_SIG_SUMMARY:
+ return sig->summary;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+const char *
+gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
+ _gpgme_attr_t what, int whatidx)
+{
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return NULL;
+
+ switch (what)
+ {
+ case GPGME_ATTR_FPR:
+ return sig->fpr;
+
+ case GPGME_ATTR_ERRTOK:
+ if (whatidx == 1)
+ return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+ else
+ return "";
+ default:
+ break;
+ }
+
+ return NULL;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/version.c b/libtdenetwork/libgpgme-copy/gpgme/version.c
new file mode 100644
index 000000000..133b23c7e
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/version.c
@@ -0,0 +1,231 @@
+/* version.c - Version check routines.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "gpgme.h"
+#include "priv-io.h"
+
+/* For _gpgme_sema_subsystem_init (). */
+#include "sema.h"
+
+#ifdef HAVE_ASSUAN_H
+#include "assuan.h"
+#endif
+
+
+/* Bootstrap the subsystems needed for concurrent operation. This
+ must be done once at startup. We can not guarantee this using a
+ lock, though, because the semaphore subsystem needs to be
+ initialized itself before it can be used. So we expect that the
+ user performs the necessary syncrhonization. */
+static void
+do_subsystem_inits (void)
+{
+ static int done = 0;
+
+ if (done)
+ return;
+
+ _gpgme_sema_subsystem_init ();
+ _gpgme_io_subsystem_init ();
+#ifdef HAVE_ASSUAN_H
+ assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME);
+#endif
+
+ done = 1;
+}
+
+
+/* Read the next number in the version string STR and return it in
+ *NUMBER. Return a pointer to the tail of STR after parsing, or
+ *NULL if the version string was invalid. */
+static const char *
+parse_version_number (const char *str, int *number)
+{
+#define MAXVAL ((INT_MAX - 10) / 10)
+ int val = 0;
+
+ /* Leading zeros are not allowed. */
+ if (*str == '0' && isdigit(str[1]))
+ return NULL;
+
+ while (isdigit (*str) && val <= MAXVAL)
+ {
+ val *= 10;
+ val += *(str++) - '0';
+ }
+ *number = val;
+ return val > MAXVAL ? NULL : str;
+}
+
+
+/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
+ example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
+ as integers. The function returns the tail of the string that
+ follows the version number. This might be te empty string if there
+ is nothing following the version number, or a patchlevel. The
+ function returns NULL if the version string is not valid. */
+static const char *
+parse_version_string (const char *str, int *major, int *minor, int *micro)
+{
+ str = parse_version_number (str, major);
+ if (!str || *str != '.')
+ return NULL;
+ str++;
+
+ str = parse_version_number (str, minor);
+ if (!str || *str != '.')
+ return NULL;
+ str++;
+
+ str = parse_version_number (str, micro);
+ if (!str)
+ return NULL;
+
+ /* A patchlevel might follow. */
+ return str;
+}
+
+
+/* Return true if MY_VERSION is at least RETQ_VERSION, and false
+ otherwise. */
+int
+_gpgme_compare_versions (const char *my_version,
+ const char *rq_version)
+{
+ int my_major, my_minor, my_micro;
+ int rq_major, rq_minor, rq_micro;
+ const char *my_plvl, *rq_plvl;
+
+ if (!rq_version)
+ return 1;
+ if (!my_version)
+ return 0;
+
+ my_plvl = parse_version_string (my_version, &my_major, &my_minor, &my_micro);
+ if (!my_plvl)
+ return 0;
+
+ rq_plvl = parse_version_string (rq_version, &rq_major, &rq_minor, &rq_micro);
+ if (!rq_plvl)
+ return 0;
+
+ if (my_major > rq_major
+ || (my_major == rq_major && my_minor > rq_minor)
+ || (my_major == rq_major && my_minor == rq_minor
+ && my_micro > rq_micro)
+ || (my_major == rq_major && my_minor == rq_minor
+ && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0))
+ return 1;
+
+ return 0;
+}
+
+
+/* Check that the the version of the library is at minimum the
+ requested one and return the version string; return NULL if the
+ condition is not met. If a NULL is passed to this function, no
+ check is done and the version string is simply returned.
+
+ This function must be run once at startup, as it also initializes
+ some subsystems. Its invocation must be synchronized against
+ calling any of the other functions in a multi-threaded
+ environments. */
+const char *
+gpgme_check_version (const char *req_version)
+{
+ do_subsystem_inits ();
+ return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
+}
+
+
+#define LINELENGTH 80
+
+/* Retrieve the version number from the --version output of the
+ program FILE_NAME. */
+char *
+_gpgme_get_program_version (const char *const file_name)
+{
+ char line[LINELENGTH] = "";
+ int linelen = 0;
+ char *mark = NULL;
+ int rp[2];
+ int nread;
+ char *argv[] = {NULL /* file_name */, "--version", 0};
+ struct spawn_fd_item_s pfd[] = { {0, -1}, {-1, -1} };
+ struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */}, {-1, -1} };
+ int status;
+
+ if (!file_name)
+ return NULL;
+ argv[0] = (char *) file_name;
+
+ if (_gpgme_io_pipe (rp, 1) < 0)
+ return NULL;
+
+ pfd[0].fd = rp[1];
+ cfd[0].fd = rp[1];
+
+ status = _gpgme_io_spawn (file_name, argv, cfd, pfd);
+ if (status < 0)
+ {
+ _gpgme_io_close (rp[0]);
+ _gpgme_io_close (rp[1]);
+ return NULL;
+ }
+
+ do
+ {
+ nread = _gpgme_io_read (rp[0], &line[linelen], LINELENGTH - linelen - 1);
+ if (nread > 0)
+ {
+ line[linelen + nread] = '\0';
+ mark = strchr (&line[linelen], '\n');
+ if (mark)
+ {
+ if (mark > &line[0] && *mark == '\r')
+ mark--;
+ *mark = '\0';
+ break;
+ }
+ linelen += nread;
+ }
+ }
+ while (nread > 0 && linelen < LINELENGTH - 1);
+
+ _gpgme_io_close (rp[0]);
+
+ if (mark)
+ {
+ mark = strrchr (line, ' ');
+ if (!mark)
+ return NULL;
+ return strdup (mark + 1);
+ }
+
+ return NULL;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/w32-io.c b/libtdenetwork/libgpgme-copy/gpgme/w32-io.c
new file mode 100644
index 000000000..677c14e30
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/w32-io.c
@@ -0,0 +1,1152 @@
+/* w32-io.c - W32 API I/O functions.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <windows.h>
+#include <io.h>
+
+#include "util.h"
+#include "sema.h"
+#include "priv-io.h"
+#include "debug.h"
+
+/* We assume that a HANDLE can be represented by an int which should
+ be true for all i386 systems (HANDLE is defined as void *) and
+ these are the only systems for which Windows is available. Further
+ we assume that -1 denotes an invalid handle. */
+
+#define fd_to_handle(a) ((HANDLE)(a))
+#define handle_to_fd(a) ((int)(a))
+#define pid_to_handle(a) ((HANDLE)(a))
+#define handle_to_pid(a) ((int)(a))
+
+#define READBUF_SIZE 4096
+#define WRITEBUF_SIZE 4096
+#define PIPEBUF_SIZE 4096
+#define MAX_READERS 20
+#define MAX_WRITERS 20
+
+static struct {
+ int inuse;
+ int fd;
+ void (*handler)(int,void*);
+ void *value;
+} notify_table[256];
+DEFINE_STATIC_LOCK (notify_table_lock);
+
+
+struct reader_context_s {
+ HANDLE file_hd;
+ HANDLE thread_hd;
+ DECLARE_LOCK (mutex);
+
+ int stop_me;
+ int eof;
+ int eof_shortcut;
+ int error;
+ int error_code;
+
+ HANDLE have_data_ev; /* manually reset */
+ HANDLE have_space_ev; /* auto reset */
+ HANDLE stopped;
+ size_t readpos, writepos;
+ char buffer[READBUF_SIZE];
+};
+
+
+static struct {
+ volatile int used;
+ int fd;
+ struct reader_context_s *context;
+} reader_table[MAX_READERS];
+static int reader_table_size= MAX_READERS;
+DEFINE_STATIC_LOCK (reader_table_lock);
+
+
+struct writer_context_s {
+ HANDLE file_hd;
+ HANDLE thread_hd;
+ DECLARE_LOCK (mutex);
+
+ int stop_me;
+ int error;
+ int error_code;
+
+ HANDLE have_data; /* manually reset */
+ HANDLE is_empty;
+ HANDLE stopped;
+ size_t nbytes;
+ char buffer[WRITEBUF_SIZE];
+};
+
+
+static struct {
+ volatile int used;
+ int fd;
+ struct writer_context_s *context;
+} writer_table[MAX_WRITERS];
+static int writer_table_size= MAX_WRITERS;
+DEFINE_STATIC_LOCK (writer_table_lock);
+
+
+
+static int
+get_desired_thread_priority (void)
+{
+ int value;
+
+ if (!_gpgme_get_conf_int ("IOThreadPriority", &value))
+ {
+ value = THREAD_PRIORITY_HIGHEST;
+ DEBUG1 ("** Using standard IOThreadPriority of %d\n", value);
+ }
+ else
+ DEBUG1 ("** Configured IOThreadPriority is %d\n", value);
+
+ return value;
+}
+
+
+static HANDLE
+set_synchronize (HANDLE h)
+{
+ HANDLE tmp;
+
+ /* For NT we have to set the sync flag. It seems that the only
+ * way to do it is by duplicating the handle. Tsss.. */
+ if (!DuplicateHandle( GetCurrentProcess(), h,
+ GetCurrentProcess(), &tmp,
+ EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE, 0 ) ) {
+ DEBUG1 ("** Set SYNCRONIZE failed: ec=%d\n", (int)GetLastError());
+ }
+ else {
+ CloseHandle (h);
+ h = tmp;
+ }
+ return h;
+}
+
+
+
+static DWORD CALLBACK
+reader (void *arg)
+{
+ struct reader_context_s *c = arg;
+ int nbytes;
+ DWORD nread;
+
+ DEBUG2 ("reader thread %p for file %p started", c->thread_hd, c->file_hd );
+ for (;;) {
+ LOCK (c->mutex);
+ /* leave a 1 byte gap so that we can see whether it is empty or full*/
+ if ((c->writepos + 1) % READBUF_SIZE == c->readpos) {
+ /* wait for space */
+ if (!ResetEvent (c->have_space_ev) )
+ DEBUG1 ("ResetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+ DEBUG1 ("reader thread %p: waiting for space ...", c->thread_hd );
+ WaitForSingleObject (c->have_space_ev, INFINITE);
+ DEBUG1 ("reader thread %p: got space", c->thread_hd );
+ LOCK (c->mutex);
+ }
+ if ( c->stop_me ) {
+ UNLOCK (c->mutex);
+ break;
+ }
+ nbytes = (c->readpos + READBUF_SIZE - c->writepos-1) % READBUF_SIZE;
+ if ( nbytes > READBUF_SIZE - c->writepos )
+ nbytes = READBUF_SIZE - c->writepos;
+ UNLOCK (c->mutex);
+
+ DEBUG2 ("reader thread %p: reading %d bytes", c->thread_hd, nbytes );
+ if ( !ReadFile ( c->file_hd,
+ c->buffer+c->writepos, nbytes, &nread, NULL) ) {
+ c->error_code = (int)GetLastError ();
+ if (c->error_code == ERROR_BROKEN_PIPE ) {
+ c->eof=1;
+ DEBUG1 ("reader thread %p: got eof (broken pipe)",
+ c->thread_hd );
+ }
+ else {
+ c->error = 1;
+ DEBUG2 ("reader thread %p: read error: ec=%d",
+ c->thread_hd, c->error_code );
+ }
+ break;
+ }
+ if ( !nread ) {
+ c->eof = 1;
+ DEBUG1 ("reader thread %p: got eof", c->thread_hd );
+ break;
+ }
+ DEBUG2 ("reader thread %p: got %d bytes", c->thread_hd, (int)nread );
+
+ LOCK (c->mutex);
+ if (c->stop_me) {
+ UNLOCK (c->mutex);
+ break;
+ }
+ c->writepos = (c->writepos + nread) % READBUF_SIZE;
+ if ( !SetEvent (c->have_data_ev) )
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+ }
+ /* indicate that we have an error or eof */
+ if ( !SetEvent (c->have_data_ev) )
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ DEBUG1 ("reader thread %p ended", c->thread_hd );
+ SetEvent (c->stopped);
+
+ return 0;
+}
+
+
+static struct reader_context_s *
+create_reader (HANDLE fd)
+{
+ struct reader_context_s *c;
+ SECURITY_ATTRIBUTES sec_attr;
+ DWORD tid;
+
+ DEBUG1 ("creating new read thread for file handle %p", fd );
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ c = calloc (1, sizeof *c );
+ if (!c)
+ return NULL;
+
+ c->file_hd = fd;
+ c->have_data_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
+ c->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL);
+ c->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
+ if (!c->have_data_ev || !c->have_space_ev || !c->stopped ) {
+ DEBUG1 ("** CreateEvent failed: ec=%d\n", (int)GetLastError ());
+ if (c->have_data_ev)
+ CloseHandle (c->have_data_ev);
+ if (c->have_space_ev)
+ CloseHandle (c->have_space_ev);
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ free (c);
+ return NULL;
+ }
+
+ c->have_data_ev = set_synchronize (c->have_data_ev);
+ INIT_LOCK (c->mutex);
+
+ c->thread_hd = CreateThread (&sec_attr, 0, reader, c, 0, &tid );
+ if (!c->thread_hd) {
+ DEBUG1 ("** failed to create reader thread: ec=%d\n",
+ (int)GetLastError ());
+ DESTROY_LOCK (c->mutex);
+ if (c->have_data_ev)
+ CloseHandle (c->have_data_ev);
+ if (c->have_space_ev)
+ CloseHandle (c->have_space_ev);
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ free (c);
+ return NULL;
+ }
+ else {
+ /* We set the priority of the thread higher because we know that
+ it only runs for a short time. This greatly helps to increase
+ the performance of the I/O. */
+ SetThreadPriority (c->thread_hd, get_desired_thread_priority ());
+ }
+
+ return c;
+}
+
+static void
+destroy_reader (struct reader_context_s *c)
+{
+ LOCK (c->mutex);
+ c->stop_me = 1;
+ if (c->have_space_ev)
+ SetEvent (c->have_space_ev);
+ UNLOCK (c->mutex);
+
+ DEBUG1 ("waiting for thread %p termination ...", c->thread_hd );
+ WaitForSingleObject (c->stopped, INFINITE);
+ DEBUG1 ("thread %p has terminated", c->thread_hd );
+
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ if (c->have_data_ev)
+ CloseHandle (c->have_data_ev);
+ if (c->have_space_ev)
+ CloseHandle (c->have_space_ev);
+ CloseHandle (c->thread_hd);
+ DESTROY_LOCK (c->mutex);
+ free (c);
+}
+
+
+/*
+ * Find a reader context or create a new one
+ * Note that the reader context will last until a io_close.
+ */
+static struct reader_context_s *
+find_reader (int fd, int start_it)
+{
+ int i;
+
+ for (i=0; i < reader_table_size ; i++ ) {
+ if ( reader_table[i].used && reader_table[i].fd == fd )
+ return reader_table[i].context;
+ }
+ if (!start_it)
+ return NULL;
+
+ LOCK (reader_table_lock);
+ for (i=0; i < reader_table_size; i++ ) {
+ if (!reader_table[i].used) {
+ reader_table[i].fd = fd;
+ reader_table[i].context = create_reader (fd_to_handle (fd));
+ reader_table[i].used = 1;
+ UNLOCK (reader_table_lock);
+ return reader_table[i].context;
+ }
+ }
+ UNLOCK (reader_table_lock);
+ return NULL;
+}
+
+
+static void
+kill_reader (int fd)
+{
+ int i;
+
+ LOCK (reader_table_lock);
+ for (i=0; i < reader_table_size; i++ ) {
+ if (reader_table[i].used && reader_table[i].fd == fd ) {
+ destroy_reader (reader_table[i].context);
+ reader_table[i].context = NULL;
+ reader_table[i].used = 0;
+ break;
+ }
+ }
+ UNLOCK (reader_table_lock);
+}
+
+
+
+int
+_gpgme_io_read ( int fd, void *buffer, size_t count )
+{
+ int nread;
+ struct reader_context_s *c = find_reader (fd,1);
+
+ DEBUG2 ("fd %d: about to read %d bytes\n", fd, (int)count );
+ if ( !c ) {
+ DEBUG0 ( "no reader thread\n");
+ return -1;
+ }
+ if (c->eof_shortcut) {
+ DEBUG1 ("fd %d: EOF (again)", fd );
+ return 0;
+ }
+
+ LOCK (c->mutex);
+ if (c->readpos == c->writepos && !c->error) { /*no data avail*/
+ UNLOCK (c->mutex);
+ DEBUG2 ("fd %d: waiting for data from thread %p", fd, c->thread_hd);
+ WaitForSingleObject (c->have_data_ev, INFINITE);
+ DEBUG2 ("fd %d: data from thread %p available", fd, c->thread_hd);
+ LOCK (c->mutex);
+ }
+
+ if (c->readpos == c->writepos || c->error) {
+ UNLOCK (c->mutex);
+ c->eof_shortcut = 1;
+ if (c->eof) {
+ DEBUG1 ("fd %d: EOF", fd );
+ return 0;
+ }
+ if (!c->error) {
+ DEBUG1 ("fd %d: EOF but eof flag not set", fd );
+ return 0;
+ }
+ DEBUG1 ("fd %d: read error", fd );
+ return -1;
+ }
+
+ nread = c->readpos < c->writepos? c->writepos - c->readpos
+ : READBUF_SIZE - c->readpos;
+ if (nread > count)
+ nread = count;
+ memcpy (buffer, c->buffer+c->readpos, nread);
+ c->readpos = (c->readpos + nread) % READBUF_SIZE;
+ if (c->readpos == c->writepos && !c->eof) {
+ if ( !ResetEvent (c->have_data_ev) )
+ DEBUG1 ("ResetEvent failed: ec=%d", (int)GetLastError ());
+ }
+ if (!SetEvent (c->have_space_ev))
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+
+ DEBUG2 ("fd %d: got %d bytes\n", fd, nread );
+ if (nread > 0)
+ _gpgme_debug (2, "fd %d: got `%.*s'\n", fd, nread, buffer);
+
+ return nread;
+}
+/*
+ * The writer does use a simple buffering strategy so that we are
+ * informed about write errors as soon as possible (i.e. with the the
+ * next call to the write function
+ */
+static DWORD CALLBACK
+writer (void *arg)
+{
+ struct writer_context_s *c = arg;
+ DWORD nwritten;
+
+ DEBUG2 ("writer thread %p for file %p started", c->thread_hd, c->file_hd );
+ for (;;) {
+ LOCK (c->mutex);
+ if ( c->stop_me ) {
+ UNLOCK (c->mutex);
+ break;
+ }
+ if ( !c->nbytes ) {
+ if (!SetEvent (c->is_empty))
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ if (!ResetEvent (c->have_data) )
+ DEBUG1 ("ResetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+ DEBUG1 ("writer thread %p: idle ...", c->thread_hd );
+ WaitForSingleObject (c->have_data, INFINITE);
+ DEBUG1 ("writer thread %p: got data to send", c->thread_hd );
+ LOCK (c->mutex);
+ }
+ if ( c->stop_me ) {
+ UNLOCK (c->mutex);
+ break;
+ }
+ UNLOCK (c->mutex);
+
+ DEBUG2 ("writer thread %p: writing %d bytes",
+ c->thread_hd, c->nbytes );
+ if ( c->nbytes && !WriteFile ( c->file_hd, c->buffer, c->nbytes,
+ &nwritten, NULL)) {
+ c->error_code = (int)GetLastError ();
+ c->error = 1;
+ DEBUG2 ("writer thread %p: write error: ec=%d",
+ c->thread_hd, c->error_code );
+ break;
+ }
+ DEBUG2 ("writer thread %p: wrote %d bytes",
+ c->thread_hd, (int)nwritten );
+
+ LOCK (c->mutex);
+ c->nbytes -= nwritten;
+ UNLOCK (c->mutex);
+ }
+ /* indicate that we have an error */
+ if ( !SetEvent (c->is_empty) )
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ DEBUG1 ("writer thread %p ended", c->thread_hd );
+ SetEvent (c->stopped);
+
+ return 0;
+}
+
+
+static struct writer_context_s *
+create_writer (HANDLE fd)
+{
+ struct writer_context_s *c;
+ SECURITY_ATTRIBUTES sec_attr;
+ DWORD tid;
+
+ DEBUG1 ("creating new write thread for file handle %p", fd );
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ c = calloc (1, sizeof *c );
+ if (!c)
+ return NULL;
+
+ c->file_hd = fd;
+ c->have_data = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
+ c->is_empty = CreateEvent (&sec_attr, TRUE, TRUE, NULL);
+ c->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL);
+ if (!c->have_data || !c->is_empty || !c->stopped ) {
+ DEBUG1 ("** CreateEvent failed: ec=%d\n", (int)GetLastError ());
+ if (c->have_data)
+ CloseHandle (c->have_data);
+ if (c->is_empty)
+ CloseHandle (c->is_empty);
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ free (c);
+ return NULL;
+ }
+
+ c->is_empty = set_synchronize (c->is_empty);
+ INIT_LOCK (c->mutex);
+
+ c->thread_hd = CreateThread (&sec_attr, 0, writer, c, 0, &tid );
+ if (!c->thread_hd) {
+ DEBUG1 ("** failed to create writer thread: ec=%d\n",
+ (int)GetLastError ());
+ DESTROY_LOCK (c->mutex);
+ if (c->have_data)
+ CloseHandle (c->have_data);
+ if (c->is_empty)
+ CloseHandle (c->is_empty);
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ free (c);
+ return NULL;
+ }
+ else {
+ /* We set the priority of the thread higher because we know that
+ it only runs for a short time. This greatly helps to increase
+ the performance of the I/O. */
+ SetThreadPriority (c->thread_hd, get_desired_thread_priority ());
+ }
+
+ return c;
+}
+
+static void
+destroy_writer (struct writer_context_s *c)
+{
+ LOCK (c->mutex);
+ c->stop_me = 1;
+ if (c->have_data)
+ SetEvent (c->have_data);
+ UNLOCK (c->mutex);
+
+ DEBUG1 ("waiting for thread %p termination ...", c->thread_hd );
+ WaitForSingleObject (c->stopped, INFINITE);
+ DEBUG1 ("thread %p has terminated", c->thread_hd );
+
+ if (c->stopped)
+ CloseHandle (c->stopped);
+ if (c->have_data)
+ CloseHandle (c->have_data);
+ if (c->is_empty)
+ CloseHandle (c->is_empty);
+ CloseHandle (c->thread_hd);
+ DESTROY_LOCK (c->mutex);
+ free (c);
+}
+
+
+/*
+ * Find a writer context or create a new one
+ * Note that the writer context will last until a io_close.
+ */
+static struct writer_context_s *
+find_writer (int fd, int start_it)
+{
+ int i;
+
+ for (i=0; i < writer_table_size ; i++ ) {
+ if ( writer_table[i].used && writer_table[i].fd == fd )
+ return writer_table[i].context;
+ }
+ if (!start_it)
+ return NULL;
+
+ LOCK (writer_table_lock);
+ for (i=0; i < writer_table_size; i++ ) {
+ if (!writer_table[i].used) {
+ writer_table[i].fd = fd;
+ writer_table[i].context = create_writer (fd_to_handle (fd));
+ writer_table[i].used = 1;
+ UNLOCK (writer_table_lock);
+ return writer_table[i].context;
+ }
+ }
+ UNLOCK (writer_table_lock);
+ return NULL;
+}
+
+
+static void
+kill_writer (int fd)
+{
+ int i;
+
+ LOCK (writer_table_lock);
+ for (i=0; i < writer_table_size; i++ ) {
+ if (writer_table[i].used && writer_table[i].fd == fd ) {
+ destroy_writer (writer_table[i].context);
+ writer_table[i].context = NULL;
+ writer_table[i].used = 0;
+ break;
+ }
+ }
+ UNLOCK (writer_table_lock);
+}
+
+
+
+
+int
+_gpgme_io_write ( int fd, const void *buffer, size_t count )
+{
+ struct writer_context_s *c = find_writer (fd,1);
+
+ DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int)count );
+ _gpgme_debug (2, "fd %d: write `%.*s'\n", fd, (int) count, buffer);
+ if ( !c ) {
+ DEBUG0 ( "no writer thread\n");
+ return -1;
+ }
+
+ LOCK (c->mutex);
+ if ( c->nbytes ) { /* bytes are pending for send */
+ /* Reset the is_empty event. Better safe than sorry. */
+ if (!ResetEvent (c->is_empty))
+ DEBUG1 ("ResetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+ DEBUG2 ("fd %d: waiting for empty buffer in thread %p",
+ fd, c->thread_hd);
+ WaitForSingleObject (c->is_empty, INFINITE);
+ DEBUG2 ("fd %d: thread %p buffer is empty", fd, c->thread_hd);
+ LOCK (c->mutex);
+ }
+
+ if ( c->error) {
+ UNLOCK (c->mutex);
+ DEBUG1 ("fd %d: write error", fd );
+ return -1;
+ }
+
+ /* If no error occured, the number of bytes in the buffer must be
+ zero. */
+ assert (!c->nbytes);
+
+ if (count > WRITEBUF_SIZE)
+ count = WRITEBUF_SIZE;
+ memcpy (c->buffer, buffer, count);
+ c->nbytes = count;
+
+ /* We have to reset the is_empty event early, because it is also
+ used by the select() implementation to probe the channel. */
+ if (!ResetEvent (c->is_empty))
+ DEBUG1 ("ResetEvent failed: ec=%d", (int)GetLastError ());
+ if (!SetEvent (c->have_data))
+ DEBUG1 ("SetEvent failed: ec=%d", (int)GetLastError ());
+ UNLOCK (c->mutex);
+
+ DEBUG2 ("fd %d: copied %d bytes\n",
+ fd, (int)count );
+ return (int)count;
+}
+
+
+int
+_gpgme_io_pipe ( int filedes[2], int inherit_idx )
+{
+ HANDLE r, w;
+ SECURITY_ATTRIBUTES sec_attr;
+
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ if (!CreatePipe ( &r, &w, &sec_attr, PIPEBUF_SIZE))
+ return -1;
+ /* Make one end inheritable. */
+ if ( inherit_idx == 0 ) {
+ HANDLE h;
+ if (!DuplicateHandle( GetCurrentProcess(), r,
+ GetCurrentProcess(), &h, 0,
+ TRUE, DUPLICATE_SAME_ACCESS ) ) {
+ DEBUG1 ("DuplicateHandle failed: ec=%d\n", (int)GetLastError());
+ CloseHandle (r);
+ CloseHandle (w);
+ return -1;
+ }
+ CloseHandle (r);
+ r = h;
+ }
+ else if ( inherit_idx == 1 ) {
+ HANDLE h;
+ if (!DuplicateHandle( GetCurrentProcess(), w,
+ GetCurrentProcess(), &h, 0,
+ TRUE, DUPLICATE_SAME_ACCESS ) ) {
+ DEBUG1 ("DuplicateHandle failed: ec=%d\n", (int)GetLastError());
+ CloseHandle (r);
+ CloseHandle (w);
+ return -1;
+ }
+ CloseHandle (w);
+ w = h;
+ }
+
+ filedes[0] = handle_to_fd (r);
+ filedes[1] = handle_to_fd (w);
+ DEBUG5 ("CreatePipe %p %p %d %d inherit=%d\n", r, w,
+ filedes[0], filedes[1], inherit_idx );
+ return 0;
+}
+
+int
+_gpgme_io_close ( int fd )
+{
+ int i;
+ void (*handler)(int, void*) = NULL;
+ void *value = NULL;
+
+ if ( fd == -1 )
+ return -1;
+
+ DEBUG1 ("** closing handle for fd %d\n", fd);
+ kill_reader (fd);
+ kill_writer (fd);
+ LOCK (notify_table_lock);
+ for ( i=0; i < DIM (notify_table); i++ ) {
+ if (notify_table[i].inuse && notify_table[i].fd == fd) {
+ handler = notify_table[i].handler;
+ value = notify_table[i].value;
+ notify_table[i].handler = NULL;
+ notify_table[i].value = NULL;
+ notify_table[i].inuse = 0;
+ break;
+ }
+ }
+ UNLOCK (notify_table_lock);
+ if (handler)
+ handler (fd, value);
+
+ if ( !CloseHandle (fd_to_handle (fd)) ) {
+ DEBUG2 ("CloseHandle for fd %d failed: ec=%d\n",
+ fd, (int)GetLastError ());
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+_gpgme_io_set_close_notify (int fd, void (*handler)(int, void*), void *value)
+{
+ int i;
+
+ assert (fd != -1);
+
+ LOCK (notify_table_lock);
+ for (i=0; i < DIM (notify_table); i++ ) {
+ if ( notify_table[i].inuse && notify_table[i].fd == fd )
+ break;
+ }
+ if ( i == DIM (notify_table) ) {
+ for (i=0; i < DIM (notify_table); i++ ) {
+ if ( !notify_table[i].inuse )
+ break;
+ }
+ }
+ if ( i == DIM (notify_table) ) {
+ UNLOCK (notify_table_lock);
+ return -1;
+ }
+ notify_table[i].fd = fd;
+ notify_table[i].handler = handler;
+ notify_table[i].value = value;
+ notify_table[i].inuse = 1;
+ UNLOCK (notify_table_lock);
+ DEBUG2 ("set notification for fd %d (idx=%d)", fd, i );
+ return 0;
+}
+
+
+int
+_gpgme_io_set_nonblocking ( int fd )
+{
+ return 0;
+}
+
+
+static char *
+build_commandline (char **argv)
+{
+ int i;
+ int j;
+ int n = 0;
+ char *buf;
+ char *p;
+
+ /* We have to quote some things because under Windows the program
+ parses the commandline and does some unquoting. We enclose the
+ whole argument in double-quotes, and escape literal double-quotes
+ as well as backslashes with a backslash. We end up with a
+ trailing space at the end of the line, but that is harmless. */
+ for (i = 0; argv[i]; i++)
+ {
+ p = argv[i];
+ /* The leading double-quote. */
+ n++;
+ while (*p)
+ {
+ /* An extra one for each literal that must be escaped. */
+ if (*p == '\\' || *p == '"')
+ n++;
+ n++;
+ p++;
+ }
+ /* The trailing double-quote and the delimiter. */
+ n += 2;
+ }
+ /* And a trailing zero. */
+ n++;
+
+ buf = p = malloc (n);
+ if (!buf)
+ return NULL;
+ for (i = 0; argv[i]; i++)
+ {
+ char *argvp = argv[i];
+
+ *(p++) = '"';
+ while (*argvp)
+ {
+ if (*argvp == '\\' || *argvp == '"')
+ *(p++) = '\\';
+ *(p++) = *(argvp++);
+ }
+ *(p++) = '"';
+ *(p++) = ' ';
+ }
+ *(p++) = 0;
+
+ return buf;
+}
+
+
+int
+_gpgme_io_spawn ( const char *path, char **argv,
+ struct spawn_fd_item_s *fd_child_list,
+ struct spawn_fd_item_s *fd_parent_list )
+{
+ SECURITY_ATTRIBUTES sec_attr;
+ PROCESS_INFORMATION pi = {
+ NULL, /* returns process handle */
+ 0, /* returns primary thread handle */
+ 0, /* returns pid */
+ 0 /* returns tid */
+ };
+ STARTUPINFO si;
+ char *envblock = NULL;
+ int cr_flags = CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ());
+ int i;
+ char *arg_string;
+ int duped_stdin = 0;
+ int duped_stderr = 0;
+ HANDLE hnul = INVALID_HANDLE_VALUE;
+ /* FIXME. */
+ int debug_me = 0;
+
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ arg_string = build_commandline ( argv );
+ if (!arg_string )
+ return -1;
+
+ memset (&si, 0, sizeof si);
+ si.cb = sizeof (si);
+ si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+ si.wShowWindow = debug_me? SW_SHOW : SW_HIDE;
+ si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
+ si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
+ si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
+
+ for (i=0; fd_child_list[i].fd != -1; i++ ) {
+ if (fd_child_list[i].dup_to == 0 ) {
+ si.hStdInput = fd_to_handle (fd_child_list[i].fd);
+ DEBUG1 ("using %d for stdin", fd_child_list[i].fd );
+ duped_stdin=1;
+ }
+ else if (fd_child_list[i].dup_to == 1 ) {
+ si.hStdOutput = fd_to_handle (fd_child_list[i].fd);
+ DEBUG1 ("using %d for stdout", fd_child_list[i].fd );
+ }
+ else if (fd_child_list[i].dup_to == 2 ) {
+ si.hStdError = fd_to_handle (fd_child_list[i].fd);
+ DEBUG1 ("using %d for stderr", fd_child_list[i].fd );
+ duped_stderr = 1;
+ }
+ }
+
+ if( !duped_stdin || !duped_stderr ) {
+ SECURITY_ATTRIBUTES sa;
+
+ memset (&sa, 0, sizeof sa );
+ sa.nLength = sizeof sa;
+ sa.bInheritHandle = TRUE;
+ hnul = CreateFile ( "nul",
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ &sa,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+ if ( hnul == INVALID_HANDLE_VALUE ) {
+ DEBUG1 ("can't open `nul': ec=%d\n", (int)GetLastError ());
+ free (arg_string);
+ return -1;
+ }
+ /* Make sure that the process has a connected stdin */
+ if ( !duped_stdin ) {
+ si.hStdInput = hnul;
+ DEBUG1 ("using %d for dummy stdin", (int)hnul );
+ }
+ /* We normally don't want all the normal output */
+ if ( !duped_stderr ) {
+ si.hStdError = hnul;
+ DEBUG1 ("using %d for dummy stderr", (int)hnul );
+ }
+ }
+
+ DEBUG2 ("CreateProcess, path=`%s' args=`%s'", path, arg_string);
+ cr_flags |= CREATE_SUSPENDED;
+ if ( !CreateProcessA (path,
+ arg_string,
+ &sec_attr, /* process security attributes */
+ &sec_attr, /* thread security attributes */
+ TRUE, /* inherit handles */
+ cr_flags, /* creation flags */
+ envblock, /* environment */
+ NULL, /* use current drive/directory */
+ &si, /* startup information */
+ &pi /* returns process information */
+ ) ) {
+ DEBUG1 ("CreateProcess failed: ec=%d\n", (int) GetLastError ());
+ free (arg_string);
+ return -1;
+ }
+
+ /* Close the /dev/nul handle if used. */
+ if (hnul != INVALID_HANDLE_VALUE ) {
+ if ( !CloseHandle ( hnul ) )
+ DEBUG1 ("CloseHandle(hnul) failed: ec=%d\n", (int)GetLastError());
+ }
+
+ /* Close the other ends of the pipes. */
+ for (i = 0; fd_parent_list[i].fd != -1; i++)
+ _gpgme_io_close (fd_parent_list[i].fd);
+
+ DEBUG4 ("CreateProcess ready\n"
+ "- hProcess=%p hThread=%p\n"
+ "- dwProcessID=%d dwThreadId=%d\n",
+ pi.hProcess, pi.hThread,
+ (int) pi.dwProcessId, (int) pi.dwThreadId);
+
+ if ( ResumeThread ( pi.hThread ) < 0 ) {
+ DEBUG1 ("ResumeThread failed: ec=%d\n", (int)GetLastError ());
+ }
+
+ if ( !CloseHandle (pi.hThread) ) {
+ DEBUG1 ("CloseHandle of thread failed: ec=%d\n",
+ (int)GetLastError ());
+ }
+
+ return handle_to_pid (pi.hProcess);
+}
+
+
+/*
+ * Select on the list of fds.
+ * Returns: -1 = error
+ * 0 = timeout or nothing to select
+ * >0 = number of signaled fds
+ */
+int
+_gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds, int nonblock )
+{
+ HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
+ int waitidx[MAXIMUM_WAIT_OBJECTS];
+ int code, nwait;
+ int i, any;
+ int count;
+ void *dbg_help;
+
+ restart:
+ DEBUG_BEGIN (dbg_help, 3, "select on [ ");
+ any = 0;
+ nwait = 0;
+ count = 0;
+ for ( i=0; i < nfds; i++ ) {
+ if ( fds[i].fd == -1 )
+ continue;
+ fds[i].signaled = 0;
+ if ( fds[i].for_read || fds[i].for_write ) {
+ if ( fds[i].frozen ) {
+ DEBUG_ADD1 (dbg_help, "f%d ", fds[i].fd );
+ }
+ else if ( fds[i].for_read ) {
+ struct reader_context_s *c = find_reader (fds[i].fd,1);
+
+ if (!c) {
+ DEBUG1 ("oops: no reader thread for fd %d", fds[i].fd);
+ }
+ else {
+ if ( nwait >= DIM (waitbuf) ) {
+ DEBUG_END (dbg_help, "oops ]");
+ DEBUG0 ("Too many objects for WFMO!" );
+ return -1;
+ }
+ waitidx[nwait] = i;
+ waitbuf[nwait++] = c->have_data_ev;
+ }
+ DEBUG_ADD1 (dbg_help, "r%d ", fds[i].fd );
+ any = 1;
+ }
+ else if ( fds[i].for_write ) {
+ struct writer_context_s *c = find_writer (fds[i].fd,1);
+
+ if (!c) {
+ DEBUG1 ("oops: no writer thread for fd %d", fds[i].fd);
+ }
+ else {
+ if ( nwait >= DIM (waitbuf) ) {
+ DEBUG_END (dbg_help, "oops ]");
+ DEBUG0 ("Too many objects for WFMO!" );
+ return -1;
+ }
+ waitidx[nwait] = i;
+ waitbuf[nwait++] = c->is_empty;
+ }
+ DEBUG_ADD1 (dbg_help, "w%d ", fds[i].fd );
+ any = 1;
+ }
+ }
+ }
+ DEBUG_END (dbg_help, "]");
+ if (!any)
+ return 0;
+
+ code = WaitForMultipleObjects ( nwait, waitbuf, 0, nonblock ? 0 : 1000);
+ if ( code >= WAIT_OBJECT_0 && code < WAIT_OBJECT_0 + nwait ) {
+ /* This WFMO is a really silly function: It does return either
+ * the index of the signaled object or if 2 objects have been
+ * signalled at the same time, the index of the object with the
+ * lowest object is returned - so and how do we find out
+ * how many objects have been signaled???.
+ * The only solution I can imagine is to test each object starting
+ * with the returned index individually - how dull.
+ */
+ any = 0;
+ for (i=code - WAIT_OBJECT_0; i < nwait; i++ ) {
+ if (WaitForSingleObject (waitbuf[i], 0) == WAIT_OBJECT_0) {
+ assert (waitidx[i] >=0 && waitidx[i] < nfds);
+ fds[waitidx[i]].signaled = 1;
+ any = 1;
+ count++;
+ }
+ }
+ if (!any) {
+ DEBUG0 ("Oops: No signaled objects found after WFMO");
+ count = -1;
+ }
+ }
+ else if ( code == WAIT_TIMEOUT ) {
+ DEBUG0 ("WFMO timed out\n" );
+ }
+ else if (code == WAIT_FAILED ) {
+ int le = (int)GetLastError ();
+ if ( le == ERROR_INVALID_HANDLE ) {
+ int k, j = handle_to_fd (waitbuf[i]);
+
+ DEBUG1 ("WFMO invalid handle %d removed\n", j);
+ for (k=0 ; k < nfds; k++ ) {
+ if ( fds[k].fd == j ) {
+ fds[k].for_read = fds[k].for_write = 0;
+ goto restart;
+ }
+ }
+ DEBUG0 (" oops, or not???\n");
+ }
+ DEBUG1 ("WFMO failed: %d\n", le );
+ count = -1;
+ }
+ else {
+ DEBUG1 ("WFMO returned %d\n", code );
+ count = -1;
+ }
+
+ if ( count ) {
+ DEBUG_BEGIN (dbg_help, 3, " signaled [ ");
+ for ( i=0; i < nfds; i++ ) {
+ if ( fds[i].fd == -1 )
+ continue;
+ if ( (fds[i].for_read || fds[i].for_write) && fds[i].signaled ) {
+ DEBUG_ADD2 (dbg_help, "%c%d ",
+ fds[i].for_read? 'r':'w',fds[i].fd );
+ }
+ }
+ DEBUG_END (dbg_help, "]");
+ }
+
+ return count;
+}
+
+void
+_gpgme_io_subsystem_init (void)
+{
+
+}
+
+
+/* Write the printable version of FD to the buffer BUF of length
+ BUFLEN. The printable version is the representation on the command
+ line that the child process expects. */
+int
+_gpgme_io_fd2str (char *buf, int buflen, int fd)
+{
+ return snprintf (buf, buflen, "%d", fd);
+}
+
+
+/* The following interface is only useful for GPGME Glib. */
+
+/* Look up the giochannel for file descriptor FD. */
+void *
+gpgme_get_giochannel (int fd)
+{
+ return NULL;
+}
+
diff --git a/libtdenetwork/libgpgme-copy/gpgme/w32-sema.c b/libtdenetwork/libgpgme-copy/gpgme/w32-sema.c
new file mode 100644
index 000000000..2b20cab3e
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/w32-sema.c
@@ -0,0 +1,115 @@
+/* w32-sema.c
+ Copyright (C) 2001 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <windows.h>
+#include <io.h>
+
+#include "util.h"
+#include "sema.h"
+#include "debug.h"
+
+static void
+sema_fatal (const char *text)
+{
+ fprintf (stderr, "sema.c: %s\n", text);
+ abort ();
+}
+
+
+static void
+critsect_init (struct critsect_s *s)
+{
+ CRITICAL_SECTION *mp;
+ static CRITICAL_SECTION init_lock;
+ static int initialized;
+
+ if (!initialized) {
+ /* The very first time we call this function, we assume that
+ only one thread is running, so that we can bootstrap the
+ semaphore code. */
+ InitializeCriticalSection (&init_lock);
+ initialized = 1;
+ }
+ if (!s)
+ return; /* we just want to initialize ourself */
+
+ /* first test whether it is really not initialized */
+ EnterCriticalSection (&init_lock);
+ if ( s->private ) {
+ LeaveCriticalSection (&init_lock);
+ return;
+ }
+ /* now init it */
+ mp = malloc ( sizeof *mp );
+ if (!mp) {
+ LeaveCriticalSection (&init_lock);
+ sema_fatal ("out of core while creating critical section lock");
+ }
+ InitializeCriticalSection (mp);
+ s->private = mp;
+ LeaveCriticalSection (&init_lock);
+}
+
+void
+_gpgme_sema_subsystem_init ()
+{
+ /* fixme: we should check that there is only one thread running */
+ critsect_init (NULL);
+}
+
+
+void
+_gpgme_sema_cs_enter ( struct critsect_s *s )
+{
+ if (!s->private)
+ critsect_init (s);
+ EnterCriticalSection ( (CRITICAL_SECTION*)s->private );
+}
+
+void
+_gpgme_sema_cs_leave (struct critsect_s *s)
+{
+ if (!s->private)
+ critsect_init (s);
+ LeaveCriticalSection ((CRITICAL_SECTION*)s->private);
+}
+
+void
+_gpgme_sema_cs_destroy ( struct critsect_s *s )
+{
+ if (s && s->private) {
+ DeleteCriticalSection ((CRITICAL_SECTION*)s->private);
+ free (s->private);
+ s->private = NULL;
+ }
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/w32-util.c b/libtdenetwork/libgpgme-copy/gpgme/w32-util.c
new file mode 100644
index 000000000..646f4a009
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/w32-util.c
@@ -0,0 +1,317 @@
+/* w32-util.c - Utility functions for the W32 API
+ Copyright (C) 1999 Free Software Foundation, Inc
+ Copyright (C) 2001 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <windows.h>
+#include <shlobj.h>
+#include <io.h>
+
+#include "util.h"
+#include "sema.h"
+#include "debug.h"
+
+DEFINE_STATIC_LOCK (get_path_lock);
+
+
+#define RTLD_LAZY 0
+
+static __inline__ void *
+dlopen (const char * name, int flag)
+{
+ void * hd = LoadLibrary (name);
+ return hd;
+}
+
+static __inline__ void *
+dlsym (void * hd, const char * sym)
+{
+ if (hd && sym)
+ {
+ void * fnc = GetProcAddress (hd, sym);
+ if (!fnc)
+ return NULL;
+ return fnc;
+ }
+ return NULL;
+}
+
+static __inline__ int
+dlclose (void * hd)
+{
+ if (hd)
+ {
+ FreeLibrary (hd);
+ return 0;
+ }
+ return -1;
+}
+
+
+/* Return a string from the W32 Registry or NULL in case of error.
+ Caller must release the return value. A NULL for root is an alias
+ for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
+static char *
+read_w32_registry_string (const char *root, const char *dir, const char *name)
+{
+ HKEY root_key, key_handle;
+ DWORD n1, nbytes, type;
+ char *result = NULL;
+
+ if ( !root )
+ root_key = HKEY_CURRENT_USER;
+ else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
+ root_key = HKEY_CLASSES_ROOT;
+ else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
+ root_key = HKEY_CURRENT_USER;
+ else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
+ root_key = HKEY_LOCAL_MACHINE;
+ else if ( !strcmp( root, "HKEY_USERS" ) )
+ root_key = HKEY_USERS;
+ else if ( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
+ root_key = HKEY_PERFORMANCE_DATA;
+ else if ( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
+ root_key = HKEY_CURRENT_CONFIG;
+ else
+ return NULL;
+
+ if ( RegOpenKeyEx ( root_key, dir, 0, KEY_READ, &key_handle ) )
+ {
+ if (root)
+ return NULL; /* no need for a RegClose, so return direct */
+ /* It seems to be common practise to fall back to HKLM. */
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
+ return NULL; /* still no need for a RegClose, so return direct */
+ }
+
+ nbytes = 1;
+ if ( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) )
+ {
+ if (root)
+ goto leave;
+ /* Try to fallback to HKLM also vor a missing value. */
+ RegCloseKey (key_handle);
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
+ return NULL; /* Nope. */
+ if (RegQueryValueEx ( key_handle, name, 0, NULL, NULL, &nbytes))
+ goto leave;
+ }
+ result = malloc ( (n1=nbytes+1) );
+ if ( !result )
+ goto leave;
+ if ( RegQueryValueEx ( key_handle, name, 0, &type, result, &n1 ) )
+ {
+ free(result); result = NULL;
+ goto leave;
+ }
+ result[nbytes] = 0; /* Make sure it is really a string. */
+ if (type == REG_EXPAND_SZ && strchr (result, '%'))
+ {
+ char *tmp;
+
+ n1 += 1000;
+ tmp = malloc (n1+1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1)
+ {
+ free (tmp);
+ n1 = nbytes;
+ tmp = malloc (n1 + 1);
+ if (!tmp)
+ goto leave;
+ nbytes = ExpandEnvironmentStrings (result, tmp, n1);
+ if (nbytes && nbytes > n1) {
+ free (tmp); /* Oops - truncated, better don't expand at all. */
+ goto leave;
+ }
+ tmp[nbytes] = 0;
+ free (result);
+ result = tmp;
+ }
+ else if (nbytes) /* Okay, reduce the length. */
+ {
+ tmp[nbytes] = 0;
+ free (result);
+ result = malloc (strlen (tmp)+1);
+ if (!result)
+ result = tmp;
+ else
+ {
+ strcpy (result, tmp);
+ free (tmp);
+ }
+ }
+ else /* Error - don't expand. */
+ {
+ free (tmp);
+ }
+ }
+
+ leave:
+ RegCloseKey( key_handle );
+ return result;
+}
+
+
+/* This is a helper function to load and run a Windows function from
+ either of one DLLs. */
+static HRESULT
+w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
+{
+ static int initialized;
+ static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
+
+ if (!initialized)
+ {
+ static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
+ void *handle;
+ int i;
+
+ initialized = 1;
+
+ for (i=0, handle = NULL; !handle && dllnames[i]; i++)
+ {
+ handle = dlopen (dllnames[i], RTLD_LAZY);
+ if (handle)
+ {
+ func = dlsym (handle, "SHGetFolderPathA");
+ if (!func)
+ {
+ dlclose (handle);
+ handle = NULL;
+ }
+ }
+ }
+ }
+
+ if (func)
+ return func (a,b,c,d,e);
+ else
+ return -1;
+}
+
+
+static char *
+find_program_in_registry (const char *name)
+{
+ char *program = NULL;
+
+ program = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", name);
+ if (program)
+ {
+ int i;
+
+ DEBUG2 ("found %s in registry: `%s'", name, program);
+ for (i = 0; program[i]; i++)
+ {
+ if (program[i] == '/')
+ program[i] = '\\';
+ }
+ }
+ return program;
+}
+
+
+static char *
+find_program_at_standard_place (const char *name)
+{
+ char path[MAX_PATH];
+ char *result = NULL;
+
+ if (w32_shgetfolderpath (NULL, CSIDL_PROGRAM_FILES, NULL, 0, path) >= 0)
+ {
+ result = malloc (strlen (path) + 1 + strlen (name) + 1);
+ if (result)
+ {
+ strcpy (stpcpy (stpcpy (result, path), "\\"), name);
+ if (access (result, F_OK))
+ {
+ free (result);
+ result = NULL;
+ }
+ }
+ }
+ return result;
+}
+
+const char *
+_gpgme_get_gpg_path (void)
+{
+ static char *gpg_program;
+
+ LOCK (get_path_lock);
+ if (!gpg_program)
+ gpg_program = find_program_in_registry ("gpgProgram");
+ if (!gpg_program)
+ gpg_program = find_program_at_standard_place ("GNU\\GnuPG\\gpg.exe");
+#ifdef GPG_PATH
+ if (!gpg_program)
+ gpg_program = GPG_PATH;
+#endif
+ UNLOCK (get_path_lock);
+ return gpg_program;
+}
+
+const char *
+_gpgme_get_gpgsm_path (void)
+{
+ static char *gpgsm_program;
+
+ LOCK (get_path_lock);
+ if (!gpgsm_program)
+ gpgsm_program = find_program_in_registry ("gpgsmProgram");
+ if (!gpgsm_program)
+ gpgsm_program = find_program_at_standard_place ("GNU\\GnuPG\\gpgsm.exe");
+#ifdef GPGSM_PATH
+ if (!gpgsm_program)
+ gpgsm_program = GPGSM_PATH;
+#endif
+ UNLOCK (get_path_lock);
+ return gpgsm_program;
+}
+
+
+/* Return an integer value from gpgme specific configuration
+ entries. VALUE receives that value; function returns true if a value
+ has been configured and false if not. */
+int
+_gpgme_get_conf_int (const char *key, int *value)
+{
+ char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key);
+ if (!tmp)
+ return 0;
+ *value = atoi (tmp);
+ free (tmp);
+ return 1;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/wait-global.c b/libtdenetwork/libgpgme-copy/gpgme/wait-global.c
new file mode 100644
index 000000000..bfa618dd1
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/wait-global.c
@@ -0,0 +1,384 @@
+/* wait-global.c
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "sema.h"
+#include "util.h"
+#include "context.h"
+#include "wait.h"
+#include "priv-io.h"
+
+/* The global event loop is used for all asynchronous operations
+ (except key listing) for which no user I/O callbacks are specified.
+
+ A context sets up its initial I/O callbacks and then sends the
+ GPGME_EVENT_START event. After that, it is added to the global
+ list of active contexts.
+
+ The gpgme_wait function contains a select() loop over all file
+ descriptors in all active contexts. If an error occurs, it closes
+ all fds in that context and moves the context to the global done
+ list. Likewise, if a context has removed all I/O callbacks, it is
+ moved to the global done list.
+
+ All contexts in the global done list are eligible for being
+ returned by gpgme_wait if requested by the caller. */
+
+/* The ctx_list_lock protects the list of active and done contexts.
+ Insertion into any of these lists is only allowed when the lock is
+ held. This allows a muli-threaded program to loop over gpgme_wait
+ and in parallel start asynchronous gpgme operations.
+
+ However, the fd tables in the contexts are not protected by this
+ lock. They are only allowed to change either before the context is
+ added to the active list (ie, before the start event is signalled)
+ or in a callback handler. */
+DEFINE_STATIC_LOCK (ctx_list_lock);
+
+/* A ctx_list_item is an item in the global list of active or done
+ contexts. */
+struct ctx_list_item
+{
+ /* Every ctx_list_item is an element in a doubly linked list. The
+ list pointers are protected by the ctx_list_lock. */
+ struct ctx_list_item *next;
+ struct ctx_list_item *prev;
+
+ gpgme_ctx_t ctx;
+ /* The status is set when the ctx is moved to the done list. */
+ gpgme_error_t status;
+};
+
+/* The active list contains all contexts that are in the global event
+ loop, have active I/O callbacks, and have already seen the start
+ event. */
+static struct ctx_list_item *ctx_active_list;
+
+/* The done list contains all contexts that have previously been
+ active but now are not active any longer, either because they
+ finished successfully or an I/O callback returned an error. The
+ status field in the list item contains the error value (or 0 if
+ successful). */
+static struct ctx_list_item *ctx_done_list;
+
+
+/* Enter the context CTX into the active list. */
+static gpgme_error_t
+ctx_active (gpgme_ctx_t ctx)
+{
+ struct ctx_list_item *li = malloc (sizeof (struct ctx_list_item));
+ if (!li)
+ return gpg_error_from_errno (errno);
+ li->ctx = ctx;
+
+ LOCK (ctx_list_lock);
+ /* Add LI to active list. */
+ li->next = ctx_active_list;
+ li->prev = NULL;
+ if (ctx_active_list)
+ ctx_active_list->prev = li;
+ ctx_active_list = li;
+ UNLOCK (ctx_list_lock);
+ return 0;
+}
+
+
+/* Enter the context CTX into the done list with status STATUS. */
+static void
+ctx_done (gpgme_ctx_t ctx, gpgme_error_t status)
+{
+ struct ctx_list_item *li;
+
+ LOCK (ctx_list_lock);
+ li = ctx_active_list;
+ while (li && li->ctx != ctx)
+ li = li->next;
+ assert (li);
+
+ /* Remove LI from active list. */
+ if (li->next)
+ li->next->prev = li->prev;
+ if (li->prev)
+ li->prev->next = li->next;
+ else
+ ctx_active_list = li->next;
+
+ li->status = status;
+
+ /* Add LI to done list. */
+ li->next = ctx_done_list;
+ li->prev = NULL;
+ if (ctx_done_list)
+ ctx_done_list->prev = li;
+ ctx_done_list = li;
+ UNLOCK (ctx_list_lock);
+}
+
+
+/* Find finished context CTX (or any context if CTX is NULL) and
+ return its status in STATUS after removing it from the done list.
+ If a matching context could be found, return it. Return NULL if no
+ context could be found. */
+static gpgme_ctx_t
+ctx_wait (gpgme_ctx_t ctx, gpgme_error_t *status)
+{
+ struct ctx_list_item *li;
+
+ LOCK (ctx_list_lock);
+ li = ctx_done_list;
+ if (ctx)
+ {
+ /* A specific context is requested. */
+ while (li && li->ctx != ctx)
+ li = li->next;
+ }
+ if (li)
+ {
+ ctx = li->ctx;
+ if (status)
+ *status = li->status;
+
+ /* Remove LI from done list. */
+ if (li->next)
+ li->next->prev = li->prev;
+ if (li->prev)
+ li->prev->next = li->next;
+ else
+ ctx_done_list = li->next;
+ free (li);
+ }
+ else
+ ctx = NULL;
+ UNLOCK (ctx_list_lock);
+ return ctx;
+}
+
+
+/* Internal I/O callback functions. */
+
+/* The add_io_cb and remove_io_cb handlers are shared with the private
+ event loops. */
+
+void
+_gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) data;
+
+ assert (ctx);
+
+ switch (type)
+ {
+ case GPGME_EVENT_START:
+ {
+ gpgme_error_t err = ctx_active (ctx);
+
+ if (err)
+ {
+ /* An error occured. Close all fds in this context, and
+ send the error in a done event. */
+ unsigned int idx;
+
+ for (idx = 0; idx <= ctx->fdt.size; idx++)
+ if (ctx->fdt.fds[idx].fd != -1)
+ _gpgme_io_close (ctx->fdt.fds[idx].fd);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+ }
+ }
+ break;
+
+ case GPGME_EVENT_DONE:
+ {
+ gpgme_error_t *errp = (gpgme_error_t *) type_data;
+ assert (errp);
+ ctx_done (ctx, *errp);
+ }
+ break;
+
+ case GPGME_EVENT_NEXT_KEY:
+ assert (!"Unexpected event GPGME_EVENT_NEXT_KEY");
+ break;
+
+ case GPGME_EVENT_NEXT_TRUSTITEM:
+ assert (!"Unexpected event GPGME_EVENT_NEXT_TRUSTITEM");
+ break;
+
+ default:
+ assert (!"Unexpected event");
+ break;
+ }
+}
+
+
+
+/* Perform asynchronous operations in the global event loop (ie, any
+ asynchronous operation except key listing and trustitem listing
+ operations). If CTX is not a null pointer, the function will
+ return if the asynchronous operation in the context CTX finished.
+ Otherwise the function will return if any asynchronous operation
+ finished. If HANG is zero, the function will not block for a long
+ time. Otherwise the function does not return until an operation
+ matching CTX finished.
+
+ If a matching context finished, it is returned, and *STATUS is set
+ to the error value of the operation in that context. Otherwise, if
+ the timeout expires, NULL is returned and *STATUS is 0. If an
+ error occurs, NULL is returned and *STATUS is set to the error
+ value. */
+gpgme_ctx_t
+gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)
+{
+ do
+ {
+ unsigned int i = 0;
+ struct ctx_list_item *li;
+ struct fd_table fdt;
+ int nr;
+
+ /* Collect the active file descriptors. */
+ LOCK (ctx_list_lock);
+ for (li = ctx_active_list; li; li = li->next)
+ i += li->ctx->fdt.size;
+ fdt.fds = malloc (i * sizeof (struct io_select_fd_s));
+ if (!fdt.fds)
+ {
+ int saved_errno = errno;
+ UNLOCK (ctx_list_lock);
+ if (status)
+ *status = gpg_error_from_errno (saved_errno);
+ return NULL;
+ }
+ fdt.size = i;
+ i = 0;
+ for (li = ctx_active_list; li; li = li->next)
+ {
+ memcpy (&fdt.fds[i], li->ctx->fdt.fds,
+ li->ctx->fdt.size * sizeof (struct io_select_fd_s));
+ i += li->ctx->fdt.size;
+ }
+ UNLOCK (ctx_list_lock);
+
+ nr = _gpgme_io_select (fdt.fds, fdt.size, 0);
+ if (nr < 0)
+ {
+ int saved_errno = errno;
+ free (fdt.fds);
+ if (status)
+ *status = gpg_error_from_errno (saved_errno);
+ return NULL;
+ }
+
+ for (i = 0; i < fdt.size && nr; i++)
+ {
+ if (fdt.fds[i].fd != -1 && fdt.fds[i].signaled)
+ {
+ gpgme_ctx_t ictx;
+ gpgme_error_t err;
+ struct wait_item_s *item;
+
+ assert (nr);
+ nr--;
+
+ item = (struct wait_item_s *) fdt.fds[i].opaque;
+ assert (item);
+ ictx = item->ctx;
+ assert (ictx);
+
+ err = _gpgme_run_io_cb (&fdt.fds[i], 0);
+ if (err)
+ {
+ /* An error occured. Close all fds in this context,
+ and signal it. */
+ unsigned int idx;
+
+ for (idx = 0; idx < ictx->fdt.size; idx++)
+ if (ictx->fdt.fds[idx].fd != -1)
+ _gpgme_io_close (ictx->fdt.fds[idx].fd);
+ _gpgme_engine_io_event (ictx->engine, GPGME_EVENT_DONE,
+ &err);
+
+ /* Break out of the loop, and retry the select()
+ from scratch, because now all fds should be
+ gone. */
+ break;
+ }
+ }
+ }
+ free (fdt.fds);
+
+ /* Now some contexts might have finished successfully. */
+ LOCK (ctx_list_lock);
+ retry:
+ for (li = ctx_active_list; li; li = li->next)
+ {
+ gpgme_ctx_t actx = li->ctx;
+
+ for (i = 0; i < actx->fdt.size; i++)
+ if (actx->fdt.fds[i].fd != -1)
+ break;
+ if (i == actx->fdt.size)
+ {
+ gpgme_error_t err = 0;
+
+ /* FIXME: This does not perform too well. We have to
+ release the lock because the I/O event handler
+ acquires it to remove the context from the active
+ list. Two alternative strategies are worth
+ considering: Either implement the DONE event handler
+ here in a lock-free manner, or save a list of all
+ contexts to be released and call the DONE events
+ afterwards. */
+ UNLOCK (ctx_list_lock);
+ _gpgme_engine_io_event (actx->engine, GPGME_EVENT_DONE, &err);
+ LOCK (ctx_list_lock);
+ goto retry;
+ }
+ }
+ UNLOCK (ctx_list_lock);
+
+ {
+ gpgme_ctx_t dctx = ctx_wait (ctx, status);
+
+ if (dctx)
+ {
+ ctx = dctx;
+ hang = 0;
+ }
+ else if (!hang)
+ {
+ ctx = NULL;
+ if (status)
+ *status = 0;
+ }
+ }
+ }
+ while (hang);
+
+ return ctx;
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/wait-private.c b/libtdenetwork/libgpgme-copy/gpgme/wait-private.c
new file mode 100644
index 000000000..3f2b819d2
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/wait-private.c
@@ -0,0 +1,147 @@
+/* wait-private.c
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "wait.h"
+#include "ops.h"
+#include "priv-io.h"
+#include "util.h"
+
+
+/* The private event loops are used for all blocking operations, and
+ for the key and trust item listing operations. They are completely
+ separated from each other. */
+
+
+/* Internal I/O callback functions. */
+
+/* The add_io_cb and remove_io_cb handlers are shared with the global
+ event loops. */
+
+void
+_gpgme_wait_private_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data)
+{
+ switch (type)
+ {
+ case GPGME_EVENT_START:
+ /* Nothing to do here, as the wait routine is called after the
+ initialization is finished. */
+ break;
+
+ case GPGME_EVENT_DONE:
+ break;
+
+ case GPGME_EVENT_NEXT_KEY:
+ _gpgme_op_keylist_event_cb (data, type, type_data);
+ break;
+
+ case GPGME_EVENT_NEXT_TRUSTITEM:
+ _gpgme_op_trustlist_event_cb (data, type, type_data);
+ break;
+ }
+}
+
+
+/* If COND is a null pointer, wait until the blocking operation in CTX
+ finished and return its error value. Otherwise, wait until COND is
+ satisfied or the operation finished. */
+gpgme_error_t
+_gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond)
+{
+ gpgme_error_t err = 0;
+ int hang = 1;
+
+ do
+ {
+ int nr = _gpgme_io_select (ctx->fdt.fds, ctx->fdt.size, 0);
+ unsigned int i;
+
+ if (nr < 0)
+ {
+ /* An error occured. Close all fds in this context, and
+ signal it. */
+ unsigned int idx;
+
+ err = gpg_error_from_errno (errno);
+ for (idx = 0; idx < ctx->fdt.size; idx++)
+ if (ctx->fdt.fds[idx].fd != -1)
+ _gpgme_io_close (ctx->fdt.fds[idx].fd);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+
+ return err;
+ }
+
+ for (i = 0; i < ctx->fdt.size && nr; i++)
+ {
+ if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled)
+ {
+ ctx->fdt.fds[i].signaled = 0;
+ assert (nr);
+ nr--;
+
+ err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0);
+ if (err)
+ {
+ /* An error occured. Close all fds in this context,
+ and signal it. */
+ unsigned int idx;
+
+ for (idx = 0; idx < ctx->fdt.size; idx++)
+ if (ctx->fdt.fds[idx].fd != -1)
+ _gpgme_io_close (ctx->fdt.fds[idx].fd);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+ return err;
+ }
+ }
+ }
+
+ for (i = 0; i < ctx->fdt.size; i++)
+ if (ctx->fdt.fds[i].fd != -1)
+ break;
+ if (i == ctx->fdt.size)
+ {
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+ hang = 0;
+ }
+ if (cond && *cond)
+ hang = 0;
+ }
+ while (hang);
+
+ return 0;
+}
+
+
+/* Wait until the blocking operation in context CTX has finished and
+ return the error value. */
+gpgme_error_t
+_gpgme_wait_one (gpgme_ctx_t ctx)
+{
+ return _gpgme_wait_on_condition (ctx, NULL);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/wait-user.c b/libtdenetwork/libgpgme-copy/gpgme/wait-user.c
new file mode 100644
index 000000000..064d80095
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/wait-user.c
@@ -0,0 +1,122 @@
+/* wait-user.c
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+
+#include "gpgme.h"
+#include "context.h"
+#include "priv-io.h"
+#include "wait.h"
+
+
+/* The user event loops are used for all asynchronous operations for
+ which a user callback is defined. */
+
+
+/* Internal I/O Callbacks. */
+
+gpgme_error_t
+_gpgme_user_io_cb_handler (void *data, int fd)
+{
+ gpgme_error_t err;
+ struct tag *tag = (struct tag *) data;
+ gpgme_ctx_t ctx;
+
+ assert (data);
+ ctx = tag->ctx;
+ assert (ctx);
+
+ err = _gpgme_run_io_cb (&ctx->fdt.fds[tag->idx], 0);
+ if (err)
+ {
+ unsigned int idx;
+
+ for (idx = 0; idx < ctx->fdt.size; idx++)
+ if (ctx->fdt.fds[idx].fd != -1)
+ _gpgme_io_close (ctx->fdt.fds[idx].fd);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+ }
+ else
+ {
+ unsigned int i;
+
+ for (i = 0; i < ctx->fdt.size; i++)
+ if (ctx->fdt.fds[i].fd != -1)
+ break;
+ if (i == ctx->fdt.size)
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+ }
+ return 0;
+}
+
+
+/* Register the file descriptor FD with the handler FNC (which gets
+ FNC_DATA as its first argument) for the direction DIR. DATA should
+ be the context for which the fd is added. R_TAG will hold the tag
+ that can be used to remove the fd. */
+gpgme_error_t
+_gpgme_wait_user_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
+ void *fnc_data, void **r_tag)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) data;
+ struct tag *tag;
+ gpgme_error_t err;
+
+ assert (ctx);
+ err = _gpgme_add_io_cb (data, fd, dir, fnc, fnc_data, r_tag);
+ if (err)
+ return err;
+ tag = *r_tag;
+ assert (tag);
+ err = (*ctx->io_cbs.add) (ctx->io_cbs.add_priv, fd, dir,
+ _gpgme_user_io_cb_handler, *r_tag,
+ &tag->user_tag);
+ if (err)
+ _gpgme_remove_io_cb (*r_tag);
+ return err;
+}
+
+
+void
+_gpgme_wait_user_remove_io_cb (void *data)
+{
+ struct tag *tag = (struct tag *) data;
+ gpgme_ctx_t ctx;
+
+ assert (tag);
+ ctx = tag->ctx;
+
+ (*ctx->io_cbs.remove) (tag->user_tag);
+ _gpgme_remove_io_cb (data);
+}
+
+
+void
+_gpgme_wait_user_event_cb (void *data, gpgme_event_io_t type, void *type_data)
+{
+ gpgme_ctx_t ctx = data;
+
+ if (ctx->io_cbs.event)
+ (*ctx->io_cbs.event) (ctx->io_cbs.event_priv, type, type_data);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/wait.c b/libtdenetwork/libgpgme-copy/gpgme/wait.c
new file mode 100644
index 000000000..dca8d5003
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/wait.c
@@ -0,0 +1,204 @@
+/* wait.c
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "util.h"
+#include "context.h"
+#include "ops.h"
+#include "wait.h"
+#include "sema.h"
+#include "priv-io.h"
+#include "engine.h"
+#include "debug.h"
+
+
+void
+_gpgme_fd_table_init (fd_table_t fdt)
+{
+ fdt->fds = NULL;
+ fdt->size = 0;
+}
+
+void
+_gpgme_fd_table_deinit (fd_table_t fdt)
+{
+ if (fdt->fds)
+ free (fdt->fds);
+}
+
+
+/* XXX We should keep a marker and roll over for speed. */
+static gpgme_error_t
+fd_table_put (fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
+{
+ unsigned int i, j;
+ struct io_select_fd_s *new_fds;
+
+ for (i = 0; i < fdt->size; i++)
+ {
+ if (fdt->fds[i].fd == -1)
+ break;
+ }
+ if (i == fdt->size)
+ {
+#define FDT_ALLOCSIZE 10
+ new_fds = realloc (fdt->fds, (fdt->size + FDT_ALLOCSIZE)
+ * sizeof (*new_fds));
+ if (!new_fds)
+ return gpg_error_from_errno (errno);
+
+ fdt->fds = new_fds;
+ fdt->size += FDT_ALLOCSIZE;
+ for (j = 0; j < FDT_ALLOCSIZE; j++)
+ fdt->fds[i + j].fd = -1;
+ }
+
+ fdt->fds[i].fd = fd;
+ fdt->fds[i].for_read = (dir == 1);
+ fdt->fds[i].for_write = (dir == 0);
+ fdt->fds[i].frozen = 0;
+ fdt->fds[i].signaled = 0;
+ fdt->fds[i].opaque = opaque;
+ *idx = i;
+ return 0;
+}
+
+
+/* Register the file descriptor FD with the handler FNC (which gets
+ FNC_DATA as its first argument) for the direction DIR. DATA should
+ be the context for which the fd is added. R_TAG will hold the tag
+ that can be used to remove the fd. */
+gpgme_error_t
+_gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
+ void *fnc_data, void **r_tag)
+{
+ gpgme_error_t err;
+ gpgme_ctx_t ctx = (gpgme_ctx_t) data;
+ fd_table_t fdt;
+ struct wait_item_s *item;
+ struct tag *tag;
+
+ assert (fnc);
+ assert (ctx);
+
+ fdt = &ctx->fdt;
+ assert (fdt);
+
+ tag = malloc (sizeof *tag);
+ if (!tag)
+ return gpg_error_from_errno (errno);
+ tag->ctx = ctx;
+
+ /* Allocate a structure to hold information about the handler. */
+ item = calloc (1, sizeof *item);
+ if (!item)
+ {
+ int saved_errno = errno;
+ free (tag);
+ return gpg_error_from_errno (saved_errno);
+ }
+ item->ctx = ctx;
+ item->dir = dir;
+ item->handler = fnc;
+ item->handler_value = fnc_data;
+
+ err = fd_table_put (fdt, fd, dir, item, &tag->idx);
+ if (err)
+ {
+ free (tag);
+ free (item);
+ return err;
+ }
+
+ *r_tag = tag;
+ return 0;
+}
+
+
+void
+_gpgme_remove_io_cb (void *data)
+{
+ struct tag *tag = data;
+ gpgme_ctx_t ctx;
+ fd_table_t fdt;
+ int idx;
+
+ assert (tag);
+ ctx = tag->ctx;
+ assert (ctx);
+ fdt = &ctx->fdt;
+ assert (fdt);
+ idx = tag->idx;
+
+ DEBUG2 ("setting fd %d (item=%p) done", fdt->fds[idx].fd,
+ fdt->fds[idx].opaque);
+ free (fdt->fds[idx].opaque);
+ free (tag);
+
+ /* Free the table entry. */
+ fdt->fds[idx].fd = -1;
+ fdt->fds[idx].for_read = 0;
+ fdt->fds[idx].for_write = 0;
+ fdt->fds[idx].opaque = NULL;
+}
+
+
+/* This is slightly embarrassing. The problem is that running an I/O
+ callback _may_ influence the status of other file descriptors. Our
+ own event loops could compensate for that, but the external event
+ loops cannot. FIXME: We may still want to optimize this a bit when
+ we are called from our own event loops. So if CHECKED is 1, the
+ check is skipped. */
+gpgme_error_t
+_gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked)
+{
+ struct wait_item_s *item;
+ item = (struct wait_item_s *) an_fds->opaque;
+ assert (item);
+
+ if (!checked)
+ {
+ int nr;
+ struct io_select_fd_s fds;
+
+ fds = *an_fds;
+ fds.signaled = 0;
+ /* Just give it a quick poll. */
+ nr = _gpgme_io_select (&fds, 1, 1);
+ assert (nr <= 1);
+ if (nr < 0)
+ return errno;
+ else if (nr == 0)
+ /* The status changed in the meantime, there is nothing left
+ to do. */
+ return 0;
+ }
+
+ return item->handler (item->handler_value, an_fds->fd);
+}
diff --git a/libtdenetwork/libgpgme-copy/gpgme/wait.h b/libtdenetwork/libgpgme-copy/gpgme/wait.h
new file mode 100644
index 000000000..79582f884
--- /dev/null
+++ b/libtdenetwork/libgpgme-copy/gpgme/wait.h
@@ -0,0 +1,82 @@
+/* wait.h - Definitions for the wait queue interface.
+ Copyright (C) 2000 Werner Koch (dd9jn)
+ Copyright (C) 2001, 2002, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef WAIT_H
+#define WAIT_H
+
+#include "gpgme.h"
+#include "sema.h"
+
+struct fd_table
+{
+ struct io_select_fd_s *fds;
+ size_t size;
+};
+typedef struct fd_table *fd_table_t;
+
+/* Wait items are hooked into the io_select_fd_s to connect an fd with
+ a callback handler. */
+struct wait_item_s
+{
+ gpgme_ctx_t ctx;
+ gpgme_io_cb_t handler;
+ void *handler_value;
+ int dir;
+};
+
+/* A registered fd handler is removed later using the tag that
+ identifies it. */
+struct tag
+{
+ /* The context for which the fd was registered. */
+ gpgme_ctx_t ctx;
+
+ /* The index into the fd table for this context. */
+ int idx;
+
+ /* This is used by the wrappers for the user event loop. */
+ void *user_tag;
+};
+
+
+void _gpgme_fd_table_init (fd_table_t fdt);
+void _gpgme_fd_table_deinit (fd_table_t fdt);
+
+gpgme_error_t _gpgme_add_io_cb (void *data, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data, void **r_tag);
+void _gpgme_remove_io_cb (void *tag);
+void _gpgme_wait_private_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data);
+void _gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data);
+
+gpgme_error_t _gpgme_wait_user_add_io_cb (void *data, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data,
+ void **r_tag);
+void _gpgme_wait_user_remove_io_cb (void *tag);
+void _gpgme_wait_user_event_cb (void *data, gpgme_event_io_t type,
+ void *type_data);
+
+gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx);
+
+gpgme_error_t _gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked);
+
+#endif /* WAIT_H */