From cvs at cvs.gnupg.org Sat Sep 1 00:00:07 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Sat, 01 Sep 2007 00:00:07 +0200 Subject: [svn] GpgEX - r8 - trunk/src Message-ID: Author: marcus Date: 2007-08-31 23:59:38 +0200 (Fri, 31 Aug 2007) New Revision: 8 Modified: trunk/src/ChangeLog trunk/src/gpgex.cc Log: 2007-08-31 Marcus Brinkmann * gpgex.cc (gpgex_t::QueryContextMenu): Fix menu separators. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-30 15:48:38 UTC (rev 7) +++ trunk/src/ChangeLog 2007-08-31 21:59:38 UTC (rev 8) @@ -1,3 +1,7 @@ +2007-08-31 Marcus Brinkmann + + * gpgex.cc (gpgex_t::QueryContextMenu): Fix menu separators. + 2007-08-30 Marcus Brinkmann * gpgex.h (ID_CMD_HELP, ID_CMD_VERIFY_DECRYPT) Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-08-30 15:48:38 UTC (rev 7) +++ trunk/src/gpgex.cc 2007-08-31 21:59:38 UTC (rev 8) @@ -237,9 +237,7 @@ if (uFlags & CMF_DEFAULTONLY) return TRACE_RES (MAKE_HRESULT (SEVERITY_SUCCESS, FACILITY_NULL, 0)); - /* Windows puts a separator after our entries, but not before. */ - /* FIXME: Check error. */ - res = InsertMenu (hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL); + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); @@ -280,6 +278,10 @@ return TRACE_RES (HRESULT_FROM_WIN32 (last_error)); } + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + if (! res) + return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_VERIFY_DECRYPT, ID_CMD_STR_VERIFY_DECRYPT); @@ -295,11 +297,10 @@ res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_IMPORT, ID_CMD_STR_IMPORT); if (res) - res = InsertMenu (hMenu, idx++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_HELP, ID_CMD_STR_HELP); - if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); From cvs at cvs.gnupg.org Sun Sep 2 16:09:55 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Sun, 02 Sep 2007 16:09:55 +0200 Subject: [svn] GnuPG - r4576 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2007-09-02 16:09:24 +0200 (Sun, 02 Sep 2007) New Revision: 4576 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/import.c Log: * import.c (collapse_uids): Significant speedup for de-duping user IDs. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-08-31 08:24:52 UTC (rev 4575) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-09-02 14:09:24 UTC (rev 4576) @@ -1,3 +1,8 @@ +2007-09-02 David Shaw + + * import.c (collapse_uids): Significant speedup for de-duping user + IDs. + 2007-08-24 Werner Koch * keyring.c (keyring_register_filename): Use same_file_p. Modified: branches/STABLE-BRANCH-1-4/g10/import.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/import.c 2007-08-31 08:24:52 UTC (rev 4575) +++ branches/STABLE-BRANCH-1-4/g10/import.c 2007-09-02 14:09:24 UTC (rev 4576) @@ -1644,90 +1644,102 @@ * It may happen that the imported keyblock has duplicated user IDs. * We check this here and collapse those user IDs together with their * sigs into one. - * Returns: True if the keyblock hash changed. + * Returns: True if the keyblock has changed. */ int collapse_uids( KBNODE *keyblock ) { - KBNODE n, n2; - int in_uid; - int any=0; + KBNODE uid1; + int any=0; - restart: - for( n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype != PKT_USER_ID ) + for(uid1=*keyblock;uid1;uid1=uid1->next) + { + KBNODE uid2; + + if(uid1->pkt->pkttype!=PKT_USER_ID) + continue; + + for(uid2=uid1->next;uid2;uid2=uid2->next) + { + if(uid2->pkt->pkttype!=PKT_USER_ID) continue; - for( n2 = n->next; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - && !cmp_user_ids( n->pkt->pkt.user_id, - n2->pkt->pkt.user_id ) ) { - /* found a duplicate */ - any = 1; - if( !n2->next - || n2->next->pkt->pkttype == PKT_USER_ID - || n2->next->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->next->pkt->pkttype == PKT_SECRET_SUBKEY ) { - /* no more signatures: delete the user ID - * and start over */ - remove_kbnode( keyblock, n2 ); + + if(cmp_user_ids(uid1->pkt->pkt.user_id, + uid2->pkt->pkt.user_id)==0) + { + /* We have a duplicated uid */ + KBNODE sig1,last; + + any=1; + + /* Now take uid2's signatures, and attach them to + uid1 */ + for(last=uid2;last->next;last=last->next) + { + if(last->next->pkt->pkttype==PKT_USER_ID + || last->next->pkt->pkttype==PKT_PUBLIC_SUBKEY + || last->next->pkt->pkttype==PKT_SECRET_SUBKEY) + break; } - else { - /* The simple approach: Move one signature and - * then start over to delete the next one :-( */ - move_kbnode( keyblock, n2->next, n->next ); - } - goto restart; - } - } - } - if( !any ) - return 0; - restart_sig: - /* now we may have duplicate signatures on one user ID: fix this */ - for( in_uid = 0, n = *keyblock; n; n = n->next ) { - if( n->pkt->pkttype == PKT_USER_ID ) - in_uid = 1; - else if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n->pkt->pkttype == PKT_SECRET_SUBKEY ) - in_uid = 0; - else if( in_uid ) { - n2 = n; - do { - KBNODE ncmp = NULL; - for( ; n2; n2 = n2->next ) { - if( n2->pkt->pkttype == PKT_USER_ID - || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY - || n2->pkt->pkttype == PKT_SECRET_SUBKEY ) + /* Snip out uid2 */ + (find_prev_kbnode(*keyblock,uid2,0))->next=last->next; + + /* Now put uid2 in place as part of uid1 */ + last->next=uid1->next; + uid1->next=uid2; + remove_kbnode(keyblock,uid2); + + /* Now dedupe uid1 */ + for(sig1=uid1->next;sig1;sig1=sig1->next) + { + KBNODE sig2; + + if(sig1->pkt->pkttype==PKT_USER_ID + || sig1->pkt->pkttype==PKT_PUBLIC_SUBKEY + || sig1->pkt->pkttype==PKT_SECRET_SUBKEY) + break; + + if(sig1->pkt->pkttype!=PKT_SIGNATURE) + continue; + + for(sig2=sig1->next,last=sig1;sig2;last=sig2,sig2=sig2->next) + { + if(sig2->pkt->pkttype==PKT_USER_ID + || sig2->pkt->pkttype==PKT_PUBLIC_SUBKEY + || sig2->pkt->pkttype==PKT_SECRET_SUBKEY) break; - if( n2->pkt->pkttype != PKT_SIGNATURE ) - ; - else if( !ncmp ) - ncmp = n2; - else if( !cmp_signatures( ncmp->pkt->pkt.signature, - n2->pkt->pkt.signature )) { - remove_kbnode( keyblock, n2 ); - goto restart_sig; + + if(sig2->pkt->pkttype!=PKT_SIGNATURE) + continue; + + if(cmp_signatures(sig1->pkt->pkt.signature, + sig2->pkt->pkt.signature)==0) + { + /* We have a match, so delete the second + signature */ + remove_kbnode(&uid1,sig2); + sig2=last; + } } } - n2 = ncmp? ncmp->next : NULL; - } while( n2 ); + } } } - if(!opt.quiet) - { - const char *key="???"; + if(any && !opt.quiet) + { + const char *key="???"; - if( (n = find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) - key=keystr_from_pk(n->pkt->pkt.public_key); - else if( (n = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) - key=keystr_from_sk(n->pkt->pkt.secret_key); + if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) + key=keystr_from_pk(uid1->pkt->pkt.public_key); + else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) + key=keystr_from_sk(uid1->pkt->pkt.secret_key); - log_info(_("key %s: duplicated user ID detected - merged\n"),key); - } + log_info(_("key %s: duplicated user ID detected - merged\n"),key); + } - return 1; + return any; } /* Check for a 0x20 revocation from a revocation key that is not From cvs at cvs.gnupg.org Mon Sep 3 14:29:39 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 14:29:39 +0200 Subject: [svn] assuan - r251 - in trunk: doc src Message-ID: Author: marcus Date: 2007-09-03 14:29:07 +0200 (Mon, 03 Sep 2007) New Revision: 251 Modified: trunk/doc/ChangeLog trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-defs.h trunk/src/assuan-inquire.c trunk/src/assuan.h Log: doc/ 2007-09-03 Marcus Brinkmann * assuan.texi: Fix prototype and documentation for assuan_inquire_ext. src/ 2007-09-03 Marcus Brinkmann * assuan.h (assuan_inquire_ext): Move buffer and buffer_length arguments callback in prototype. * assuan-defs.h (struct assuan_context_s): Remove members inquire_r_buffer and inquire_r_buffer_len. Add buffer and buffer length arguments to inquire_cb. * assuan-inquire.c (_assuan_inquire_ext_cb): Return buffer and buffer length via callback. (assuan_inquire_ext): Move buffer and buffer length arguments to callback. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/doc/ChangeLog 2007-09-03 12:29:07 UTC (rev 251) @@ -1,3 +1,8 @@ +2007-09-03 Marcus Brinkmann + + * assuan.texi: Fix prototype and documentation for + assuan_inquire_ext. + 2007-08-24 Werner Koch * lgpl.texi: Replace by LGPLv2.1 version. Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/doc/assuan.texi 2007-09-03 12:29:07 UTC (rev 251) @@ -1295,12 +1295,13 @@ regular end. @end deftypefun - at deftypefun assuan_error_t assuan_inquire_ext (@w{assuan_context_t @var{ctx}}, @w{const char *@var{keyword}}, @w{unsigned char **@var{r_buffer}}, @w{size_t *@var{r_length}}, @w{size_t @var{maxlen}}, @w{int (*@var{cb}) (void *cb_data, int rc)}, @w{void *@var{cb_data}}) + at deftypefun assuan_error_t assuan_inquire_ext (@w{assuan_context_t @var{ctx}}, @w{const char *@var{keyword}}, @w{size_t @var{maxlen}}, @w{int (*@var{cb}) (void *cb_data, int rc, unsigned char *buffer, size_t buffer_len)}, @w{void *@var{cb_data}}) -This is the same as @code{assuan_inquire} but the caller has to -provide the outer loop (using @code{assuan_process_next}). The caller -should specify a continuation with @var{cb}, which receives - at var{cb_data} as its first argument. +This is similar to @code{assuan_inquire} but the caller has to provide +the outer loop (using @code{assuan_process_next}). The caller should +specify a continuation with @var{cb}, which receives @var{cb_data} as +its first argument, and the error code as well as the inquired data as +its remaining arguments. @end deftypefun Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/src/ChangeLog 2007-09-03 12:29:07 UTC (rev 251) @@ -1,3 +1,17 @@ +<<<<<<< .mine +2007-09-03 Marcus Brinkmann + + * assuan.h (assuan_inquire_ext): Move buffer and buffer_length + arguments callback in prototype. + * assuan-defs.h (struct assuan_context_s): Remove members + inquire_r_buffer and inquire_r_buffer_len. Add buffer and buffer + length arguments to inquire_cb. + * assuan-inquire.c (_assuan_inquire_ext_cb): Return buffer and + buffer length via callback. + (assuan_inquire_ext): Move buffer and buffer length arguments to + callback. + +======= 2007-08-24 Werner Koch Switched license to back to LGPLv2.1. @@ -2,2 +16,3 @@ +>>>>>>> .r250 2007-08-09 Marcus Brinkmann Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/src/assuan-defs.h 2007-09-03 12:29:07 UTC (rev 251) @@ -1,5 +1,5 @@ /* assuan-defs.c - Internal definitions to Assuan - * Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -107,10 +107,8 @@ int in_command; /* The following members are used by assuan_inquire_ext. */ - int (*inquire_cb) (void *cb_data, int rc); + int (*inquire_cb) (void *cb_data, int rc, unsigned char *buf, size_t len); void *inquire_cb_data; - unsigned char **inquire_r_buffer; - size_t *inquire_r_buffer_len; void *inquire_membuf; char *hello_line; Modified: trunk/src/assuan-inquire.c =================================================================== --- trunk/src/assuan-inquire.c 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/src/assuan-inquire.c 2007-09-03 12:29:07 UTC (rev 251) @@ -1,5 +1,5 @@ /* assuan-inquire.c - handle inquire stuff - * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -310,15 +310,20 @@ return 0; leave: - if (mb) - { - *(ctx->inquire_r_buffer) = get_membuf (mb, ctx->inquire_r_buffer_len); - if (!*(ctx->inquire_r_buffer)) - rc = _assuan_error (ASSUAN_Out_Of_Core); - free_membuf (mb); - free (mb); - } - (ctx->inquire_cb) (ctx->inquire_cb_data, rc); + { + size_t buf_len = 0; + unsigned char *buf = NULL; + + if (mb) + { + buf = get_membuf (mb, &buf_len); + if (!buf) + rc = _assuan_error (ASSUAN_Out_Of_Core); + free_membuf (mb); + free (mb); + } + (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len); + } return rc; } @@ -326,8 +331,6 @@ * assuan_inquire_ext: * @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. * @cb: A callback handler which is invoked after the operation completed. * @cb_data: A user-provided value passed to the callback handler. @@ -339,9 +342,10 @@ * Return value: 0 on success or an ASSUAN error code **/ assuan_error_t -assuan_inquire_ext (assuan_context_t ctx, const char *keyword, - unsigned char **r_buffer, size_t *r_length, size_t maxlen, - int (*cb) (void *cb_data, int rc), void *cb_data) +assuan_inquire_ext (assuan_context_t ctx, const char *keyword, size_t maxlen, + int (*cb) (void *cb_data, int rc, unsigned char *buf, + size_t len), + void *cb_data) { assuan_error_t rc; struct membuf *mb = NULL; @@ -350,9 +354,7 @@ 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); + nodataexpected = !maxlen; if (!ctx->is_server) return _assuan_error (ASSUAN_Not_A_Server); if (ctx->in_inquire) @@ -381,8 +383,6 @@ ctx->inquire_cb = cb; ctx->inquire_cb_data = cb_data; ctx->inquire_membuf = mb; - ctx->inquire_r_buffer = r_buffer; - ctx->inquire_r_buffer_len = r_length; return 0; } Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-08-24 05:59:50 UTC (rev 250) +++ trunk/src/assuan.h 2007-09-03 12:29:07 UTC (rev 251) @@ -466,9 +466,10 @@ unsigned char **r_buffer, size_t *r_length, size_t maxlen); assuan_error_t assuan_inquire_ext (assuan_context_t ctx, const char *keyword, - unsigned char **r_buffer, size_t *r_length, size_t maxlen, - int (*cb) (void *cb_data, int rc), + int (*cb) (void *cb_data, int rc, + unsigned char *buf, + size_t buf_len), void *cb_data); /*-- assuan-buffer.c --*/ assuan_error_t assuan_read_line (assuan_context_t ctx, From cvs at cvs.gnupg.org Mon Sep 3 15:08:29 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 15:08:29 +0200 Subject: [svn] assuan - r252 - trunk/src Message-ID: Author: marcus Date: 2007-09-03 15:07:59 +0200 (Mon, 03 Sep 2007) New Revision: 252 Modified: trunk/src/ChangeLog Log: doc/ 2007-09-03 Marcus Brinkmann * assuan.texi: Fix prototype and documentation for assuan_inquire_ext. src/ 2007-09-03 Marcus Brinkmann * assuan.h (assuan_inquire_ext): Move buffer and buffer_length arguments callback in prototype. * assuan-defs.h (struct assuan_context_s): Remove members inquire_r_buffer and inquire_r_buffer_len. Add buffer and buffer length arguments to inquire_cb. * assuan-inquire.c (_assuan_inquire_ext_cb): Return buffer and buffer length via callback. (assuan_inquire_ext): Move buffer and buffer length arguments to callback. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-03 12:29:07 UTC (rev 251) +++ trunk/src/ChangeLog 2007-09-03 13:07:59 UTC (rev 252) @@ -1,4 +1,3 @@ -<<<<<<< .mine 2007-09-03 Marcus Brinkmann * assuan.h (assuan_inquire_ext): Move buffer and buffer_length @@ -11,12 +10,10 @@ (assuan_inquire_ext): Move buffer and buffer length arguments to callback. -======= 2007-08-24 Werner Koch Switched license to back to LGPLv2.1. ->>>>>>> .r250 2007-08-09 Marcus Brinkmann * assuan.h (assuan_process_done, assuan_inquire_ext): New From cvs at cvs.gnupg.org Mon Sep 3 16:17:11 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 16:17:11 +0200 Subject: [svn] assuan - r254 - trunk/src Message-ID: Author: marcus Date: 2007-09-03 16:16:40 +0200 (Mon, 03 Sep 2007) New Revision: 254 Modified: trunk/src/assuan.h Log: Fix filename at top of file. Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-09-03 14:15:52 UTC (rev 253) +++ trunk/src/assuan.h 2007-09-03 14:16:40 UTC (rev 254) @@ -1,4 +1,4 @@ -/* assuan.c - Definitions for the Assuan IPC library +/* assuan.h - Definitions for the Assuan IPC library * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. From cvs at cvs.gnupg.org Mon Sep 3 16:19:59 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 16:19:59 +0200 Subject: [svn] gpgme - r1249 - trunk/assuan Message-ID: Author: marcus Date: 2007-09-03 16:19:29 +0200 (Mon, 03 Sep 2007) New Revision: 1249 Modified: trunk/assuan/ChangeLog trunk/assuan/assuan.h Log: 2007-09-03 Marcus Brinkmann * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames with _ASSUAN_PREFIX. Modified: trunk/assuan/ChangeLog =================================================================== --- trunk/assuan/ChangeLog 2007-08-22 17:29:41 UTC (rev 1248) +++ trunk/assuan/ChangeLog 2007-09-03 14:19:29 UTC (rev 1249) @@ -1,3 +1,8 @@ +2007-09-03 Marcus Brinkmann + + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames + with _ASSUAN_PREFIX. + 2007-08-02 Werner Koch * assuan-pipe-connect.c (pipe_connect_w32): A bit more debug output. Modified: trunk/assuan/assuan.h =================================================================== --- trunk/assuan/assuan.h 2007-08-22 17:29:41 UTC (rev 1248) +++ trunk/assuan/assuan.h 2007-09-03 14:19:29 UTC (rev 1249) @@ -1,5 +1,5 @@ -/* assuan.c - Definitions for the Assuan IPC library - * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +/* assuan.h - Definitions for the Assuan IPC library + * Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -156,6 +156,9 @@ _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) +#define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2) +#define assuan_set_assuan_log_prefix \ + _ASSUAN_PREFIX(assuan_set_assuan_log_prefix) /* And now the internal functions, argh... */ #define _assuan_read_line _ASSUAN_PREFIX(_assuan_read_line) @@ -187,6 +190,13 @@ #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) +#define _assuan_error _ASSUAN_PREFIX(_assuan_error) +#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io) +#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds) +#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit) +#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg) +#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg) +#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid) #define _assuan_funopen _gpgme_funopen #endif /*_ASSUAN_EXT_SYM_PREFIX*/ From cvs at cvs.gnupg.org Mon Sep 3 16:16:23 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 16:16:23 +0200 Subject: [svn] assuan - r253 - trunk/src Message-ID: Author: marcus Date: 2007-09-03 16:15:52 +0200 (Mon, 03 Sep 2007) New Revision: 253 Modified: trunk/src/ChangeLog trunk/src/assuan.h Log: 2007-09-03 Marcus Brinkmann * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames with _ASSUAN_PREFIX. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-03 13:07:59 UTC (rev 252) +++ trunk/src/ChangeLog 2007-09-03 14:15:52 UTC (rev 253) @@ -1,5 +1,8 @@ 2007-09-03 Marcus Brinkmann + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames + with _ASSUAN_PREFIX. + * assuan.h (assuan_inquire_ext): Move buffer and buffer_length arguments callback in prototype. * assuan-defs.h (struct assuan_context_s): Remove members Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-09-03 13:07:59 UTC (rev 252) +++ trunk/src/assuan.h 2007-09-03 14:15:52 UTC (rev 253) @@ -129,7 +129,11 @@ _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) +#define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2) +#define assuan_set_assuan_log_prefix \ + _ASSUAN_PREFIX(assuan_set_assuan_log_prefix) + /* 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) @@ -160,6 +164,13 @@ #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) +#define _assuan_error _ASSUAN_PREFIX(_assuan_error) +#define _assuan_init_uds_io _ASSUAN_PREFIX(_assuan_init_uds_io) +#define _assuan_uds_close_fds _ASSUAN_PREFIX(_assuan_uds_close_fds) +#define _assuan_uds_deinit _ASSUAN_PREFIX(_assuan_uds_deinit) +#define _assuan_simple_recvmsg _ASSUAN_PREFIX(_assuan_simple_recvmsg) +#define _assuan_simple_sendmsg _ASSUAN_PREFIX(_assuan_simple_sendmsg) +#define _assuan_waitpid _ASSUAN_PREFIX(_assuan_waitpid) #endif /*_ASSUAN_EXT_SYM_PREFIX*/ From cvs at cvs.gnupg.org Mon Sep 3 23:52:05 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 03 Sep 2007 23:52:05 +0200 Subject: [svn] GpgEX - r9 - in trunk: . m4 src Message-ID: Author: marcus Date: 2007-09-03 23:51:34 +0200 (Mon, 03 Sep 2007) New Revision: 9 Added: trunk/src/bitmaps.cc trunk/src/bitmaps.h trunk/src/icon-key-12.bmp trunk/src/icon-key-16.bmp trunk/src/icons.rc Modified: trunk/ChangeLog trunk/m4/Makefile.am trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/gpgex.cc trunk/src/gpgex.h Log: m4/ 2007-09-03 Marcus Brinkmann * m4/Makefile.am (EXTRA_DIST): Remove gpgme.m4 and gpg-error.m4. src/ 2007-09-03 Marcus Brinkmann * bitmaps.h, bitmaps.cc, icons.rc, icon-key-12.bmp, icon-key-16.bmp: New files. * Makefile.am (gpgex_SOURCES): Add icons.rc, bitmaps.h and bitmaps.cc. (noinst_gpgex_SOURCES): Add versioninfo.rc. (gpgex_LDADD): Add -lgdi32. (resource.o): Remove target. * gpgex.h: Include bitmaps.h. (class gpgex_t): New member key_bitmap. (gpgex_t::gpgex_t, gpgex_t::~gpgex_t): Initialize and deinitialize it. * gpgex.cc (gpgex_t::QueryContextMenu): Add dummy bitmap for menu. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/ChangeLog 2007-09-03 21:51:34 UTC (rev 9) @@ -1,3 +1,7 @@ +2007-09-03 Marcus Brinkmann + + * m4/Makefile.am (EXTRA_DIST): Remove gpgme.m4 and gpg-error.m4. + 2007-08-23 Marcus Brinkmann * Initial commit. Modified: trunk/m4/Makefile.am =================================================================== --- trunk/m4/Makefile.am 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/m4/Makefile.am 2007-09-03 21:51:34 UTC (rev 9) @@ -1,4 +1,4 @@ -EXTRA_DIST = gpgme.m4 codeset.m4 gettext.m4 glibc21.m4 gpg-error.m4 \ - iconv.m4 intdiv0.m4 inttypes-pri.m4 inttypes.m4 inttypes_h.m4 \ - isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 \ - nls.m4 po.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 +EXTRA_DIST = codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 \ + inttypes-pri.m4 inttypes.m4 inttypes_h.m4 isc-posix.m4 \ + lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 nls.m4 \ + po.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/ChangeLog 2007-09-03 21:51:34 UTC (rev 9) @@ -1,3 +1,18 @@ +2007-09-03 Marcus Brinkmann + + * bitmaps.h, bitmaps.cc, icons.rc, icon-key-12.bmp, + icon-key-16.bmp: New files. + * Makefile.am (gpgex_SOURCES): Add icons.rc, bitmaps.h and + bitmaps.cc. + (noinst_gpgex_SOURCES): Add versioninfo.rc. + (gpgex_LDADD): Add -lgdi32. + (resource.o): Remove target. + * gpgex.h: Include bitmaps.h. + (class gpgex_t): New member key_bitmap. + (gpgex_t::gpgex_t, gpgex_t::~gpgex_t): Initialize and deinitialize + it. + * gpgex.cc (gpgex_t::QueryContextMenu): Add dummy bitmap for menu. + 2007-08-31 Marcus Brinkmann * gpgex.cc (gpgex_t::QueryContextMenu): Fix menu separators. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/Makefile.am 2007-09-03 21:51:34 UTC (rev 9) @@ -18,21 +18,22 @@ AM_CFLAGS = $(GPGME_CFLAGS) -shared AM_CXXFLAGS = $(GPGME_CFLAGS) -shared -gpgex_SOURCES = \ +nodist_gpgex_SOURCES = versioninfo.rc +gpgex_SOURCES = \ gpgex.def \ + icons.rc \ registry.h registry.c \ w32-gettext.c w32-gettext.h \ gpgex-class.h gpgex-class.cc \ gpgex-factory.h gpgex-factory.cc \ + bitmaps.h bitmaps.cc \ gpgex.h gpgex.cc \ main.h main.cc #gpgex_LDADD = $(srcdir)/gpgex.def \ -# -L . -lshell32 -lgdi32 -lcomdlg32 \ -# -loleaut32 -lws2_32 -ladvapi32 -gpgex_LDADD = $(srcdir)/gpgex.def -L . -lshell32 -lws2_32 -lole32 -luuid +# -L . -lshell32 -lcomdlg32 -loleaut32 -ladvapi32 +gpgex_LDADD = $(srcdir)/gpgex.def -L . \ + -lshell32 -lgdi32 -lws2_32 -lole32 -luuid -resource.o: versioninfo.rc - .rc.o: $(WINDRES) -I $(srcdir) -I . `test -f '$<' || echo '$(srcdir)/'`$< $@ Added: trunk/src/bitmaps.cc =================================================================== --- trunk/src/bitmaps.cc 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/bitmaps.cc 2007-09-03 21:51:34 UTC (rev 9) @@ -0,0 +1,94 @@ +/* bitmaps.cc - gpgex bitmap implementation + Copyright (C) 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX 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 of the License, or (at your option) any later version. + + GpgEX 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 +#endif + +#include +#include + +using std::string; + +#include + +#include "main.h" + +#include "bitmaps.h" + + +/* The size of the icons. */ +int gpgex_bitmaps_t::size; + +/* The available bitmap sizes in ascending order. */ +int gpgex_bitmaps_t::available_sizes[] = { 12, 16 }; + + +/* The global singleton object. */ +class gpgex_bitmaps_t gpgex_bitmaps; + + +gpgex_bitmaps_t::gpgex_bitmaps_t (void) +{ + /* Note about bitmaps: The required size is given by + GetSystemMetrics and can vary depending on the display size. A + typical value is 12x12. The color depth should be 8 bits. The + upper left corner pixel color is replaced by transparent + automatically. */ + int width = GetSystemMetrics (SM_CXMENUCHECK); + int height = GetSystemMetrics (SM_CYMENUCHECK); + + /* All our images are square, so take the minimum and look for the + biggest available size that fits in there. */ + int max_size = (width < height) ? width : height; + + for (unsigned int i = 0; i < (sizeof (this->available_sizes) + / sizeof (this->available_sizes[0])); i++) + if (max_size >= this->available_sizes[i]) + this->size = this->available_sizes[i]; + else + break; + + (void) TRACE3 (DEBUG_INIT, "gpgex_bitmaps_t::gpgex_bitmaps_t", this, + "GetSystemMetrics: %ix%i (using %i)", width, height, + this->size); +} + + +/* Load the bitmap with name NAME. */ +HBITMAP gpgex_bitmaps_t::load_bitmap (string name) +{ + HBITMAP bmap; + std::ostringstream out; + + out << name << "-" << this->size; + bmap = LoadBitmap (gpgex_server::instance, out.str().c_str()); + if (bmap == NULL) + (void) TRACE2 (DEBUG_INIT, "gpgex_bitmaps_t::load_bitmap", this, + "LoadImage %s failed: ec=%x", + out.str().c_str(), GetLastError ()); + else + (void) TRACE1 (DEBUG_INIT, "gpgex_bitmaps_t::load_bitmap", this, + "loaded image %s", out.str().c_str()); + + /* FIXME: Create cache of images. */ + return bmap; +} + Added: trunk/src/bitmaps.h =================================================================== --- trunk/src/bitmaps.h 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/bitmaps.h 2007-09-03 21:51:34 UTC (rev 9) @@ -0,0 +1,52 @@ +/* bitmaps.h - gpgex bitmap prototypes + Copyright (C) 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX 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 of the License, or (at your option) any later version. + + GpgEX 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 GPGEX_BITMAPS_H +#define GPGEX_BITMAPS_H + +#include + +using std::string; + +#include + + +/* The class used to load bitmap resources. */ +class gpgex_bitmaps_t +{ + /* The icon size used. */ + static int size; + + /* The available sizes. */ + static int available_sizes[]; + + public: + /* Constructor. */ + gpgex_bitmaps_t (void); + + /* Load the bitmap with name NAME. */ + HBITMAP load_bitmap (string name); +}; + + +/* The global singleton object. */ +extern gpgex_bitmaps_t gpgex_bitmaps; + +#endif /* ! GPGEX_BITMAPS_H */ Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/gpgex.cc 2007-09-03 21:51:34 UTC (rev 9) @@ -278,16 +278,21 @@ return TRACE_RES (HRESULT_FROM_WIN32 (last_error)); } - res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + if (this->key_bitmap) + { + // indexMenu - 1!!! + res = SetMenuItemBitmaps (hMenu, indexMenu - 1, MF_BYPOSITION, + this->key_bitmap, this->key_bitmap); + } + if (res) + res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, + 0, NULL); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_VERIFY_DECRYPT, ID_CMD_STR_VERIFY_DECRYPT); - // idx - 1!!! - // res = SetMenuItemBitmaps (hPopup, idx - 1, MF_BYPOSITION, - // MenuVerifyDecryptBitmap, MenuVerifyDecryptBitmap); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, Modified: trunk/src/gpgex.h =================================================================== --- trunk/src/gpgex.h 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/gpgex.h 2007-09-03 21:51:34 UTC (rev 9) @@ -30,6 +30,8 @@ #include #include +#include "bitmaps.h" + /* For context menus. */ #define ID_CMD_HELP 0 #define ID_CMD_VERIFY_DECRYPT 1 @@ -100,19 +102,33 @@ BOOL all_files_gpg; /* Support for the context menu. */ - + HBITMAP key_bitmap; + public: /* Constructors and destructors. For these, we update the global component reference counter. */ - gpgex_t () + gpgex_t (void) : refcount (0) { + TRACE_BEG (DEBUG_INIT, "gpgex_t::gpgex_t", this); + gpgex_server::add_ref (); + + this->key_bitmap = gpgex_bitmaps.load_bitmap ("Key"); + + (void) TRACE_SUC (); } - ~gpgex_t () + ~gpgex_t (void) { + TRACE_BEG (DEBUG_INIT, "gpgex_t::~gpgex_t", this); + + if (this->key_bitmap != NULL) + DeleteObject (this->key_bitmap); + gpgex_server::release (); + + (void) TRACE_SUC (); } /* Reset the instance between operations. */ Added: trunk/src/icon-key-12.bmp =================================================================== (Binary files differ) Property changes on: trunk/src/icon-key-12.bmp ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/src/icon-key-16.bmp =================================================================== (Binary files differ) Property changes on: trunk/src/icon-key-16.bmp ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/src/icons.rc =================================================================== --- trunk/src/icons.rc 2007-08-31 21:59:38 UTC (rev 8) +++ trunk/src/icons.rc 2007-09-03 21:51:34 UTC (rev 9) @@ -0,0 +1,2 @@ +Key-12 BITMAP "icon-key-12.bmp" +Key-16 BITMAP "icon-key-16.bmp" From cvs at cvs.gnupg.org Tue Sep 4 07:59:43 2007 From: cvs at cvs.gnupg.org (svn author mo) Date: Tue, 04 Sep 2007 07:59:43 +0200 Subject: [svn] GnuPG - r4577 - trunk/tools Message-ID: Author: mo Date: 2007-09-04 07:59:07 +0200 (Tue, 04 Sep 2007) New Revision: 4577 Modified: trunk/tools/ChangeLog trunk/tools/gpgkey2ssh.c Log: 2007-09-04 Moritz Schulte * gpgkey2ssh.c: Include sysutils.h so that gnupg_tmpfile() is declared. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-09-02 14:09:24 UTC (rev 4576) +++ trunk/tools/ChangeLog 2007-09-04 05:59:07 UTC (rev 4577) @@ -1,3 +1,8 @@ +2007-09-04 Moritz Schulte + + * gpgkey2ssh.c: Include sysutils.h so that gnupg_tmpfile() is + declared. + 2007-08-31 Werner Koch * gpgconf-comp.c (gc_component_list_components): List the programs Modified: trunk/tools/gpgkey2ssh.c =================================================================== --- trunk/tools/gpgkey2ssh.c 2007-09-02 14:09:24 UTC (rev 4576) +++ trunk/tools/gpgkey2ssh.c 2007-09-04 05:59:07 UTC (rev 4577) @@ -27,6 +27,7 @@ #include #include "util.h" +#include "sysutils.h" From cvs at cvs.gnupg.org Tue Sep 4 09:17:18 2007 From: cvs at cvs.gnupg.org (svn author mo) Date: Tue, 04 Sep 2007 09:17:18 +0200 Subject: [svn] GnuPG - r4578 - trunk/tools Message-ID: Author: mo Date: 2007-09-04 09:16:49 +0200 (Tue, 04 Sep 2007) New Revision: 4578 Modified: trunk/tools/ChangeLog trunk/tools/gpgsm-gencert.sh Log: 2007-09-04 Moritz Schulte * gpgsm-gencert.sh: Use printf instead of echo. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-09-04 05:59:07 UTC (rev 4577) +++ trunk/tools/ChangeLog 2007-09-04 07:16:49 UTC (rev 4578) @@ -1,5 +1,9 @@ 2007-09-04 Moritz Schulte + * gpgsm-gencert.sh: Use printf instead of echo. + +2007-09-04 Moritz Schulte + * gpgkey2ssh.c: Include sysutils.h so that gnupg_tmpfile() is declared. Modified: trunk/tools/gpgsm-gencert.sh =================================================================== --- trunk/tools/gpgsm-gencert.sh 2007-09-04 05:59:07 UTC (rev 4577) +++ trunk/tools/gpgsm-gencert.sh 2007-09-04 07:16:49 UTC (rev 4578) @@ -27,7 +27,7 @@ INPUT FD=$ASSUAN_FP_IN\n\ OUTPUT FD=$ASSUAN_FP_OUT --armor\n\ GENKEY\n\ -BYE" +BYE\n" ANSWER="" @@ -191,7 +191,7 @@ [ "$ANSWER" != "yes" ] && exit 1 -echo -e "$ASSUAN_COMMANDS" | \ +printf "$ASSUAN_COMMANDS" | \ gpgsm --no-log-file --debug-level none --debug-none \ --server 4< "$file_parameter" 5>"$outfile" >/dev/null From cvs at cvs.gnupg.org Tue Sep 4 09:43:13 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 04 Sep 2007 09:43:13 +0200 Subject: [svn] dirmngr - r267 - in trunk: . doc/examples src Message-ID: Author: wk Date: 2007-09-04 09:42:42 +0200 (Tue, 04 Sep 2007) New Revision: 267 Modified: trunk/ChangeLog trunk/configure.ac trunk/doc/examples/Makefile.am trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/get-path.c Log: Small build fixes by Moritz Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/ChangeLog 2007-09-04 07:42:42 UTC (rev 267) @@ -1,3 +1,7 @@ +2007-09-04 Werner Koch + + * configure.ac: Add test for locale.h. + 2007-08-23 Werner Koch * doc/Makefile.am (SUBDIRS): New. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/configure.ac 2007-09-04 07:42:42 UTC (rev 267) @@ -315,7 +315,7 @@ # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([string.h]) +AC_CHECK_HEADERS([string.h locale.h]) # Checks for typedefs, structures, and compiler characteristics. Modified: trunk/doc/examples/Makefile.am =================================================================== --- trunk/doc/examples/Makefile.am 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/doc/examples/Makefile.am 2007-09-04 07:42:42 UTC (rev 267) @@ -1,19 +1,23 @@ -EXTRA_DIST = README dirmngr.conf bnetza-10r-ocsp.signer +doc_exampledir = $(docdir)/examples -EXTRA_DIST += trusted-certs/README \ +dist_doc_example_DATA = README dirmngr.conf bnetza-10r-ocsp.signer + +dist_doc_example_DATA += \ + trusted-certs/README \ trusted-certs/bnetza-10r-ca.crt -EXTRA_DIST += extra-certs/bnetza-10r-ocsp-1.crt \ - extra-certs/bnetza-10r-ocsp-2.crt \ - extra-certs/bnetza-10r-ocsp-3.crt \ - extra-certs/bnetza-10r-ocsp-4.crt \ - extra-certs/bnetza-10r-ocsp-5.crt \ - extra-certs/bnetza-10r-ocsp-6.crt \ - extra-certs/bnetza-10r-ocsp-7.crt \ - extra-certs/bnetza-10r-ocsp-8.crt \ - extra-certs/bnetza-10r-ocsp-9.crt \ - extra-certs/bnetza-10r-ocsp-10.crt \ - extra-certs/bnetza-10r-ocsp-11.crt \ - extra-certs/bnetza-10r-ocsp-12.crt +dist_doc_example_DATA += \ + extra-certs/bnetza-10r-ocsp-1.crt \ + extra-certs/bnetza-10r-ocsp-2.crt \ + extra-certs/bnetza-10r-ocsp-3.crt \ + extra-certs/bnetza-10r-ocsp-4.crt \ + extra-certs/bnetza-10r-ocsp-5.crt \ + extra-certs/bnetza-10r-ocsp-6.crt \ + extra-certs/bnetza-10r-ocsp-7.crt \ + extra-certs/bnetza-10r-ocsp-8.crt \ + extra-certs/bnetza-10r-ocsp-9.crt \ + extra-certs/bnetza-10r-ocsp-10.crt \ + extra-certs/bnetza-10r-ocsp-11.crt \ + extra-certs/bnetza-10r-ocsp-12.crt Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/src/ChangeLog 2007-09-04 07:42:42 UTC (rev 267) @@ -1,3 +1,10 @@ +2007-08-27 Moritz Schulte + + * src/Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SOCKETDIR based on + $(localstatedir). + * src/get-path.c (default_socket_name): Use DIRMNGR_SOCKETDIR + instead of hard-coded "/var/run/dirmngr". + 2007-08-16 Werner Koch * get-path.c (get_dirmngr_ldap_path): Make PATHNAME const. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/src/Makefile.am 2007-09-04 07:42:42 UTC (rev 267) @@ -33,6 +33,7 @@ AM_CPPFLAGS += -DDIRMNGR_LIBEXECDIR="\"$(libexecdir)\"" AM_CPPFLAGS += -DDIRMNGR_DATADIR="\"$(localstatedir)/lib/@PACKAGE@\"" AM_CPPFLAGS += -DDIRMNGR_CACHEDIR="\"$(localstatedir)/cache/@PACKAGE@\"" +AM_CPPFLAGS += -DDIRMNGR_SOCKETDIR="\"$(localstatedir)/run/@PACKAGE@\"" AM_CFLAGS = -I$(top_srcdir)/jnlib $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) \ $(KSBA_CFLAGS) $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS) Modified: trunk/src/get-path.c =================================================================== --- trunk/src/get-path.c 2007-08-23 09:56:16 UTC (rev 266) +++ trunk/src/get-path.c 2007-09-04 07:42:42 UTC (rev 267) @@ -517,6 +517,6 @@ } return name; #else /*!HAVE_W32_SYSTEM*/ - return "/var/run/dirmngr/socket"; + return DIRMNGR_SOCKETDIR "/socket"; #endif /*!HAVE_W32_SYSTEM*/ } From cvs at cvs.gnupg.org Tue Sep 4 18:07:32 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 04 Sep 2007 18:07:32 +0200 Subject: [svn] GpgEX - r10 - in trunk: . m4 po src Message-ID: Author: marcus Date: 2007-09-04 18:07:02 +0200 (Tue, 04 Sep 2007) New Revision: 10 Added: trunk/m4/gpg-error.m4 trunk/m4/libassuan.m4 trunk/src/client.cc trunk/src/client.h Modified: trunk/ChangeLog trunk/configure.ac trunk/po/POTFILES.in trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/gpgex.cc trunk/src/main.cc trunk/src/main.h Log: 2007-09-04 Marcus Brinkmann * m4/libassuan.m4, m4/gpg-error.m4: New files. * configure.ac: Check for libgpg-error and libassuan. * po/POTFILES.in: Add src/client.cc, src/gpgex.h and src/gpgex.cc. src/ 2007-09-04 Marcus Brinkmann * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Remove $(GPGME_CFLAGS), add $(LIBASSUAN_CFLAGS) and $(GPG_ERROR_CFLAGS). (gpgex_SOURCES): Add client.h and client.cc. (libgpg-error.a, libassuan.a, clean-local): New targets. (gpgex_LDADD): Add ./libassuan.a and ./libgpg-error.a. * client.h, client.cc: New files. * gpgex.cc: Include client.h. (gpgex_t::InvokeCommand): Use client class to implement bunch of functionality. * main.h: Include . (DEBUG_ASSUAN, REGKEY, TRACE_GPGERR): New macros. * main.cc: Include and . (REGKEY): Deleted. (debug_init): Free filename and add DEBUG_ASSUAN to debug flags. (DllMain): Set assuan log stream and prefix, and the error source. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/ChangeLog 2007-09-04 16:07:02 UTC (rev 10) @@ -1,3 +1,9 @@ +2007-09-04 Marcus Brinkmann + + * m4/libassuan.m4, m4/gpg-error.m4: New files. + * configure.ac: Check for libgpg-error and libassuan. + * po/POTFILES.in: Add src/client.cc, src/gpgex.h and src/gpgex.cc. + 2007-09-03 Marcus Brinkmann * m4/Makefile.am (EXTRA_DIST): Remove gpgme.m4 and gpg-error.m4. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/configure.ac 2007-09-04 16:07:02 UTC (rev 10) @@ -29,6 +29,11 @@ PACKAGE_GT=${PACKAGE_NAME} VERSION=$PACKAGE_VERSION +NEED_GPG_ERROR_VERSION=1.4 + +NEED_LIBASSUAN_API=1 +NEED_LIBASSUAN_VERSION=0.9.3 + AC_CONFIG_SRCDIR(src/gpgex.def) AM_CONFIG_HEADER(config.h) AC_CANONICAL_TARGET @@ -36,6 +41,9 @@ AC_GNU_SOURCE +have_gpg_error=no +have_libassuan=no + AC_SUBST(PACKAGE) AC_SUBST(PACKAGE_GT) AC_SUBST(VERSION) @@ -169,12 +177,52 @@ AC_SUBST(W32LIBS) +# +# libgpg-error is a library with error codes shared between GnuPG +# related projects. +# +AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", + have_gpg_error=yes,have_gpg_error=no) +AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_USER_1, + [The default error source for GpgEX.]) # +# libassuan is used for IPC +# +AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION", + have_libassuan=yes,have_libassuan=no) + + +AH_BOTTOM([ +/* We don't want the old assuan codes anymore. */ +#define _ASSUAN_ONLY_GPG_ERRORS 1 +]) + +# # Print errors here so that they are visible all # together and the user can acquire them all together. # die=no +if test "$have_gpg_error" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libgpg-error to build this program. +** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/libgpg-error +*** (at least version $NEED_GPG_ERROR_VERSION is required.) +***]]) +fi +if test "$have_libassuan" = "no"; then + die=yes + AC_MSG_NOTICE([[ +*** +*** You need libassuan to build this program. +*** This library is for example available at +*** ftp://ftp.gnupg.org/pub/gcrypt/libassuan/ +*** (at least version $NEED_LIBASSUAN_VERSION is required). +***]]) +fi if test "$die" = "yes"; then AC_MSG_ERROR([[ *** Added: trunk/m4/gpg-error.m4 =================================================================== --- trunk/m4/gpg-error.m4 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/m4/gpg-error.m4 2007-09-04 16:07:02 UTC (rev 10) @@ -0,0 +1,56 @@ +dnl Autoconf macros for libgpg-error + +dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpg-error and define GPG_ERROR_CFLAGS and GPG_ERROR_LIBS +dnl +AC_DEFUN([AM_PATH_GPG_ERROR], +[ AC_ARG_WITH(gpg-error-prefix, + AC_HELP_STRING([--with-gpg-error-prefix=PFX], + [prefix where GPG Error is installed (optional)]), + gpg_error_config_prefix="$withval", gpg_error_config_prefix="") + if test x$gpg_error_config_prefix != x ; then + if test x${GPG_ERROR_CONFIG+set} != xset ; then + GPG_ERROR_CONFIG=$gpg_error_config_prefix/bin/gpg-error-config + fi + fi + + AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) + min_gpg_error_version=ifelse([$1], ,0.0,$1) + AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) + ok=no + if test "$GPG_ERROR_CONFIG" != "no" ; then + req_major=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpg_error_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` + major=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + minor=`echo $gpg_error_config_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + if test "$major" -gt "$req_major"; then + ok=yes + else + if test "$major" -eq "$req_major"; then + if test "$minor" -ge "$req_minor"; then + ok=yes + fi + fi + fi + fi + if test $ok = yes; then + GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` + GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + GPG_ERROR_CFLAGS="" + GPG_ERROR_LIBS="" + AC_MSG_RESULT(no) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPG_ERROR_CFLAGS) + AC_SUBST(GPG_ERROR_LIBS) +]) + Added: trunk/m4/libassuan.m4 =================================================================== --- trunk/m4/libassuan.m4 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/m4/libassuan.m4 2007-09-04 16:07:02 UTC (rev 10) @@ -0,0 +1,175 @@ +dnl Autoconf macros for libassuan +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. +dnl +dnl This file is free software; as a special exception the author gives +dnl unlimited permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl +dnl This file is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +dnl +dnl Common code used for libassuan detection [internal] +dnl Returns ok set to yes or no. +dnl +AC_DEFUN([_AM_PATH_LIBASSUAN_COMMON], +[ AC_ARG_WITH(libassuan-prefix, + AC_HELP_STRING([--with-libassuan-prefix=PFX], + [prefix where LIBASSUAN is installed (optional)]), + libassuan_config_prefix="$withval", libassuan_config_prefix="") + if test x$libassuan_config_prefix != x ; then + libassuan_config_args="$libassuan_config_args --prefix=$libassuan_config_prefix" + if test x${LIBASSUAN_CONFIG+set} != xset ; then + LIBASSUAN_CONFIG=$libassuan_config_prefix/bin/libassuan-config + fi + fi + AC_PATH_PROG(LIBASSUAN_CONFIG, libassuan-config, no) + + tmp=ifelse([$1], ,1:0.9.2,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libassuan_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libassuan_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libassuan_api=0 + min_libassuan_version="$tmp" + fi + + if test "$LIBASSUAN_CONFIG" != "no" ; then + libassuan_version=`$LIBASSUAN_CONFIG --version` + fi + libassuan_version_major=`echo $libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + libassuan_version_minor=`echo $libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + libassuan_version_micro=`echo $libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + + AC_MSG_CHECKING(for LIBASSUAN ifelse([$2], ,,[$2 ])- version >= $min_libassuan_version) + ok=no + if test "$LIBASSUAN_CONFIG" != "no" ; then + ifelse([$2], ,,[if `$LIBASSUAN_CONFIG --thread=$2 2> /dev/null` ; then]) + req_major=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_libassuan_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$libassuan_version_major" -gt "$req_major"; then + ok=yes + else + if test "$libassuan_version_major" -eq "$req_major"; then + if test "$libassuan_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$libassuan_version_minor" -eq "$req_minor"; then + if test "$libassuan_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + ifelse([$2], ,,[fi]) + fi + + if test $ok = yes; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + + if test $ok = yes; then + if test "$req_libassuan_api" -gt 0 ; then + tmp=`$LIBASSUAN_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + AC_MSG_CHECKING([LIBASSUAN ifelse([$2], ,,[$2 ])API version]) + if test "$req_libassuan_api" -eq "$tmp" ; then + AC_MSG_RESULT(okay) + else + ok=no + AC_MSG_RESULT([does not match. want=$req_libassuan_api got=$tmp.]) + fi + fi + fi + fi + +]) + +dnl AM_CHECK_LIBASSUAN([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test whether libassuan has at least MINIMUM-VERSION. This is +dnl used to test for features only available in newer versions. +dnl +AC_DEFUN([AM_CHECK_LIBASSUAN], +[ _AM_PATH_LIBASSUAN_COMMON($1) + if test $ok = yes; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , :, [$3]) + fi +]) + + + + +dnl AM_PATH_LIBASSUAN([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libassuan and define LIBASSUAN_CFLAGS and LIBASSUAN_LIBS +dnl +AC_DEFUN([AM_PATH_LIBASSUAN], +[ _AM_PATH_LIBASSUAN_COMMON($1) + if test $ok = yes; then + LIBASSUAN_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --cflags` + LIBASSUAN_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --libs` + ifelse([$2], , :, [$2]) + else + LIBASSUAN_CFLAGS="" + LIBASSUAN_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBASSUAN_CFLAGS) + AC_SUBST(LIBASSUAN_LIBS) +]) + + +dnl AM_PATH_LIBASSUAN_PTH([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libassuan and define LIBASSUAN_PTH_CFLAGS and LIBASSUAN_PTH_LIBS +dnl +AC_DEFUN([AM_PATH_LIBASSUAN_PTH], +[ _AM_PATH_LIBASSUAN_COMMON($1,pth) + if test $ok = yes; then + LIBASSUAN_PTH_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --cflags` + LIBASSUAN_PTH_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pth --libs` + ifelse([$2], , :, [$2]) + else + LIBASSUAN_PTH_CFLAGS="" + LIBASSUAN_PTH_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBASSUAN_PTH_CFLAGS) + AC_SUBST(LIBASSUAN_PTH_LIBS) +]) + + +dnl AM_PATH_LIBASSUAN_PTHREAD([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libassuan and define LIBASSUAN_PTHREAD_CFLAGS +dnl and LIBASSUAN_PTHREAD_LIBS +dnl +AC_DEFUN([AM_PATH_LIBASSUAN_PTHREAD], +[ _AM_PATH_LIBASSUAN_COMMON($1,pthread) + if test $ok = yes; then + LIBASSUAN_PTHREAD_CFLAGS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --cflags` + LIBASSUAN_PTHREAD_LIBS=`$LIBASSUAN_CONFIG $libassuan_config_args --thread=pthread --libs` + ifelse([$2], , :, [$2]) + else + LIBASSUAN_PTHREAD_CFLAGS="" + LIBASSUAN_PTHREAD_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(LIBASSUAN_PTHREAD_CFLAGS) + AC_SUBST(LIBASSUAN_PTHREAD_LIBS) +]) + Modified: trunk/po/POTFILES.in =================================================================== --- trunk/po/POTFILES.in 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/po/POTFILES.in 2007-09-04 16:07:02 UTC (rev 10) @@ -1 +1,4 @@ src/main.cc +src/client.cc +src/gpgex.h +src/gpgex.cc Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/ChangeLog 2007-09-04 16:07:02 UTC (rev 10) @@ -1,3 +1,21 @@ +2007-09-04 Marcus Brinkmann + + * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Remove $(GPGME_CFLAGS), + add $(LIBASSUAN_CFLAGS) and $(GPG_ERROR_CFLAGS). + (gpgex_SOURCES): Add client.h and client.cc. + (libgpg-error.a, libassuan.a, clean-local): New targets. + (gpgex_LDADD): Add ./libassuan.a and ./libgpg-error.a. + * client.h, client.cc: New files. + * gpgex.cc: Include client.h. + (gpgex_t::InvokeCommand): Use client class to implement bunch of + functionality. + * main.h: Include . + (DEBUG_ASSUAN, REGKEY, TRACE_GPGERR): New macros. + * main.cc: Include and . + (REGKEY): Deleted. + (debug_init): Free filename and add DEBUG_ASSUAN to debug flags. + (DllMain): Set assuan log stream and prefix, and the error source. + 2007-09-03 Marcus Brinkmann * bitmaps.h, bitmaps.cc, icons.rc, icon-key-12.bmp, Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/Makefile.am 2007-09-04 16:07:02 UTC (rev 10) @@ -15,8 +15,8 @@ EXTRA_DIST = versioninfo.rc.in EXEEXT = .dll -AM_CFLAGS = $(GPGME_CFLAGS) -shared -AM_CXXFLAGS = $(GPGME_CFLAGS) -shared +AM_CFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) -shared +AM_CXXFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) -shared nodist_gpgex_SOURCES = versioninfo.rc gpgex_SOURCES = \ @@ -28,12 +28,24 @@ gpgex-factory.h gpgex-factory.cc \ bitmaps.h bitmaps.cc \ gpgex.h gpgex.cc \ + client.h client.cc \ main.h main.cc #gpgex_LDADD = $(srcdir)/gpgex.def \ # -L . -lshell32 -lcomdlg32 -loleaut32 -ladvapi32 + +libgpg-error.a: + ln -s $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a + +libassuan.a: + ln -s $(shell $(LIBASSUAN_CONFIG) --prefix)/lib/libassuan.a + +clean-local: + rm -f libgpg-error.a libassuan.a + gpgex_LDADD = $(srcdir)/gpgex.def -L . \ - -lshell32 -lgdi32 -lws2_32 -lole32 -luuid + -lshell32 -lgdi32 -lws2_32 -lole32 -luuid \ + ./libassuan.a ./libgpg-error.a .rc.o: $(WINDRES) -I $(srcdir) -I . `test -f '$<' || echo '$(srcdir)/'`$< $@ Added: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/client.cc 2007-09-04 16:07:02 UTC (rev 10) @@ -0,0 +1,161 @@ +/* client.cc - gpgex assuan client implementation + Copyright (C) 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX 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 of the License, or (at your option) any later version. + + GpgEX 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 +#endif + +#include +#include +#include + +using std::vector; +using std::string; + +#include + +#include + +#include "registry.h" +#include "main.h" + +#include "client.h" + + +static const char * +default_socket_name (void) +{ + static string name; + + if (name.size() == 0) + { + char *dir = NULL; + + /* FIXME: Wrong directory. */ + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + "Install Directory"); + if (dir) + { + try { name = ((string) dir) + "\\S.kleopatra"; } catch (...) {} + free ((void *) dir); + } + } + + return name.c_str (); +} + + +bool +client_t::call_assuan (const char *cmd, vector &filenames) +{ + int rc = 0; + assuan_context_t ctx = NULL; + const char *socket_name; + string msg; + + TRACE_BEG2 (DEBUG_ASSUAN, "client_t::call_assuan", this, + "%s on %u files", cmd, filenames.size ()); + + socket_name = default_socket_name (); + if (! socket_name || ! *socket_name) + { + (void) TRACE_LOG ("invalid socket name"); + rc = gpg_error (GPG_ERR_INV_ARG); + goto leave; + } + + (void) TRACE_LOG1 ("socket name: %s", socket_name); + rc = assuan_socket_connect (&ctx, socket_name, -1); + if (rc) + goto leave; + + try + { + /* Set the input files. FIXME: Might need to set the output files + as well. */ + for (unsigned int i = 0; i < filenames.size (); i++) + { + msg = "INPUT FILE=\"" + filenames[i] + "\" --continued"; + + (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); + + rc = assuan_transact (ctx, msg.c_str (), + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + goto leave; + } + + /* Set the --nohup option, so that the operation continues and + completes in the background. */ + msg = "OPTION --nohup"; + (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); + rc = assuan_transact (ctx, msg.c_str (), + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + goto leave; + + msg = cmd; + (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); + rc = assuan_transact (ctx, msg.c_str (), + NULL, NULL, NULL, NULL, NULL, NULL); + } + catch (std::bad_alloc) + { + rc = gpg_error (GPG_ERR_ENOMEM); + } + catch (...) + { + rc = gpg_error (GPG_ERR_GENERAL); + } + + /* Fall-through. */ + leave: + TRACE_GPGERR (rc); + if (ctx) + assuan_disconnect (ctx); + if (rc) + { + MessageBox (this->window, + _("Can not access Kleopatra, see log file for details"), + "GpgEX", MB_ICONINFORMATION); + } + + return rc ? false : true; +} + + +void +client_t::decrypt_verify (vector &filenames) +{ + this->call_assuan ("DECRYPT_VERIFY", filenames); +} + + +void +client_t::encrypt_sign (vector &filenames) +{ + this->call_assuan ("ENCRPYT_SIGN", filenames); +} + +void +client_t::import (vector &filenames) +{ + this->call_assuan ("IMPORT", filenames); +} Added: trunk/src/client.h =================================================================== --- trunk/src/client.h 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/client.h 2007-09-04 16:07:02 UTC (rev 10) @@ -0,0 +1,50 @@ +/* client.h - gpgex assuan client interface + Copyright (C) 2007 g10 Code GmbH + + This file is part of GpgEX. + + GpgEX 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 of the License, or (at your option) any later version. + + GpgEX 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 CLIENT_H +#define CLIENT_H + +#include +#include + +using std::vector; +using std::string; + +#include + +class client_t +{ + private: + HWND window; + + bool call_assuan (const char *cmd, vector &filenames); + + public: + client_t (HWND window_handle) + : window (window_handle) + { + } + + void decrypt_verify (vector &filenames); + void encrypt_sign (vector &filenames); + void import (vector &filenames); +}; + +#endif /* ! CLIENT_H */ Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/gpgex.cc 2007-09-04 16:07:02 UTC (rev 10) @@ -32,6 +32,7 @@ #include #include "main.h" +#include "client.h" #include "gpgex.h" @@ -350,9 +351,7 @@ STDMETHODIMP gpgex_t::InvokeCommand (LPCMINVOKECOMMANDINFO lpcmi) { - string cmd; - - TRACE_BEG1 (DEBUG_CONTEXT_MENU, "gpgex_t::GetCommandString", this, + TRACE_BEG1 (DEBUG_CONTEXT_MENU, "gpgex_t::InvokeCommand", this, "lpcmi=%p", lpcmi); /* If lpVerb really points to a string, ignore this function call @@ -360,38 +359,38 @@ if (HIWORD (lpcmi->lpVerb) != 0) return TRACE_RES (E_INVALIDARG); + client_t client (lpcmi->hwnd); + /* Get the command index, which is the offset to IDCMDFIRST of QueryContextMenu, ie zero based). */ switch (LOWORD (lpcmi->lpVerb)) { case ID_CMD_HELP: - cmd = "HELP"; + { + string msg; + unsigned int i; + + msg = "Invoked Help on files:\n\n"; + for (i = 0; i < this->filenames.size (); i++) + msg = msg + this->filenames[i] + '\n'; + + MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); + } break; case ID_CMD_VERIFY_DECRYPT: - cmd = "VERIFY_DECRYPT"; + client.decrypt_verify (this->filenames); break; case ID_CMD_SIGN_ENCRYPT: - cmd = "SIGN_ENCRYPT"; + client.encrypt_sign (this->filenames); break; case ID_CMD_IMPORT: - cmd = "IMPORT"; + client.import (this->filenames); break; default: return TRACE_RES (E_INVALIDARG); break; } - /* FIXME: Need to send commands to Kleopatra. */ - - string msg; - unsigned int i; - - msg = "Invoked " + cmd + "on files:\n\n"; - for (i = 0; i < this->filenames.size (); i++) - msg = msg + this->filenames[i] + '\n'; - - MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); - return TRACE_RES (S_OK); } Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/main.cc 2007-09-04 16:07:02 UTC (rev 10) @@ -26,6 +26,9 @@ #include #include +#include +#include + #include "registry.h" #include "gpgex-class.h" #include "gpgex-factory.h" @@ -42,10 +45,6 @@ LONG gpgex_server::refcount; -/* Registry key for this software. */ -#define REGKEY "Software\\GNU\\GnuPG" - - static char * get_locale_dir (void) { @@ -141,11 +140,12 @@ return; debug_file = fopen (filename, "a"); + free (filename); if (!debug_file) return; /* FIXME: Make this configurable eventually. */ - debug_flags = DEBUG_INIT | DEBUG_CONTEXT_MENU; + debug_flags = DEBUG_INIT | DEBUG_CONTEXT_MENU | DEBUG_ASSUAN; } @@ -198,6 +198,13 @@ debug_init (); + if (debug_flags & DEBUG_ASSUAN) + { + assuan_set_assuan_log_stream (debug_file); + assuan_set_assuan_log_prefix ("gpgex:assuan"); + } + assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT); + (void) TRACE0 (DEBUG_INIT, "DllMain", hinst, "reason=DLL_PROCESS_ATTACH"); } Modified: trunk/src/main.h =================================================================== --- trunk/src/main.h 2007-09-03 21:51:34 UTC (rev 9) +++ trunk/src/main.h 2007-09-04 16:07:02 UTC (rev 10) @@ -23,12 +23,18 @@ #include +#include + #include "w32-gettext.h" #define _(a) gettext (a) #define N_(a) gettext_noop (a) +/* Registry key for this software. */ +#define REGKEY "Software\\GNU\\GnuPG" + + /* We use a class just for namespace cleanliness. */ class gpgex_server { @@ -63,6 +69,7 @@ #define DEBUG_INIT 1 #define DEBUG_CONTEXT_MENU 2 +#define DEBUG_ASSUAN 4 #define STRINGIFY(v) #v @@ -163,6 +170,13 @@ name, STRINGIFY (tag), (void *) tag, arg1, arg2, arg3, \ arg4, arg5, arg6), 0) +#define TRACE_GPGERR(err) \ + err == 0 ? (TRACE_SUC ()) : \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): error: %s <%s>\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, gpg_strerror (err), \ + gpg_strsource (err)), (err)) + #define TRACE_RES(err) \ err == S_OK ? (TRACE_SUC ()) : \ (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): %s: ec=%x\n", \ From cvs at cvs.gnupg.org Wed Sep 5 16:24:47 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 05 Sep 2007 16:24:47 +0200 Subject: [svn] GpgEX - r11 - trunk/src Message-ID: Author: marcus Date: 2007-09-05 16:24:18 +0200 (Wed, 05 Sep 2007) New Revision: 11 Modified: trunk/src/ChangeLog trunk/src/Makefile.am Log: 2007-09-05 Marcus Brinkmann * Makefile.am (gpgex_LDADD): More -lws2_32 after ./libassuan.a. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-04 16:07:02 UTC (rev 10) +++ trunk/src/ChangeLog 2007-09-05 14:24:18 UTC (rev 11) @@ -1,3 +1,7 @@ +2007-09-05 Marcus Brinkmann + + * Makefile.am (gpgex_LDADD): More -lws2_32 after ./libassuan.a. + 2007-09-04 Marcus Brinkmann * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Remove $(GPGME_CFLAGS), Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-04 16:07:02 UTC (rev 10) +++ trunk/src/Makefile.am 2007-09-05 14:24:18 UTC (rev 11) @@ -44,8 +44,8 @@ rm -f libgpg-error.a libassuan.a gpgex_LDADD = $(srcdir)/gpgex.def -L . \ - -lshell32 -lgdi32 -lws2_32 -lole32 -luuid \ - ./libassuan.a ./libgpg-error.a + -lshell32 -lgdi32 -lole32 -luuid \ + ./libassuan.a ./libgpg-error.a -lws2_32 .rc.o: $(WINDRES) -I $(srcdir) -I . `test -f '$<' || echo '$(srcdir)/'`$< $@ From cvs at cvs.gnupg.org Wed Sep 5 16:37:15 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 05 Sep 2007 16:37:15 +0200 Subject: [svn] GpgEX - r12 - trunk/src Message-ID: Author: marcus Date: 2007-09-05 16:36:45 +0200 (Wed, 05 Sep 2007) New Revision: 12 Modified: trunk/src/ChangeLog trunk/src/Makefile.am Log: 2007-09-05 Marcus Brinkmann * Makefile.am (ICON_NAMES, ICON_SIZES, ICONS): New variables. (gpgex_SOURCES): Add $(ICONS). Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-05 14:24:18 UTC (rev 11) +++ trunk/src/ChangeLog 2007-09-05 14:36:45 UTC (rev 12) @@ -1,6 +1,10 @@ 2007-09-05 Marcus Brinkmann + * Makefile.am (ICON_NAMES, ICON_SIZES, ICONS): New variables. + (gpgex_SOURCES): Add $(ICONS). + * Makefile.am (gpgex_LDADD): More -lws2_32 after ./libassuan.a. + 2007-09-04 Marcus Brinkmann Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-05 14:24:18 UTC (rev 11) +++ trunk/src/Makefile.am 2007-09-05 14:36:45 UTC (rev 12) @@ -18,6 +18,11 @@ AM_CFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) -shared AM_CXXFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) -shared +ICON_NAMES = key +ICON_SIZES = 12 16 +ICONS = $(addprefix icon-, \ + $(foreach size,$(ICON_SIZES),$(addsuffix -$(size).bmp, $(ICON_NAMES)))) + nodist_gpgex_SOURCES = versioninfo.rc gpgex_SOURCES = \ gpgex.def \ @@ -29,7 +34,8 @@ bitmaps.h bitmaps.cc \ gpgex.h gpgex.cc \ client.h client.cc \ - main.h main.cc + main.h main.cc \ + $(ICONS) #gpgex_LDADD = $(srcdir)/gpgex.def \ # -L . -lshell32 -lcomdlg32 -loleaut32 -ladvapi32 From cvs at cvs.gnupg.org Wed Sep 5 16:42:12 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 05 Sep 2007 16:42:12 +0200 Subject: [svn] GpgEX - r13 - trunk/src Message-ID: Author: marcus Date: 2007-09-05 16:41:42 +0200 (Wed, 05 Sep 2007) New Revision: 13 Modified: trunk/src/ChangeLog trunk/src/gpgex.h Log: 2007-09-05 Marcus Brinkmann * gpgex.h (class gpgex_t): Make destructor virtual to silence compiler warning. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-05 14:36:45 UTC (rev 12) +++ trunk/src/ChangeLog 2007-09-05 14:41:42 UTC (rev 13) @@ -1,5 +1,8 @@ 2007-09-05 Marcus Brinkmann + * gpgex.h (class gpgex_t): Make destructor virtual to silence + compiler warning. + * Makefile.am (ICON_NAMES, ICON_SIZES, ICONS): New variables. (gpgex_SOURCES): Add $(ICONS). Modified: trunk/src/gpgex.h =================================================================== --- trunk/src/gpgex.h 2007-09-05 14:36:45 UTC (rev 12) +++ trunk/src/gpgex.h 2007-09-05 14:41:42 UTC (rev 13) @@ -119,7 +119,8 @@ (void) TRACE_SUC (); } - ~gpgex_t (void) + /* The "virtual" fixes a compile time warning. */ + virtual ~gpgex_t (void) { TRACE_BEG (DEBUG_INIT, "gpgex_t::~gpgex_t", this); From cvs at cvs.gnupg.org Wed Sep 5 18:03:06 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 05 Sep 2007 18:03:06 +0200 Subject: [svn] assuan - r255 - trunk/src Message-ID: Author: marcus Date: 2007-09-05 18:02:37 +0200 (Wed, 05 Sep 2007) New Revision: 255 Modified: trunk/src/ChangeLog trunk/src/assuan-handler.c Log: 2007-09-05 Marcus Brinkmann * assuan-handler.c (dispatch_command): Return non-critical errors with PROCESS_DONE (). Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-03 14:16:40 UTC (rev 254) +++ trunk/src/ChangeLog 2007-09-05 16:02:37 UTC (rev 255) @@ -1,3 +1,8 @@ +2007-09-05 Marcus Brinkmann + + * assuan-handler.c (dispatch_command): Return non-critical errors + with PROCESS_DONE (). + 2007-09-03 Marcus Brinkmann * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames @@ -3,4 +8,9 @@ with _ASSUAN_PREFIX. +2007-09-03 Marcus Brinkmann + + * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames + with _ASSUAN_PREFIX. + * assuan.h (assuan_inquire_ext): Move buffer and buffer_length arguments callback in prototype. Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-09-03 14:16:40 UTC (rev 254) +++ trunk/src/assuan-handler.c 2007-09-05 16:02:37 UTC (rev 255) @@ -434,13 +434,21 @@ const char *s; int shift, i; + /* Note that as this function is invoked by assuan_process_next as + well, we need to hide non-critical errors with PROCESS_DONE. */ + if (*line == 'D' && line[1] == ' ') /* divert to special handler */ - return handle_data_line (ctx, line+2, linelen-2); + /* FIXME: Depending on the final implementation of + handle_data_line, this may be wrong here. For example, if a + user callback is invoked, and that callback is responsible for + calling assuan_process_done, then this is wrong. */ + return PROCESS_DONE (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"); + return PROCESS_DONE + (ctx, set_error (ctx, Syntax_Error, "leading white-space")); if (*p) { /* Skip over leading WS after the keyword */ *p++ = 0; @@ -463,7 +471,7 @@ } } if (!s) - return set_error (ctx, Unknown_Command, NULL); + return PROCESS_DONE (ctx, set_error (ctx, Unknown_Command, NULL)); line += shift; linelen -= shift; From cvs at cvs.gnupg.org Fri Sep 7 00:41:44 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 00:41:44 +0200 Subject: [svn] gpgme - r1250 - in trunk: . gpgme m4 Message-ID: Author: marcus Date: 2007-09-07 00:41:11 +0200 (Fri, 07 Sep 2007) New Revision: 1250 Added: trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/kdpipeiodevice.h trunk/gpgme/kdpipeiodevice.moc trunk/gpgme/moc_kdpipeiodevice.cpp trunk/gpgme/w32-qt-io.cpp trunk/m4/pkg.m4 Modified: trunk/ChangeLog trunk/configure.ac trunk/gpgme/ChangeLog trunk/gpgme/Makefile.am trunk/gpgme/gpgme.def trunk/gpgme/posix-sema.c trunk/gpgme/sema.h trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-io.c trunk/gpgme/w32-sema.c Log: 2007-09-07 Marcus Brinkmann * configure.ac: Check for C++, Qt and support --enable-w32-qt. * m4/pkg.m4: New file. gpgme/ 2007-09-07 Marcus Brinkmann * kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp, kdpipeiodevice.moc, w32-qt-io.c: New files. * Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib. (ltlib_gpgme_qt): New variable. (lib_LTLIBRARIES): Add $(ltlib_gpgme_qt). (libgpgme_qt_la_SOURCES): New variable. (AM_CPPFLAGS): Add @QT4_CORE_INCLUDES@ (AM_CFLAGS): Add @QT4_CORE_CFLAGS at . (libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES) (libgpgme_qt_la_LIBADD): New variables. * sema.h (struct critsect_s): Rename "private" to "priv" to make C++ users happy. Change users. * posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave) (_gpgme_sema_cs_destroy): Likewise. * w32-sema.c (critsect_init, _gpgme_sema_cs_enter) (_gpgme_sema_cs_leave, _gpgme_sema_cs_destroy): Likewise. * w32-glib-io.c (gpgme_get_giochannel): Change return type to void*. (gpgme_get_fdptr): New function. * w32-io.c (gpgme_get_fdptr): New function * gpgme.def: Add gpgme_get_fdptr. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/ChangeLog 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,3 +1,8 @@ +2007-09-07 Marcus Brinkmann + + * configure.ac: Check for C++, Qt and support --enable-w32-qt. + * m4/pkg.m4: New file. + 2007-08-21 Marcus Brinkmann * configure.ac (--enable-w32-glib): Use --enableval, not @@ -775,7 +780,7 @@ * autogen.sh: Added option --build-w32. - Copyright 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/configure.ac 2007-09-06 22:41:11 UTC (rev 1250) @@ -83,6 +83,7 @@ #endif]) AC_PROG_CC +AC_PROG_CXX AC_SUBST(LIBGPGME_LT_CURRENT) AC_SUBST(LIBGPGME_LT_AGE) @@ -162,6 +163,13 @@ build_w32_glib=$enableval) AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes) +build_w32_qt=no +PKG_CHECK_MODULES(QT4_CORE, QtCore) +AC_ARG_ENABLE(w32-qt, + AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]), + build_w32_qt=$enableval) +AM_CONDITIONAL(BUILD_W32_QT, test "$build_w32_qt" = yes) + AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes") Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/ChangeLog 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,3 +1,27 @@ +2007-09-07 Marcus Brinkmann + + * kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp, + kdpipeiodevice.moc, w32-qt-io.c: New files. + * Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib. + (ltlib_gpgme_qt): New variable. + (lib_LTLIBRARIES): Add $(ltlib_gpgme_qt). + (libgpgme_qt_la_SOURCES): New variable. + (AM_CPPFLAGS): Add @QT4_CORE_INCLUDES@ + (AM_CFLAGS): Add @QT4_CORE_CFLAGS at . + (libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES) + (libgpgme_qt_la_LIBADD): New variables. + * sema.h (struct critsect_s): Rename "private" to "priv" to make + C++ users happy. Change users. + * posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave) + (_gpgme_sema_cs_destroy): Likewise. + * w32-sema.c (critsect_init, _gpgme_sema_cs_enter) + (_gpgme_sema_cs_leave, _gpgme_sema_cs_destroy): Likewise. + * w32-glib-io.c (gpgme_get_giochannel): Change return type to + void*. + (gpgme_get_fdptr): New function. + * w32-io.c (gpgme_get_fdptr): New function + * gpgme.def: Add gpgme_get_fdptr. + 2007-08-22 Marcus Brinkmann * w32-io.c (_gpgme_io_write): Return early if COUNT is zero. Modified: trunk/gpgme/Makefile.am =================================================================== --- trunk/gpgme/Makefile.am 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/Makefile.am 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,5 +1,5 @@ # Copyright (C) 2000 Werner Koch (dd9jn) -# Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH # # This file is part of GPGME. # @@ -40,12 +40,18 @@ endif if BUILD_W32_GLIB -ltlib_gpgme_extra = libgpgme-glib.la +ltlib_gpgme_glib = libgpgme-glib.la else -ltlib_gpgme_extra = +ltlib_gpgme_glib = endif -lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_extra) \ +if BUILD_W32_QT +ltlib_gpgme_qt = libgpgme-qt.la +else +ltlib_gpgme_qt = +endif + +lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \ $(ltlib_gpgme_pthread) $(ltlib_gpgme_pth) if HAVE_LD_VERSION_SCRIPT @@ -107,10 +113,24 @@ libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c endif +if BUILD_W32_QT +libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \ + kdpipeiodevice.h kdpipeiodevice.cpp moc_kdpipeiodevice.cpp \ + kdpipeiodevice.moc + +# These are built sources (normally). +# moc_kdpipeiodevice.cpp: kdpipeiodevice.h +# $(MOC4) -o $@ $< +# +# kdpipeiodevice.moc: kdpipeiodevice.cpp +# $(MOC4) -o $@ $< +endif + # We use a global CFLAGS and CPPFLAGS setting for all library # versions, because then every object file is only compiled once. -AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ -AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ +AM_CPPFLAGS = $(assuan_cppflags) @GPG_ERROR_CFLAGS@ @PTH_CPPFLAGS@ \ + @QT4_CORE_CFLAGS@ +AM_CFLAGS = @PTH_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@ if HAVE_W32_SYSTEM @@ -181,6 +201,16 @@ @GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@ endif +if BUILD_W32_QT +libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \ + $(export_symbols) $(libgpgme_version_script_cmd) -version-info \ + @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@ +libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \ + @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps) +libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ + @GPG_ERROR_LIBS@ @QT4_CORE_LIB@ @NETLIBS@ +endif + status-table.h : gpgme.h $(srcdir)/mkstatus < $(srcdir)/gpgme.h > status-table.h Modified: trunk/gpgme/gpgme.def =================================================================== --- trunk/gpgme/gpgme.def 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/gpgme.def 2007-09-06 22:41:11 UTC (rev 1250) @@ -154,5 +154,7 @@ gpgme_free @120 gpgme_get_giochannel @121 + gpgme_get_fdptr @122 + ; END Added: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,760 @@ +/* + Copyright (C) 2007 Klar?lvdalens Datakonsult AB + + KDPipeIODevice 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. + + KDPipeIODevice 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 KDPipeIODevice; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kdpipeiodevice.h" + +#include + +#include +#include +#include + +#ifdef Q_OS_WIN32 +# define NOMINMAX +# include +# include +#else +# include +# include +#endif + +#ifndef KDAB_CHECK_THIS +# define KDAB_CHECK_CTOR (void)1 +# define KDAB_CHECK_DTOR KDAB_CHECK_CTOR +# define KDAB_CHECK_THIS KDAB_CHECK_CTOR +#endif + +#define LOCKED( d ) const QMutexLocker locker( &d->mutex ) +#define synchronized( d ) if ( int i = 0 ) {} else for ( const QMutexLocker locker( &d->mutex ) ; !i ; ++i ) + +const unsigned int BUFFER_SIZE = 4096; +const bool ALLOW_QIODEVICE_BUFFERING = true; + +// comment to get trace output: +#define qDebug if(1){}else qDebug + +namespace { +class Reader : public QThread { + Q_OBJECT +public: + Reader( int fd, Qt::HANDLE handle ); + ~Reader(); + + qint64 readData( char * data, qint64 maxSize ); + + unsigned int bytesInBuffer() const { + return ( wptr + sizeof buffer - rptr ) % sizeof buffer ; + } + + bool bufferFull() const { + return bytesInBuffer() == sizeof buffer - 1; + } + + bool bufferEmpty() const { + return bytesInBuffer() == 0; + } + + bool bufferContains( char ch ) { + const unsigned int bib = bytesInBuffer(); + for ( unsigned int i = rptr ; i < rptr + bib ; ++i ) + if ( buffer[i%sizeof buffer] == ch ) + return true; + return false; + } + +Q_SIGNALS: + void readyRead(); + +protected: + /* reimp */ void run(); + +private: + int fd; + Qt::HANDLE handle; +public: + QMutex mutex; + QWaitCondition bufferNotFullCondition; + QWaitCondition bufferNotEmptyCondition; + QWaitCondition hasStarted; + bool cancel; + bool eof; + bool error; + bool eofShortCut; + int errorCode; +private: + unsigned int rptr, wptr; + char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state +}; + + +Reader::Reader( int fd_, Qt::HANDLE handle_ ) + : QThread(), + fd( fd_ ), + handle( handle_ ), + mutex(), + bufferNotFullCondition(), + bufferNotEmptyCondition(), + hasStarted(), + cancel( false ), + eof( false ), + error( false ), + eofShortCut( false ), + errorCode( 0 ), + rptr( 0 ), wptr( 0 ) +{ + +} + +Reader::~Reader() {} + + +class Writer : public QThread { + Q_OBJECT +public: + Writer( int fd, Qt::HANDLE handle ); + ~Writer(); + + qint64 writeData( const char * data, qint64 size ); + + unsigned int bytesInBuffer() const { return numBytesInBuffer; } + + bool bufferFull() const { + return numBytesInBuffer == sizeof buffer; + } + + bool bufferEmpty() const { + return numBytesInBuffer == 0; + } + +Q_SIGNALS: + void bytesWritten( qint64 ); + +protected: + /* reimp */ void run(); + +private: + int fd; + Qt::HANDLE handle; +public: + QMutex mutex; + QWaitCondition bufferEmptyCondition; + QWaitCondition bufferNotEmptyCondition; + QWaitCondition hasStarted; + bool cancel; + bool error; + int errorCode; +private: + unsigned int numBytesInBuffer; + char buffer[BUFFER_SIZE]; +}; +} + +Writer::Writer( int fd_, Qt::HANDLE handle_ ) + : QThread(), + fd( fd_ ), + handle( handle_ ), + mutex(), + bufferEmptyCondition(), + bufferNotEmptyCondition(), + hasStarted(), + cancel( false ), + error( false ), + errorCode( 0 ), + numBytesInBuffer( 0 ) +{ + +} + +Writer::~Writer() {} + + +class KDPipeIODevice::Private { + friend class ::KDPipeIODevice; + KDPipeIODevice * const q; +public: + explicit Private( KDPipeIODevice * qq ); + ~Private(); + + bool doOpen( int, Qt::HANDLE, OpenMode ); + +private: + int fd; + Qt::HANDLE handle; + Reader * reader; + Writer * writer; +}; + +KDPipeIODevice::Private::Private( KDPipeIODevice * qq ) + : q( qq ), + fd( -1 ), + handle( 0 ), + reader( 0 ), + writer( 0 ) +{ + +} + + +KDPipeIODevice::Private::~Private() {} + + +KDPipeIODevice::KDPipeIODevice( QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; +} + +KDPipeIODevice::KDPipeIODevice( int fd, OpenMode mode, QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; + open( fd, mode ); +} + +KDPipeIODevice::KDPipeIODevice( Qt::HANDLE handle, OpenMode mode, QObject * p ) + : QIODevice( p ), d( new Private( this ) ) +{ + KDAB_CHECK_CTOR; + open( handle, mode ); +} + +KDPipeIODevice::~KDPipeIODevice() { KDAB_CHECK_DTOR; + if ( isOpen() ) + close(); + delete d; d = 0; +} + + +bool KDPipeIODevice::open( int fd, OpenMode mode ) { KDAB_CHECK_THIS; + +#ifdef Q_OS_WIN32 + return d->doOpen( fd, (HANDLE)_get_osfhandle( fd ), mode ); +#else + return d->doOpen( fd, 0, mode ); +#endif + +} + +bool KDPipeIODevice::open( Qt::HANDLE h, OpenMode mode ) { KDAB_CHECK_THIS; + +#ifdef Q_OS_WIN32 + return d->doOpen( 0, h, mode ); +#else + Q_UNUSED( h ); + Q_UNUSED( mode ); + assert( !"KDPipeIODevice::open( Qt::HANDLE, OpenMode ) should never be called except on Windows." ); +#endif + +} + +bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) { + + if ( q->isOpen() || fd_ < 0 ) + return false; + +#ifdef Q_OS_WIN32 + if ( !handle_ ) + return false; +#endif + + if ( !(mode_ & ReadWrite) ) + return false; // need to have at least read -or- write + + fd = fd_; + handle = handle_; + + std::auto_ptr reader_; + std::auto_ptr writer_; + + if ( mode_ & ReadOnly ) { + reader_.reset( new Reader( fd_, handle_ ) ); + LOCKED( reader_ ); + reader_->start( QThread::HighestPriority ); + if ( !reader_->hasStarted.wait( &reader_->mutex, 1000 ) ) + return false; + connect( reader_.get(), SIGNAL(readyRead()), q, SIGNAL(readyRead()), Qt::QueuedConnection ); + } + if ( mode_ & WriteOnly ) { + writer_.reset( new Writer( fd_, handle_ ) ); + LOCKED( writer_ ); + writer_->start( QThread::HighestPriority ); + if ( !writer_->hasStarted.wait( &writer_->mutex, 1000 ) ) + return false; + connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection ); + } + + // commit to *this: + fd = fd_; + handle = handle_; + reader = reader_.release(); + writer = writer_.release(); + + q->setOpenMode( mode_|Unbuffered ); + + return true; +} + +int KDPipeIODevice::descriptor() const { KDAB_CHECK_THIS; + return d->fd; +} + +Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS; + return d->handle; +} + +qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS; + const qint64 base = QIODevice::bytesAvailable(); + if ( d->reader ) + synchronized( d->reader ) return base + d->reader->bytesInBuffer(); + return base; +} + +qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS; + const qint64 base = QIODevice::bytesToWrite(); + if ( d->writer ) + synchronized( d->writer ) return base + d->writer->bytesInBuffer(); + return base; +} + +bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS; + if ( QIODevice::canReadLine() ) + return true; + if ( d->reader ) + synchronized( d->reader ) return d->reader->bufferContains( '\n' ); + return true; +} + +bool KDPipeIODevice::isSequential() const { + return true; +} + +bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS; + if ( !QIODevice::atEnd() ) { + qDebug( "KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", static_cast(bytesAvailable()) ); + return false; + } + if ( !isOpen() ) + return true; + if ( d->reader->eofShortCut ) + return true; + LOCKED( d->reader ); + const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty(); + if ( !eof ) { + if ( !d->reader->error && !d->reader->eof ) + qDebug( "KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof" ); + if ( !d->reader->bufferEmpty() ) + qDebug( "KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()" ); + } + return eof; +} + +bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS; + Writer * const w = d->writer; + if ( !w ) + return true; + LOCKED( w ); + return w->bufferEmpty() || w->error || w->bufferEmptyCondition.wait( &w->mutex, msecs ) ; +} + +bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS; + if ( ALLOW_QIODEVICE_BUFFERING ) { + if ( bytesAvailable() > 0 ) + return true; + } + Reader * const r = d->reader; + if ( !r || r->eofShortCut ) + return true; + LOCKED( r ); + return r->bytesInBuffer() != 0 || r->eof || r->error || r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ; +} + +qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS; + + qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld", data, maxSize ); + + Reader * const r = d->reader; + + assert( r ); + //assert( r->isRunning() ); // wrong (might be eof, error) + assert( data || maxSize == 0 ); + assert( maxSize >= 0 ); + + if ( r->eofShortCut ) { + qDebug( "KDPipeIODevice::readData: hit eofShortCut, returning 0" ); + return 0; + } + + if ( maxSize < 0 ) + maxSize = 0; + + if ( ALLOW_QIODEVICE_BUFFERING ) { + if ( bytesAvailable() > 0 ) + maxSize = std::min( maxSize, bytesAvailable() ); // don't block + } + + LOCKED( r ); + if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? + qDebug( "KDPipeIODevice::readData: waiting for bufferNotEmptyCondition" ); + r->bufferNotEmptyCondition.wait( &r->mutex ); + } + + if ( r->bufferEmpty() ) { + qDebug( "KDPipeIODevice::readData: got empty buffer, signal eof" ); + // woken with an empty buffer must mean either EOF or error: + assert( r->eof || r->error ); + r->eofShortCut = true; + return r->eof ? 0 : -1 ; + } + + qDebug( "KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", maxSize ); + const qint64 bytesRead = r->readData( data, maxSize ); + qDebug( "KDPipeIODevice::readData: read %lld bytes", bytesRead ); + return bytesRead; +} + +qint64 Reader::readData( char * data, qint64 maxSize ) { + + qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ; + if ( numRead > maxSize ) + numRead = maxSize; + + qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", + data, maxSize, rptr, wptr, bytesInBuffer(), numRead ); + + std::memcpy( data, buffer + rptr, numRead ); + + rptr = ( rptr + numRead ) % sizeof buffer ; + + if ( !bufferFull() ) { + qDebug( "KDPipeIODevice::readData: signal bufferNotFullCondition" ); + bufferNotFullCondition.wakeAll(); + } + + return numRead; +} + +qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS; + + Writer * const w = d->writer; + + assert( w ); + assert( w->error || w->isRunning() ); + assert( data || size == 0 ); + assert( size >= 0 ); + + LOCKED( w ); + + while ( !w->error && !w->bufferEmpty() ) + w->bufferEmptyCondition.wait( &w->mutex ); + + if ( w->error ) + return -1; + + assert( w->bufferEmpty() ); + + return w->writeData( data, size ); +} + +qint64 Writer::writeData( const char * data, qint64 size ) { + + assert( bufferEmpty() ); + + if ( size > static_cast( sizeof buffer ) ) + size = sizeof buffer; + + std::memcpy( buffer, data, size ); + + numBytesInBuffer = size; + + if ( !bufferEmpty() ) + bufferNotEmptyCondition.wakeAll(); + + return size; +} + +void KDPipeIODevice::close() { KDAB_CHECK_THIS; + + if ( !isOpen() ) + return; + + // tell clients we're about to close: + emit aboutToClose(); + + if ( d->writer && bytesToWrite() > 0 ) + waitForBytesWritten( -1 ); + + assert( bytesToWrite() == 0 ); + + if ( Reader * & r = d->reader ) { + synchronized( r ) { + // tell thread to cancel: + r->cancel = true; + // and wake it, so it can terminate: + r->bufferNotFullCondition.wakeAll(); + } + r->wait(); + delete r; r = 0; + } + if ( Writer * & w = d->writer ) { + synchronized( w ) { + // tell thread to cancel: + w->cancel = true; + // and wake it, so it can terminate: + w->bufferNotEmptyCondition.wakeAll(); + } + w->wait(); + delete w; w = 0; + } + +#ifdef Q_OS_WIN32 + CloseHandle( d->handle ); +#else + ::close( d->fd ); +#endif + + setOpenMode( NotOpen ); + d->fd = -1; + d->handle = 0; +} + +void Reader::run() { + + LOCKED( this ); + + // too bad QThread doesn't have that itself; a signal isn't enough + hasStarted.wakeAll(); + + qDebug( "Reader::run: started" ); + + while ( true ) { + + while ( !cancel && bufferFull() ) { + bufferNotEmptyCondition.wakeAll(); + qDebug( "Reader::run: buffer is full, going to sleep" ); + bufferNotFullCondition.wait( &mutex ); + qDebug( "Reader::run: woke up" ); + } + + if ( cancel ) { + qDebug( "Reader::run: detected cancel" ); + goto leave; + } + + if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty + rptr = wptr = 0; + + unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer; + if ( numBytes > sizeof buffer - wptr ) + numBytes = sizeof buffer - wptr; + + qDebug( "Reader::run: rptr=%d, wptr=%d -> numBytes=%d", rptr, wptr, numBytes ); + + assert( numBytes > 0 ); + + qDebug( "Reader::run: trying to read %d bytes", numBytes ); +#ifdef Q_OS_WIN32 + DWORD numRead; + mutex.unlock(); + const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 ); + mutex.lock(); + if ( !ok ) { + errorCode = static_cast( GetLastError() ); + if ( errorCode == ERROR_BROKEN_PIPE ) { + qDebug( "Reader::run: got eof" ); + eof = true; + } else { + qDebug( "Reader::run: got error: %d", errorCode ); + error = true; + } + goto leave; + } +#else + qint64 numRead; + mutex.unlock(); + do { + numRead = ::read( fd, buffer + wptr, numBytes ); + } while ( numRead == -1 && errno == EINTR ); + mutex.lock(); + + if ( numRead < 0 ) { + errorCode = errno; + error = true; + qDebug( "Reader::run: got error: %d", errorCode ); + goto leave; + } +#endif + qDebug( "Reader::run: read %ld bytes", static_cast(numRead) ); + if ( numRead == 0 ) { + qDebug( "Reader::run: eof detected" ); + eof = true; + goto leave; + } + + if ( cancel ) { + qDebug( "Reader::run: detected cancel" ); + goto leave; + } + qDebug( "Reader::run: buffer before: rptr=%4d, wptr=%4d", rptr, wptr ); + wptr = ( wptr + numRead ) % sizeof buffer; + qDebug( "Reader::run: buffer after: rptr=%4d, wptr=%4d", rptr, wptr ); + if ( !bufferEmpty() ) { + qDebug( "Reader::run: buffer no longer empty, waking everyone" ); + bufferNotEmptyCondition.wakeAll(); + emit readyRead(); + } + } + leave: + qDebug( "Reader::run: terminating" ); + bufferNotEmptyCondition.wakeAll(); + emit readyRead(); +} + +void Writer::run() { + + LOCKED( this ); + + // too bad QThread doesn't have that itself; a signal isn't enough + hasStarted.wakeAll(); + + qDebug( "Writer::run: started" ); + + while ( true ) { + + while ( !cancel && bufferEmpty() ) { + bufferEmptyCondition.wakeAll(); + qDebug( "Writer::run: buffer is empty, going to sleep" ); + bufferNotEmptyCondition.wait( &mutex ); + qDebug( "Writer::run: woke up" ); + } + + if ( cancel ) { + qDebug( "Writer::run: detected cancel" ); + goto leave; + } + + assert( numBytesInBuffer > 0 ); + + qDebug( "Writer::run: Trying to write %u bytes", numBytesInBuffer ); + qint64 totalWritten = 0; + do { + mutex.unlock(); +#ifdef Q_OS_WIN32 + DWORD numWritten; + if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) { + mutex.lock(); + errorCode = static_cast( GetLastError() ); + qDebug( "Writer::run: got error code: %d", errorCode ); + error = true; + goto leave; + } +#else + qint64 numWritten; + do { + numWritten = ::write( fd, buffer + totalWritten, numBytesInBuffer - totalWritten ); + } while ( numWritten == -1 && errno == EINTR ); + + if ( numWritten < 0 ) { + mutex.lock(); + errorCode = errno; + qDebug( "Writer::run: got error code: %d", errorCode ); + error = true; + goto leave; + } +#endif + totalWritten += numWritten; + mutex.lock(); + } while ( totalWritten < numBytesInBuffer ); + + qDebug( "Writer::run: wrote %lld bytes", totalWritten ); + + numBytesInBuffer = 0; + bufferEmptyCondition.wakeAll(); + emit bytesWritten( totalWritten ); + } + leave: + qDebug( "Writer::run: terminating" ); + numBytesInBuffer = 0; + bufferEmptyCondition.wakeAll(); + emit bytesWritten( 0 ); +} + +// static +std::pair KDPipeIODevice::makePairOfConnectedPipes() { + KDPipeIODevice * read = 0; + KDPipeIODevice * write = 0; +#ifdef Q_OS_WIN32 + HANDLE rh; + HANDLE wh; + SECURITY_ATTRIBUTES sa; + memset( &sa, 0, sizeof(sa) ); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + if ( CreatePipe( &rh, &wh, &sa, BUFFER_SIZE ) ) { + read = new KDPipeIODevice; + read->open( rh, ReadOnly ); + write = new KDPipeIODevice; + write->open( wh, WriteOnly ); + } +#else + int fds[2]; + if ( pipe( fds ) == 0 ) { + read = new KDPipeIODevice; + read->open( fds[0], ReadOnly ); + write = new KDPipeIODevice; + write->open( fds[1], WriteOnly ); + } +#endif + return std::make_pair( read, write ); +} + +#ifdef KDAB_DEFINE_CHECKS +KDAB_DEFINE_CHECKS( KDPipeIODevice ) { + if ( !isOpen() ) { + assert( openMode() == NotOpen ); + assert( !d->reader ); + assert( !d->writer ); +#ifdef Q_OS_WIN32 + assert( !d->handle ); +#else + assert( d->fd < 0 ); +#endif + } else { + assert( openMode() != NotOpen ); + assert( openMode() & ReadWrite ); + if ( openMode() & ReadOnly ) { + assert( d->reader ); + synchronized( d->reader ) + assert( d->reader->eof || d->reader->error || d->reader->isRunning() ); + } + if ( openMode() & WriteOnly ) { + assert( d->writer ); + synchronized( d->writer ) + assert( d->writer->error || d->writer->isRunning() ); + } +#ifdef Q_OS_WIN32 + assert( d->handle ); +#else + assert( d->fd >= 0 ); +#endif + } +} +#endif // KDAB_DEFINE_CHECKS + +#include "moc_kdpipeiodevice.cpp" +#include "kdpipeiodevice.moc" Added: trunk/gpgme/kdpipeiodevice.h =================================================================== --- trunk/gpgme/kdpipeiodevice.h 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/kdpipeiodevice.h 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,66 @@ +/* + Copyright (C) 2007 Klar?lvdalens Datakonsult AB + + KDPipeIODevice 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. + + KDPipeIODevice 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 KDPipeIODevice; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __KDTOOLSCORE_KDPIPEIODEVICE_H__ +#define __KDTOOLSCORE_KDPIPEIODEVICE_H__ + +#include + +#include + +//#include "checker.h" + +class KDPipeIODevice : public QIODevice { + Q_OBJECT + //KDAB_MAKE_CHECKABLE( KDPipeIODevice ) +public: + explicit KDPipeIODevice( QObject * parent=0 ); + explicit KDPipeIODevice( int fd, OpenMode=ReadOnly, QObject * parent=0 ); + explicit KDPipeIODevice( Qt::HANDLE handle, OpenMode=ReadOnly, QObject * parent=0 ); + ~KDPipeIODevice(); + + static std::pair makePairOfConnectedPipes(); + + bool open( int fd, OpenMode mode=ReadOnly ); + bool open( Qt::HANDLE handle, OpenMode mode=ReadOnly ); + + Qt::HANDLE handle() const; + int descriptor() const; + + /* reimp */ qint64 bytesAvailable() const; + /* reimp */ qint64 bytesToWrite() const; + /* reimp */ bool canReadLine() const; + /* reimp */ void close(); + /* reimp */ bool isSequential() const; + /* reimp */ bool atEnd() const; + + /* reimp */ bool waitForBytesWritten( int msecs ); + /* reimp */ bool waitForReadyRead( int msecs ); + +protected: + /* reimp */ qint64 readData( char * data, qint64 maxSize ); + /* reimp */ qint64 writeData( const char * data, qint64 maxSize ); + +private: + class Private; + Private * d; +}; + +#endif /* __KDTOOLSCORE_KDPIPEIODEVICE_H__ */ + Added: trunk/gpgme/kdpipeiodevice.moc =================================================================== --- trunk/gpgme/kdpipeiodevice.moc 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/kdpipeiodevice.moc 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,132 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'kdpipeiodevice.cpp' +** +** Created: Mon Aug 27 15:17:18 2007 +** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'kdpipeiodevice.cpp' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 59 +#error "This file was generated using the moc from 4.3.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +static const uint qt_meta_data_Reader[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // signals: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x05, + + 0 // eod +}; + +static const char qt_meta_stringdata_Reader[] = { + "Reader\0\0readyRead()\0" +}; + +const QMetaObject Reader::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_Reader, + qt_meta_data_Reader, 0 } +}; + +const QMetaObject *Reader::metaObject() const +{ + return &staticMetaObject; +} + +void *Reader::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Reader)) + return static_cast(const_cast< Reader*>(this)); + return QThread::qt_metacast(_clname); +} + +int Reader::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: readyRead(); break; + } + _id -= 1; + } + return _id; +} + +// SIGNAL 0 +void Reader::readyRead() +{ + QMetaObject::activate(this, &staticMetaObject, 0, 0); +} +static const uint qt_meta_data_Writer[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 1, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // signals: signature, parameters, type, tag, flags + 8, 7, 7, 7, 0x05, + + 0 // eod +}; + +static const char qt_meta_stringdata_Writer[] = { + "Writer\0\0bytesWritten(qint64)\0" +}; + +const QMetaObject Writer::staticMetaObject = { + { &QThread::staticMetaObject, qt_meta_stringdata_Writer, + qt_meta_data_Writer, 0 } +}; + +const QMetaObject *Writer::metaObject() const +{ + return &staticMetaObject; +} + +void *Writer::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_Writer)) + return static_cast(const_cast< Writer*>(this)); + return QThread::qt_metacast(_clname); +} + +int Writer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QThread::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: bytesWritten((*reinterpret_cast< qint64(*)>(_a[1]))); break; + } + _id -= 1; + } + return _id; +} + +// SIGNAL 0 +void Writer::bytesWritten(qint64 _t1) +{ + void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; + QMetaObject::activate(this, &staticMetaObject, 0, _a); +} Added: trunk/gpgme/moc_kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/moc_kdpipeiodevice.cpp 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/moc_kdpipeiodevice.cpp 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,60 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'kdpipeiodevice.h' +** +** Created: Mon Aug 27 15:17:18 2007 +** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "kdpipeiodevice.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'kdpipeiodevice.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 59 +#error "This file was generated using the moc from 4.3.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +static const uint qt_meta_data_KDPipeIODevice[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + + 0 // eod +}; + +static const char qt_meta_stringdata_KDPipeIODevice[] = { + "KDPipeIODevice\0" +}; + +const QMetaObject KDPipeIODevice::staticMetaObject = { + { &QIODevice::staticMetaObject, qt_meta_stringdata_KDPipeIODevice, + qt_meta_data_KDPipeIODevice, 0 } +}; + +const QMetaObject *KDPipeIODevice::metaObject() const +{ + return &staticMetaObject; +} + +void *KDPipeIODevice::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice)) + return static_cast(const_cast< KDPipeIODevice*>(this)); + return QIODevice::qt_metacast(_clname); +} + +int KDPipeIODevice::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QIODevice::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} Modified: trunk/gpgme/posix-sema.c =================================================================== --- trunk/gpgme/posix-sema.c 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/posix-sema.c 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,6 +1,6 @@ /* posix-sema.c Copyright (C) 2001 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2004 g10 Code GmbH + Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH This file is part of GPGME. @@ -45,18 +45,18 @@ void _gpgme_sema_cs_enter (struct critsect_s *s) { - _gpgme_ath_mutex_lock (&s->private); + _gpgme_ath_mutex_lock (&s->priv); } void _gpgme_sema_cs_leave (struct critsect_s *s) { - _gpgme_ath_mutex_unlock (&s->private); + _gpgme_ath_mutex_unlock (&s->priv); } void _gpgme_sema_cs_destroy (struct critsect_s *s) { - _gpgme_ath_mutex_destroy (&s->private); - s->private = NULL; + _gpgme_ath_mutex_destroy (&s->priv); + s->priv = NULL; } Modified: trunk/gpgme/sema.h =================================================================== --- trunk/gpgme/sema.h 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/sema.h 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,6 +1,6 @@ /* sema.h - Definitions for semaphores. Copyright (C) 2000 Werner Koch (dd9jn) - Copyright (C) 2001, 2003, 2004 g10 Code GmbH + Copyright (C) 2001, 2003, 2004, 2007 g10 Code GmbH This file is part of GPGME. @@ -25,7 +25,7 @@ struct critsect_s { const char *name; - void *private; + void *priv; }; #define DEFINE_GLOBAL_LOCK(name) \ @@ -39,7 +39,7 @@ do \ { \ (a).name = #a; \ - (a).private = NULL; \ + (a).priv = NULL; \ } \ while (0) #define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name)) Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/w32-glib-io.c 2007-09-06 22:41:11 UTC (rev 1250) @@ -97,14 +97,23 @@ return giochannel_table[fd]; } -/* Look up the giochannel for "file descriptor" FD. */ -GIOChannel * + +/* Compatibility interface. Obsolete. */ +void * gpgme_get_giochannel (int fd) { return find_channel (fd, 0); } +/* Look up the giochannel for "file descriptor" FD. */ +void * +gpgme_get_fdptr (int fd) +{ + return find_channel (fd, 0); +} + + /* 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. */ Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/w32-io.c 2007-09-06 22:41:11 UTC (rev 1250) @@ -1403,9 +1403,9 @@ } -/* The following interface is only useful for GPGME Glib. */ +/* The following interface is only useful for GPGME Glib and Qt. */ -/* Look up the giochannel for file descriptor FD. */ +/* Compatibility interface, obsolete. */ void * gpgme_get_giochannel (int fd) { @@ -1413,3 +1413,9 @@ } +/* Look up the giochannel or qiodevice for file descriptor FD. */ +void * +gpgme_get_fdptr (int fd) +{ + return NULL; +} Added: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,609 @@ +/* w32-glib-io.c - W32 Glib I/O functions + Copyright (C) 2000 Werner Koch (dd9jn) + Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + GPGME is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kdpipeiodevice.h" + +extern "C" +{ +#include "util.h" +#include "priv-io.h" +#include "sema.h" +#include "debug.h" +} + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 +#endif +#endif + + +/* This file is an ugly hack to get GPGME working with Qt on Windows + targets. On Windows, you can not select() on file descriptors. + The only way to check if there is something to read is to read + something. This means that GPGME can not let Qt check for data + without letting Qt also handle the data on Windows targets. + + The ugly consequence is that we need to work on QIODevices in + GPGME, creating a Qt dependency. Also, we need to export an + interface for the application to get at GPGME's QIODevices. There + is no good way to abstract all this with callbacks, because the + whole thing is also interconnected with the creation of pipes and + child processes. + + The following rule applies only to this I/O backend: + + * ALL operations must use the user defined event loop. GPGME can + not anymore provide its own event loop. This is mostly a sanity + requirement: Although we have in theory all information we need to + make the GPGME W32 code for select still work, it would be a big + complication and require changes throughout GPGME. + + Eventually, we probably have to bite the bullet and make some + really nice callback interfaces to let the user control all this at + a per-context level. */ + + +#define MAX_SLAFD 256 + +QIODevice *iodevice_table[MAX_SLAFD]; + + +static QIODevice * +find_channel (int fd, int create) +{ + if (fd < 0 || fd >= MAX_SLAFD) + return NULL; + + if (create && !iodevice_table[fd]) + iodevice_table[fd] = new KDPipeIODevice + (fd, QIODevice::ReadOnly|QIODevice::Unbuffered); + + return iodevice_table[fd]; +} + + +/* 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, "%ld", (long) _get_osfhandle (fd)); +} + + +void +_gpgme_io_subsystem_init (void) +{ +} + + +static struct +{ + _gpgme_close_notify_handler_t handler; + void *value; +} notify_table[MAX_SLAFD]; + + +int +_gpgme_io_read (int fd, void *buffer, size_t count) +{ + int saved_errno = 0; + qint64 nread; + QIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, + "buffer=%p, count=%u", buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("no channel registered"); + errno = EINVAL; + return TRACE_SYSRES (-1); + } + TRACE_LOG1 ("channel %p", chan); + + { +// GError *err = NULL; +// status = g_io_channel_read_chars (chan, (gchar *) buffer, +// count, &nread, &err); + nread = chan->read( buffer, count ); + if ( nread < 0 ) { + TRACE_LOG1 ("err %s", qPrintable( chan->errorString() ) ); + saved_errno = EIO; + nread = -1; + } + } + + TRACE_LOGBUF (buffer, nread); + + errno = saved_errno; + return TRACE_SYSRES (nread); +} + + +int +_gpgme_io_write (int fd, const void *buffer, size_t count) +{ + qint64 nwritten; + QIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, + "buffer=%p, count=%u", buffer, count); + TRACE_LOGBUF (buffer, count); + + chan = find_channel (fd, 0); + if (!chan) + { + TRACE_LOG ("fd %d: no channel registered"); + errno = EINVAL; + return -1; + } + + nwritten = chan->write( buffer, count ); + + if (nwritten < 0) + { + nwritten = -1; + errno = EIO; + return TRACE_SYSRES(-1) + } + errno = 0; + return TRACE_SYSRES (nwritten); +} + + +int +_gpgme_io_pipe (int filedes[2], int inherit_idx) +{ + QIODevice *chan; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, + "inherit_idx=%i (GPGME uses it for %s)", + inherit_idx, inherit_idx ? "writing" : "reading"); + +#define PIPEBUF_SIZE 4096 + if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) + return TRACE_SYSRES (-1); + + /* Make one end inheritable. */ + if (inherit_idx == 0) + { + int new_read; + + new_read = _dup (filedes[0]); + _close (filedes[0]); + filedes[0] = new_read; + + if (new_read < 0) + { + _close (filedes[1]); + return TRACE_SYSRES (-1); + } + } + else if (inherit_idx == 1) + { + int new_write; + + new_write = _dup (filedes[1]); + _close (filedes[1]); + filedes[1] = new_write; + + if (new_write < 0) + { + _close (filedes[0]); + return TRACE_SYSRES (-1); + } + } + + /* Now we have a pipe with the right end inheritable. The other end + should have a giochannel. */ + chan = find_channel (filedes[1 - inherit_idx], 1); + if (!chan) + { + int saved_errno = errno; + _close (filedes[0]); + _close (filedes[1]); + errno = saved_errno; + return TRACE_SYSRES (-1); + } + + return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p", + filedes[0], (HANDLE) _get_osfhandle (filedes[0]), + filedes[1], (HANDLE) _get_osfhandle (filedes[1]), + chan); +} + + +int +_gpgme_io_close (int fd) +{ + QIODevice *chan; + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); + + if (fd < 0 || fd >= MAX_SLAFD) + { + errno = EBADF; + return TRACE_SYSRES (-1); + } + + /* First call the notify handler. */ + 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. */ + chan = iodevice_table[fd]; + if (chan) + { + chan->close(); + delete chan; + iodevice_table[fd] = NULL; + } + else + _close (fd); + + return 0; +} + + +int +_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, + void *value) +{ + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, + "close_handler=%p/%p", handler, value); + + assert (fd != -1); + + if (fd < 0 || fd >= (int) DIM (notify_table)) + { + errno = EINVAL; + return TRACE_SYSRES (-1); + } + notify_table[fd].handler = handler; + notify_table[fd].value = value; + return TRACE_SYSRES (0); +} + + +int +_gpgme_io_set_nonblocking (int fd) +{ + /* Qt always uses non-blocking IO, except for files, maybe, but who + uses that? */ + TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); + + return TRACE_SYSRES (0); +} + + +static char * +build_commandline (char **argv) +{ + int i; + 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; + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, + "path=%s", path); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + 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 TRACE_SYSRES (-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 = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdin", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + duped_stdin = 1; + } + else if (fd_child_list[i].dup_to == 1) + { + si.hStdOutput = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stdout", fd_child_list[i].fd, + _get_osfhandle (fd_child_list[i].fd)); + } + else if (fd_child_list[i].dup_to == 2) + { + si.hStdError = (HANDLE) _get_osfhandle (fd_child_list[i].fd); + TRACE_LOG2 ("using 0x%x/%p for stderr", fd_child_list[i].fd, + _get_osfhandle (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) + { + TRACE_LOG1 ("CreateFile (\"nul\") failed: ec=%d", + (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + /* Make sure that the process has a connected stdin. */ + if (!duped_stdin) + { + si.hStdInput = hnul; + TRACE_LOG1 ("using 0x%x for dummy stdin", (int) hnul); + } + /* We normally don't want all the normal output. */ + if (!duped_stderr) + { + si.hStdError = hnul; + TRACE_LOG1 ("using %d for dummy stderr", (int)hnul); + } + } + + cr_flags |= CREATE_SUSPENDED; + cr_flags |= DETACHED_PROCESS; + 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 */ + { + TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ()); + free (arg_string); + /* FIXME: Should translate the error code. */ + errno = EIO; + return TRACE_SYSRES (-1); + } + + /* Close the /dev/nul handle if used. */ + if (hnul != INVALID_HANDLE_VALUE) + { + if (!CloseHandle (hnul)) + TRACE_LOG1 ("CloseHandle (hnul) failed: ec=%d (ignored)", + (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); + + TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, " + "dwProcessID=%d, dwThreadId=%d", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + if (ResumeThread (pi.hThread) < 0) + TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ()); + + if (!CloseHandle (pi.hThread)) + TRACE_LOG1 ("CloseHandle of thread failed: ec=%d", + (int) GetLastError ()); + + TRACE_SUC1 ("process=%p", pi.hProcess); + 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) +{ + int i; + int count; + /* Use a 1s timeout. */ + + void *dbg_help = NULL; + TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, + "nfds=%u, nonblock=%u", nfds, nonblock); + + // we only implement the special case of nonblock == true + assert( nonblock ); + + count = 0; + + TRACE_SEQ (dbg_help, "select on [ "); + for (i = 0; i < nfds; i++) + { + if (fds[i].fd == -1) + { + fds[i].signaled = 0; + } + else if (fds[i].frozen) + { + TRACE_ADD1 (dbg_help, "f0x%x ", fds[i].fd); + fds[i].signaled = 0; + } + else if (fds[i].for_read ) + { + const QIODevice * const chan = find_channel (fds[i].fd, 0); + assert (chan); + fds[i].signaled = chan->bytesAvailable() > 0 ? 1 : 0 ; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + count++; + } + else if (fds[i].for_write) + { + const QIODevice * const chan = find_channel (fds[i].fd, 0); + assert (chan); + fds[i].signaled = chan->bytesToWrite() > 0 ? 0 : 1 ; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + count++; + } + } + TRACE_END (dbg_help, "]"); + + return TRACE_SYSRES (count); +} + + +int +_gpgme_io_dup (int fd) +{ + return _dup (fd); +} + + +/* Look up the qiodevice for file descriptor FD. */ +extern "C" +void * +gpgme_get_fdptr (int fd) +{ + return find_channel (fd, 0); +} + + +/* Obsolete compatibility interface. */ +extern "C" +void * +gpgme_get_giochannel (int fd) +{ + return NULL; +} + Modified: trunk/gpgme/w32-sema.c =================================================================== --- trunk/gpgme/w32-sema.c 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/gpgme/w32-sema.c 2007-09-06 22:41:11 UTC (rev 1250) @@ -1,6 +1,6 @@ /* w32-sema.c Copyright (C) 2001 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2004 g10 Code GmbH + Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH This file is part of GPGME. @@ -65,7 +65,7 @@ /* first test whether it is really not initialized */ EnterCriticalSection (&init_lock); - if ( s->private ) { + if ( s->priv ) { LeaveCriticalSection (&init_lock); return; } @@ -76,7 +76,7 @@ sema_fatal ("out of core while creating critical section lock"); } InitializeCriticalSection (mp); - s->private = mp; + s->priv = mp; LeaveCriticalSection (&init_lock); } @@ -91,25 +91,25 @@ void _gpgme_sema_cs_enter ( struct critsect_s *s ) { - if (!s->private) + if (!s->priv) critsect_init (s); - EnterCriticalSection ( (CRITICAL_SECTION*)s->private ); + EnterCriticalSection ( (CRITICAL_SECTION*)s->priv ); } void _gpgme_sema_cs_leave (struct critsect_s *s) { - if (!s->private) + if (!s->priv) critsect_init (s); - LeaveCriticalSection ((CRITICAL_SECTION*)s->private); + LeaveCriticalSection ((CRITICAL_SECTION*)s->priv); } void _gpgme_sema_cs_destroy ( struct critsect_s *s ) { - if (s && s->private) { - DeleteCriticalSection ((CRITICAL_SECTION*)s->private); - free (s->private); - s->private = NULL; + if (s && s->priv) { + DeleteCriticalSection ((CRITICAL_SECTION*)s->priv); + free (s->priv); + s->priv = NULL; } } Added: trunk/m4/pkg.m4 =================================================================== --- trunk/m4/pkg.m4 2007-09-03 14:19:29 UTC (rev 1249) +++ trunk/m4/pkg.m4 2007-09-06 22:41:11 UTC (rev 1250) @@ -0,0 +1,157 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright ?? 2004 Scott James Remnant . +# +# This program 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. +# +# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES From cvs at cvs.gnupg.org Fri Sep 7 00:37:53 2007 From: cvs at cvs.gnupg.org (svn author mo) Date: Fri, 07 Sep 2007 00:37:53 +0200 Subject: [svn] assuan - r256 - trunk/doc Message-ID: Author: mo Date: 2007-09-07 00:37:22 +0200 (Fri, 07 Sep 2007) New Revision: 256 Modified: trunk/doc/ChangeLog trunk/doc/assuan.texi Log: 2007-09-07 Moritz Schulte * assuan.texi (Client code): mention assuan_send_data() instead of assuan_write_data(). Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-09-05 16:02:37 UTC (rev 255) +++ trunk/doc/ChangeLog 2007-09-06 22:37:22 UTC (rev 256) @@ -1,3 +1,8 @@ +2007-09-07 Moritz Schulte + + * assuan.texi (Client code): mention assuan_send_data() instead of + assuan_write_data(). + 2007-09-03 Marcus Brinkmann * assuan.texi: Fix prototype and documentation for Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-09-05 16:02:37 UTC (rev 255) +++ trunk/doc/assuan.texi 2007-09-06 22:37:22 UTC (rev 256) @@ -771,7 +771,7 @@ @var{inquire_cb} is called by Libassuan when the server requests additional information from the client while processing the command. This callback shall check the provided inquiry name and send the data -as requested back using the @code{assuan_write_data}. The server +as requested back using the @code{assuan_send_data}. The server passed @var{inquiry_cb_arg} along with the inquiry name to the callback. From cvs at cvs.gnupg.org Fri Sep 7 02:19:34 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 02:19:34 +0200 Subject: [svn] assuan - r257 - trunk/src Message-ID: Author: marcus Date: 2007-09-07 02:19:05 +0200 (Fri, 07 Sep 2007) New Revision: 257 Modified: trunk/src/ChangeLog trunk/src/assuan-inquire.c Log: 2007-09-07 Marcus Brinkmann * assuan-inquire.c (_assuan_inquire_ext_cb): Clear CTX->in_inquire before invoking callback and returning. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-06 22:37:22 UTC (rev 256) +++ trunk/src/ChangeLog 2007-09-07 00:19:05 UTC (rev 257) @@ -1,3 +1,8 @@ +2007-09-07 Marcus Brinkmann + + * assuan-inquire.c (_assuan_inquire_ext_cb): Clear CTX->in_inquire + before invoking callback and returning. + 2007-09-05 Marcus Brinkmann * assuan-handler.c (dispatch_command): Return non-critical errors Modified: trunk/src/assuan-inquire.c =================================================================== --- trunk/src/assuan-inquire.c 2007-09-06 22:37:22 UTC (rev 256) +++ trunk/src/assuan-inquire.c 2007-09-07 00:19:05 UTC (rev 257) @@ -322,6 +322,7 @@ free_membuf (mb); free (mb); } + ctx->in_inquire = 0; (ctx->inquire_cb) (ctx->inquire_cb_data, rc, buf, buf_len); } return rc; From cvs at cvs.gnupg.org Fri Sep 7 14:11:23 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 14:11:23 +0200 Subject: [svn] assuan - r258 - trunk/src Message-ID: Author: marcus Date: 2007-09-07 14:10:52 +0200 (Fri, 07 Sep 2007) New Revision: 258 Modified: trunk/src/assuan-handler.c Log: Fix last change. Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-09-07 00:19:05 UTC (rev 257) +++ trunk/src/assuan-handler.c 2007-09-07 12:10:52 UTC (rev 258) @@ -442,7 +442,7 @@ handle_data_line, this may be wrong here. For example, if a user callback is invoked, and that callback is responsible for calling assuan_process_done, then this is wrong. */ - return PROCESS_DONE (handle_data_line (ctx, line+2, linelen-2)); + return PROCESS_DONE (ctx, handle_data_line (ctx, line+2, linelen-2)); for (p=line; *p && *p != ' ' && *p != '\t'; p++) ; From cvs at cvs.gnupg.org Fri Sep 7 17:40:02 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 17:40:02 +0200 Subject: [svn] assuan - r259 - trunk/src Message-ID: Author: marcus Date: 2007-09-07 17:39:32 +0200 (Fri, 07 Sep 2007) New Revision: 259 Modified: trunk/src/ChangeLog Log: 2007-09-07 Marcus Brinkmann * assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still initialize MEMBUF. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-07 12:10:52 UTC (rev 258) +++ trunk/src/ChangeLog 2007-09-07 15:39:32 UTC (rev 259) @@ -1,5 +1,8 @@ 2007-09-07 Marcus Brinkmann + * assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still + initialize MEMBUF. + * assuan-inquire.c (_assuan_inquire_ext_cb): Clear CTX->in_inquire before invoking callback and returning. From cvs at cvs.gnupg.org Fri Sep 7 17:55:44 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 17:55:44 +0200 Subject: [svn] assuan - r260 - trunk/src Message-ID: Author: marcus Date: 2007-09-07 17:55:14 +0200 (Fri, 07 Sep 2007) New Revision: 260 Modified: trunk/src/assuan-inquire.c Log: 2007-09-07 Marcus Brinkmann * assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still initialize MEMBUF. Modified: trunk/src/assuan-inquire.c =================================================================== --- trunk/src/assuan-inquire.c 2007-09-07 15:39:32 UTC (rev 259) +++ trunk/src/assuan-inquire.c 2007-09-07 15:55:14 UTC (rev 260) @@ -351,23 +351,18 @@ assuan_error_t rc; struct membuf *mb = NULL; char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */ - int nodataexpected; if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf))) return _assuan_error (ASSUAN_Invalid_Value); - nodataexpected = !maxlen; if (!ctx->is_server) return _assuan_error (ASSUAN_Not_A_Server); if (ctx->in_inquire) return _assuan_error (ASSUAN_Nested_Commands); - if (!nodataexpected) - { - mb = malloc (sizeof (struct membuf)); - if (!mb) - return _assuan_error (ASSUAN_Out_Of_Core); - init_membuf (mb, maxlen ? maxlen : 1024, maxlen); - } + mb = malloc (sizeof (struct membuf)); + if (!mb) + return _assuan_error (ASSUAN_Out_Of_Core); + init_membuf (mb, maxlen ? maxlen : 1024, maxlen); strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword); rc = assuan_write_line (ctx, cmdbuf); From cvs at cvs.gnupg.org Fri Sep 7 21:39:20 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 21:39:20 +0200 Subject: [svn] gpgme - r1251 - in trunk: . gpgme Message-ID: Author: marcus Date: 2007-09-07 21:38:50 +0200 (Fri, 07 Sep 2007) New Revision: 1251 Modified: trunk/configure.ac trunk/gpgme/ChangeLog trunk/gpgme/Makefile.am trunk/gpgme/gpgme.h trunk/gpgme/w32-io.c trunk/gpgme/w32-qt-io.cpp Log: 2007-09-07 Marcus Brinkmann * configure.ac: Work around for missing Qt cross compilation support. Check for glib and qt only on w32 targets. gpgme/ 2007-09-07 Marcus Brinkmann * w32-qt-io.cpp (_gpgme_io_spawn): Fix several cast errors and typos. * w32-io.c (_gpgme_io_write): Use TRACE_SYSRES instead of TRACE_SYS. (libgpgme_qt_la_LIBADD): Add QT4_CORE_LIBS, not QT4_CORE_LIB. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/configure.ac 2007-09-07 19:38:50 UTC (rev 1251) @@ -118,6 +118,8 @@ component_system=None have_dosish_system=no have_w32_system=no +build_w32_glib=no +build_w32_qt=no case "${host}" in *-mingw32*) # special stuff for Windoze NT @@ -126,6 +128,23 @@ GPG_DEFAULT='c:\\gnupg\\gpg.exe' GPGSM_DEFAULT='c:\\gnupg\\gpgsm.exe' #component_system='COM+' + + AM_PATH_GLIB_2_0 + AC_ARG_ENABLE(w32-glib, + AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), + build_w32_glib=$enableval) + + # Check disabled, because the qt-dev packages in gpg4win do + # not provide any support for cross compilation. + # PKG_CHECK_MODULES(QT4_CORE, QtCore) + + # Use it like this: + # ./configure --enable-w32-qt QT4_CORE_CFLAGS="..." QT4_CORE_LIBS="..." + AC_SUBST(QT4_CORE_CFLAGS) + AC_SUBST(QT4_CORE_LIBS) + AC_ARG_ENABLE(w32-qt, + AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]), + build_w32_qt=$enableval) ;; *) AC_CHECK_PTH(1.2.0,,,no,have_pth=yes) @@ -155,19 +174,7 @@ AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system]) fi AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) - -build_w32_glib=no -AM_PATH_GLIB_2_0 -AC_ARG_ENABLE(w32-glib, - AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), - build_w32_glib=$enableval) AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes) - -build_w32_qt=no -PKG_CHECK_MODULES(QT4_CORE, QtCore) -AC_ARG_ENABLE(w32-qt, - AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]), - build_w32_qt=$enableval) AM_CONDITIONAL(BUILD_W32_QT, test "$build_w32_qt" = yes) AM_CONDITIONAL(HAVE_PTH, test "$have_pth" = "yes") Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/gpgme/ChangeLog 2007-09-07 19:38:50 UTC (rev 1251) @@ -1,5 +1,9 @@ 2007-09-07 Marcus Brinkmann + * w32-qt-io.cpp (_gpgme_io_spawn): Fix several cast errors and typos. + * w32-io.c (_gpgme_io_write): Use TRACE_SYSRES instead of TRACE_SYS. + (libgpgme_qt_la_LIBADD): Add QT4_CORE_LIBS, not QT4_CORE_LIB. + * kdpipeiodevice.h, kdpipeiodevice.cpp, moc_kdpipeiodevice.cpp, kdpipeiodevice.moc, w32-qt-io.c: New files. * Makefile.am (ltlib_gpgme_extra): Rename to ltlib_gpgme_glib. @@ -10,6 +14,7 @@ (AM_CFLAGS): Add @QT4_CORE_CFLAGS at . (libgpgme_qt_la_LDFLAGS, libgpgme_qt_la_DEPENDENCIES) (libgpgme_qt_la_LIBADD): New variables. + * sema.h (struct critsect_s): Rename "private" to "priv" to make C++ users happy. Change users. * posix-sema.c (_gpgme_sema_cs_enter, _gpgme_sema_cs_leave) Modified: trunk/gpgme/Makefile.am =================================================================== --- trunk/gpgme/Makefile.am 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/gpgme/Makefile.am 2007-09-07 19:38:50 UTC (rev 1251) @@ -208,7 +208,7 @@ libgpgme_qt_la_DEPENDENCIES = $(assuan_libobjs) \ @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps) libgpgme_qt_la_LIBADD = $(assuan_libobjs) @LTLIBOBJS@ \ - @GPG_ERROR_LIBS@ @QT4_CORE_LIB@ @NETLIBS@ + @GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@ endif status-table.h : gpgme.h Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/gpgme/gpgme.h 2007-09-07 19:38:50 UTC (rev 1251) @@ -73,7 +73,7 @@ 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.5-cvs1228" +#define GPGME_VERSION "1.1.5-cvs1250" Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/gpgme/w32-io.c 2007-09-07 19:38:50 UTC (rev 1251) @@ -727,7 +727,7 @@ TRACE_LOGBUF (buffer, count); if (count == 0) - return TRACE_SYS (0); + return TRACE_SYSRES (0); ctx = find_writer (fd, 1); if (!ctx) Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-06 22:41:11 UTC (rev 1250) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-07 19:38:50 UTC (rev 1251) @@ -140,19 +140,15 @@ } TRACE_LOG1 ("channel %p", chan); - { -// GError *err = NULL; -// status = g_io_channel_read_chars (chan, (gchar *) buffer, -// count, &nread, &err); - nread = chan->read( buffer, count ); - if ( nread < 0 ) { - TRACE_LOG1 ("err %s", qPrintable( chan->errorString() ) ); - saved_errno = EIO; - nread = -1; + nread = chan->read ((char *) buffer, count); + if (nread < 0) + { + TRACE_LOG1 ("err %s", qPrintable (chan->errorString ())); + saved_errno = EIO; + nread = -1; } - } - TRACE_LOGBUF (buffer, nread); + TRACE_LOGBUF ((char *) buffer, nread); errno = saved_errno; return TRACE_SYSRES (nread); @@ -166,7 +162,7 @@ QIODevice *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, "buffer=%p, count=%u", buffer, count); - TRACE_LOGBUF (buffer, count); + TRACE_LOGBUF ((char *) buffer, count); chan = find_channel (fd, 0); if (!chan) @@ -176,13 +172,13 @@ return -1; } - nwritten = chan->write( buffer, count ); + nwritten = chan->write ((char *) buffer, count); if (nwritten < 0) { nwritten = -1; errno = EIO; - return TRACE_SYSRES(-1) + return TRACE_SYSRES(-1); } errno = 0; return TRACE_SYSRES (nwritten); @@ -348,7 +344,7 @@ /* And a trailing zero. */ n++; - buf = p = malloc (n); + buf = p = (char *) malloc (n); if (!buf) return NULL; for (i = 0; argv[i]; i++) @@ -543,8 +539,8 @@ TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, "nfds=%u, nonblock=%u", nfds, nonblock); - // we only implement the special case of nonblock == true - assert( nonblock ); + /* We only implement the special case of nonblock == true. */ + assert (nonblock); count = 0; From cvs at cvs.gnupg.org Fri Sep 7 22:54:42 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 07 Sep 2007 22:54:42 +0200 Subject: [svn] gpgme - r1252 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-07 22:54:12 +0200 (Fri, 07 Sep 2007) New Revision: 1252 Modified: trunk/gpgme/ChangeLog trunk/gpgme/Makefile.am trunk/gpgme/gpgme.h Log: 2007-09-07 Marcus Brinkmann * Makefile.am (libgpgme_qt_la_SOURCES): Move moc_kdpipeiodevice.cpp to EXTRA_DIST, as this is only included by another file (it's more like a header file than a cpp file, but automake doesn't know that). Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-07 19:38:50 UTC (rev 1251) +++ trunk/gpgme/ChangeLog 2007-09-07 20:54:12 UTC (rev 1252) @@ -1,5 +1,10 @@ 2007-09-07 Marcus Brinkmann + * Makefile.am (libgpgme_qt_la_SOURCES): Move + moc_kdpipeiodevice.cpp to EXTRA_DIST, as this is only included by + another file (it's more like a header file than a cpp file, but + automake doesn't know that). + * w32-qt-io.cpp (_gpgme_io_spawn): Fix several cast errors and typos. * w32-io.c (_gpgme_io_write): Use TRACE_SYSRES instead of TRACE_SYS. (libgpgme_qt_la_LIBADD): Add QT4_CORE_LIBS, not QT4_CORE_LIB. Modified: trunk/gpgme/Makefile.am =================================================================== --- trunk/gpgme/Makefile.am 2007-09-07 19:38:50 UTC (rev 1251) +++ trunk/gpgme/Makefile.am 2007-09-07 20:54:12 UTC (rev 1252) @@ -19,8 +19,9 @@ ## Process this file with automake to produce Makefile.in +# Note: moc_kdpipeiodevice should actually be a dependcy below. EXTRA_DIST = gpgme-config.in gpgme.m4 mkstatus libgpgme.vers \ - versioninfo.rc.in gpgme.def + versioninfo.rc.in gpgme.def moc_kdpipeiodevice.cpp BUILT_SOURCES = status-table.h MOSTLYCLEANFILES = status-table.h bin_SCRIPTS = gpgme-config @@ -115,8 +116,8 @@ if BUILD_W32_QT libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \ - kdpipeiodevice.h kdpipeiodevice.cpp moc_kdpipeiodevice.cpp \ - kdpipeiodevice.moc + kdpipeiodevice.h kdpipeiodevice.cpp kdpipeiodevice.moc +# FIXME: Add extra depedency: moc_kdpipeiodevice.cpp # These are built sources (normally). # moc_kdpipeiodevice.cpp: kdpipeiodevice.h Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-07 19:38:50 UTC (rev 1251) +++ trunk/gpgme/gpgme.h 2007-09-07 20:54:12 UTC (rev 1252) @@ -73,7 +73,7 @@ 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.5-cvs1250" +#define GPGME_VERSION "1.1.5-cvs1251" From cvs at cvs.gnupg.org Sat Sep 8 13:19:07 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Sat, 08 Sep 2007 13:19:07 +0200 Subject: [svn] GpgOL - r175 - trunk/src Message-ID: Author: wk Date: 2007-09-08 13:18:38 +0200 (Sat, 08 Sep 2007) New Revision: 175 Modified: trunk/src/mimemaker.c trunk/src/util.h Log: Added framework for PGP/MIME encryption. Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-09-07 15:19:08 UTC (rev 174) +++ trunk/src/mimemaker.c 2007-09-08 11:18:38 UTC (rev 175) @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -53,10 +54,51 @@ "abcdefghijklmnopqrstuvwxyz" "0123456789+/"); -/* The maximum length of a line we are able to process. RFC822 allows - only for 1000 bytes; thus 2000 seems to be a reasonable value. */ -#define LINEBUFSIZE 2000 +/* The object we use instead of IStream. It allows us to have a + callback method for output and thus for processing stuff + recursively. */ +struct sink_s; +typedef struct sink_s *sink_t; +struct sink_s +{ + void *cb_data; + int (*writefnc)(sink_t sink, const void *data, size_t datalen); +}; + +/*** local prototypes ***/ +static int write_multistring (sink_t sink, const char *text1, + ...) GPGOL_GCC_A_SENTINEL(0); + + + + + +/* Standard write method used with a sink_t object. */ +static int +sink_std_write (sink_t sink, const void *data, size_t datalen) +{ + HRESULT hr; + LPSTREAM stream = sink->cb_data; + + if (!stream) + { + log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__); + return -1; + } + if (!data) + return 0; /* Flush - nothing to do here. */ + + hr = IStream_Write (stream, data, datalen, NULL); + if (hr) + { + log_error ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr); + return -1; + } + return 0; +} + + /* Make sure that PROTOCOL is usable or return a suitable protocol. On error PROTOCOL_UNKNOWN is returned. */ static protocol_t @@ -84,7 +126,7 @@ retruned. The caller needs to call SaveChanges. Returns NULL on failure in which case STREAM will be set to NULL. */ static LPATTACH -create_mapi_attachment (LPMESSAGE message, LPSTREAM *stream) +create_mapi_attachment (LPMESSAGE message, sink_t sink) { HRESULT hr; ULONG pos; @@ -92,7 +134,8 @@ LPATTACH att = NULL; LPUNKNOWN punk; - *stream = NULL; + sink->cb_data = NULL; + sink->writefnc = NULL; hr = IMessage_CreateAttach (message, NULL, 0, &pos, &att); if (hr) { @@ -165,7 +208,8 @@ SRCNAME, __func__, hr); goto failure; } - *stream = (LPSTREAM)punk; + sink->cb_data = (LPSTREAM)punk; + sink->writefnc = sink_std_write; return att; failure: @@ -174,49 +218,69 @@ } -/* Wrapper around IStream::Write to print an error message. */ +/* Write data to a sink_t. */ static int -write_buffer (LPSTREAM stream, const void *data, size_t datalen) +write_buffer (sink_t sink, const void *data, size_t datalen) { - HRESULT hr; - - hr = IStream_Write (stream, data, datalen, NULL); - if (hr) + if (!sink || !sink->writefnc) { - log_error ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr); + log_error ("%s:%s: sink not properliy setup", SRCNAME, __func__); return -1; } - return 0; + return sink->writefnc (sink, data, datalen); } + /* Write the string TEXT to the IStream STREAM. Returns 0 on sucsess, prints an error message and returns -1 on error. */ static int -write_string (LPSTREAM stream, const char *text) +write_string (sink_t sink, const char *text) { - return write_buffer (stream, text, strlen (text)); + return write_buffer (sink, text, strlen (text)); } -/* Helper to write a boundary to the output stream. The leading LF +/* Write the string TEXT1 and all folloing arguments of type (const + char*) to the SINK. The list of argumens needs to be terminated + with a NULL. Returns 0 on sucsess, prints an error message and + returns -1 on error. */ +static int +write_multistring (sink_t sink, const char *text1, ...) +{ + va_list arg_ptr; + int rc; + const char *s; + + va_start (arg_ptr, text1); + s = text1; + do + rc = write_string (sink, s); + while (!rc && (s=va_arg (arg_ptr, const char *))); + va_end (arg_ptr); + return rc; +} + + + +/* Helper to write a boundary to the output sink. The leading LF will be written as well. */ static int -write_boundary (LPSTREAM stream, const char *boundary, int lastone) +write_boundary (sink_t sink, const char *boundary, int lastone) { - int rc = write_string (stream, "\r\n--"); + int rc = write_string (sink, "\r\n--"); if (!rc) - rc = write_string (stream, boundary); + rc = write_string (sink, boundary); if (!rc) - rc = write_string (stream, lastone? "--\r\n":"\r\n"); + rc = write_string (sink, lastone? "--\r\n":"\r\n"); return rc; } -/* Write DATALEN bytes of DATA to STREAM in base64 encoding. This +/* Write DATALEN bytes of DATA to SINK in base64 encoding. This creates a complete Base64 chunk including the trailing fillers. */ static int -write_b64 (LPSTREAM stream, const void *data, size_t datalen) +write_b64 (sink_t sink, const void *data, size_t datalen) { int rc; const unsigned char *p; @@ -224,6 +288,7 @@ int idx, quads; char outbuf[4]; + log_debug (" writing base64 of length %d\n", (int)datalen); idx = quads = 0; for (p = data; datalen; p++, datalen--) { @@ -234,13 +299,13 @@ outbuf[1] = bintoasc[(((*inbuf<<4)&060)|((inbuf[1] >> 4)&017))&077]; outbuf[2] = bintoasc[(((inbuf[1]<<2)&074)|((inbuf[2]>>6)&03))&077]; outbuf[3] = bintoasc[inbuf[2]&077]; - if ((rc = write_buffer (stream, outbuf, 4))) + if ((rc = write_buffer (sink, outbuf, 4))) return rc; idx = 0; if (++quads >= (64/4)) { quads = 0; - if ((rc = write_buffer (stream, "\r\n", 2))) + if ((rc = write_buffer (sink, "\r\n", 2))) return rc; } } @@ -261,21 +326,21 @@ outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077]; outbuf[3] = '='; } - if ((rc = write_buffer (stream, outbuf, 4))) + if ((rc = write_buffer (sink, outbuf, 4))) return rc; ++quads; } if (quads) - if ((rc = write_buffer (stream, "\r\n", 2))) + if ((rc = write_buffer (sink, "\r\n", 2))) return rc; return 0; } -/* Write DATALEN bytes of DATA to STREAM in quoted-prinable encoding. */ +/* Write DATALEN bytes of DATA to SINK in quoted-prinable encoding. */ static int -write_qp (LPSTREAM stream, const void *data, size_t datalen) +write_qp (sink_t sink, const void *data, size_t datalen) { int rc; const unsigned char *p; @@ -297,12 +362,13 @@ outbuf[outidx++] = '='; \ outbuf[outidx++] = '\r'; \ outbuf[outidx++] = '\n'; \ - if ((rc = write_buffer (stream, outbuf, outidx))) \ + if ((rc = write_buffer (sink, outbuf, outidx))) \ return rc; \ outidx = 0; \ } \ } while (0) + log_debug (" writing qp of length %d\n", (int)datalen); outidx = 0; for (p = data; datalen; p++, datalen--) { @@ -311,7 +377,7 @@ /* Line break. */ outbuf[outidx++] = '\r'; outbuf[outidx++] = '\n'; - if ((rc = write_buffer (stream, outbuf, outidx))) + if ((rc = write_buffer (sink, outbuf, outidx))) return rc; outidx = 0; if (*p == '\r') @@ -363,7 +429,7 @@ { outbuf[outidx++] = '\r'; outbuf[outidx++] = '\n'; - if ((rc = write_buffer (stream, outbuf, outidx))) + if ((rc = write_buffer (sink, outbuf, outidx))) return rc; } @@ -373,15 +439,16 @@ } -/* Write DATALEN bytes of DATA to STREAM in plain ascii encoding. */ +/* Write DATALEN bytes of DATA to SINK in plain ascii encoding. */ static int -write_plain (LPSTREAM stream, const void *data, size_t datalen) +write_plain (sink_t sink, const void *data, size_t datalen) { int rc; const unsigned char *p; char outbuf[100]; int outidx; + log_debug (" writing ascii of length %d\n", (int)datalen); outidx = 0; for (p = data; datalen; p++, datalen--) { @@ -389,7 +456,7 @@ { outbuf[outidx++] = '\r'; outbuf[outidx++] = '\n'; - if ((rc = write_buffer (stream, outbuf, outidx))) + if ((rc = write_buffer (sink, outbuf, outidx))) return rc; outidx = 0; if (*p == '\r') @@ -424,7 +491,7 @@ { outbuf[outidx++] = '\r'; outbuf[outidx++] = '\n'; - if ((rc = write_buffer (stream, outbuf, outidx))) + if ((rc = write_buffer (sink, outbuf, outidx))) return rc; } @@ -660,18 +727,43 @@ -/* Write a MIME part to STREAM. The BOUNDARY is written first the - DATA is analyzed and appropriate headers are written. If FILENAME - is given it will be added to the part's header. IS_MAPIBODY should - be true if teh data has been retrieved from the body property. */ +/* Write a MIME part to SINK. First the BOUNDARY is written (unless + it is NULL) then the DATA is analyzed and appropriate headers are + written. If FILENAME is given it will be added to the part's + header. IS_MAPIBODY should be passed as true if the data has been + retrieved from the body property. */ static int -write_part (LPSTREAM stream, const char *data, size_t datalen, +write_part (sink_t sink, const char *data, size_t datalen, const char *boundary, const char *filename, int is_mapibody) { int rc; const char *ct; int use_b64, use_qp, is_text; + if (filename) + { + /* If there is a filename strip the directory part. Take care + that there might be slashes of backslashes. */ + const char *s1 = strrchr (filename, '/'); + const char *s2 = strrchr (filename, '\\'); + + if (!s1) + s1 = s2; + else if (s1 && s2 && s2 > s1) + s1 = s2; + + if (s1) + filename = s1; + if (*filename && filename[1] == ':') + filename += 2; + if (!*filename) + filename = NULL; + } + + log_debug ("Writing part of length %d%s filename=`%s'\n", + (int)datalen, is_mapibody? " (body)":"", + filename?filename:"[none]"); + ct = infer_content_type (data, datalen, filename, is_mapibody, &use_b64); use_qp = 0; if (!use_b64) @@ -685,42 +777,60 @@ } is_text = !strncmp (ct, "text/", 5); - if ((rc = write_boundary (stream, boundary, 0))) + if (boundary) + if ((rc = write_boundary (sink, boundary, 0))) + return rc; + if ((rc=write_multistring (sink, + "Content-Type: ", ct, + (is_text || filename? ";\r\n" :"\r\n"), + NULL))) return rc; - if (!(rc = write_string (stream, "Content-Type: "))) - if (!(rc = write_string (stream, ct))) - rc = write_string (stream, is_text? ";\r\n":"\r\n"); - if (rc) - return rc; /* OL inserts a charset parameter in many cases, so we do it right away for all text parts. We can assume us-ascii if no special encoding is required. */ if (is_text) - if ((rc = write_string (stream, (!use_qp && !use_b64)? - "\tcharset=\"us-ascii\"\r\n": - "\tcharset=\"utf-8\"\r\n"))) + if ((rc=write_multistring (sink, + "\tcharset=\"", + (!use_qp && !use_b64? "us-ascii" : "utf-8"), + filename ? "\";\r\n" : "\"\r\n", + NULL))) return rc; - + + if (filename) + if ((rc=write_multistring (sink, + "\tname=\"", filename, "\"\r\n", + NULL))) + return rc; + /* Note that we need to output even 7bit because OL inserts that anyway. */ - if (!(rc = write_string (stream, "Content-Transfer-Encoding: "))) - rc = write_string (stream, (use_b64? "base64\r\n": - use_qp? "quoted-printable\r\n":"7bit\r\n")); - if (rc) + if ((rc = write_multistring (sink, + "Content-Transfer-Encoding: ", + (use_b64? "base64\r\n": + use_qp? "quoted-printable\r\n":"7bit\r\n"), + NULL))) return rc; + if (filename) + if ((rc=write_multistring (sink, + "Content-Disposition: attachment;\r\n" + "\tfilename=\"", filename, "\"\r\n", + NULL))) + return rc; + + /* Write delimiter. */ - if ((rc = write_string (stream, "\r\n"))) + if ((rc = write_string (sink, "\r\n"))) return rc; /* Write the content. */ if (use_b64) - rc = write_b64 (stream, data, datalen); + rc = write_b64 (sink, data, datalen); else if (use_qp) - rc = write_qp (stream, data, datalen); + rc = write_qp (sink, data, datalen); else - rc = write_plain (stream, data, datalen); + rc = write_plain (sink, data, datalen); return rc; } @@ -741,11 +851,10 @@ return count; } -/* Write old all attachments from TABLE separated by BOUNDARY to - STREAM. This function needs to be syncronized with - count_usable_attachments. */ +/* Write old all attachments from TABLE separated by BOUNDARY to SINK. + This function needs to be syncronized with count_usable_attachments. */ static int -write_attachments (LPSTREAM stream, +write_attachments (sink_t sink, LPMESSAGE message, mapi_attach_item_t *table, const char *boundary) { @@ -765,7 +874,7 @@ log_debug ("Attachment at index %d: length=%d\n", idx, (int)buflen); if (!buffer) return -1; - rc = write_part (stream, buffer, buflen, boundary, + rc = write_part (sink, buffer, buflen, boundary, table[idx].filename, 0); xfree (buffer); } @@ -798,6 +907,118 @@ +/* Commit changes to the attachment ATTACH and release the object. + SINK needs to be passed as well and will also be closed. Note that + the address of ATTACH is expected so that the fucntion can set it + to NULL. */ +static int +close_mapi_attachment (LPATTACH *attach, sink_t sink) +{ + HRESULT hr; + LPSTREAM stream = sink? sink->cb_data : NULL; + + if (!stream) + { + log_error ("%s:%s: sink not setup", SRCNAME, __func__); + return -1; + } + hr = IStream_Commit (stream, 0); + if (hr) + { + log_error ("%s:%s: Commiting output stream failed: hr=%#lx", + SRCNAME, __func__, hr); + return -1; + } + IStream_Release (stream); + sink->cb_data = NULL; + hr = IAttach_SaveChanges (*attach, 0); + if (hr) + { + log_error ("%s:%s: SaveChanges of the attachment failed: hr=%#lx\n", + SRCNAME, __func__, hr); + return -1; + } + IAttach_Release (*attach); + *attach = NULL; + return 0; +} + + +/* Cancel changes to the attachment ATTACH and release the object. + SINK needs to be passed as well and will also be closed. Note that + the address of ATTACH is expected so that the fucntion can set it + to NULL. */ +static void +cancel_mapi_attachment (LPATTACH *attach, sink_t sink) +{ + LPSTREAM stream = sink? sink->cb_data : NULL; + + if (stream) + { + IStream_Revert (stream); + IStream_Release (stream); + sink->cb_data = NULL; + } + if (*attach) + { + /* Fixme: Should we try to delete it or is there a Revert method? */ + IAttach_Release (*attach); + *attach = NULL; + } +} + + + +/* Do the final processing for a message. */ +static int +finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table) +{ + HRESULT hr; + SPropValue prop; + + /* Set the message class. */ + prop.ulPropTag = PR_MESSAGE_CLASS_A; + prop.Value.lpszA = "IPM.Note.SMIME.MultipartSigned"; + hr = IMessage_SetProps (message, 1, &prop, NULL); + if (hr) + { + log_error ("%s:%s: error setting the message class: hr=%#lx\n", + SRCNAME, __func__, hr); + return -1; + } + + /* Now delete all parts of the MAPI message except for the one + attachment we just created. */ + if (delete_all_attachments (message, att_table)) + return -1; + { + /* Delete the body parts. We don't return any error because there + might be no body part at all. To avoid aliasing problems when + using static initialized array (SizedSPropTagArray macro) we + call it two times in a row. */ + SPropTagArray proparray; + + proparray.cValues = 1; + proparray.aulPropTag[0] = PR_BODY; + IMessage_DeleteProps (message, &proparray, NULL); + proparray.cValues = 1; + proparray.aulPropTag[0] = PR_BODY_HTML; + IMessage_DeleteProps (message, &proparray, NULL); + } + + /* Save the Changes. */ + hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE); + if (hr) + { + log_error ("%s:%s: SaveChanges to the message failed: hr=%#lx\n", + SRCNAME, __func__, hr); + return -1; + } + + return 0; +} + + /* Sign the MESSAGE using PROTOCOL. If PROTOCOL is PROTOCOL_UNKNOWN the engine decides what protocol to use. On return MESSAGE is modified so that sending it will result in a properly MOSS (that is @@ -807,13 +1028,13 @@ int mime_sign (LPMESSAGE message, protocol_t protocol) { + int result = -1; int rc; - HRESULT hr; - LPATTACH outattach; - LPSTREAM outstream; + LPATTACH attach; + struct sink_s sinkmem; + sink_t sink = &sinkmem; char boundary[BOUNDARYSIZE+1]; char inner_boundary[BOUNDARYSIZE+1]; - SPropValue prop; mapi_attach_item_t *att_table = NULL; char *body = NULL; int n_att_usable; @@ -822,8 +1043,8 @@ if (protocol == PROTOCOL_UNKNOWN) return -1; - outattach = create_mapi_attachment (message, &outstream); - if (!outattach) + attach = create_mapi_attachment (message, sink); + if (!attach) return -1; /* Get the attachment info and the body. */ @@ -843,75 +1064,71 @@ /* Write the top header. */ generate_boundary (boundary); - rc = write_string (outstream, ("MIME-Version: 1.0\r\n" - "Content-Type: multipart/signed;\r\n" - "\tprotocol=\"application/")); - if (!rc) - rc = write_string (outstream, - (protocol == PROTOCOL_OPENPGP - ? "pgp-signature" - : "pkcs7-signature")); - if (!rc) - rc = write_string (outstream, ("\";\r\n\tboundary=\"")); - if (!rc) - rc = write_string (outstream, boundary); - if (!rc) - rc = write_string (outstream, "\"\r\n"); + rc = write_multistring (sink, + "MIME-Version: 1.0\r\n" + "Content-Type: multipart/signed;\r\n" + "\tprotocol=\"application/", + (protocol == PROTOCOL_OPENPGP + ? "pgp-signature" + : "pkcs7-signature"), + "\";\r\n\tboundary=\"", + boundary, + "\"\r\n", + NULL); if (rc) goto failure; - + if ((body && n_att_usable) || n_att_usable > 1) { /* A body and at least one attachment or more than one attachment */ generate_boundary (inner_boundary); - rc = write_boundary (outstream, boundary, 0); - if (!rc) - rc = write_string (outstream, ("Content-Type: multipart/mixed;\r\n" - "\tboundary=\"")); - if (!rc) - rc = write_string (outstream, inner_boundary); - if (!rc) - rc = write_string (outstream, "\"\r\n"); - if (rc) + if ((rc = write_boundary (sink, boundary, 0))) goto failure; + if ((rc=write_multistring (sink, + "Content-Type: multipart/mixed;\r\n", + "\tboundary=\"", inner_boundary, "\"\r\n", + NULL))) + goto failure; } - else - { - /* Only one part. */ - *inner_boundary = 0; - } + else /* Only one part. */ + *inner_boundary = 0; + if (body) - rc = write_part (outstream, body, strlen (body), + rc = write_part (sink, body, strlen (body), *inner_boundary? inner_boundary : boundary, NULL, 1); if (!rc && n_att_usable) - rc = write_attachments (outstream, message, att_table, + rc = write_attachments (sink, message, att_table, *inner_boundary? inner_boundary : boundary); if (rc) goto failure; + + xfree (body); + body = NULL; + /* Finish the possible multipart/mixed. */ if (*inner_boundary) { - rc = write_boundary (outstream, inner_boundary, 1); + rc = write_boundary (sink, inner_boundary, 1); if (rc) goto failure; } - /* Write signature attachment. We don't write it directly but a - palceholder there. This spaceholder starts with the prefix of a - boundary so that it won't accidently occur in the actual content. */ - if ((rc = write_boundary (outstream, boundary, 0))) + + /* Write signature attachment. We don't write it directly but use a + placeholder. */ + if ((rc = write_boundary (sink, boundary, 0))) goto failure; - if ((rc = write_string (outstream, - (protocol == PROTOCOL_OPENPGP)? - "Content-Type: application/pgp-signature\r\n": - "Content-Type: application/pkcs7-signature\r\n"))) + if ((rc=write_string (sink, + (protocol == PROTOCOL_OPENPGP + ? "Content-Type: application/pgp-signature\r\n" + : "Content-Type: application/pkcs7-signature\r\n")))) goto failure; /* If we would add "Content-Transfer-Encoding: 7bit\r\n" to this - atatchment, Outlooks does not processed with sending and even + attachment, Outlooks does not processed with sending and even does not return any error. A wild guess is that while OL adds this header itself, it detects that it already exists and somehow gets into a problem. It is not a problem with the other parts, @@ -919,104 +1136,193 @@ Any way, it is not required that we add it as we won't hash it. */ - - if ((rc = write_string (outstream, "\r\n"))) + if ((rc = write_string (sink, "\r\n"))) goto failure; - if ((rc = write_string (outstream, "--=-=@SIGNATURE@\r\n\r\n"))) + /* Let the placeholder start with the prefix of a boundary so that + it won't accidently occur in the actual content. */ + if ((rc = write_string (sink, "--=-=@SIGNATURE@\r\n\r\n"))) goto failure; /* Write the final boundary and finish the attachment. */ - if ((rc = write_boundary (outstream, boundary, 1))) + if ((rc = write_boundary (sink, boundary, 1))) goto failure; - hr = IStream_Commit (outstream, 0); - if (hr) + if (close_mapi_attachment (&attach, sink)) + goto failure; + + if (finalize_message (message, att_table)) + goto failure; + + result = 0; /* Everything is fine, fall through the cleanup now. */ + + failure: + cancel_mapi_attachment (&attach, sink); + xfree (body); + mapi_release_attach_table (att_table); + return result; +} + + + +/* Sink write method used by mime_encrypt. */ +static int +sink_encryption_write (sink_t encsink, const void *data, size_t datalen) +{ + sink_t outsink = encsink->cb_data; + + if (!outsink) { - log_error ("%s:%s: Commiting output stream failed: hr=%#lx", - SRCNAME, __func__, hr); - goto failure; + log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__); + return -1; } - IStream_Release (outstream); - outstream = NULL; - hr = IAttach_SaveChanges (outattach, KEEP_OPEN_READWRITE); - if (hr) + if (!data) { - log_error ("%s:%s: SaveChanges of the attachment failed: hr=%#lx\n", - SRCNAME, __func__, hr); - goto failure; + /* Flush */ + return 0; } - IAttach_Release (outattach); - outattach = NULL; - /* Set the message class. */ - prop.ulPropTag = PR_MESSAGE_CLASS_A; - prop.Value.lpszA = "IPM.Note.SMIME.MultipartSigned"; - hr = IMessage_SetProps (message, 1, &prop, NULL); - if (hr) + return write_buffer (outsink, data, datalen); +} + + +/* Encrypt the MESSAGE. */ +int +mime_encrypt (LPMESSAGE message, protocol_t protocol) +{ + int result = -1; + int rc; + LPATTACH attach; + struct sink_s sinkmem; + sink_t sink = &sinkmem; + struct sink_s encsinkmem; + sink_t encsink = &encsinkmem; + char boundary[BOUNDARYSIZE+1]; + char inner_boundary[BOUNDARYSIZE+1]; + mapi_attach_item_t *att_table = NULL; + char *body = NULL; + int n_att_usable; + + protocol = check_protocol (protocol); + if (protocol == PROTOCOL_UNKNOWN) + return -1; + + /* FIXME For now only PGP/MIME is supported. */ + + attach = create_mapi_attachment (message, sink); + if (!attach) + return -1; + + /* Get the attachment info and the body. */ + body = mapi_get_body (message, NULL); + if (body && !*body) { - log_error ("%s:%s: error setting the message class: hr=%#lx\n", - SRCNAME, __func__, hr); + xfree (body); + body = NULL; + } + att_table = mapi_create_attach_table (message, 0); + n_att_usable = count_usable_attachments (att_table); + if (!n_att_usable && !body) + { + log_debug ("%s:%s: can't encrypt an empty message\n", SRCNAME, __func__); goto failure; } - /* Now delete all parts of the MAPI message except for the one - attachment we just created. */ - if ((rc = delete_all_attachments (message, att_table))) + /* Write the top header. */ + generate_boundary (boundary); + if ((rc=write_multistring (sink, + "MIME-Version: 1.0\r\n" + "Content-Type: multipart/encrypted;\r\n" + "\tprotocol=\"application/pgp-encrypted\";\r\n", + "\tboundary=\"", boundary, "\"\r\n", + NULL))) goto failure; - { - /* Delete the body parts. We don't return any error because there - might be no body part at all. To avoid aliasing problems when - using static initialized array (SizedSPropTagArray macro) we - call it two times in a row. */ - SPropTagArray proparray; - proparray.cValues = 1; - proparray.aulPropTag[0] = PR_BODY; - IMessage_DeleteProps (message, &proparray, NULL); - proparray.cValues = 1; - proparray.aulPropTag[0] = PR_BODY_HTML; - IMessage_DeleteProps (message, &proparray, NULL); - } + /* Write the PGP/MIME encrypted part. */ + if ((rc = write_boundary (sink, boundary, 0))) + goto failure; + if ((rc=write_multistring (sink, + "Content-Type: application/pgp-encrypted\r\n" + "\r\n" + "Version: 1\r\n", + NULL))) + goto failure; + + /* And start the second part. */ + if ((rc = write_boundary (sink, boundary, 0))) + goto failure; + if ((rc=write_multistring (sink, + "Content-Type: application/octet-stream\r\n" + "\r\n", NULL))) + goto failure; + + /* Create a new sink for encrypting the following stuff. */ + encsink->cb_data = sink; + encsink->writefnc = sink_encryption_write; + - /* Save the Changes. */ - hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE); - if (hr) + if ((body && n_att_usable) || n_att_usable > 1) { - log_error ("%s:%s: SaveChanges to the message failed: hr=%#lx\n", - SRCNAME, __func__, hr); - goto failure; + /* A body and at least one attachment or more than one attachment */ + generate_boundary (inner_boundary); + if ((rc=write_multistring (encsink, + "Content-Type: multipart/mixed;\r\n", + "\tboundary=\"", inner_boundary, "\"\r\n", + NULL))) + goto failure; } + else /* Only one part. */ + *inner_boundary = 0; + + if (body) + rc = write_part (encsink, body, strlen (body), + *inner_boundary? inner_boundary : NULL, NULL, 1); + if (!rc && n_att_usable) + rc = write_attachments (encsink, message, att_table, + *inner_boundary? inner_boundary : NULL); + if (rc) + goto failure; + xfree (body); - mapi_release_attach_table (att_table); - return 0; + body = NULL; + /* Finish the possible multipart/mixed. */ + if (*inner_boundary && (rc = write_boundary (encsink, inner_boundary, 1))) + goto failure; + + /* Flush the encryption sink and thus wait for the encryption to + get ready. */ + if ((rc = write_buffer (encsink, NULL, 0))) + goto failure; + /* FIXME: Release the encryption context etc. Using the flush above + is not a clean way of doing it. */ + encsink->cb_data = NULL; /* Not needed anymore. */ + + + /* Write the final boundary and finish the attachment. */ + if ((rc = write_boundary (sink, boundary, 1))) + goto failure; + + if (close_mapi_attachment (&attach, sink)) + goto failure; + + if (finalize_message (message, att_table)) + goto failure; + + result = 0; /* Everything is fine, fall through the cleanup now. */ + failure: - if (outstream) - { - IStream_Revert (outstream); - IStream_Release (outstream); - } - if (outattach) - { - /* Fixme: Should we try to delete it or is tehre a Revert method? */ - IAttach_Release (outattach); - } + if (encsink->cb_data) + ;/*FIXME: Cancel the encryption. */ + cancel_mapi_attachment (&attach, sink); xfree (body); mapi_release_attach_table (att_table); - return -1; + return result; } int -mime_encrypt (LPMESSAGE message, protocol_t protocol) -{ - return -1; -} - - -int mime_sign_encrypt (LPMESSAGE message, protocol_t protocol) { return -1; Modified: trunk/src/util.h =================================================================== --- trunk/src/util.h 2007-09-07 15:19:08 UTC (rev 174) +++ trunk/src/util.h 2007-09-08 11:18:38 UTC (rev 175) @@ -29,6 +29,13 @@ #endif #endif +#if __GNUC__ >= 4 +# define GPGOL_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) +#else +# define GPGOL_GCC_A_SENTINEL(a) +#endif + + /* To avoid that a compiler optimizes certain memset calls away, these macros may be used instead. */ #define wipememory2(_ptr,_set,_len) do { \ From cvs at cvs.gnupg.org Mon Sep 10 16:27:45 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 10 Sep 2007 16:27:45 +0200 Subject: [svn] assuan - r261 - trunk Message-ID: Author: marcus Date: 2007-09-10 16:27:16 +0200 (Mon, 10 Sep 2007) New Revision: 261 Modified: trunk/configure.ac Log: Set is_cvs. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-07 15:55:14 UTC (rev 260) +++ trunk/configure.ac 2007-09-10 14:27:16 UTC (rev 261) @@ -25,7 +25,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [1.0.3]) -m4_define([my_issvn], [no]) +#m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) From cvs at cvs.gnupg.org Mon Sep 10 16:42:34 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 10 Sep 2007 16:42:34 +0200 Subject: [svn] assuan - r262 - trunk Message-ID: Author: marcus Date: 2007-09-10 16:42:04 +0200 (Mon, 10 Sep 2007) New Revision: 262 Modified: trunk/configure.ac Log: Really enable snapshop packagin. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-10 14:27:16 UTC (rev 261) +++ trunk/configure.ac 2007-09-10 14:42:04 UTC (rev 262) @@ -25,7 +25,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [1.0.3]) -#m4_define([my_issvn], [no]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) From cvs at cvs.gnupg.org Mon Sep 10 17:41:26 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 10 Sep 2007 17:41:26 +0200 Subject: [svn] GnuPG - r4579 - in trunk: . po tools Message-ID: Author: wk Date: 2007-09-10 17:40:29 +0200 (Mon, 10 Sep 2007) New Revision: 4579 Modified: trunk/ChangeLog trunk/NEWS trunk/README.maint trunk/TODO trunk/configure.ac trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.po trunk/po/de.po trunk/po/el.po trunk/po/eo.po trunk/po/es.po trunk/po/et.po trunk/po/fi.po trunk/po/fr.po trunk/po/gl.po trunk/po/hu.po trunk/po/id.po trunk/po/it.po trunk/po/ja.po trunk/po/nb.po trunk/po/pl.po trunk/po/pt.po trunk/po/pt_BR.po trunk/po/ro.po trunk/po/ru.po trunk/po/sk.po trunk/po/sv.po trunk/po/tr.po trunk/po/zh_CN.po trunk/po/zh_TW.po trunk/tools/ChangeLog trunk/tools/gpgparsemail.c trunk/tools/rfc822parse.c Log: Preparing 2.0.7 Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/ChangeLog 2007-09-10 15:40:29 UTC (rev 4579) @@ -1,3 +1,7 @@ +2007-09-10 Werner Koch + + Released 2.0.7. + 2007-08-27 Werner Koch * configure.ac: Remove remaining support for internal regex. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/NEWS 2007-09-10 15:40:29 UTC (rev 4579) @@ -1,4 +1,4 @@ -Noteworthy changes in version 2.0.7 +Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ * Fixed encryption problem if duplicate certificates are in the Modified: trunk/README.maint =================================================================== --- trunk/README.maint 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/README.maint 2007-09-10 15:40:29 UTC (rev 4579) @@ -30,8 +30,8 @@ * Run "./autogen.sh --force" (--force is required for the svn magic in configure.ac and a good idea in any case) - * Run configure as usual. - * Run "make distcheck" + * Run "configure --enable-maintainer-mode". + * Run "make distcheck". * Build and test the new tarball (best on a different machine). * Build and test the W32 version. * Using the final test build run a "make -C doc online". Modified: trunk/TODO =================================================================== --- trunk/TODO 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/TODO 2007-09-10 15:40:29 UTC (rev 4579) @@ -125,7 +125,7 @@ * Howtos ** Migrate OpenPGP keys to another system -* Duplicate certifciates +* Duplicate certificates This may happen and lead to an Ambiguous Name error. Solution is to check the certs for identity before throwing this error. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/configure.ac 2007-09-10 15:40:29 UTC (rev 4579) @@ -25,7 +25,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [2.0.7]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ Modified: trunk/po/be.po =================================================================== --- trunk/po/be.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/be.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2003-10-30 16:35+0200\n" "Last-Translator: Ales Nyakhaychyk \n" "Language-Team: Belarusian \n" @@ -664,7 +664,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "?????????????? ???????????????????? \"%s\": %s\n" @@ -7545,7 +7545,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/ca.po =================================================================== --- trunk/po/ca.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/ca.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -27,7 +27,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2005-02-04 02:04+0100\n" "Last-Translator: Jordi Mallach \n" "Language-Team: Catalan \n" @@ -700,7 +700,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "error en la creaci?? de la contrasenya: %s\n" @@ -8134,7 +8134,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/cs.po =================================================================== --- trunk/po/cs.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/cs.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: gnupg-1.3.92\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-11-26 09:12+0200\n" "Last-Translator: Roman Pavlik \n" "Language-Team: Czech \n" @@ -676,7 +676,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "chyba p?i vytv??en? hesla: %s\n" @@ -7815,7 +7815,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/da.po =================================================================== --- trunk/po/da.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/da.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: gnupg 1.0.0h\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2003-12-03 16:11+0100\n" "Last-Translator: Birger Langkjer \n" "Language-Team: Danish \n" @@ -669,7 +669,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "fejl ved oprettelse af kodes?tning: %s\n" @@ -7700,7 +7700,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/de.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg-2.0.6\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2007-08-29 18:51+0200\n" "Last-Translator: Walter Koch \n" "Language-Team: German \n" @@ -688,7 +688,7 @@ msgid "I'll change it later" msgstr "Ich werde sie sp??ter ??ndern" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, c-format msgid "error creating a pipe: %s\n" msgstr "Fehler beim Erzeugen einer \"Pipe\": %s\n" @@ -7907,7 +7907,7 @@ msgid "Configuration for OCSP" msgstr "Konfiguration zu OCSP" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "Beachten Sie, da?? Gruppenspezifiaktionen ignoriert werden\n" Modified: trunk/po/el.po =================================================================== --- trunk/po/el.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/el.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg-1.1.92\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2003-06-27 12:00+0200\n" "Last-Translator: Dokianakis Theofanis \n" "Language-Team: Greek \n" @@ -674,7 +674,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "?????? ??? ?????????? ??? ?????? ??????: %s\n" @@ -7988,7 +7988,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/eo.po =================================================================== --- trunk/po/eo.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/eo.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.0.6d\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2002-04-14 14:33+0100\n" "Last-Translator: Edmund GRIMLEY EVANS \n" "Language-Team: Esperanto \n" @@ -674,7 +674,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "eraro dum kreado de pasfrazo: %s\n" @@ -7934,7 +7934,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/es.po =================================================================== --- trunk/po/es.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/es.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.1\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2007-08-16 11:35+0200\n" "Last-Translator: Jaime Su?rez \n" "Language-Team: Spanish \n" @@ -705,7 +705,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "error creando frase contrase?a: %s\n" @@ -7862,7 +7862,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/et.po =================================================================== --- trunk/po/et.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/et.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-17 11:04+0300\n" "Last-Translator: Toomas Soome \n" "Language-Team: Estonian \n" @@ -673,7 +673,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "viga parooli loomisel: %s\n" @@ -7893,7 +7893,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/fi.po =================================================================== --- trunk/po/fi.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/fi.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -22,7 +22,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-16 22:40+0300\n" "Last-Translator: Tommi Vainikainen \n" "Language-Team: Finnish \n" @@ -690,7 +690,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "virhe luotaessa salasanaa: %s\n" @@ -7972,7 +7972,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/fr.po =================================================================== --- trunk/po/fr.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/fr.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.2rc2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2005-06-28 00:24+0200\n" "Last-Translator: Ga?l Qu?ri \n" "Language-Team: French \n" @@ -690,7 +690,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "erreur pendant la cr?ation de la phrase de passe: %s\n" @@ -8019,7 +8019,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/gl.po =================================================================== --- trunk/po/gl.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/gl.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.4\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2003-12-04 11:39+0100\n" "Last-Translator: Jacobo Tarrio \n" "Language-Team: Galician \n" @@ -678,7 +678,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "erro ao crea-lo contrasinal: %s\n" @@ -7983,7 +7983,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/hu.po =================================================================== --- trunk/po/hu.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/hu.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.5\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-19 21:53+0200\n" "Last-Translator: Nagy Ferenc L?szl? \n" "Language-Team: Hungarian \n" @@ -673,7 +673,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "Hiba a jelsz? l?trehoz?sakor: %s.\n" @@ -7934,7 +7934,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/id.po =================================================================== --- trunk/po/id.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/id.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: gnupg-id\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-17 16:32+0700\n" "Last-Translator: Tedi Heriyanto \n" "Language-Team: Indonesian \n" @@ -675,7 +675,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "kesalahan penciptaan passphrase: %s\n" @@ -7936,7 +7936,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/it.po =================================================================== --- trunk/po/it.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/it.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.1.92\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-16 17:01+0200\n" "Last-Translator: Marco d'Itri \n" "Language-Team: Italian \n" @@ -673,7 +673,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "errore nella creazione della passhprase: %s\n" @@ -7982,7 +7982,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/ja.po =================================================================== --- trunk/po/ja.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/ja.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg 1.3.92\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-11-23 11:14+0900\n" "Last-Translator: IIDA Yosiaki \n" "Language-Team: Japanese \n" @@ -676,7 +676,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "????????????????????????: %s\n" @@ -7749,7 +7749,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/nb.po =================================================================== --- trunk/po/nb.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/nb.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -10,7 +10,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.3\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2006-06-13 20:31+0200\n" "Last-Translator: Trond Endrest?l \n" "Language-Team: Norwegian Bokm?l \n" @@ -671,7 +671,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "feil ved opprettelse av passfrase: %s\n" @@ -7618,7 +7618,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/pl.po =================================================================== --- trunk/po/pl.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/pl.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: gnupg-1.2.2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-06-23 15:54+0200\n" "Last-Translator: Janusz A. Urbanowicz \n" "Language-Team: Polish \n" @@ -684,7 +684,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "b??d podczas tworzenia has?a: %s\n" @@ -7979,7 +7979,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/pt.po =================================================================== --- trunk/po/pt.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/pt.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2002-09-13 18:26+0100\n" "Last-Translator: Pedro Morais \n" "Language-Team: pt \n" @@ -677,7 +677,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "erro na cria??o da frase secreta: %s\n" @@ -7950,7 +7950,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/pt_BR.po =================================================================== --- trunk/po/pt_BR.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/pt_BR.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -13,7 +13,7 @@ msgstr "" "Project-Id-Version: gnupg 1.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2007-08-16 11:35+0200\n" "Last-Translator:\n" "Language-Team: ?\n" @@ -678,7 +678,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "erro na cria??o da frase secreta: %s\n" @@ -7902,7 +7902,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/ro.po =================================================================== --- trunk/po/ro.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/ro.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.2rc1\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2005-05-31 22:00-0500\n" "Last-Translator: Laurentiu Buzdugan \n" "Language-Team: Romanian \n" @@ -682,7 +682,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "eroare la crearea frazei-parol?: %s\n" @@ -7843,7 +7843,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/ru.po =================================================================== --- trunk/po/ru.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/ru.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: GnuPG 2.0.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2006-11-07 19:31+0300\n" "Last-Translator: Maxim Britov \n" "Language-Team: Russian \n" @@ -660,7 +660,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, c-format msgid "error creating a pipe: %s\n" msgstr "" @@ -7703,7 +7703,7 @@ msgid "Configuration for OCSP" msgstr "?????????????????? OCSP" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/sk.po =================================================================== --- trunk/po/sk.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/sk.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: gnupg 1.2.5\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2004-07-20 15:52+0200\n" "Last-Translator: Michal Majer \n" "Language-Team: Slovak \n" @@ -674,7 +674,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "chyba pri vytv?ran? hesla: %s\n" @@ -7954,7 +7954,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/sv.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -24,7 +24,7 @@ msgstr "" "Project-Id-Version: gnupg 2.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2007-02-17 13:13+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -695,7 +695,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, c-format msgid "error creating a pipe: %s\n" msgstr "fel n??r ett r??r skapades: %s\n" @@ -7916,7 +7916,7 @@ msgid "Configuration for OCSP" msgstr "Konfiguration f??r OCSP" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/tr.po =================================================================== --- trunk/po/tr.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/tr.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: gnupg 1.9.94\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2006-11-04 03:45+0200\n" "Last-Translator: Nilg??n Belma Bug??ner \n" "Language-Team: Turkish \n" @@ -665,7 +665,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, c-format msgid "error creating a pipe: %s\n" msgstr "boru olu??turulurken hata: %s\n" @@ -7791,7 +7791,7 @@ msgid "Configuration for OCSP" msgstr "OCSP i??in yap??land??rma" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/zh_CN.po =================================================================== --- trunk/po/zh_CN.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/zh_CN.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.4\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2006-07-02 10:58+0800\n" "Last-Translator: Meng Jie \n" "Language-Team: Chinese (simplified) \n" @@ -680,7 +680,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "????????????????????????????????????%s\n" @@ -7651,7 +7651,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/po/zh_TW.po =================================================================== --- trunk/po/zh_TW.po 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/po/zh_TW.po 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg 1.4.2\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-08-29 18:43+0200\n" +"POT-Creation-Date: 2007-09-10 17:28+0200\n" "PO-Revision-Date: 2005-07-29 09:49+0800\n" "Last-Translator: Jedi \n" "Language-Team: Chinese (traditional) \n" @@ -676,7 +676,7 @@ msgid "I'll change it later" msgstr "" -#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1313 +#: common/exechelp.c:371 common/exechelp.c:459 tools/gpgconf-comp.c:1340 #, fuzzy, c-format msgid "error creating a pipe: %s\n" msgstr "?????????????????????????????????: %s\n" @@ -7691,7 +7691,7 @@ msgid "Configuration for OCSP" msgstr "" -#: tools/gpgconf-comp.c:2955 +#: tools/gpgconf-comp.c:2982 msgid "Note that group specifications are ignored\n" msgstr "" Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/tools/ChangeLog 2007-09-10 15:40:29 UTC (rev 4579) @@ -9,6 +9,8 @@ 2007-08-31 Werner Koch + * gpgparsemail.c: Support PGP/MIME signed messages. + * gpgconf-comp.c (gc_component_list_components): List the programs names. Modified: trunk/tools/gpgparsemail.c =================================================================== --- trunk/tools/gpgparsemail.c 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/tools/gpgparsemail.c 2007-09-10 15:40:29 UTC (rev 4579) @@ -1,5 +1,5 @@ /* gpgparsemail.c - Standalone crypto mail parser - * Copyright (C) 2004 Free Software Foundation, Inc. + * Copyright (C) 2004, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -64,7 +64,9 @@ int is_pkcs7; /* Old style S/MIME message. */ - int gpgsm_mime; /* gpgsm shall be used from S/MIME. */ + int moss_state; /* State of PGP/MIME or S/MIME parsing. */ + int is_smime; /* This is S/MIME and not PGP/MIME. */ + char *signing_protocol; int hashing_level; /* The nesting level we are hashing. */ int hashing; @@ -167,7 +169,6 @@ int i, c, is_status; unsigned int pos; char status_buf[10]; - const char *cmd = smime? "gpgsm":"gpg"; FILE *fp; if (pipe (rp) == -1) @@ -218,15 +219,25 @@ close (fd); errno = 0; - execlp (cmd, cmd, - "--enable-special-filenames", - "--status-fd", "2", - "--assume-base64", - "--verify", - "--", - "-", data_fd == -1? NULL : data_fd_buf, - NULL); - + if (smime) + execlp ("gpgsm", "gpgsm", + "--enable-special-filenames", + "--status-fd", "2", + "--assume-base64", + "--verify", + "--", + "-", data_fd == -1? NULL : data_fd_buf, + NULL); + else + execlp ("gpg", "gpg", + "--enable-special-filenames", + "--status-fd", "2", + "--verify", + "--debug=512", + "--", + "-", data_fd == -1? NULL : data_fd_buf, + NULL); + die ("failed to exec the crypto command: %s", strerror (errno)); } @@ -323,7 +334,7 @@ /* rewind (info->sig_file); */ close_list[0] = -1; - run_gnupg (1, fileno (info->sig_file), + run_gnupg (info->is_smime, fileno (info->sig_file), info->hash_file ? fileno (info->hash_file) : -1, close_list); } @@ -342,18 +353,31 @@ if (s) { printf ("h signed.protocol: %s\n", s); - if (!strcmp (s, "application/pkcs7-signature") - || !strcmp (s, "application/x-pkcs7-signature")) + if (!strcmp (s, "application/pgp-signature")) { - if (info->gpgsm_mime) - err ("note: ignoring nested pkcs7-signature"); + if (info->moss_state) + err ("note: ignoring nested PGP/MIME or S/MIME signature"); else { - info->gpgsm_mime = 1; + info->moss_state = 1; + info->is_smime = 0; free (info->signing_protocol); info->signing_protocol = xstrdup (s); } } + else if (!strcmp (s, "application/pkcs7-signature") + || !strcmp (s, "application/x-pkcs7-signature")) + { + if (info->moss_state) + err ("note: ignoring nested PGP/MIME or S/MIME signature"); + else + { + info->moss_state = 1; + info->is_smime = 1; + free (info->signing_protocol); + info->signing_protocol = xstrdup (s); + } + } else if (verbose) printf ("# this protocol is not supported\n"); } @@ -435,6 +459,30 @@ if (debug) show_event (event); + + if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY) + { + /* We need to check here whether to start collecting signed data + because attachments might come without header lines and thus + we won't see the BEGIN_HEADER event. */ + if (info->moss_state == 1) + { + printf ("c begin_hash\n"); + info->hashing = 1; + info->hashing_level = info->nesting_level; + info->moss_state++; + + if (opt_crypto) + { + assert (!info->hash_file); + info->hash_file = tmpfile (); + if (!info->hash_file) + die ("failed to create temporary file: %s", strerror (errno)); + } + } + } + + if (event == RFC822PARSE_OPEN) { /* Initialize for a new message. */ @@ -453,18 +501,19 @@ { printf ("h media: %*s%s %s\n", info->nesting_level*2, "", s1, s2); - if (info->gpgsm_mime == 3) + if (info->moss_state == 3) { char *buf = xmalloc (strlen (s1) + strlen (s2) + 2); strcpy (stpcpy (stpcpy (buf, s1), "/"), s2); assert (info->signing_protocol); if (strcmp (buf, info->signing_protocol)) - err ("invalid S/MIME structure; expected `%s', found `%s'", + err ("invalid %s structure; expected `%s', found `%s'", + info->is_smime? "S/MIME":"PGP/MIME", info->signing_protocol, buf); else { printf ("c begin_signature\n"); - info->gpgsm_mime++; + info->moss_state++; if (opt_crypto) { assert (!info->sig_file); @@ -490,12 +539,14 @@ } else printf ("h media: %*s none\n", info->nesting_level*2, ""); - + rfc822parse_release_field (ctx); } else printf ("h media: %*stext plain [assumed]\n", info->nesting_level*2, ""); + + info->show_header = 0; info->show_data = 1; info->skip_show = 1; @@ -528,37 +579,19 @@ else printf ("b last\n"); - if (info->gpgsm_mime == 2 && info->nesting_level == info->hashing_level) + if (info->moss_state == 2 && info->nesting_level == info->hashing_level) { printf ("c end_hash\n"); - info->gpgsm_mime++; + info->moss_state++; info->hashing = 0; } - else if (info->gpgsm_mime == 4) + else if (info->moss_state == 4) { printf ("c end_signature\n"); info->verify_now = 1; } } - else if (event == RFC822PARSE_BEGIN_HEADER) - { - if (info->gpgsm_mime == 1) - { - printf ("c begin_hash\n"); - info->hashing = 1; - info->hashing_level = info->nesting_level; - info->gpgsm_mime++; - if (opt_crypto) - { - assert (!info->hash_file); - info->hash_file = tmpfile (); - if (!info->hash_file) - die ("failed to create temporary file: %s", strerror (errno)); - } - } - } - return 0; } @@ -634,7 +667,8 @@ info.hash_file = NULL; fclose (info.sig_file); info.sig_file = NULL; - info.gpgsm_mime = 0; + info.moss_state = 0; + info.is_smime = 0; info.is_pkcs7 = 0; } else @@ -760,6 +794,6 @@ /* Local Variables: -compile-command: "gcc -Wall -g -o gpgparsemail rfc822parse.c gpgparsemail.c" +compile-command: "gcc -Wall -Wno-pointer-sign -g -o gpgparsemail rfc822parse.c gpgparsemail.c" End: */ Modified: trunk/tools/rfc822parse.c =================================================================== --- trunk/tools/rfc822parse.c 2007-09-04 07:16:49 UTC (rev 4578) +++ trunk/tools/rfc822parse.c 2007-09-10 15:40:29 UTC (rev 4579) @@ -1251,6 +1251,6 @@ /* Local Variables: -compile-command: "gcc -Wall -g -DTESTING -o rfc822parse rfc822parse.c" +compile-command: "gcc -Wall -Wno-pointer-sign -g -DTESTING -o rfc822parse rfc822parse.c" End: */ From cvs at cvs.gnupg.org Mon Sep 10 18:36:44 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 10 Sep 2007 18:36:44 +0200 Subject: [svn] GnuPG - r4580 - tags Message-ID: Author: wk Date: 2007-09-10 18:36:15 +0200 (Mon, 10 Sep 2007) New Revision: 4580 Added: tags/gnupg-2.0.7/ Log: Release, yeah! Copied: tags/gnupg-2.0.7 (from rev 4579, trunk) From cvs at cvs.gnupg.org Mon Sep 10 18:38:33 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 10 Sep 2007 18:38:33 +0200 Subject: [svn] GnuPG - r4581 - trunk Message-ID: Author: wk Date: 2007-09-10 18:38:04 +0200 (Mon, 10 Sep 2007) New Revision: 4581 Modified: trunk/NEWS trunk/configure.ac Log: post release version bump Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-10 16:36:15 UTC (rev 4580) +++ trunk/NEWS 2007-09-10 16:38:04 UTC (rev 4581) @@ -1,3 +1,7 @@ +Noteworthy changes in version 2.0.8 +------------------------------------------------ + + Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-10 16:36:15 UTC (rev 4580) +++ trunk/configure.ac 2007-09-10 16:38:04 UTC (rev 4581) @@ -24,8 +24,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.0.7]) -m4_define([my_issvn], [no]) +m4_define([my_version], [2.0.8]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ From cvs at cvs.gnupg.org Tue Sep 11 00:37:33 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 00:37:33 +0200 Subject: [svn] GpgEX - r14 - in trunk: . po Message-ID: Author: marcus Date: 2007-09-11 00:37:03 +0200 (Tue, 11 Sep 2007) New Revision: 14 Added: trunk/po/de.po Modified: trunk/ChangeLog trunk/Makefile.am trunk/po/LINGUAS Log: 2007-09-11 Marcus Brinkmann * po/de.po: New file. * po/LINGUAS: Add de. * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --with-libassuan-prefix and --with-gpg-error-prefix. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-05 14:41:42 UTC (rev 13) +++ trunk/ChangeLog 2007-09-10 22:37:03 UTC (rev 14) @@ -1,3 +1,10 @@ +2007-09-11 Marcus Brinkmann + + * po/de.po: New file. + * po/LINGUAS: Add de. + * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add + --with-libassuan-prefix and --with-gpg-error-prefix. + 2007-09-04 Marcus Brinkmann * m4/libassuan.m4, m4/gpg-error.m4: New files. Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-09-05 14:41:42 UTC (rev 13) +++ trunk/Makefile.am 2007-09-10 22:37:03 UTC (rev 14) @@ -15,6 +15,8 @@ AUTOMAKE_OPTIONS = dist-bzip2 # Because we can only build the w32 version e need to help automake here a bit. DISTCHECK_CONFIGURE_FLAGS = --host=i586-mingw32msvc --build=i686-pc-linux-gnu \ + --with-libassuan-prefix=@prefix@ \ + --with-gpg-error-prefix=@prefix@ \ --prefix=@prefix@ EXTRA_DIST = autogen.sh Modified: trunk/po/LINGUAS =================================================================== --- trunk/po/LINGUAS 2007-09-05 14:41:42 UTC (rev 13) +++ trunk/po/LINGUAS 2007-09-10 22:37:03 UTC (rev 14) @@ -1,2 +1,2 @@ # Set of available languages. - +de Added: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-05 14:41:42 UTC (rev 13) +++ trunk/po/de.po 2007-09-10 22:37:03 UTC (rev 14) @@ -0,0 +1,41 @@ +# German translations for gpgex package. +# Copyright (C) 2007 g10 Code GmbH +# This file is distributed under the same license as the gpgex package. +# Marcus Brinkmann , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: gpgex 0.0.0-svn10\n" +"Report-Msgid-Bugs-To: bug-gpgex at g10code.com\n" +"POT-Creation-Date: 2007-09-10 22:59+0200\n" +"PO-Revision-Date: 2007-09-10 23:05+0200\n" +"Last-Translator: Marcus Brinkmann \n" +"Language-Team: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/client.cc:136 +msgid "Can not access Kleopatra, see log file for details" +msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei fuer Details" + +#: src/gpgex.h:42 +msgid "Help on GpgEX" +msgstr "Hilfe zu GpgEX" + +#: src/gpgex.h:43 +msgid "Decrypt and verify" +msgstr "Entschl?sseln und verifizieren" + +#: src/gpgex.h:44 +msgid "Sign and encrypt" +msgstr "Verschl?sseln und signieren" + +#: src/gpgex.h:45 +msgid "Zertifikate importieren" +msgstr "" + +#: src/gpgex.cc:274 +msgid "Mehr GpgEX Optionen" +msgstr "" From cvs at cvs.gnupg.org Tue Sep 11 12:36:53 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 12:36:53 +0200 Subject: [svn] assuan - r263 - trunk/src Message-ID: Author: marcus Date: 2007-09-11 12:36:23 +0200 (Tue, 11 Sep 2007) New Revision: 263 Modified: trunk/src/ChangeLog trunk/src/assuan.h Log: 2007-09-11 Marcus Brinkmann * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-10 14:42:04 UTC (rev 262) +++ trunk/src/ChangeLog 2007-09-11 10:36:23 UTC (rev 263) @@ -1,3 +1,7 @@ +2007-09-11 Marcus Brinkmann + + * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. + 2007-09-07 Marcus Brinkmann * assuan-inquire.c (assuan_inquire_ext): If MAXLEN is 0, still Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-09-10 14:42:04 UTC (rev 262) +++ trunk/src/assuan.h 2007-09-11 10:36:23 UTC (rev 263) @@ -455,7 +455,7 @@ /*-- assuan-connect.c --*/ void assuan_disconnect (assuan_context_t ctx); pid_t assuan_get_pid (assuan_context_t ctx); -#ifndef HAVE_W32_SYSTEM +#ifndef _WIN32 assuan_error_t assuan_get_peercred (assuan_context_t ctx, pid_t *pid, uid_t *uid, gid_t *gid); #endif From cvs at cvs.gnupg.org Tue Sep 11 15:04:03 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 15:04:03 +0200 Subject: [svn] GpgEX - r15 - trunk/po Message-ID: Author: marcus Date: 2007-09-11 15:03:34 +0200 (Tue, 11 Sep 2007) New Revision: 15 Modified: trunk/po/de.po Log: Fix translations. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-10 22:37:03 UTC (rev 14) +++ trunk/po/de.po 2007-09-11 13:03:34 UTC (rev 15) @@ -8,7 +8,7 @@ "Project-Id-Version: gpgex 0.0.0-svn10\n" "Report-Msgid-Bugs-To: bug-gpgex at g10code.com\n" "POT-Creation-Date: 2007-09-10 22:59+0200\n" -"PO-Revision-Date: 2007-09-10 23:05+0200\n" +"PO-Revision-Date: 2007-09-11 14:56+0200\n" "Last-Translator: Marcus Brinkmann \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -33,9 +33,9 @@ msgstr "Verschl?sseln und signieren" #: src/gpgex.h:45 -msgid "Zertifikate importieren" -msgstr "" +msgid "Import keys" +msgstr "Zertifikate importieren" #: src/gpgex.cc:274 -msgid "Mehr GpgEX Optionen" -msgstr "" +msgid "More GpgEX options" +msgstr "Mehr GpgEX Optionen" From cvs at cvs.gnupg.org Tue Sep 11 15:53:08 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 15:53:08 +0200 Subject: [svn] GpgEX - r16 - trunk/src Message-ID: Author: marcus Date: 2007-09-11 15:52:39 +0200 (Tue, 11 Sep 2007) New Revision: 16 Modified: trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/client.cc trunk/src/registry.c trunk/src/registry.h Log: 2007-09-11 Marcus Brinkmann * Makefile.am (libgpg-error.a, libassuan.a): Use -f flag with ln. * registry.h (default_dir): New prototype. * registry.c (default_dir, standard_homedir): New functions. * client.cc (default_socket_name): Use default home dir instead install directory. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-11 13:03:34 UTC (rev 15) +++ trunk/src/ChangeLog 2007-09-11 13:52:39 UTC (rev 16) @@ -1,3 +1,11 @@ +2007-09-11 Marcus Brinkmann + + * Makefile.am (libgpg-error.a, libassuan.a): Use -f flag with ln. + * registry.h (default_dir): New prototype. + * registry.c (default_dir, standard_homedir): New functions. + * client.cc (default_socket_name): Use default home dir instead + install directory. + 2007-09-05 Marcus Brinkmann * gpgex.h (class gpgex_t): Make destructor virtual to silence Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-11 13:03:34 UTC (rev 15) +++ trunk/src/Makefile.am 2007-09-11 13:52:39 UTC (rev 16) @@ -41,10 +41,10 @@ # -L . -lshell32 -lcomdlg32 -loleaut32 -ladvapi32 libgpg-error.a: - ln -s $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a + ln -sf $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a libassuan.a: - ln -s $(shell $(LIBASSUAN_CONFIG) --prefix)/lib/libassuan.a + ln -sf $(shell $(LIBASSUAN_CONFIG) --prefix)/lib/libassuan.a clean-local: rm -f libgpg-error.a libassuan.a Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-09-11 13:03:34 UTC (rev 15) +++ trunk/src/client.cc 2007-09-11 13:52:39 UTC (rev 16) @@ -44,16 +44,15 @@ { static string name; - if (name.size() == 0) + if (name.size () == 0) { char *dir = NULL; /* FIXME: Wrong directory. */ - dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, - "Install Directory"); + dir = default_homedir (); if (dir) { - try { name = ((string) dir) + "\\S.kleopatra"; } catch (...) {} + try { name = ((string) dir) + "\\S.uiserver"; } catch (...) {} free ((void *) dir); } } Modified: trunk/src/registry.c =================================================================== --- trunk/src/registry.c 2007-09-11 13:03:34 UTC (rev 15) +++ trunk/src/registry.c 2007-09-11 13:52:39 UTC (rev 16) @@ -22,8 +22,20 @@ #include #endif +#include #include +#include +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_FLAG_CREATE +#define CSIDL_FLAG_CREATE 0x8000 +#endif + #include "registry.h" @@ -176,3 +188,84 @@ RegCloseKey( key_handle ); return result; } + + +/* Get the standard home directory. In general this function should + not be used as it does not consider a registry value (under W32) or + the GNUPGHOME encironment variable. It is better to use + default_homedir(). */ +static char * +standard_homedir (void) +{ + static char *dir; + + if (!dir) + { + char path[MAX_PATH]; + + /* It might be better to use LOCAL_APPDATA because this is + defined as "non roaming" and thus more likely to be kept + locally. For private keys this is desired. However, given + that many users copy private keys anyway forth and back, + using a system roaming services might be better than to let + them do it manually. A security conscious user will anyway + use the registry entry to have better control. */ + if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0, path) >= 0) + { + char *tmp = malloc (strlen (path) + 6 + 1); + + strcpy (tmp, path); + strcat (tmp, "\\gnupg"); + + dir = tmp; + + /* Try to create the directory if it does not yet exists. */ + if (access (dir, F_OK)) + CreateDirectory (dir, NULL); + } + else + dir = "C:\\gnupg"; + } + return dir; +} + + +/* Retrieve the default home directory. */ +char * +default_homedir (void) +{ + char *dir; + + dir = getenv ("GNUPGHOME"); + if (!dir || !*dir) + { + static char *saved_dir; + + if (!saved_dir) + { + if (!dir || !*dir) + { + char *tmp; + + tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", + "HomeDir"); + if (tmp && *tmp) + { + free (tmp); + tmp = NULL; + } + if (tmp) + saved_dir = tmp; + } + + if (!saved_dir) + saved_dir = standard_homedir (); + } + dir = saved_dir; + } + if (!dir || !*dir) + dir = "C:\\gnupg"; + + return dir; +} Modified: trunk/src/registry.h =================================================================== --- trunk/src/registry.h 2007-09-11 13:03:34 UTC (rev 15) +++ trunk/src/registry.h 2007-09-11 13:52:39 UTC (rev 16) @@ -40,6 +40,9 @@ char *read_w32_registry_string (const char *root, const char *dir, const char *name); +/* Retrieve the default home directory. */ +char *default_homedir (void); + #ifdef __cplusplus #if 0 { From cvs at cvs.gnupg.org Tue Sep 11 16:29:27 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 16:29:27 +0200 Subject: [svn] GpgEX - r17 - in trunk: . po src Message-ID: Author: marcus Date: 2007-09-11 16:28:55 +0200 (Tue, 11 Sep 2007) New Revision: 17 Modified: trunk/ChangeLog trunk/po/POTFILES.in trunk/po/de.po trunk/src/ChangeLog trunk/src/client.cc trunk/src/client.h trunk/src/gpgex.cc trunk/src/gpgex.h Log: po/ 2007-09-11 Marcus Brinkmann * po/de.po: Update. src/ 2007-09-11 Marcus Brinkmann * client.h (class client_t): New members decrypt, verify, encrypt, and sign. * client.cc: Add implementations for these. * gpgex.h: Move all ID_CMD_* macros to ... * gpgex.cc: ... here. Add new macros for new commands. (gpgex_t::InvokeCommand, gpgex_t::QueryContextMenu): Implement new commands. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/ChangeLog 2007-09-11 14:28:55 UTC (rev 17) @@ -1,6 +1,9 @@ 2007-09-11 Marcus Brinkmann + * po/de.po: Update. + * po/de.po: New file. + * po/LINGUAS: Add de. * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --with-libassuan-prefix and --with-gpg-error-prefix. Modified: trunk/po/POTFILES.in =================================================================== --- trunk/po/POTFILES.in 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/po/POTFILES.in 2007-09-11 14:28:55 UTC (rev 17) @@ -1,4 +1,3 @@ src/main.cc src/client.cc -src/gpgex.h src/gpgex.cc Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/po/de.po 2007-09-11 14:28:55 UTC (rev 17) @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: gpgex 0.0.0-svn10\n" "Report-Msgid-Bugs-To: bug-gpgex at g10code.com\n" -"POT-Creation-Date: 2007-09-10 22:59+0200\n" -"PO-Revision-Date: 2007-09-11 14:56+0200\n" +"POT-Creation-Date: 2007-09-11 16:17+0200\n" +"PO-Revision-Date: 2007-09-11 16:20+0200\n" "Last-Translator: Marcus Brinkmann \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -16,26 +16,42 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: src/client.cc:136 +#: src/client.cc:135 msgid "Can not access Kleopatra, see log file for details" -msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei fuer Details" +msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei f?r Details" -#: src/gpgex.h:42 +#: src/gpgex.cc:51 msgid "Help on GpgEX" msgstr "Hilfe zu GpgEX" -#: src/gpgex.h:43 +#: src/gpgex.cc:52 msgid "Decrypt and verify" -msgstr "Entschl??sseln und verifizieren" +msgstr "Entschl?sseln und verifizieren" -#: src/gpgex.h:44 -msgid "Sign and encrypt" -msgstr "Verschl??sseln und signieren" +#: src/gpgex.cc:53 +msgid "Decrypt" +msgstr "Entschl?sseln" -#: src/gpgex.h:45 +#: src/gpgex.cc:54 +msgid "Verify" +msgstr "Verifizieren" + +#: src/gpgex.cc:55 +msgid "Encrypt and sign" +msgstr "Verschl?sseln und verifizieren" + +#: src/gpgex.cc:56 +msgid "Encrypt" +msgstr "Verschl?sseln" + +#: src/gpgex.cc:57 +msgid "Sign" +msgstr "Signieren" + +#: src/gpgex.cc:58 msgid "Import keys" msgstr "Zertifikate importieren" -#: src/gpgex.cc:274 +#: src/gpgex.cc:295 msgid "More GpgEX options" msgstr "Mehr GpgEX Optionen" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/src/ChangeLog 2007-09-11 14:28:55 UTC (rev 17) @@ -1,5 +1,13 @@ 2007-09-11 Marcus Brinkmann + * client.h (class client_t): New members decrypt, verify, encrypt, + and sign. + * client.cc: Add implementations for these. + * gpgex.h: Move all ID_CMD_* macros to ... + * gpgex.cc: ... here. Add new macros for new commands. + (gpgex_t::InvokeCommand, gpgex_t::QueryContextMenu): Implement new + commands. + * Makefile.am (libgpg-error.a, libassuan.a): Use -f flag with ln. * registry.h (default_dir): New prototype. * registry.c (default_dir, standard_homedir): New functions. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/src/client.cc 2007-09-11 14:28:55 UTC (rev 17) @@ -148,12 +148,41 @@ void +client_t::verify (vector &filenames) +{ + this->call_assuan ("VERIFY", filenames); +} + + +void +client_t::decrypt (vector &filenames) +{ + this->call_assuan ("DECRYPT", filenames); +} + + +void client_t::encrypt_sign (vector &filenames) { this->call_assuan ("ENCRPYT_SIGN", filenames); } + void +client_t::encrypt (vector &filenames) +{ + this->call_assuan ("ENCRPYT", filenames); +} + + +void +client_t::sign (vector &filenames) +{ + this->call_assuan ("SIGN", filenames); +} + + +void client_t::import (vector &filenames) { this->call_assuan ("IMPORT", filenames); Modified: trunk/src/client.h =================================================================== --- trunk/src/client.h 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/src/client.h 2007-09-11 14:28:55 UTC (rev 17) @@ -43,7 +43,11 @@ } void decrypt_verify (vector &filenames); + void decrypt (vector &filenames); + void verify (vector &filenames); void encrypt_sign (vector &filenames); + void encrypt (vector &filenames); + void sign (vector &filenames); void import (vector &filenames); }; Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/src/gpgex.cc 2007-09-11 14:28:55 UTC (rev 17) @@ -37,6 +37,27 @@ #include "gpgex.h" +/* For context menus. */ +#define ID_CMD_HELP 0 +#define ID_CMD_DECRYPT_VERIFY 1 +#define ID_CMD_DECRYPT 2 +#define ID_CMD_VERIFY 3 +#define ID_CMD_ENCRYPT_SIGN 4 +#define ID_CMD_ENCRYPT 5 +#define ID_CMD_SIGN 6 +#define ID_CMD_IMPORT 7 +#define ID_CMD_MAX 7 + +#define ID_CMD_STR_HELP _("Help on GpgEX") +#define ID_CMD_STR_DECRYPT_VERIFY _("Decrypt and verify") +#define ID_CMD_STR_DECRYPT _("Decrypt") +#define ID_CMD_STR_VERIFY _("Verify") +#define ID_CMD_STR_ENCRYPT_SIGN _("Encrypt and sign") +#define ID_CMD_STR_ENCRYPT _("Encrypt") +#define ID_CMD_STR_SIGN _("Sign") +#define ID_CMD_STR_IMPORT _("Import keys") + + /* Reset the instance between operations. */ void gpgex_t::reset (void) @@ -246,8 +267,8 @@ if (this->all_files_gpg) { res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_VERIFY_DECRYPT, - ID_CMD_STR_VERIFY_DECRYPT); + idCmdFirst + ID_CMD_DECRYPT_VERIFY, + ID_CMD_STR_DECRYPT_VERIFY); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); } @@ -255,8 +276,8 @@ { /* FIXME: Check error. */ res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_SIGN_ENCRYPT, - ID_CMD_STR_SIGN_ENCRYPT); + idCmdFirst + ID_CMD_ENCRYPT_SIGN, + ID_CMD_STR_ENCRYPT_SIGN); if (! res) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); } @@ -292,15 +313,30 @@ return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_VERIFY_DECRYPT, - ID_CMD_STR_VERIFY_DECRYPT); - + idCmdFirst + ID_CMD_DECRYPT_VERIFY, + ID_CMD_STR_DECRYPT_VERIFY); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_SIGN_ENCRYPT, - ID_CMD_STR_SIGN_ENCRYPT); + idCmdFirst + ID_CMD_DECRYPT, + ID_CMD_STR_DECRYPT); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_VERIFY, + ID_CMD_STR_VERIFY); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_ENCRYPT_SIGN, + ID_CMD_STR_ENCRYPT_SIGN); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_ENCRYPT, + ID_CMD_STR_ENCRYPT); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_SIGN, + ID_CMD_STR_SIGN); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_IMPORT, ID_CMD_STR_IMPORT); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); @@ -377,12 +413,24 @@ MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); } break; - case ID_CMD_VERIFY_DECRYPT: + case ID_CMD_DECRYPT_VERIFY: client.decrypt_verify (this->filenames); break; - case ID_CMD_SIGN_ENCRYPT: + case ID_CMD_DECRYPT: + client.decrypt (this->filenames); + break; + case ID_CMD_VERIFY: + client.verify (this->filenames); + break; + case ID_CMD_ENCRYPT_SIGN: client.encrypt_sign (this->filenames); break; + case ID_CMD_ENCRYPT: + client.encrypt (this->filenames); + break; + case ID_CMD_SIGN: + client.sign (this->filenames); + break; case ID_CMD_IMPORT: client.import (this->filenames); break; Modified: trunk/src/gpgex.h =================================================================== --- trunk/src/gpgex.h 2007-09-11 13:52:39 UTC (rev 16) +++ trunk/src/gpgex.h 2007-09-11 14:28:55 UTC (rev 17) @@ -32,19 +32,6 @@ #include "bitmaps.h" -/* For context menus. */ -#define ID_CMD_HELP 0 -#define ID_CMD_VERIFY_DECRYPT 1 -#define ID_CMD_SIGN_ENCRYPT 2 -#define ID_CMD_IMPORT 3 -#define ID_CMD_MAX 3 - -#define ID_CMD_STR_HELP _("Help on GpgEX") -#define ID_CMD_STR_VERIFY_DECRYPT _("Decrypt and verify") -#define ID_CMD_STR_SIGN_ENCRYPT _("Sign and encrypt") -#define ID_CMD_STR_IMPORT _("Import keys") - - /* Our shell extension interface. We use multiple inheritance to achieve polymorphy. From cvs at cvs.gnupg.org Tue Sep 11 16:53:37 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 11 Sep 2007 16:53:37 +0200 Subject: [svn] GpgEX - r18 - trunk/src Message-ID: Author: marcus Date: 2007-09-11 16:53:06 +0200 (Tue, 11 Sep 2007) New Revision: 18 Modified: trunk/src/ChangeLog trunk/src/client.cc Log: 2007-09-11 Marcus Brinkmann * client.cc (client_t::call_assuan): Send --nohup as argument to command. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-11 14:28:55 UTC (rev 17) +++ trunk/src/ChangeLog 2007-09-11 14:53:06 UTC (rev 18) @@ -1,5 +1,8 @@ 2007-09-11 Marcus Brinkmann + * client.cc (client_t::call_assuan): Send --nohup as argument to + command. + * client.h (class client_t): New members decrypt, verify, encrypt, and sign. * client.cc: Add implementations for these. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-09-11 14:28:55 UTC (rev 17) +++ trunk/src/client.cc 2007-09-11 14:53:06 UTC (rev 18) @@ -87,8 +87,7 @@ try { - /* Set the input files. FIXME: Might need to set the output files - as well. */ + /* Set the input files. We don't specify the output files. */ for (unsigned int i = 0; i < filenames.size (); i++) { msg = "INPUT FILE=\"" + filenames[i] + "\" --continued"; @@ -103,17 +102,10 @@ /* Set the --nohup option, so that the operation continues and completes in the background. */ - msg = "OPTION --nohup"; + msg = ((string) cmd) + " --nohup"; (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); rc = assuan_transact (ctx, msg.c_str (), NULL, NULL, NULL, NULL, NULL, NULL); - if (rc) - goto leave; - - msg = cmd; - (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); - rc = assuan_transact (ctx, msg.c_str (), - NULL, NULL, NULL, NULL, NULL, NULL); } catch (std::bad_alloc) { From cvs at cvs.gnupg.org Wed Sep 12 18:40:52 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 12 Sep 2007 18:40:52 +0200 Subject: [svn] GpgOL - r176 - trunk/src Message-ID: Author: wk Date: 2007-09-12 18:40:23 +0200 (Wed, 12 Sep 2007) New Revision: 176 Added: trunk/src/engine-assuan.c trunk/src/engine-assuan.h trunk/src/engine.c Modified: trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/engine-gpgme.c trunk/src/engine.h trunk/src/ext-commands.cpp trunk/src/message-events.cpp trunk/src/message.cpp trunk/src/message.h trunk/src/mimemaker.c trunk/src/mimemaker.h trunk/src/ol-ext-callback.cpp trunk/src/olflange.cpp trunk/src/rfc822parse.c trunk/src/versioninfo.rc.in Log: First PGP/MIME encrypted message sent. Changed encryption to make use of callbacks. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/ChangeLog 2007-09-12 16:40:23 UTC (rev 176) @@ -1,3 +1,14 @@ +2007-09-11 Werner Koch + + * engine-gpgme.c (op_encrypt_data): New. + +2007-09-08 Werner Koch + + * engine.c: New. + * engine.h: Rewrite. Factor existing stuff out to .. + * engine-gpgme.h: .. new. + * engine-assuan.h, engine-assuan.c: New. + 2007-09-07 Werner Koch * common.c (qp_decode): Handle softe line breaks. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/Makefile.am 2007-09-12 16:40:23 UTC (rev 176) @@ -34,7 +34,9 @@ mimeparser.c mimeparser.h \ mimemaker.c mimemaker.h \ msgcache.c msgcache.h \ - engine-gpgme.c engine.h \ + engine.c engine.h \ + engine-assuan.c engine-assuan.h \ + engine-gpgme.c engine-gpgme.h \ rfc822parse.c rfc822parse.h \ common.h common.c util.h \ xmalloc.h \ Added: trunk/src/engine-assuan.c =================================================================== --- trunk/src/engine-assuan.c 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/engine-assuan.c 2007-09-12 16:40:23 UTC (rev 176) @@ -0,0 +1,1448 @@ +/* engine-assuan.c - Crypto engine suing an Assuan server + * Copyright (C) 2005, 2006, 1007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL 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. + * + * GpgOL 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 GpgOL; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* Please note that we assume UTF-8 strings everywhere except when + noted. */ + +#if 0 +#include + +#include +#include +#include +#include +#include + +#define COBJMACROS +#include +#include /* For IStream. */ + +#include "common.h" +#include "passcache.h" +#include "engine.h" + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + + +static char *debug_file = NULL; +static int init_done = 0; + + +static void add_verify_attestation (gpgme_data_t at, + gpgme_ctx_t ctx, + gpgme_verify_result_t res, + const char *filename); + + + +static void +cleanup (void) +{ + if (debug_file) + { + xfree (debug_file); + debug_file = NULL; + } +} + + +/* Enable or disable the debug mode. */ +void +op_set_debug_mode (int val, const char *file) +{ + cleanup (); + /* FIXME: Enable assuan debugging. */ +} + + +/* Cleanup static resources. */ +void +op_deinit (void) +{ + cleanup (); +} + + +/* Initialize this operation subsystem. */ +int +op_init (void) +{ + if (init_done == 1) + return 0; + + /*FIXME*/ + + + init_done = 1; + return 0; +} + + +/* The read callback used by Assuan to read data from an IStream object. */ +static ssize_t +stream_read_cb (void *handle, void *buffer, size_t size) +{ + LPSTREAM stream = handle; + HRESULT hr; + ULONG nread; + + /* For EOF detection we assume that Read returns no error and thus + nread will be 0. The specs say that "Depending on the + implementation, either S_FALSE or an error code could be returned + when reading past the end of the stream"; thus we are not really + sure whether our assumption is correct. OTOH, at another place + the docuemntation says that the implementation used by + ISequentialStream exhibits the same EOF behaviour has found on + the MSDOS FAT file system. So we seem to have good karma. */ + hr = IStream_Read (stream, buffer, size, &nread); + if (hr != S_OK) + { + log_debug ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr); + errno = EIO; + return -1; + } + return nread; +} + +/* The write callback used by Assuan to write data to an IStream object. */ +static ssize_t +stream_write_cb (void *handle, const void *buffer, size_t size) +{ + LPSTREAM stream = handle; + HRESULT hr; + ULONG nwritten; + + hr = IStream_Write (stream, buffer, size, &nwritten); + if (hr != S_OK) + { + log_debug ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr); + errno = EIO; + return -1; + } + return nwritten; +} + + + + +/* Try to figure out why the encryption failed and provide a more + suitable error code than the one returned by the encryption + routine. */ +static gpgme_error_t +check_encrypt_result (gpgme_ctx_t ctx, gpgme_error_t err) +{ + gpgme_encrypt_result_t res; + + res = 0 /*gpgme_op_encrypt_result (ctx)*/; + if (!res) + return err; + if (res->invalid_recipients != NULL) + return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); + /* XXX: we need to do more here! */ + return err; +} + + +/* Encrypt the data in INBUF into a newly malloced buffer stored on + success at OUTBUF. The caller should release this buffer using + gpgme_free. The recipients are expected in the NULL terminated + array KEYS. If SIGN_KEY is not NULl, the data will also be signed + using this key. TTL is the time the passphrase should be + cached. */ +int +op_encrypt (const char *inbuf, char **outbuf, gpgme_key_t *keys, + gpgme_key_t sign_key, int ttl) +{ + struct passphrase_cb_s cb; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_error_t err; + gpgme_ctx_t ctx = NULL; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 0; + + *outbuf = NULL; + + op_init (); + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); + if (err) + goto leave; + + err = gpgme_data_new (&out); + if (err) + goto leave; + + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + if (sign_key) + { + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + err = gpgme_signers_add (ctx, sign_key); + if (!err) + err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, + in, out); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + } + else + err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + if (err) + err = check_encrypt_result (ctx, err); + else + { + /* Return the buffer but first make sure it is a string. */ + if (gpgme_data_write (out, "", 1) == 1) + { + *outbuf = gpgme_data_release_and_get_mem (out, NULL); + out = NULL; + } + } + + + leave: + if (ctx) + gpgme_release (ctx); + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + + +/* Encrypt the stream INSTREAM to the OUTSTREAM for all recpients + given in the NULL terminated array KEYS. If SIGN_KEY is not NULL + the message will also be signed. */ +int +op_encrypt_stream (LPSTREAM instream, LPSTREAM outstream, gpgme_key_t *keys, + gpgme_key_t sign_key, int ttl) +{ + struct passphrase_cb_s cb; + struct gpgme_data_cbs cbs; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + cbs.write = stream_write_cb; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 0; + + err = gpgme_data_new_from_cbs (&in, &cbs, instream); + if (err) + goto fail; + + err = gpgme_data_new_from_cbs (&out, &cbs, outstream); + if (err) + goto fail; + + err = gpgme_new (&ctx); + if (err) + goto fail; + + gpgme_set_armor (ctx, 1); + /* FIXME: We should not hardcode always trust. */ + if (sign_key) + { + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + err = gpgme_signers_add (ctx, sign_key); + if (!err) + err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, + in, out); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + } + else + err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); + if (err) + err = check_encrypt_result (ctx, err); + + fail: + if (ctx) + gpgme_release (ctx); + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + +/* Sign and encrypt the data in INBUF into a newly allocated buffer at + OUTBUF. Caller needs to free the returned buffer using gpgme_free. */ +int +op_sign (const char *inbuf, char **outbuf, int mode, + gpgme_key_t sign_key, int ttl) +{ + struct passphrase_cb_s cb; + gpgme_error_t err; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_ctx_t ctx = NULL; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 0; + + *outbuf = NULL; + op_init (); + + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); + if (err) + goto leave; + + err = gpgme_data_new (&out); + if (err) + goto leave; + + if (sign_key) + gpgme_signers_add (ctx, sign_key); + + if (mode == GPGME_SIG_MODE_CLEAR) + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + err = gpgme_op_sign (ctx, in, out, mode); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + + if (!err) + { + /* Return the buffer but first make sure it is a string. */ + if (gpgme_data_write (out, "", 1) == 1) + { + *outbuf = gpgme_data_release_and_get_mem (out, NULL); + out = NULL; + } + } + + leave: + if (ctx) + gpgme_release (ctx); + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + +/* Create a signature from INSTREAM and write it to OUTSTREAM. Use + signature mode MODE and a passphrase caching time of TTL. */ +int +op_sign_stream (LPSTREAM instream, LPSTREAM outstream, int mode, + gpgme_key_t sign_key, int ttl) +{ + struct gpgme_data_cbs cbs; + struct passphrase_cb_s cb; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + cbs.write = stream_write_cb; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 0; + + err = gpgme_data_new_from_cbs (&in, &cbs, instream); + if (err) + goto fail; + + err = gpgme_data_new_from_cbs (&out, &cbs, outstream); + if (err) + goto fail; + + err = gpgme_new (&ctx); + if (err) + goto fail; + + if (sign_key) + gpgme_signers_add (ctx, sign_key); + + if (mode == GPGME_SIG_MODE_CLEAR) + gpgme_set_textmode (ctx, 1); + gpgme_set_armor (ctx, 1); + + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + err = gpgme_op_sign (ctx, in, out, mode); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + + fail: + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + if (ctx) + gpgme_release (ctx); + return err; +} + + + +/* Run the decryption. Decrypts INBUF to OUTBUF; caller needs to free + the returned result at OUTBUF using gpgme_free. the result at + OUTBUF. TTL is the time in seconds to cache a passphrase. If + FILENAME is not NULL it will be displayed along with status + outputs. If ATTESTATION is not NULL a text with the result of the + signature verification will get printed to it. */ +int +op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename, + gpgme_data_t attestation, int preview_mode) +{ + struct passphrase_cb_s cb; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_ctx_t ctx; + gpgme_error_t err; + + *outbuf = NULL; + op_init (); + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 1; + + err = gpgme_new (&ctx); + if (err) + return err; + + err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); + if (err) + goto leave; + err = gpgme_data_new (&out); + if (err) + goto leave; + + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + if (preview_mode) + err = gpgme_op_decrypt (ctx, in, out); + else + err = gpgme_op_decrypt_verify (ctx, in, out); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + + /* Act upon the result of the decryption operation. */ + if (!err && preview_mode) + ; + else if (!err) + { + /* Decryption succeeded. Store the result at OUTBUF. */ + gpgme_verify_result_t res; + + /* Return the buffer but first make sure it is a string. */ + if (gpgme_data_write (out, "", 1) == 1) + { + *outbuf = gpgme_data_release_and_get_mem (out, NULL); + out = NULL; + } + + /* Now check the state of any signature. */ + res = gpgme_op_verify_result (ctx); + if (res && res->signatures) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && res->signatures && attestation) + add_verify_attestation (attestation, ctx, res, filename); + } + else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED) + { + /* The decryption failed. See whether we can determine the real + problem. */ + gpgme_decrypt_result_t res; + res = gpgme_op_decrypt_result (ctx); + if (res != NULL && res->recipients != NULL && + gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) + err = GPG_ERR_NO_SECKEY; + /* XXX: return the keyids */ + } + else + { + /* Decryption failed for other reasons. */ + } + + + /* If the callback indicated a cancel operation, set the error + accordingly. */ + if (err && (cb.opts & OPT_FLAG_CANCEL)) + err = gpg_error (GPG_ERR_CANCELED); + +leave: + if (ctx) + gpgme_release (ctx); + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + +/* Decrypt the GPGME data object IN into the data object OUT. Returns + 0 on success or an gpgme error code on failure. If FILENAME is not + NULL it will be displayed along with status outputs. If ATTESTATION + is not NULL a text with the result of the signature verification + will get printed to it. */ +static int +decrypt_stream (gpgme_protocol_t protocol, + gpgme_data_t in, gpgme_data_t out, int ttl, + const char *filename, gpgme_data_t attestation, + int preview_mode) +{ + struct passphrase_cb_s cb; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 1; + + err = gpgme_new (&ctx); + if (err) + goto fail; + + err = gpgme_set_protocol (ctx, protocol); + if (err) + goto fail; + + /* GPGME does not support a command handler for gpgsm. Thus we + can't set the passphrase callback. */ + if (protocol != GPGME_PROTOCOL_CMS) + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + + cb.ctx = ctx; + if (preview_mode) + err = gpgme_op_decrypt (ctx, in, out); + else + err = gpgme_op_decrypt_verify (ctx, in, out); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + /* Act upon the result of the decryption operation. */ + if (!err && preview_mode) + ; + else if (!err) + { + gpgme_verify_result_t res; + + /* Decryption succeeded. Now check the state of the signatures. */ + res = gpgme_op_verify_result (ctx); + if (res && res->signatures) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && res->signatures && attestation) + add_verify_attestation (attestation, ctx, res, filename); + } + else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED) + { + /* The decryption failed. See whether we can determine the real + problem. */ + gpgme_decrypt_result_t res; + res = gpgme_op_decrypt_result (ctx); + if (res != NULL && res->recipients != NULL && + gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) + err = GPG_ERR_NO_SECKEY; + /* XXX: return the keyids */ + } + else + { + /* Decryption failed for other reasons. */ + } + + + /* If the callback indicated a cancel operation, set the error + accordingly. */ + if (err && (cb.opts & OPT_FLAG_CANCEL)) + err = gpg_error (GPG_ERR_CANCELED); + + fail: + if (ctx) + gpgme_release (ctx); + return err; +} + +/* Decrypt the stream INSTREAM directly to the stream OUTSTREAM. + Returns 0 on success or an gpgme error code on failure. If + FILENAME is not NULL it will be displayed along with status + outputs. */ +int +op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl, + const char *filename, gpgme_data_t attestation) +{ + struct gpgme_data_cbs cbs; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_error_t err; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + cbs.write = stream_write_cb; + + err = gpgme_data_new_from_cbs (&in, &cbs, instream); + if (!err) + err = gpgme_data_new_from_cbs (&out, &cbs, outstream); + if (!err) + err = decrypt_stream (GPGME_PROTOCOL_OpenPGP, + in, out, ttl, filename, attestation, 0); + + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + +/* Decrypt the stream INSTREAM directly to the newly allocated buffer + OUTBUF. Caller needs to free the returned buffer using gpgme_free. + Returns 0 on success or an gpgme error code on failure. If + FILENAME is not NULL it will be displayed along with status + outputs. */ +int +op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl, + const char *filename, gpgme_data_t attestation) +{ + struct gpgme_data_cbs cbs; + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_error_t err; + + *outbuf = NULL; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + + err = gpgme_data_new_from_cbs (&in, &cbs, instream); + if (!err) + err = gpgme_data_new (&out); + if (!err) + err = decrypt_stream (GPGME_PROTOCOL_OpenPGP, + in, out, ttl, filename, attestation, 0); + if (!err) + { + /* Return the buffer but first make sure it is a string. */ + if (gpgme_data_write (out, "", 1) == 1) + { + *outbuf = gpgme_data_release_and_get_mem (out, NULL); + out = NULL; + } + } + + if (in) + gpgme_data_release (in); + if (out) + gpgme_data_release (out); + return err; +} + + +/* Decrypt the stream INSTREAM directly to the GPGME data object OUT. + Returns 0 on success or an gpgme error code on failure. If + FILENAME is not NULL it will be displayed along with status + outputs. */ +int +op_decrypt_stream_to_gpgme (gpgme_protocol_t protocol, + LPSTREAM instream, gpgme_data_t out, int ttl, + const char *filename, gpgme_data_t attestation, + int preview_mode) +{ + struct gpgme_data_cbs cbs; + gpgme_data_t in = NULL; + gpgme_error_t err; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + + err = gpgme_data_new_from_cbs (&in, &cbs, instream); + if (!err) + err = decrypt_stream (protocol, + in, out, ttl, filename, attestation, preview_mode); + + if (in) + gpgme_data_release (in); + return err; +} + + + +/* Verify a message in INBUF and return the new message (i.e. the one + with stripped off dash escaping) in a newly allocated buffer + OUTBUF. If OUTBUF is NULL only the verification result will be + displayed (this is suitable for PGP/MIME messages). A dialog box + will show the result of the verification. If FILENAME is not NULL + it will be displayed along with status outputs. If ATTESTATION is + not NULL a text with the result of the signature verification will + get printed to it. Caller needs to free the returned buffer at + OUTBUF using gpgme_free. */ +int +op_verify (const char *inbuf, char **outbuf, const char *filename, + gpgme_data_t attestation) +{ + gpgme_data_t in = NULL; + gpgme_data_t out = NULL; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_verify_result_t res = NULL; + + if (outbuf) + *outbuf = NULL; + + op_init (); + + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); + if (err) + goto leave; + + err = gpgme_data_new (&out); + if (err) + goto leave; + + err = gpgme_op_verify (ctx, in, NULL, out); + if (!err) + { + if (outbuf) + { + /* Return the buffer but first make sure it is a string. */ + if (gpgme_data_write (out, "", 1) == 1) + { + *outbuf = gpgme_data_release_and_get_mem (out, NULL); + out = NULL; + } + } + res = gpgme_op_verify_result (ctx); + } + if (res) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && attestation) + add_verify_attestation (attestation, ctx, res, filename); + + leave: + if (out) + gpgme_data_release (out); + if (in) + gpgme_data_release (in); + if (ctx) + gpgme_release (ctx); + return err; +} + +/* Verify a detached message where the data is to be read from the + DATA_STREAM and the signature itself is expected to be the string + SIG_STRING. FILENAME will be shown by the verification status + dialog box. If ATTESTATION is not NULL a text with the result of + the signature verification will get printed to it. */ +int +op_verify_detached_sig (LPSTREAM data_stream, + const char *sig_string, const char *filename, + gpgme_data_t attestation) +{ + struct gpgme_data_cbs cbs; + gpgme_data_t data = NULL; + gpgme_data_t sig = NULL; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_verify_result_t res = NULL; + + memset (&cbs, 0, sizeof cbs); + cbs.read = stream_read_cb; + cbs.write = stream_write_cb; + + op_init (); + + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_data_new_from_cbs (&data, &cbs, data_stream); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&sig, sig_string, strlen (sig_string), 0); + if (err) + goto leave; + + err = gpgme_op_verify (ctx, sig, data, NULL); + if (!err) + { + res = gpgme_op_verify_result (ctx); + if (res) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && attestation) + add_verify_attestation (attestation, ctx, res, filename); + } + + leave: + if (data) + gpgme_data_release (data); + if (sig) + gpgme_data_release (sig); + if (ctx) + gpgme_release (ctx); + return err; +} + +/* Verify a detached message where the data is in the string + DATA_STRING and the signature itself is expected to be the string + SIG_STRING. FILENAME will be shown by the verification status + dialog box. If ATTESTATION is not NULL a text with the result of + the signature verification will get printed to it. */ +int +op_verify_detached_sig_mem (const char *data_string, + const char *sig_string, const char *filename, + gpgme_data_t attestation) +{ + gpgme_data_t data = NULL; + gpgme_data_t sig = NULL; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_verify_result_t res = NULL; + + op_init (); + + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&data, data_string, strlen (data_string), 0); + if (err) + goto leave; + + err = gpgme_data_new_from_mem (&sig, sig_string, strlen (sig_string), 0); + if (err) + goto leave; + + err = gpgme_op_verify (ctx, sig, data, NULL); + if (!err) + { + res = gpgme_op_verify_result (ctx); + if (res) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && attestation) + add_verify_attestation (attestation, ctx, res, filename); + } + + leave: + if (data) + gpgme_data_release (data); + if (sig) + gpgme_data_release (sig); + if (ctx) + gpgme_release (ctx); + return err; +} + + +/* Verify a detached message where the data is in the gpgme object + DATA and the signature is the gpgme object SIG. FILENAME will be + shown by the verification status dialog box. If ATTESTATION is not + NULL a text with the result of the signature verification will get + printed to it. */ +int +op_verify_detached_sig_gpgme (gpgme_protocol_t protocol, + gpgme_data_t data, gpgme_data_t sig, + const char *filename, gpgme_data_t attestation) +{ + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_verify_result_t res = NULL; + + op_init (); + + err = gpgme_new (&ctx); + if (err) + goto leave; + + err = gpgme_set_protocol (ctx, protocol); + if (err) + goto leave; + + err = gpgme_op_verify (ctx, sig, data, NULL); + if (!err) + { + res = gpgme_op_verify_result (ctx); + if (res) + verify_dialog_box (gpgme_get_protocol (ctx), res, filename); + if (res && attestation) + add_verify_attestation (attestation, ctx, res, filename); + } + + leave: + if (ctx) + gpgme_release (ctx); + return err; +} + + + +static void +at_puts (gpgme_data_t a, const char *s) +{ + gpgme_data_write (a, s, strlen (s)); +} + +static void +at_print_time (gpgme_data_t a, time_t t) +{ + char buf[200]; + + strftime (buf, sizeof (buf)-1, "%c", localtime (&t)); + at_puts (a, buf); +} + +static void +at_fingerprint (gpgme_data_t a, gpgme_key_t key) +{ + const char *s; + int i, is_pgp; + char *buf, *p; + const char *prefix = _("Fingerprint: "); + + if (!key) + return; + s = key->subkeys ? key->subkeys->fpr : NULL; + if (!s) + return; + is_pgp = (key->protocol == GPGME_PROTOCOL_OpenPGP); + + buf = xmalloc ( strlen (prefix) + strlen(s) * 4 + 2 ); + p = stpcpy (buf, prefix); + if (is_pgp && strlen (s) == 40) + { + /* v4 style formatted. */ + for (i=0; *s && s[1] && s[2] && s[3] && s[4]; s += 4, i++) + { + *p++ = s[0]; + *p++ = s[1]; + *p++ = s[2]; + *p++ = s[3]; + *p++ = ' '; + if (i == 4) + *p++ = ' '; + } + } + else + { + /* v3 style or X.509 formatted. */ + for (i=0; *s && s[1] && s[2]; s += 2, i++) + { + *p++ = s[0]; + *p++ = s[1]; + *p++ = is_pgp? ' ':':'; + if (is_pgp && i == 7) + *p++ = ' '; + } + } + + /* Just in case print remaining odd digits */ + for (; *s; s++) + *p++ = *s; + *p++ = '\n'; + *p = 0; + at_puts (a, buf); + xfree (buf); +} + + +/* Print common attributes of the signature summary SUM. Returns + true if a severe warning has been encountered. */ +static int +at_sig_summary (gpgme_data_t a, + unsigned long sum, gpgme_signature_t sig, gpgme_key_t key) +{ + int severe = 0; + + if ((sum & GPGME_SIGSUM_VALID)) + at_puts (a, _("This signature is valid\n")); + if ((sum & GPGME_SIGSUM_GREEN)) + at_puts (a, _("signature state is \"green\"\n")); + if ((sum & GPGME_SIGSUM_RED)) + at_puts (a, _("signature state is \"red\"\n")); + + if ((sum & GPGME_SIGSUM_KEY_REVOKED)) + { + at_puts (a, _("Warning: One of the keys has been revoked\n")); + severe = 1; + } + + if ((sum & GPGME_SIGSUM_KEY_EXPIRED)) + { + time_t t = key->subkeys->expires ? key->subkeys->expires : 0; + + if (t) + { + at_puts (a, _("Warning: The key used to create the " + "signature expired at: ")); + at_print_time (a, t); + at_puts (a, "\n"); + } + else + at_puts (a, _("Warning: At least one certification key " + "has expired\n")); + } + + if ((sum & GPGME_SIGSUM_SIG_EXPIRED)) + { + at_puts (a, _("Warning: The signature expired at: ")); + at_print_time (a, sig ? sig->exp_timestamp : 0); + at_puts (a, "\n"); + } + + if ((sum & GPGME_SIGSUM_KEY_MISSING)) + at_puts (a, _("Can't verify due to a missing key or certificate\n")); + + if ((sum & GPGME_SIGSUM_CRL_MISSING)) + { + at_puts (a, _("The CRL is not available\n")); + severe = 1; + } + + if ((sum & GPGME_SIGSUM_CRL_TOO_OLD)) + { + at_puts (a, _("Available CRL is too old\n")); + severe = 1; + } + + if ((sum & GPGME_SIGSUM_BAD_POLICY)) + at_puts (a, _("A policy requirement was not met\n")); + + if ((sum & GPGME_SIGSUM_SYS_ERROR)) + { + const char *t0 = NULL, *t1 = NULL; + + at_puts (a, _("A system error occured")); + + /* Try to figure out some more detailed system error information. */ + if (sig) + { + t0 = ""; + t1 = sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; + } + + if (t0 || t1) + { + at_puts (a, ": "); + if (t0) + at_puts (a, t0); + if (t1 && !(t0 && !strcmp (t0, t1))) + { + if (t0) + at_puts (a, ","); + at_puts (a, t1); + } + } + at_puts (a, "\n"); + } + + return severe; +} + + +/* Print the validity of a key used for one signature. */ +static void +at_sig_validity (gpgme_data_t a, gpgme_signature_t sig) +{ + const char *txt = NULL; + + switch (sig ? sig->validity : 0) + { + case GPGME_VALIDITY_UNKNOWN: + txt = _("WARNING: We have NO indication whether " + "the key belongs to the person named " + "as shown above\n"); + break; + case GPGME_VALIDITY_UNDEFINED: + break; + case GPGME_VALIDITY_NEVER: + txt = _("WARNING: The key does NOT BELONG to " + "the person named as shown above\n"); + break; + case GPGME_VALIDITY_MARGINAL: + txt = _("WARNING: It is NOT certain that the key " + "belongs to the person named as shown above\n"); + break; + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: + txt = NULL; + break; + } + + if (txt) + at_puts (a, txt); +} + + +/* Print a text with the attestation of the signature verification + (which is in RES) to A. FILENAME may also be used in the + attestation. */ +static void +add_verify_attestation (gpgme_data_t a, gpgme_ctx_t ctx, + gpgme_verify_result_t res, const char *filename) +{ + time_t created; + const char *fpr, *uid; + gpgme_key_t key = NULL; + int i, anybad = 0, anywarn = 0; + unsigned int sum; + gpgme_user_id_t uids = NULL; + gpgme_signature_t sig; + gpgme_error_t err; + + if (!gpgme_data_seek (a, 0, SEEK_CUR)) + { + /* Nothing yet written to the stream. Insert the current time. */ + at_puts (a, _("Verification started at: ")); + at_print_time (a, time (NULL)); + at_puts (a, "\n\n"); + } + + at_puts (a, _("Verification result for: ")); + at_puts (a, filename ? filename : _("[unnamed part]")); + at_puts (a, "\n"); + if (res) + { + for (sig = res->signatures; sig; sig = sig->next) + { + created = sig->timestamp; + fpr = sig->fpr; + sum = sig->summary; + + if (gpg_err_code (sig->status) != GPG_ERR_NO_ERROR) + anybad = 1; + + err = gpgme_get_key (ctx, fpr, &key, 0); + uid = !err && key->uids && key->uids->uid ? key->uids->uid : "[?]"; + + if ((sum & GPGME_SIGSUM_GREEN)) + { + at_puts (a, _("Good signature from: ")); + at_puts (a, uid); + at_puts (a, "\n"); + for (i = 1, uids = key->uids; uids; i++, uids = uids->next) + { + if (uids->revoked) + continue; + at_puts (a, _(" aka: ")); + at_puts (a, uids->uid); + at_puts (a, "\n"); + } + at_puts (a, _(" created: ")); + at_print_time (a, created); + at_puts (a, "\n"); + if (at_sig_summary (a, sum, sig, key)) + anywarn = 1; + at_sig_validity (a, sig); + } + else if ((sum & GPGME_SIGSUM_RED)) + { + at_puts (a, _("*BAD* signature claimed to be from: ")); + at_puts (a, uid); + at_puts (a, "\n"); + at_sig_summary (a, sum, sig, key); + } + else if (!anybad && key && (key->protocol == GPGME_PROTOCOL_OpenPGP)) + { /* We can't decide (yellow) but this is a PGP key with a + good signature, so we display what a PGP user + expects: The name, fingerprint and the key validity + (which is neither fully or ultimate). */ + at_puts (a, _("Good signature from: ")); + at_puts (a, uid); + at_puts (a, "\n"); + at_puts (a, _(" created: ")); + at_print_time (a, created); + at_puts (a, "\n"); + at_sig_validity (a, sig); + at_fingerprint (a, key); + if (at_sig_summary (a, sum, sig, key)) + anywarn = 1; + } + else /* can't decide (yellow) */ + { + at_puts (a, _("Error checking signature")); + at_puts (a, "\n"); + at_sig_summary (a, sum, sig, key); + } + + gpgme_key_release (key); + } + + if (!anybad ) + { + gpgme_sig_notation_t notation; + + for (sig = res->signatures; sig; sig = sig->next) + { + if (!sig->notations) + continue; + at_puts (a, _("*** Begin Notation (signature by: ")); + at_puts (a, sig->fpr); + at_puts (a, ") ***\n"); + for (notation = sig->notations; notation; + notation = notation->next) + { + if (notation->name) + { + at_puts (a, notation->name); + at_puts (a, "="); + } + if (notation->value) + { + at_puts (a, notation->value); + if (!(*notation->value + && (notation->value[strlen (notation->value)-1] + =='\n'))) + at_puts (a, "\n"); + } + } + at_puts (a, _("*** End Notation ***\n")); + } + } + } + at_puts (a, "\n"); +} + + + + +/* Try to find a key for each item in array NAMES. Items not found are + stored as malloced strings in the newly allocated array UNKNOWN. + Found keys are stored in the newly allocated array KEYS. Both + arrays are terminated by a NULL entry. Caller needs to release + KEYS and UNKNOWN. + + Returns: 0 on success. However success may also be that one or all + keys are unknown. +*/ +int +op_lookup_keys (char **names, gpgme_key_t **keys, char ***unknown) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + size_t n; + int i, kpos, upos; + gpgme_key_t k, k2; + + *keys = NULL; + *unknown = NULL; + + err = gpgme_new (&ctx); + if (err) + return -1; /* Error. */ + + for (n=0; names[n]; n++) + ; + + *keys = xcalloc (n+1, sizeof *keys); + *unknown = xcalloc (n+1, sizeof *unknown); + + for (i=kpos=upos=0; names[i]; i++) + { + k = NULL; + err = gpgme_op_keylist_start (ctx, names[i], 0); + if (!err) + { + err = gpgme_op_keylist_next (ctx, &k); + if (!err && !gpgme_op_keylist_next (ctx, &k2)) + { + /* More than one matching key available. Take this one + as unknown. */ + gpgme_key_release (k); + gpgme_key_release (k2); + k = k2 = NULL; + } + } + gpgme_op_keylist_end (ctx); + + + /* only useable keys will be added otherwise they will be stored + in unknown (marked with their status). */ + if (k && !k->revoked && !k->disabled && !k->expired) + (*keys)[kpos++] = k; + else if (k) + { + char *p, *fmt = "%s (%s)"; + char *warn = k->revoked? "revoked" : k->expired? "expired" : "disabled"; + + p = xcalloc (1, strlen (names[i]) + strlen (warn) + strlen (fmt) +1); + sprintf (p, fmt, names[i], warn); + (*unknown)[upos++] = p; + gpgme_key_release (k); + } + else if (!k) + (*unknown)[upos++] = xstrdup (names[i]); + } + + gpgme_release (ctx); + return 0; +} + + +/* Return a GPGME key object matching PATTERN. If no key matches or + the match is ambiguous, return NULL. */ +gpgme_key_t +op_get_one_key (char *pattern) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_key_t k, k2; + + err = gpgme_new (&ctx); + if (err) + return NULL; /* Error. */ + err = gpgme_op_keylist_start (ctx, pattern, 0); + if (!err) + { + err = gpgme_op_keylist_next (ctx, &k); + if (!err && !gpgme_op_keylist_next (ctx, &k2)) + { + /* More than one matching key available. Return an error + instead. */ + gpgme_key_release (k); + gpgme_key_release (k2); + k = k2 = NULL; + } + } + gpgme_op_keylist_end (ctx); + gpgme_release (ctx); + return k; +} + + +/* Copy the data from the GPGME object DAT to a newly created file + with name OUTFILE. Returns 0 on success. */ +static gpgme_error_t +data_to_file (gpgme_data_t *dat, const char *outfile) +{ + FILE *out; + char *buf; + size_t n=0; + + out = fopen (outfile, "wb"); + if (!out) + return GPG_ERR_UNKNOWN_ERRNO; /* FIXME: We need to check why we + can't use errno here. */ + /* FIXME: Why at all are we using an in memory object wqhen we are + later going to write to a file anyway. */ + buf = gpgme_data_release_and_get_mem (*dat, &n); + *dat = NULL; + if (!n) + { + fclose (out); + return GPG_ERR_EOF; /* FIXME: wrap this into a gpgme_error() */ + } + fwrite (buf, 1, n, out); + fclose (out); + /* FIXME: We have no error checking above. */ + gpgme_free (buf); + return 0; +} + + +int +op_export_keys (const char *pattern[], const char *outfile) +{ + /* @untested@ */ + gpgme_ctx_t ctx=NULL; + gpgme_data_t out=NULL; + gpgme_error_t err; + + err = gpgme_new (&ctx); + if (err) + return err; + err = gpgme_data_new (&out); + if (err) { + gpgme_release (ctx); + return err; + } + + gpgme_set_armor (ctx, 1); + err = gpgme_op_export_ext (ctx, pattern, 0, out); + if (!err) + data_to_file (&out, outfile); + + gpgme_data_release (out); + gpgme_release (ctx); + return err; +} + + +const char * +userid_from_key (gpgme_key_t k) +{ + if (k && k->uids && k->uids->uid) + return k->uids->uid; + else + return "?"; +} + +const char * +keyid_from_key (gpgme_key_t k) +{ + + if (k && k->subkeys && k->subkeys->keyid) + return k->subkeys->keyid; + else + return "????????"; +} + + +const char* +op_strerror (int err) +{ + return gpgme_strerror (err); +} + + +const char* +op_strsource (int err) +{ + return gpgme_strsource (err); +} + + +#endif Added: trunk/src/engine-assuan.h =================================================================== --- trunk/src/engine-assuan.h 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/engine-assuan.h 2007-09-12 16:40:23 UTC (rev 176) @@ -0,0 +1,41 @@ +/* engine-assuan.h - Assuan server based crypto engine + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL 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. + * + * GpgOL 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 GpgOL; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef GPGOL_ENGINE_ASSUAN_H +#define GPGOL_ENGINE_ASSUAN_H + +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + + + + + + + +#ifdef __cplusplus +} +#endif +#endif /*GPGOL_ENGINE_ASSUAN_H*/ Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/engine-gpgme.c 2007-09-12 16:40:23 UTC (rev 176) @@ -1,21 +1,22 @@ /* engine-gpgme.c - Crypto engine with GPGME - * Copyright (C) 2005, 2006 g10 Code GmbH + * Copyright (C) 2005, 2006, 2007 g10 Code GmbH * - * This file is part of GPGol. + * This file is part of GpgOL. * - * GPGol is free software; you can redistribute it and/or + * GpgOL 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. * - * GPGol is distributed in the hope that it will be useful, + * GpgOL 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License - * along with GPGol; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU Lesser General Public + * License along with GpgOL; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /* Please note that we assume UTF-8 strings everywhere except when @@ -37,6 +38,7 @@ #include "common.h" #include "passcache.h" #include "engine.h" +#include "engine-gpgme.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ SRCNAME, __func__, __LINE__); \ @@ -47,6 +49,7 @@ static int init_done = 0; +static DWORD WINAPI waiter_thread (void *dummy); static void add_verify_attestation (gpgme_data_t at, gpgme_ctx_t ctx, gpgme_verify_result_t res, @@ -122,12 +125,57 @@ gpgme_strerror (err)); return err; } - + + { + HANDLE th; + DWORD tid; + + th = CreateThread (NULL, 64*1024, waiter_thread, NULL, 0, &tid); + if (th == INVALID_HANDLE_VALUE) + log_error ("failed to start the gpgme waiter thread\n"); + else + CloseHandle (th); + } + init_done = 1; return 0; } +static DWORD WINAPI +waiter_thread (void *dummy) +{ + gpgme_ctx_t ctx; + gpg_error_t err; + void *filter; + + (void)dummy; + + TRACEPOINT (); + for (;;) + { + /* Note: We don't use hang becuase this will end up in a tight + loop and does not do a voluntary context switch. Thus we do + this by ourself. Actually it would be better to start + gpgme-Wait only if we really have something to do but that + is more complicated. */ + ctx = gpgme_wait (NULL, &err, 0); + if (ctx) + { + gpgme_get_progress_cb (ctx, NULL, &filter); + engine_gpgme_finished (filter, err); + gpgme_release (ctx); + } + else if (err) + log_debug ("%s:%s: gpgme_wait failed: %s\n", SRCNAME, __func__, + gpg_strerror (err)); + else + Sleep (50); + } +} + + + /* The read callback used by GPGME to read data from an IStream object. */ static ssize_t stream_read_cb (void *handle, void *buffer, size_t size) @@ -154,6 +202,7 @@ return nread; } + /* The write callback used by GPGME to write data to an IStream object. */ static ssize_t stream_write_cb (void *handle, const void *buffer, size_t size) @@ -360,6 +409,196 @@ return err; } + +/* Release an array of GPGME keys. */ +static void +release_key_array (gpgme_key_t *keys) +{ + int i; + + if (keys) + { + for (i = 0; keys[i]; i++) + gpgme_key_release (keys[i]); + xfree (keys); + } +} + +/* Return the number of strings in the array STRINGS. */ +static size_t +count_strings (char **strings) +{ + size_t i; + + for (i=0; strings[i]; i++) + ; + return i; +} + +/* Return the number of keys in the gpgme_key_t array KEYS. */ +static size_t +count_keys (gpgme_key_t *keys) +{ + size_t i; + + for (i=0; keys[i]; i++) + ; + return i; +} + + +/* Return an array of gpgme key objects derived from thye list of + strings in RECPIENTS. */ +static gpg_error_t +prepare_recipient_keys (gpgme_key_t **r_keys, char **recipients, HWND hwnd) +{ + gpg_error_t err; + gpgme_key_t *keys = NULL; + char **unknown = NULL; + size_t n_keys, n_unknown, n_recp; + int i; + + *r_keys = NULL; + if (op_lookup_keys (recipients, &keys, &unknown)) + { + log_debug ("%s:%s: leave (lookup keys failed)\n", SRCNAME, __func__); + return gpg_error (GPG_ERR_GENERAL); + } + + n_recp = count_strings (recipients); + n_keys = count_keys (keys); + n_unknown = count_strings (unknown); + + log_debug ("%s:%s: found %d recipients, need %d, unknown=%d\n", + SRCNAME, __func__, (int)n_keys, (int)n_recp, (int)n_unknown); + + if (n_keys != n_recp) + { + unsigned int opts; + gpgme_key_t *keys2; + + log_debug ("%s:%s: calling recipient_dialog_box2", SRCNAME, __func__); + opts = recipient_dialog_box2 (keys, unknown, &keys2); + release_key_array (keys); + keys = keys2; + if ( (opts & OPT_FLAG_CANCEL) ) + { + err = gpg_error (GPG_ERR_CANCELED); + goto leave; + } + } + + + /* If a default key has been set, add it to the list of keys. Check + that the key is actually available. */ + if (opt.enable_default_key && opt.default_key && *opt.default_key) + { + gpgme_key_t defkey; + + defkey = op_get_one_key (opt.default_key); + if (!defkey) + { + MessageBox (hwnd, + _("The configured default encryption key is not " + "available or does not unambigiously specify a key. " + "Please fix this in the option dialog.\n\n" + "This message won't be be encrypted to this key!"), + _("Encryption"), MB_ICONWARNING|MB_OK); + } + else + { + gpgme_key_t *tmpkeys; + + n_keys = count_keys (keys) + 1; + tmpkeys = xcalloc (n_keys+1, sizeof *tmpkeys); + for (i = 0; keys[i]; i++) + { + tmpkeys[i] = keys[i]; + gpgme_key_ref (tmpkeys[i]); + } + tmpkeys[i++] = defkey; + tmpkeys[i] = NULL; + release_key_array (keys); + keys = tmpkeys; + } + } + + if (keys) + { + for (i=0; keys[i]; i++) + log_debug ("%s:%s: recp.%d 0x%s %s\n", SRCNAME, __func__, + i, keyid_from_key (keys[i]), userid_from_key (keys[i])); + } + *r_keys = keys; + keys = NULL; + err = 0; + + leave: + release_key_array (keys); + return err; +} + + +/* Encrypt the data from INDATA to the OUTDATA object for all + recpients given in the NULL terminated array KEYS. If SIGN_KEY is + not NULL the message will also be signed. On termination of the + encryption command engine_gpgme_finished() is called with + NOTIFY_DATA as the first argument. + + This global function is used to avoid allocating an extra context + just for this notification. We abuse the gpgme_set_progress_cb + value for storing the pointer with the gpgme context. */ +int +op_encrypt_data (gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data, /* FIXME: Add hwnd */ + char **recipients, gpgme_key_t sign_key, int ttl) +{ + gpg_error_t err; + struct passphrase_cb_s cb; + gpgme_ctx_t ctx = NULL; + gpgme_key_t *keys = NULL; + + memset (&cb, 0, sizeof cb); + cb.ttl = ttl; + cb.decrypt_cmd = 0; + + err = prepare_recipient_keys (&keys, recipients, NULL); + if (err) + goto leave; + + err = gpgme_new (&ctx); + if (err) + goto leave; + gpgme_set_progress_cb (ctx, NULL, notify_data); + + gpgme_set_armor (ctx, 1); + /* FIXME: We should not hardcode always trust. */ + if (sign_key) + { + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + cb.ctx = ctx; + err = gpgme_signers_add (ctx, sign_key); + if (!err) + err = gpgme_op_encrypt_sign_start (ctx, keys, + GPGME_ENCRYPT_ALWAYS_TRUST, + indata, outdata); + cb.ctx = NULL; + update_passphrase_cache (err, &cb); + } + else + err = gpgme_op_encrypt_start (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, + indata, outdata); +/* if (err) */ +/* err = check_encrypt_result (ctx, err); */ + + leave: + if (ctx && err) + gpgme_release (ctx); + release_key_array (keys); + return err; +} + + /* Sign and encrypt the data in INBUF into a newly allocated buffer at OUTBUF. Caller needs to free the returned buffer using gpgme_free. */ Added: trunk/src/engine.c =================================================================== --- trunk/src/engine.c 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/engine.c 2007-09-12 16:40:23 UTC (rev 176) @@ -0,0 +1,566 @@ +/* engine.c - Crypto engine dispatcher + * Copyright (C) 2007 g10 Code GmbH + * + * This file is part of GpgOL. + * + * GpgOL 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. + * + * GpgOL 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 GpgOL; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include +/*#define WIN32_LEAN_AND_MEAN uncomment it after remove LPSTREAM*/ +#include +#include /* For LPSTREAM in engine-gpgme.h FIXME: Remove it. */ + +#include "common.h" +#include "engine.h" +#include "engine-gpgme.h" +#include "engine-assuan.h" + +#define FILTER_BUFFER_SIZE 128 /* FIXME: Increase it after testing */ + + +#define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ + SRCNAME, __func__, __LINE__); \ + } while (0) + + +/* Definition of the key object. */ +struct engine_keyinfo_s +{ + struct { + gpgme_key_t key; + } gpgme; + +}; + + +/* Definition of the filter object. This object shall only be + accessed by one thread. */ +struct engine_filter_s +{ + struct { + CRITICAL_SECTION lock; /* The lock for the this object. */ + HANDLE condvar; /* Manual reset event signaled if LENGTH > 0. */ + size_t length; /* Number of bytes in BUFFER waiting to be + send down the pipe. */ + char buffer[FILTER_BUFFER_SIZE]; + int got_eof; /* End of file has been indicated. */ + /* These objects are only in this structure because we + use this structure's lock to protect them. */ + int ready; /* Set to true if the gpgme process has finished. */ + HANDLE ready_event; /* And the corresponding event. */ + gpg_error_t status; /* Status of the gpgme process. */ + } in; + + struct { + CRITICAL_SECTION lock; /* The lock for the this object. */ + HANDLE condvar; /* Manual reset event signaled if LENGTH == 0. */ + size_t length; /* Number of bytes in BUFFER waiting to be + send back to the caller. */ + char buffer[FILTER_BUFFER_SIZE]; + } out; + + /* The data sink as set by engine_create_filter. */ + int (*outfnc) (void *, const void *, size_t); + void *outfncdata; + + /* Objects to be released by engine_wait/cancel. */ + struct gpgme_data_cbs cb_inbound; /* Callback structure for gpgme. */ + struct gpgme_data_cbs cb_outbound; /* Ditto. */ + gpgme_data_t indata; /* Input data. */ + gpgme_data_t outdata; /* Output data. */ +}; + + + + +/* Create a new filter object. */ +static engine_filter_t +create_filter (void) +{ + engine_filter_t filter; + + filter = xcalloc (1, sizeof *filter); + + InitializeCriticalSection (&filter->in.lock); + filter->in.condvar = CreateEvent (NULL, TRUE, 0, NULL); + if (!filter->in.condvar) + log_error_w32 (-1, "%s:%s: create in.condvar failed", SRCNAME, __func__); + + InitializeCriticalSection (&filter->out.lock); + filter->out.condvar = CreateEvent (NULL, TRUE, 0, NULL); + if (!filter->out.condvar) + log_error_w32 (-1, "%s:%s: create out.condvar failed", SRCNAME, __func__); + + /* Create an automatic event (it only used one time so the type is + actually not important). */ + filter->in.ready_event = CreateEvent (NULL, 0, 0, NULL); + if (!filter->in.ready_event) + log_error_w32 (-1, "%s:%s: CreateEvent failed", SRCNAME, __func__); + TRACEPOINT (); + + return filter; +} + + +static void +release_filter (engine_filter_t filter) +{ + if (filter) + { + TRACEPOINT (); + if (filter->in.condvar) + CloseHandle (filter->in.condvar); + if (filter->out.condvar) + CloseHandle (filter->out.condvar); + if (filter->in.ready_event) + CloseHandle (filter->in.ready_event); + gpgme_data_release (filter->indata); + gpgme_data_release (filter->outdata); + xfree (filter); + } +} + + + + +/* This read callback is used by GPGME to read data from a filter + object. The function should return the number of bytes read, 0 on + EOF, and -1 on error. If an error occurs, ERRNO should be set to + describe the type of the error. */ +static ssize_t +filter_gpgme_read_cb (void *handle, void *buffer, size_t size) +{ + engine_filter_t filter = handle; + int nbytes; + + if (!filter || !buffer || !size) + { + errno = EINVAL; + return (ssize_t)(-1); + } + + log_debug ("%s:%s: enter\n", SRCNAME, __func__); + EnterCriticalSection (&filter->in.lock); + while (!filter->in.length) + { + if (filter->in.got_eof || filter->in.ready) + { + LeaveCriticalSection (&filter->in.lock); + log_debug ("%s:%s: returning EOF\n", SRCNAME, __func__); + return 0; /* Return EOF. */ + } + LeaveCriticalSection (&filter->in.lock); + log_debug ("%s:%s: waiting for in.condvar\n", SRCNAME, __func__); + WaitForSingleObject (filter->in.condvar, 500); + EnterCriticalSection (&filter->in.lock); + log_debug ("%s:%s: continuing\n", SRCNAME, __func__); + } + + log_debug ("%s:%s: requested read size=%d (filter.in.length=%d)\n", + SRCNAME, __func__, (int)size, (int)filter->in.length); + nbytes = size < filter->in.length ? size : filter->in.length; + memcpy (buffer, filter->in.buffer, nbytes); + if (filter->in.length > nbytes) + memmove (filter->in.buffer, filter->in.buffer + nbytes, + filter->in.length - nbytes); + filter->in.length -= nbytes; + LeaveCriticalSection (&filter->in.lock); + + log_debug ("%s:%s: leave; result=%d\n", + SRCNAME, __func__, (int)nbytes); + + return nbytes; +} + + +/* This write callback is used by GPGME to write data to the filter + object. The function should return the number of bytes written, + and -1 on error. If an error occurs, ERRNO should be set to + describe the type of the error. */ +static ssize_t +filter_gpgme_write_cb (void *handle, const void *buffer, size_t size) +{ + engine_filter_t filter = handle; + int nbytes; + + if (!filter || !buffer || !size) + { + errno = EINVAL; + return (ssize_t)(-1); + } + + log_debug ("%s:%s: enter\n", SRCNAME, __func__); + EnterCriticalSection (&filter->out.lock); + while (filter->out.length) + { + LeaveCriticalSection (&filter->out.lock); + log_debug ("%s:%s: waiting for out.condvar\n", SRCNAME, __func__); + WaitForSingleObject (filter->out.condvar, 500); + EnterCriticalSection (&filter->out.lock); + log_debug ("%s:%s: continuing\n", SRCNAME, __func__); + } + + log_debug ("%s:%s: requested write size=%d\n", + SRCNAME, __func__, (int)size); + nbytes = size < FILTER_BUFFER_SIZE ? size : FILTER_BUFFER_SIZE; + memcpy (filter->out.buffer, buffer, nbytes); + filter->out.length = nbytes; + LeaveCriticalSection (&filter->out.lock); + + log_debug ("%s:%s: write; result=%d\n", SRCNAME, __func__, (int)nbytes); + return nbytes; +} + +/* This function is called by the gpgme backend to notify a filter + object about the final status of an operation. It may not be + called by the engine-gpgme.c module. */ +void +engine_gpgme_finished (engine_filter_t filter, gpg_error_t status) +{ + if (!filter) + { + log_debug ("%s:%s: called without argument\n", SRCNAME, __func__); + return; + } + log_debug ("%s:%s: filter %p: process terminated: %s <%s>\n", + SRCNAME, __func__, filter, + gpg_strerror (status), gpg_strsource (status)); + + EnterCriticalSection (&filter->in.lock); + if (filter->in.ready) + log_debug ("%s:%s: filter %p: Oops: already flagged as finished\n", + SRCNAME, __func__, filter); + filter->in.ready = 1; + filter->in.status = status; + if (!SetEvent (filter->in.ready_event)) + log_error_w32 (-1, "%s:%s: SetEvent failed", SRCNAME, __func__); + LeaveCriticalSection (&filter->in.lock); + log_debug ("%s:%s: leaving\n", SRCNAME, __func__); +} + + + + + +/* Initialize the engine dispatcher. */ +int +engine_init (void) +{ + op_init (); + return 0; +} + + +/* Shutdown the engine dispatcher. */ +void +engine_deinit (void) +{ + op_deinit (); + +} + + + +/* Filter the INDATA of length INDATA and write the output using + OUTFNC. OUTFNCDATA is passed as first argument to OUTFNC, followed + by the data to be written and its length. FILTER is an object + returned for example by engine_encrypt_start. The function returns + 0 on success or an error code on error. + + Passing INDATA as NULL and INDATALEN as 0, the filter will be + flushed, that is all remaining stuff will be written to OUTFNC. + This indicates EOF and the filter won't accept anymore input. */ +int +engine_filter (engine_filter_t filter, const void *indata, size_t indatalen) +{ + gpg_error_t err; + size_t nbytes; + + log_debug ("%s:%s: enter; filter=%p\n", SRCNAME, __func__, filter); + /* Our implementation is for now straightforward without any + additional buffer filling etc. */ + if (!filter || !filter->outfnc) + return gpg_error (GPG_ERR_INV_VALUE); + if (filter->in.length > FILTER_BUFFER_SIZE + || filter->out.length > FILTER_BUFFER_SIZE) + return gpg_error (GPG_ERR_BUG); + if (filter->in.got_eof) + return gpg_error (GPG_ERR_CONFLICT); /* EOF has already been indicated. */ + + log_debug ("%s:%s: indata=%p indatalen=%d outfnc=%p\n", + SRCNAME, __func__, indata, (int)indatalen, filter->outfnc); + for (;;) + { + /* If there is something to write out, do this now to make space + for more data. */ + EnterCriticalSection (&filter->out.lock); + while (filter->out.length) + { + TRACEPOINT (); + nbytes = filter->outfnc (filter->outfncdata, + filter->out.buffer, filter->out.length); + if (nbytes == -1) + { + log_debug ("%s:%s: error writing data\n", SRCNAME, __func__); + LeaveCriticalSection (&filter->out.lock); + return gpg_error (GPG_ERR_EIO); + } + assert (nbytes < filter->out.length && nbytes >= 0); + if (nbytes < filter->out.length) + memmove (filter->out.buffer, filter->out.buffer + nbytes, + filter->out.length - nbytes); + filter->out.length =- nbytes; + } + if (!PulseEvent (filter->out.condvar)) + log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__); + LeaveCriticalSection (&filter->out.lock); + + EnterCriticalSection (&filter->in.lock); + if (!indata && !indatalen) + { + TRACEPOINT (); + filter->in.got_eof = 1; + /* Flush requested. Tell the output function to also flush. */ + nbytes = filter->outfnc (filter->outfncdata, NULL, 0); + if (nbytes == -1) + { + log_debug ("%s:%s: error flushing data\n", SRCNAME, __func__); + err = gpg_error (GPG_ERR_EIO); + } + else + err = 0; + LeaveCriticalSection (&filter->in.lock); + return err; + } + + /* Fill the input buffer, relinquish control to the callback + processor and loop until all input data has been + processed. */ + if (!filter->in.length && indatalen) + { + TRACEPOINT (); + filter->in.length = (indatalen > FILTER_BUFFER_SIZE + ? FILTER_BUFFER_SIZE : indatalen); + memcpy (filter->in.buffer, indata, filter->in.length); + indata += filter->in.length; + indatalen -= filter->in.length; + } + if (!filter->in.length || (filter->in.ready && !filter->out.length)) + { + LeaveCriticalSection (&filter->in.lock); + err = 0; + break; /* the loop. */ + } + if (!PulseEvent (filter->in.condvar)) + log_error_w32 (-1, "%s:%s: PulseEvent(in) failed", SRCNAME, __func__); + LeaveCriticalSection (&filter->in.lock); + Sleep (0); + } + + log_debug ("%s:%s: leave; err=%d\n", SRCNAME, __func__, err); + return err; +} + + +/* Create a new filter object which uses OUTFNC as its data sink. If + OUTFNC is called with NULL/0 for the data to be written, the + function should do a flush. OUTFNC is expected to return the + number of bytes actually written or -1 on error. It may return 0 + to indicate that no data has been written and the caller shall try + again. OUTFNC and OUTFNCDATA are internally used by the engine + even after the call to this function. There lifetime only ends + after an engine_wait or engine_cancel. */ +int +engine_create_filter (engine_filter_t *r_filter, + int (*outfnc) (void *, const void *, size_t), + void *outfncdata) +{ + gpg_error_t err; + engine_filter_t filter; + + filter = create_filter (); + filter->cb_inbound.read = filter_gpgme_read_cb; + filter->cb_outbound.write = filter_gpgme_write_cb; + filter->outfnc = outfnc; + filter->outfncdata = outfncdata; + + err = gpgme_data_new_from_cbs (&filter->indata, + &filter->cb_inbound, filter); + if (err) + goto failure; + + err = gpgme_data_new_from_cbs (&filter->outdata, + &filter->cb_outbound, filter); + if (err) + goto failure; + + *r_filter = filter; + return 0; + + failure: + release_filter (filter); + return err; +} + + + +/* Wait for FILTER to finish. Returns 0 on success. FILTER is not + valid after the function has returned success. */ +int +engine_wait (engine_filter_t filter) +{ + gpg_error_t err; + int more; + + TRACEPOINT (); + if (!filter || !filter->outfnc) + return gpg_error (GPG_ERR_INV_VALUE); + + /* If we are here, engine_filter is not anymore called but there is + likely stuff in the output buffer which needs to be written + out. */ + /* Argh, Busy waiting. As soon as we change fromCritical Sections + to a kernel based objects we should use WaitOnMultipleObjects to + wait for the out.lock as well as for the ready_event. */ + do + { + EnterCriticalSection (&filter->out.lock); + while (filter->out.length) + { + int nbytes; + TRACEPOINT (); + nbytes = filter->outfnc (filter->outfncdata, + filter->out.buffer, filter->out.length); + if (nbytes == -1) + { + log_debug ("%s:%s: error writing data\n", SRCNAME, __func__); + LeaveCriticalSection (&filter->out.lock); + break; + } + assert (nbytes < filter->out.length && nbytes >= 0); + if (nbytes < filter->out.length) + memmove (filter->out.buffer, filter->out.buffer + nbytes, + filter->out.length - nbytes); + filter->out.length =- nbytes; + } + if (!PulseEvent (filter->out.condvar)) + log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__); + LeaveCriticalSection (&filter->out.lock); + EnterCriticalSection (&filter->in.lock); + more = !filter->in.ready; + LeaveCriticalSection (&filter->in.lock); + if (more) + Sleep (0); + } + while (more); + + if (WaitForSingleObject (filter->in.ready_event, INFINITE) != WAIT_OBJECT_0) + { + log_error_w32 (-1, "%s:%s: WFSO failed", SRCNAME, __func__); + return gpg_error (GPG_ERR_GENERAL); + } + err = filter->in.status; + log_debug ("%s:%s: filter %p ready: %s", SRCNAME, __func__, + filter, gpg_strerror (err)); + + if (!err) + release_filter (filter); + return err; +} + + +/* Cancel FILTER. */ +void +engine_cancel (engine_filter_t filter) +{ + if (!filter) + return; + + EnterCriticalSection (&filter->in.lock); + filter->in.ready = 1; + LeaveCriticalSection (&filter->in.lock); + log_debug ("%s:%s: filter %p canceled", SRCNAME, __func__, filter); + /* FIXME: Here we need to kill the underlying gpgme process. */ + release_filter (filter); +} + + + +/* Start an encryption operation to all RECIPEINTS using PROTOCOL + RECIPIENTS is a NULL terminated array of rfc2822 addresses. FILTER + is an object create by engine_create_filter. The caller needs to + call engine_wait to finish the operation. A filter object may not + be reused after having been used through this function. However, + the lifetime of the filter object lasts until the final engine_wait + or engine_cabcel. */ +int +engine_encrypt_start (engine_filter_t filter, + protocol_t protocol, char **recipients) +{ + gpg_error_t err; + + err = op_encrypt_data (filter->indata, filter->outdata, + filter, recipients, NULL, 0); + return err; +} + + + + +/* Release a KEY. Do nothing if KEY is NULL. */ +void +engine_release_key (engine_keyinfo_t key) +{ + if (!key) + return; + gpgme_key_release (key->gpgme.key); + key->gpgme.key = NULL; +} + + +/* Return a signing key and store it at the R_KEY. the caller sahll + set ENCRYPTING to true if the message will also be encrypted. On + error true is returned and NULL stored at R_KEY. Not ethat + depending on the actual engine use the retruned key might be NULL - + thus this shall not be used as an error indication. */ +int +engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting) +{ + engine_keyinfo_t key; + gpgme_key_t sign_key = NULL; + + *r_key = NULL; + if (signer_dialog_box (&sign_key, NULL, encrypting) == -1) + { + log_debug ("%s:%s: failed to get key from dialog\n", SRCNAME, __func__); + return gpg_error (GPG_ERR_CANCELED); + } + key = xcalloc (1, sizeof **r_key); + key->gpgme.key = sign_key; + + *r_key = key; + return 0; +} + + Modified: trunk/src/engine.h =================================================================== --- trunk/src/engine.h 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/engine.h 2007-09-12 16:40:23 UTC (rev 176) @@ -1,21 +1,22 @@ -/* engine.h - Crypto engine - * Copyright (C) 2005 g10 Code GmbH +/* engine.h - Crypto engine dispatcher + * Copyright (C) 2007 g10 Code GmbH * - * This file is part of GPGol. + * This file is part of GpgOL. * - * GPGol is free software; you can redistribute it and/or + * GpgOL 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. * - * GPGol is distributed in the hope that it will be useful, + * GpgOL 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. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License - * along with GPGol; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU Lesser General Public + * License along with GpgOL; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef GPGOL_ENGINE_H @@ -28,75 +29,50 @@ #endif #endif -#include - typedef enum { OP_SIG_NORMAL = 0, OP_SIG_DETACH = 1, OP_SIG_CLEAR = 2 } -op_sigtype_t; +engine_sigtype_t; -int op_init (void); -void op_deinit (void); +/* The key info object. */ +struct engine_keyinfo_s; +typedef struct engine_keyinfo_s *engine_keyinfo_t; -#define op_debug_enable(file) op_set_debug_mode (5, (file)) -#define op_debug_disable() op_set_debug_mode (0, NULL) -void op_set_debug_mode (int val, const char *file); +/* The filter object. */ +struct engine_filter_s; +typedef struct engine_filter_s *engine_filter_t; -int op_encrypt (const char *inbuf, char **outbuf, - gpgme_key_t *keys, gpgme_key_t sign_key, int ttl); -int op_encrypt_stream (LPSTREAM instream, LPSTREAM outstream, - gpgme_key_t *keys, gpgme_key_t sign_key, int ttl); -int op_sign (const char *inbuf, char **outbuf, int mode, - gpgme_key_t sign_key, int ttl); -int op_sign_stream (LPSTREAM instream, LPSTREAM outstream, int mode, - gpgme_key_t sign_key, int ttl); -int op_decrypt (const char *inbuf, char **outbuf, int ttl, - const char *filename, gpgme_data_t attestation, - int preview_mode); -int op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl, - const char *filename, gpgme_data_t attestation); -int op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl, - const char *filename, - gpgme_data_t attestation); -int op_decrypt_stream_to_gpgme (gpgme_protocol_t protocol, - LPSTREAM instream, gpgme_data_t out, int ttl, - const char *filename, gpgme_data_t attestation, - int preview_mode); -int op_verify (const char *inbuf, char **outbuf, const char *filename, - gpgme_data_t attestation); -int op_verify_detached_sig (LPSTREAM data, const char *sig, - const char *filename, gpgme_data_t attestation); -int op_verify_detached_sig_mem (const char *data_string, - const char *sig_string, const char *filename, - gpgme_data_t attestation); -int op_verify_detached_sig_gpgme (gpgme_protocol_t protocol, - gpgme_data_t data, gpgme_data_t sig, - const char *filename, - gpgme_data_t attestation); +/*-- engine.c -- */ +int engine_init (void); +void engine_deinit (void); +/* This callback function is to be used only by engine-gpgme.c. */ +void engine_gpgme_finished (engine_filter_t filter, gpg_error_t status); -int op_export_keys (const char *pattern[], const char *outfile); +int engine_filter (engine_filter_t filter, + const void *indata, size_t indatalen); +int engine_create_filter (engine_filter_t *r_filter, + int (*outfnc) (void *, const void *, size_t), + void *outfncdata); +int engine_wait (engine_filter_t filter); +void engine_cancel (engine_filter_t filter); -int op_lookup_keys (char **names, gpgme_key_t **keys, char ***unknown); -gpgme_key_t op_get_one_key (char *pattern); +int engine_encrypt_start (engine_filter_t filter, + protocol_t protocol, char **recipients); -const char *userid_from_key (gpgme_key_t k); -const char *keyid_from_key (gpgme_key_t k); -const char *op_strerror (int err); -const char *op_strsource (int err); +void engine_release_key (engine_keyinfo_t key); +int engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting); #ifdef __cplusplus } #endif - - #endif /*GPGOL_ENGINE_H*/ Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/ext-commands.cpp 2007-09-12 16:40:23 UTC (rev 176) @@ -31,7 +31,6 @@ #include "common.h" #include "display.h" #include "msgcache.h" -#include "engine.h" #include "mapihelp.h" #include "olflange-ids.h" Modified: trunk/src/message-events.cpp =================================================================== --- trunk/src/message-events.cpp 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/message-events.cpp 2007-09-12 16:40:23 UTC (rev 176) @@ -351,7 +351,7 @@ if (m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) rc = mime_sign_encrypt (msg, PROTOCOL_OPENPGP); else if (m_pExchExt->m_gpgEncrypt && !m_pExchExt->m_gpgSign) - rc = mime_encrypt (msg, PROTOCOL_OPENPGP); + rc = message_encrypt (msg, hWnd); else if (!m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) rc = mime_sign (msg, PROTOCOL_OPENPGP); else Modified: trunk/src/message.cpp =================================================================== --- trunk/src/message.cpp 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/message.cpp 2007-09-12 16:40:23 UTC (rev 176) @@ -30,6 +30,7 @@ #include "common.h" #include "mapihelp.h" #include "mimeparser.h" +#include "mimemaker.h" #include "message.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ @@ -497,7 +498,105 @@ } + +/* Return an array of strings with the recipients of the message. On + success a malloced array is returned containing allocated strings + for each recipient. The end of the array is marked by NULL. + Caller is responsible for releasing the array. On failure NULL is + returned. */ +static char ** +get_recipients (LPMESSAGE message) +{ + static SizedSPropTagArray (1L, PropRecipientNum) = {1L, {PR_EMAIL_ADDRESS}}; + HRESULT hr; + LPMAPITABLE lpRecipientTable = NULL; + LPSRowSet lpRecipientRows = NULL; + unsigned int rowidx; + LPSPropValue row; + char **rset; + int rsetidx; + + + if (!message) + return NULL; + + hr = message->GetRecipientTable (0, &lpRecipientTable); + if (FAILED (hr)) + { + log_debug_w32 (-1, "%s:%s: GetRecipientTable failed", SRCNAME, __func__); + return NULL; + } + + hr = HrQueryAllRows (lpRecipientTable, (LPSPropTagArray) &PropRecipientNum, + NULL, NULL, 0L, &lpRecipientRows); + if (FAILED (hr)) + { + log_debug_w32 (-1, "%s:%s: HrQueryAllRows failed", SRCNAME, __func__); + if (lpRecipientTable) + lpRecipientTable->Release(); + return NULL; + } + + rset = (char**)xcalloc (lpRecipientRows->cRows+1, sizeof *rset); + + for (rowidx=0, rsetidx=0; rowidx < lpRecipientRows->cRows; rowidx++) + { + if (!lpRecipientRows->aRow[rowidx].cValues) + continue; + row = lpRecipientRows->aRow[rowidx].lpProps; + + switch (PROP_TYPE (row->ulPropTag)) + { + case PT_UNICODE: + if ((rset[rsetidx] = wchar_to_utf8 (row->Value.lpszW))) + rsetidx++; + else + log_debug ("%s:%s: error converting recipient to utf8\n", + SRCNAME, __func__); + break; + + case PT_STRING8: /* Assume ASCII. */ + rset[rsetidx++] = xstrdup (row->Value.lpszA); + break; + + default: + log_debug ("%s:%s: proptag=0x%08lx not supported\n", + SRCNAME, __func__, row->ulPropTag); + break; + } + } + + if (lpRecipientTable) + lpRecipientTable->Release(); + if (lpRecipientRows) + FreeProws(lpRecipientRows); + + log_debug ("%s:%s: got %d recipients:\n", SRCNAME, __func__, rsetidx); + for (rsetidx=0; rset[rsetidx]; rsetidx++) + log_debug ("%s:%s: \t`%s'\n", SRCNAME, __func__, rset[rsetidx]); + + return rset; +} + + +static void +release_recipient_array (char **recipients) +{ + int idx; + + if (recipients) + { + for (idx=0; recipients[idx]; idx++) + xfree (recipients[idx]); + xfree (recipients); + } +} + + + + + #if 0 /* Sign the current message. Returns 0 on success. */ @@ -644,3 +743,35 @@ } #endif + + +/* Encrypt the MESSAGE. */ +int +message_encrypt (LPMESSAGE message, HWND hwnd) +{ + gpg_error_t err; + char **recipients; + + recipients = get_recipients (message); + if (!recipients || !recipients[0]) + { + MessageBox (hwnd, _("No recipients for encrypted message given"), + "GpgOL", MB_ICONERROR|MB_OK); + + err = gpg_error (GPG_ERR_GENERAL); + } + else + { + err = mime_encrypt (message, PROTOCOL_OPENPGP, recipients); + if (err) + { + char buf[200]; + + snprintf (buf, sizeof buf, + _("Encryption failed (%s)"), gpg_strerror (err)); + MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK); + } + } + release_recipient_array (recipients); + return err; +} Modified: trunk/src/message.h =================================================================== --- trunk/src/message.h 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/message.h 2007-09-12 16:40:23 UTC (rev 176) @@ -26,5 +26,7 @@ int message_verify (LPMESSAGE message, msgtype_t msgtype, int force); int message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force); +int message_encrypt (LPMESSAGE message, HWND hwnd); + #endif /*MESSAGE_H*/ Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/mimemaker.c 2007-09-12 16:40:23 UTC (rev 176) @@ -230,6 +230,13 @@ return sink->writefnc (sink, data, datalen); } +/* Same as above but used for passing as callback function. */ +static int +write_buffer_voidarg (void *opaque, const void *data, size_t datalen) +{ + sink_t sink = opaque; + return write_buffer (sink, data, datalen); +} /* Write the string TEXT to the IStream STREAM. Returns 0 on sucsess, @@ -1039,6 +1046,8 @@ char *body = NULL; int n_att_usable; + memset (sink, 0, sizeof *sink); + protocol = check_protocol (protocol); if (protocol == PROTOCOL_UNKNOWN) return -1; @@ -1169,26 +1178,21 @@ static int sink_encryption_write (sink_t encsink, const void *data, size_t datalen) { - sink_t outsink = encsink->cb_data; + engine_filter_t filter = encsink->cb_data; - if (!outsink) + if (!filter) { log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__); return -1; } - if (!data) - { - /* Flush */ - return 0; - } - return write_buffer (outsink, data, datalen); + return engine_filter (filter, data, datalen); } /* Encrypt the MESSAGE. */ int -mime_encrypt (LPMESSAGE message, protocol_t protocol) +mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients) { int result = -1; int rc; @@ -1202,7 +1206,11 @@ mapi_attach_item_t *att_table = NULL; char *body = NULL; int n_att_usable; + engine_filter_t filter; + memset (sink, 0, sizeof *sink); + memset (encsink, 0, sizeof *encsink); + protocol = check_protocol (protocol); if (protocol == PROTOCOL_UNKNOWN) return -1; @@ -1213,6 +1221,14 @@ if (!attach) return -1; + /* Prepare the encryption. We do this early as it is quite common + that some recipients are not be available and thus the encryption + will fail early. */ + if (engine_create_filter (&filter, write_buffer_voidarg, sink)) + goto failure; + if (engine_encrypt_start (filter, protocol, recipients)) + goto failure; + /* Get the attachment info and the body. */ body = mapi_get_body (message, NULL); if (body && !*body) @@ -1257,9 +1273,8 @@ goto failure; /* Create a new sink for encrypting the following stuff. */ - encsink->cb_data = sink; + encsink->cb_data = filter; encsink->writefnc = sink_encryption_write; - if ((body && n_att_usable) || n_att_usable > 1) { @@ -1291,12 +1306,13 @@ if (*inner_boundary && (rc = write_boundary (encsink, inner_boundary, 1))) goto failure; - /* Flush the encryption sink and thus wait for the encryption to - get ready. */ + /* Flush the encryption sink and wait for the encryption to get + ready. */ if ((rc = write_buffer (encsink, NULL, 0))) goto failure; - /* FIXME: Release the encryption context etc. Using the flush above - is not a clean way of doing it. */ + if ((rc = engine_wait (filter))) + goto failure; + filter = NULL; /* Not valid anymore. */ encsink->cb_data = NULL; /* Not needed anymore. */ @@ -1313,8 +1329,7 @@ result = 0; /* Everything is fine, fall through the cleanup now. */ failure: - if (encsink->cb_data) - ;/*FIXME: Cancel the encryption. */ + engine_cancel (filter); cancel_mapi_attachment (&attach, sink); xfree (body); mapi_release_attach_table (att_table); Modified: trunk/src/mimemaker.h =================================================================== --- trunk/src/mimemaker.h 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/mimemaker.h 2007-09-12 16:40:23 UTC (rev 176) @@ -29,7 +29,7 @@ #endif int mime_sign (LPMESSAGE message, protocol_t protocol); -int mime_encrypt (LPMESSAGE message, protocol_t protocol); +int mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients); int mime_sign_encrypt (LPMESSAGE message, protocol_t protocol); Modified: trunk/src/ol-ext-callback.cpp =================================================================== --- trunk/src/ol-ext-callback.cpp 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/ol-ext-callback.cpp 2007-09-12 16:40:23 UTC (rev 176) @@ -31,7 +31,6 @@ #include "display.h" #include "common.h" #include "msgcache.h" -#include "engine.h" #include "mapihelp.h" #include "olflange-ids.h" Modified: trunk/src/olflange.cpp =================================================================== --- trunk/src/olflange.cpp 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/olflange.cpp 2007-09-12 16:40:23 UTC (rev 176) @@ -315,7 +315,7 @@ if (!g_initdll) { read_options (); - op_init (); + engine_init (); g_initdll = TRUE; log_debug ("%s:%s: first time initialization done\n", SRCNAME, __func__); @@ -336,7 +336,7 @@ { if (g_initdll) { - op_deinit (); + engine_deinit (); write_options (); g_initdll = FALSE; log_debug ("%s:%s: DLL closed down\n", SRCNAME, __func__); Modified: trunk/src/rfc822parse.c =================================================================== --- trunk/src/rfc822parse.c 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/rfc822parse.c 2007-09-12 16:40:23 UTC (rev 176) @@ -342,9 +342,7 @@ if (!rc) { /* Store the boundary if we have multipart type. */ - ctx = rfc822parse_parse_field (msg, "GnuPG-Content-Type", -1); - if (!ctx) - ctx = rfc822parse_parse_field (msg, "Content-Type", -1); + ctx = rfc822parse_parse_field (msg, "Content-Type", -1); if (ctx) { const char *s; @@ -766,7 +764,6 @@ const unsigned char *name; size_t namelen; } tspecial_header[] = { - { "GnuPG-Content-Type", 18}, { "Content-Type", 12}, { "Content-Transfer-Encoding", 25}, { "Content-Disposition", 19}, Modified: trunk/src/versioninfo.rc.in =================================================================== --- trunk/src/versioninfo.rc.in 2007-09-08 11:18:38 UTC (rev 175) +++ trunk/src/versioninfo.rc.in 2007-09-12 16:40:23 UTC (rev 176) @@ -36,14 +36,14 @@ BEGIN VALUE "Comments", "This plugin is available under the terms of the GNU Lesser General Public License.\0" VALUE "CompanyName", "g10 Code GmbH\0" - VALUE "FileDescription", "GPGol - GnuPG plugin for Outlook\0" + VALUE "FileDescription", "GpgOL - GnuPG plugin for Outlook\0" VALUE "FileVersion", "@VERSION@\0" VALUE "InternalName", "gpgol\0" VALUE "LegalCopyright", "Copyright ? 2005 g10 Code GmbH\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "gpgol.dll\0" VALUE "PrivateBuild", "\0" - VALUE "ProductName", "GPGol\0" + VALUE "ProductName", "GpgOL\0" VALUE "ProductVersion", "@VERSION@\0" VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0" END From cvs at cvs.gnupg.org Wed Sep 12 23:04:31 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 12 Sep 2007 23:04:31 +0200 Subject: [svn] dirmngr - r268 - trunk/src Message-ID: Author: marcus Date: 2007-09-12 23:04:02 +0200 (Wed, 12 Sep 2007) New Revision: 268 Modified: trunk/src/ChangeLog trunk/src/dirmngr.c Log: 2007-09-12 Marcus Brinkmann * dirmngr.c (main): Percent escape pathnames in --gpgconf-list output. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-04 07:42:42 UTC (rev 267) +++ trunk/src/ChangeLog 2007-09-12 21:04:02 UTC (rev 268) @@ -1,3 +1,7 @@ +2007-09-12 Marcus Brinkmann + + * dirmngr.c (main): Percent escape pathnames in --gpgconf-list output. + 2007-08-27 Moritz Schulte * src/Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SOCKETDIR based on Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-09-04 07:42:42 UTC (rev 267) +++ trunk/src/dirmngr.c 2007-09-12 21:04:02 UTC (rev 268) @@ -1140,6 +1140,8 @@ else if (cmd == aGPGConfList) { char *filename; + char *filename_esc; + /* List options and default values in the GPG Conf format. */ /* The following list is taken from gnupg/tools/gpgconf-comp.c. */ @@ -1162,8 +1164,10 @@ opt.config_filename = make_filename (opt.homedir, "dirmngr.conf", NULL ); + filename = percent_escape (opt.config_filename, NULL); printf ("gpgconf-dirmngr.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, opt.config_filename); + GC_OPT_FLAG_DEFAULT, filename); + xfree (filename); printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE); printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE); @@ -1181,7 +1185,10 @@ opt.system_daemon? "ldapservers.conf":"dirmngr_ldapservers.conf", NULL); - printf ("ldapserverlist-file:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, filename); + filename_esc = percent_escape (filename, NULL); + printf ("ldapserverlist-file:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, + filename_esc); + xfree (filename_esc); xfree (filename); printf ("ldaptimeout:%lu:%u\n", From cvs at cvs.gnupg.org Thu Sep 13 13:53:44 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 13 Sep 2007 13:53:44 +0200 Subject: [svn] GpgOL - r177 - in trunk: po src Message-ID: Author: wk Date: 2007-09-13 13:53:15 +0200 (Thu, 13 Sep 2007) New Revision: 177 Modified: trunk/po/de.po trunk/po/sv.po trunk/src/ChangeLog trunk/src/common.c trunk/src/engine-gpgme.c trunk/src/engine.c trunk/src/engine.h trunk/src/mimemaker.c trunk/src/xmalloc.h Log: Creating PGP/MIME signed mails works now - kind of: becuase the passphrase dialog runs in a second thread, the windows are not properly cleaned up lated. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/po/de.po 2007-09-13 11:53:15 UTC (rev 177) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol 0.9.4\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-09-06 21:27+0200\n" +"POT-Creation-Date: 2007-09-11 20:30+0200\n" "PO-Revision-Date: 2007-04-13 12:55+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" @@ -23,62 +23,62 @@ msgid "Select GPG Key Manager" msgstr "Das Schl?sselverwaltungsprogramm festlegen" -#: src/engine-gpgme.c:1004 +#: src/engine-gpgme.c:1099 msgid "Fingerprint: " msgstr "Fingerabdruck: " -#: src/engine-gpgme.c:1061 +#: src/engine-gpgme.c:1156 msgid "This signature is valid\n" msgstr "Diese Unterschrift ist korrekt\n" -#: src/engine-gpgme.c:1063 +#: src/engine-gpgme.c:1158 msgid "signature state is \"green\"\n" msgstr "Status der Unterschrift ist \"gr?n\"\n" -#: src/engine-gpgme.c:1065 +#: src/engine-gpgme.c:1160 msgid "signature state is \"red\"\n" msgstr "Status der Unterschrift ist \"rot\"\n" -#: src/engine-gpgme.c:1069 +#: src/engine-gpgme.c:1164 msgid "Warning: One of the keys has been revoked\n" msgstr "Warnung: Einer der Schl?ssel wurde widerrufen\n" -#: src/engine-gpgme.c:1079 +#: src/engine-gpgme.c:1174 msgid "Warning: The key used to create the signature expired at: " msgstr "" "Warnung: Der Schl?ssel mit der diese Unterschrift erzeugt wurde verfiel am: " -#: src/engine-gpgme.c:1085 +#: src/engine-gpgme.c:1180 msgid "Warning: At least one certification key has expired\n" msgstr "" "Warnung: Mindestens einer der Zertifizierungsschl?ssel ist abgelaufen\n" -#: src/engine-gpgme.c:1091 +#: src/engine-gpgme.c:1186 msgid "Warning: The signature expired at: " msgstr "Die Unterschrift verfiel am: " -#: src/engine-gpgme.c:1097 +#: src/engine-gpgme.c:1192 msgid "Can't verify due to a missing key or certificate\n" msgstr "" "Aufrund eines fehlenden Schl?ssels ist eine ?berpr?fung nicht m?glich\n" -#: src/engine-gpgme.c:1101 +#: src/engine-gpgme.c:1196 msgid "The CRL is not available\n" msgstr "Die CRL ist nicht verf?gbar\n" -#: src/engine-gpgme.c:1107 +#: src/engine-gpgme.c:1202 msgid "Available CRL is too old\n" msgstr "Die vorhandene CRL ist zu alt\n" -#: src/engine-gpgme.c:1112 +#: src/engine-gpgme.c:1207 msgid "A policy requirement was not met\n" msgstr "Eine Richtlinie wurde nicht erf?llt\n" -#: src/engine-gpgme.c:1118 +#: src/engine-gpgme.c:1213 msgid "A system error occured" msgstr "Ein Systemfehler ist aufgetreten" -#: src/engine-gpgme.c:1155 +#: src/engine-gpgme.c:1250 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -86,12 +86,12 @@ "WARNUNG: Es gibt keinen Hinweis darauf, ob der Schl?ssel wirklich der Person " "geh?rt, die oben angezeigt ist\n" -#: src/engine-gpgme.c:1162 +#: src/engine-gpgme.c:1257 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" msgstr "" "WARNUNG: Der Schl?ssel geh?rt NICHT der Person die oben angezeigt ist\n" -#: src/engine-gpgme.c:1166 +#: src/engine-gpgme.c:1261 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -99,43 +99,43 @@ "WARNING: Es ist nicht sicher, da? der Schl?ssel der Person geh?rt, die oben " "angezeigt ist\n" -#: src/engine-gpgme.c:1199 +#: src/engine-gpgme.c:1294 msgid "Verification started at: " msgstr "?berpr?fung begann am: " -#: src/engine-gpgme.c:1204 +#: src/engine-gpgme.c:1299 msgid "Verification result for: " msgstr "Pr?fungsresultat f?r: " -#: src/engine-gpgme.c:1205 +#: src/engine-gpgme.c:1300 msgid "[unnamed part]" msgstr "[Unbenannter Teil]" -#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253 +#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348 msgid "Good signature from: " msgstr "Korrekte Unterschrift von: " -#: src/engine-gpgme.c:1230 +#: src/engine-gpgme.c:1325 msgid " aka: " msgstr " alias: " -#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256 +#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351 msgid " created: " msgstr " erzeugt: " -#: src/engine-gpgme.c:1243 +#: src/engine-gpgme.c:1338 msgid "*BAD* signature claimed to be from: " msgstr "*FALSCHE* Unterschrift, vorgeblich von: " -#: src/engine-gpgme.c:1266 +#: src/engine-gpgme.c:1361 msgid "Error checking signature" msgstr "Fehler beim Pr?fen der Unterschrift" -#: src/engine-gpgme.c:1282 +#: src/engine-gpgme.c:1377 msgid "*** Begin Notation (signature by: " msgstr "*** Anfang Notation (Unterschrift von: " -#: src/engine-gpgme.c:1302 +#: src/engine-gpgme.c:1397 msgid "*** End Notation ***\n" msgstr "*** Ende Notation ***\n" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/po/sv.po 2007-09-13 11:53:15 UTC (rev 177) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-09-06 21:27+0200\n" +"POT-Creation-Date: 2007-09-11 20:30+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -23,59 +23,59 @@ msgid "Select GPG Key Manager" msgstr "V?lj GPG-nyckelhanterare" -#: src/engine-gpgme.c:1004 +#: src/engine-gpgme.c:1099 msgid "Fingerprint: " msgstr "Fingeravtryck: " -#: src/engine-gpgme.c:1061 +#: src/engine-gpgme.c:1156 msgid "This signature is valid\n" msgstr "Den h?r signaturen ?r giltig\n" -#: src/engine-gpgme.c:1063 +#: src/engine-gpgme.c:1158 msgid "signature state is \"green\"\n" msgstr "signaturens tillst?nd ?r \"gr?n\"\n" -#: src/engine-gpgme.c:1065 +#: src/engine-gpgme.c:1160 msgid "signature state is \"red\"\n" msgstr "signaturens tillst?nd ?r \"r?d\"\n" -#: src/engine-gpgme.c:1069 +#: src/engine-gpgme.c:1164 msgid "Warning: One of the keys has been revoked\n" msgstr "Varning: En av nycklarna har sp?rrats\n" -#: src/engine-gpgme.c:1079 +#: src/engine-gpgme.c:1174 msgid "Warning: The key used to create the signature expired at: " msgstr "Varning: Nyckeln som anv?ndes f?r att skapa signaturen gick ut den: " -#: src/engine-gpgme.c:1085 +#: src/engine-gpgme.c:1180 msgid "Warning: At least one certification key has expired\n" msgstr "Varning: ?tminstone en certifieringsnyckel har g?tt ut\n" -#: src/engine-gpgme.c:1091 +#: src/engine-gpgme.c:1186 msgid "Warning: The signature expired at: " msgstr "Varning: Signaturen gick ut den: " -#: src/engine-gpgme.c:1097 +#: src/engine-gpgme.c:1192 msgid "Can't verify due to a missing key or certificate\n" msgstr "Kan inte validera p? grund av en saknad nyckel eller certifikat\n" -#: src/engine-gpgme.c:1101 +#: src/engine-gpgme.c:1196 msgid "The CRL is not available\n" msgstr "Sp?rrlistan ?r inte tillg?nglig\n" -#: src/engine-gpgme.c:1107 +#: src/engine-gpgme.c:1202 msgid "Available CRL is too old\n" msgstr "Tillg?nglig sp?rrlista ?r f?r gammal\n" -#: src/engine-gpgme.c:1112 +#: src/engine-gpgme.c:1207 msgid "A policy requirement was not met\n" msgstr "Ett policykrav matchades inte\n" -#: src/engine-gpgme.c:1118 +#: src/engine-gpgme.c:1213 msgid "A system error occured" msgstr "Ett systemfel intr?ffade" -#: src/engine-gpgme.c:1155 +#: src/engine-gpgme.c:1250 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -83,11 +83,11 @@ "VARNING: Vi har INGA indikationer p? huruvida nyckeln tillh?r personen vars " "namn visas ovanf?r\n" -#: src/engine-gpgme.c:1162 +#: src/engine-gpgme.c:1257 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" msgstr "VARNING: Nyckeln TILLH?R INTE personen vars namn visas ovanf?r\n" -#: src/engine-gpgme.c:1166 +#: src/engine-gpgme.c:1261 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -95,43 +95,43 @@ "VARNING: Det ?r INTE s?kert att nyckeln tillh?r den person vars namn visas " "ovanf?r\n" -#: src/engine-gpgme.c:1199 +#: src/engine-gpgme.c:1294 msgid "Verification started at: " msgstr "Validering startad: " -#: src/engine-gpgme.c:1204 +#: src/engine-gpgme.c:1299 msgid "Verification result for: " msgstr "Valideringsresultat f?r: " -#: src/engine-gpgme.c:1205 +#: src/engine-gpgme.c:1300 msgid "[unnamed part]" msgstr "[ej namngiven del]" -#: src/engine-gpgme.c:1223 src/engine-gpgme.c:1253 +#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348 msgid "Good signature from: " msgstr "Korrekt signatur fr?n: " -#: src/engine-gpgme.c:1230 +#: src/engine-gpgme.c:1325 msgid " aka: " msgstr "?ven k?nd som:" -#: src/engine-gpgme.c:1234 src/engine-gpgme.c:1256 +#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351 msgid " created: " msgstr " skapad: " -#: src/engine-gpgme.c:1243 +#: src/engine-gpgme.c:1338 msgid "*BAD* signature claimed to be from: " msgstr "*FELAKTIG* signatur h?vdades komma fr?n: " -#: src/engine-gpgme.c:1266 +#: src/engine-gpgme.c:1361 msgid "Error checking signature" msgstr "Fel vid kontroll av signatur" -#: src/engine-gpgme.c:1282 +#: src/engine-gpgme.c:1377 msgid "*** Begin Notation (signature by: " msgstr "*** Notation start (signatur av: " -#: src/engine-gpgme.c:1302 +#: src/engine-gpgme.c:1397 msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/ChangeLog 2007-09-13 11:53:15 UTC (rev 177) @@ -1,3 +1,7 @@ +2007-09-13 Werner Koch + + * common.c (xrealloc): New. + 2007-09-11 Werner Koch * engine-gpgme.c (op_encrypt_data): New. Modified: trunk/src/common.c =================================================================== --- trunk/src/common.c 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/common.c 2007-09-13 11:53:15 UTC (rev 177) @@ -167,6 +167,15 @@ return p; } +void * +xrealloc (void *a, size_t n) +{ + void *p = realloc (a, n); + if (!p) + out_of_core (); + return p; +} + char* xstrdup (const char *s) { Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/engine-gpgme.c 2007-09-13 11:53:15 UTC (rev 177) @@ -50,6 +50,8 @@ static DWORD WINAPI waiter_thread (void *dummy); +static void update_passphrase_cache (int err, + struct passphrase_cb_s *pass_cb_value); static void add_verify_attestation (gpgme_data_t at, gpgme_ctx_t ctx, gpgme_verify_result_t res, @@ -70,7 +72,7 @@ /* Enable or disable GPGME debug mode. */ void -op_set_debug_mode (int val, const char *file) +op_gpgme_set_debug_mode (int val, const char *file) { const char *s= "GPGME_DEBUG"; @@ -88,7 +90,7 @@ /* Cleanup static resources. */ void -op_deinit (void) +op_gpgme_deinit (void) { cleanup (); } @@ -96,7 +98,7 @@ /* Initialize the operation system. */ int -op_init (void) +op_gpgme_init (void) { gpgme_error_t err; @@ -148,6 +150,7 @@ gpgme_ctx_t ctx; gpg_error_t err; void *filter; + void *pass_cb; (void)dummy; @@ -164,6 +167,10 @@ { gpgme_get_progress_cb (ctx, NULL, &filter); engine_gpgme_finished (filter, err); + gpgme_get_passphrase_cb (ctx, NULL, &pass_cb); + if (pass_cb) + update_passphrase_cache (err, (struct passphrase_cb_s *)pass_cb); + xfree (pass_cb); gpgme_release (ctx); } else if (err) @@ -294,7 +301,7 @@ *outbuf = NULL; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) goto leave; @@ -549,9 +556,10 @@ just for this notification. We abuse the gpgme_set_progress_cb value for storing the pointer with the gpgme context. */ int -op_encrypt_data (gpgme_data_t indata, gpgme_data_t outdata, - void *notify_data, /* FIXME: Add hwnd */ - char **recipients, gpgme_key_t sign_key, int ttl) +op_gpgme_encrypt_data (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data, /* FIXME: Add hwnd */ + char **recipients, gpgme_key_t sign_key, int ttl) { gpg_error_t err; struct passphrase_cb_s cb; @@ -569,6 +577,12 @@ err = gpgme_new (&ctx); if (err) goto leave; + if (protocol == PROTOCOL_SMIME) + { + err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + if (err) + goto leave; + } gpgme_set_progress_cb (ctx, NULL, notify_data); gpgme_set_armor (ctx, 1); @@ -599,6 +613,61 @@ } +/* Created a detached signature for INDATA and write it to OUTDATA. + On termination of the signing command engine_gpgme_finished() is + called with NOTIFY_DATA as the first argument. */ +int +op_gpgme_sign_data (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data /* FIXME: Add hwnd */) +{ + gpg_error_t err; + struct passphrase_cb_s *cb; + gpgme_ctx_t ctx = NULL; + gpgme_key_t sign_key = NULL; + + if (signer_dialog_box (&sign_key, NULL, 0) == -1) + { + log_debug ("%s:%s: leave (dialog failed)\n", SRCNAME, __func__); + return gpg_error (GPG_ERR_CANCELED); + } + + cb = xcalloc (1, sizeof *cb); + cb->ttl = 0 /*FIXME: ttl*/; + + err = gpgme_new (&ctx); + if (err) + goto leave; + if (protocol == PROTOCOL_SMIME) + { + err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + if (err) + goto leave; + } + + gpgme_set_progress_cb (ctx, NULL, notify_data); + + gpgme_set_armor (ctx, 1); + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, cb); + cb->ctx = ctx; + err = gpgme_signers_add (ctx, sign_key); + if (!err) + err = gpgme_op_sign_start (ctx, indata, outdata, GPGME_SIG_MODE_DETACH); + + leave: + if (ctx && err) + { + xfree (cb); + gpgme_release (ctx); + } + gpgme_key_unref (sign_key); + return err; +} + + + + + /* Sign and encrypt the data in INBUF into a newly allocated buffer at OUTBUF. Caller needs to free the returned buffer using gpgme_free. */ @@ -617,7 +686,7 @@ cb.decrypt_cmd = 0; *outbuf = NULL; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) @@ -740,7 +809,7 @@ gpgme_error_t err; *outbuf = NULL; - op_init (); + op_gpgme_init (); memset (&cb, 0, sizeof cb); cb.ttl = ttl; @@ -1028,7 +1097,7 @@ if (outbuf) *outbuf = NULL; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) @@ -1092,7 +1161,7 @@ cbs.read = stream_read_cb; cbs.write = stream_write_cb; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) @@ -1142,7 +1211,7 @@ gpgme_error_t err; gpgme_verify_result_t res = NULL; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) @@ -1191,7 +1260,7 @@ gpgme_error_t err; gpgme_verify_result_t res = NULL; - op_init (); + op_gpgme_init (); err = gpgme_new (&ctx); if (err) Modified: trunk/src/engine.c =================================================================== --- trunk/src/engine.c 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/engine.c 2007-09-13 11:53:15 UTC (rev 177) @@ -267,7 +267,7 @@ int engine_init (void) { - op_init (); + op_gpgme_init (); return 0; } @@ -276,7 +276,7 @@ void engine_deinit (void) { - op_deinit (); + op_gpgme_deinit (); } @@ -509,58 +509,41 @@ /* Start an encryption operation to all RECIPEINTS using PROTOCOL RECIPIENTS is a NULL terminated array of rfc2822 addresses. FILTER - is an object create by engine_create_filter. The caller needs to + is an object created by engine_create_filter. The caller needs to call engine_wait to finish the operation. A filter object may not be reused after having been used through this function. However, the lifetime of the filter object lasts until the final engine_wait - or engine_cabcel. */ + or engine_cancel. */ int engine_encrypt_start (engine_filter_t filter, protocol_t protocol, char **recipients) { gpg_error_t err; - err = op_encrypt_data (filter->indata, filter->outdata, - filter, recipients, NULL, 0); + err = op_gpgme_encrypt_data (protocol, filter->indata, filter->outdata, + filter, recipients, NULL, 0); return err; } - - -/* Release a KEY. Do nothing if KEY is NULL. */ -void -engine_release_key (engine_keyinfo_t key) +/* Start an detached signing operation. + FILTER + is an object created by engine_create_filter. The caller needs to + call engine_wait to finish the operation. A filter object may not + be reused after having been used through this function. However, + the lifetime of the filter object lasts until the final engine_wait + or engine_cancel. */ +int +engine_sign_start (engine_filter_t filter, protocol_t protocol) { - if (!key) - return; - gpgme_key_release (key->gpgme.key); - key->gpgme.key = NULL; + gpg_error_t err; + + err = op_gpgme_sign_data (protocol, filter->indata, filter->outdata, + filter); + return err; } -/* Return a signing key and store it at the R_KEY. the caller sahll - set ENCRYPTING to true if the message will also be encrypted. On - error true is returned and NULL stored at R_KEY. Not ethat - depending on the actual engine use the retruned key might be NULL - - thus this shall not be used as an error indication. */ -int -engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting) -{ - engine_keyinfo_t key; - gpgme_key_t sign_key = NULL; - *r_key = NULL; - if (signer_dialog_box (&sign_key, NULL, encrypting) == -1) - { - log_debug ("%s:%s: failed to get key from dialog\n", SRCNAME, __func__); - return gpg_error (GPG_ERR_CANCELED); - } - key = xcalloc (1, sizeof **r_key); - key->gpgme.key = sign_key; - *r_key = key; - return 0; -} - Modified: trunk/src/engine.h =================================================================== --- trunk/src/engine.h 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/engine.h 2007-09-13 11:53:15 UTC (rev 177) @@ -66,12 +66,10 @@ int engine_encrypt_start (engine_filter_t filter, protocol_t protocol, char **recipients); +int engine_sign_start (engine_filter_t filter, protocol_t protocol); -void engine_release_key (engine_keyinfo_t key); -int engine_get_signer_key (engine_keyinfo_t *r_key, int encrypting); - #ifdef __cplusplus } #endif Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/mimemaker.c 2007-09-13 11:53:15 UTC (rev 177) @@ -62,10 +62,20 @@ struct sink_s { void *cb_data; + sink_t extrasink; int (*writefnc)(sink_t sink, const void *data, size_t datalen); }; +/* Object used to collect data in a memory buffer. */ +struct databuf_s +{ + size_t len; /* Used length. */ + size_t size; /* Allocated length of BUF. */ + char *buf; /* Malloced buffer. */ +}; + + /*** local prototypes ***/ static int write_multistring (sink_t sink, const char *text1, ...) GPGOL_GCC_A_SENTINEL(0); @@ -419,6 +429,14 @@ outbuf[outidx++] = tohex ((*p>>4)&15); outbuf[outidx++] = tohex (*p&15); } + else if (!outidx && datalen >= 5 && !memcmp (p, "From ", 5)) + { + /* Protect the 'F' so that MTAs won't prefix the "From " + with an '>' */ + outbuf[outidx++] = '='; + outbuf[outidx++] = tohex ((*p>>4)&15); + outbuf[outidx++] = tohex (*p&15); + } else if (*p >= '!' && *p <= '~' && *p != '=') { do_softlf (1); @@ -713,6 +731,12 @@ We better protect it by forcing QP encoding. */ need_qp = 1; } + else if (len == 1 && datalen >= 5 && !memcmp (p, "From ", 5)) + { + /* The usual From hack is required so that MTAs do not + prefix it with an '>'. */ + need_qp = 1; + } } if (len > maxlen) maxlen = len; @@ -1012,7 +1036,7 @@ proparray.aulPropTag[0] = PR_BODY_HTML; IMessage_DeleteProps (message, &proparray, NULL); } - + /* Save the Changes. */ hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE); if (hr) @@ -1026,6 +1050,64 @@ } + +/* Sink write method used by mime_sign. We write the data to the + filter and also to the EXTRASINK but we don't pass a flush request + to EXTRASINK. */ +static int +sink_hashing_write (sink_t hashsink, const void *data, size_t datalen) +{ + int rc; + engine_filter_t filter = hashsink->cb_data; + + if (!filter || !hashsink->extrasink) + { + log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__); + return -1; + } + + rc = engine_filter (filter, data, datalen); + if (!rc && data && datalen) + write_buffer (hashsink->extrasink, data, datalen); + return rc; +} + +/* This function is called by the filter to collect the output which + is a detached signature. */ +static int +collect_signature (void *opaque, const void *data, size_t datalen) +{ + struct databuf_s *db = opaque; + + if (db->len + datalen >= db->size) + { + db->size += datalen + 1024; + db->buf = xrealloc (db->buf, db->size); + } + memcpy (db->buf + db->len, data, datalen); + db->len += datalen; + + return 0; +} + + +/* Helper to create the signing header. This includes enough space + for later fixup of the micalg parameter. */ + static void +create_top_signing_header (char *buffer, size_t buflen, protocol_t protocol, + const char *boundary, const char *micalg) +{ + snprintf (buffer, buflen, + "MIME-Version: 1.0\r\n" + "Content-Type: multipart/signed;\r\n" + "\tprotocol=\"application/%s\";\r\n" + "\tmicalg=%-15.15s;\r\n" + "\tboundary=\"%s\"\r\n" + "\r\n", + (protocol==PROTOCOL_OPENPGP? "pgp-signature":"pkcs7-signature"), + micalg, boundary); +} + /* Sign the MESSAGE using PROTOCOL. If PROTOCOL is PROTOCOL_UNKNOWN the engine decides what protocol to use. On return MESSAGE is modified so that sending it will result in a properly MOSS (that is @@ -1040,13 +1122,20 @@ LPATTACH attach; struct sink_s sinkmem; sink_t sink = &sinkmem; + struct sink_s hashsinkmem; + sink_t hashsink = &hashsinkmem; char boundary[BOUNDARYSIZE+1]; char inner_boundary[BOUNDARYSIZE+1]; mapi_attach_item_t *att_table = NULL; char *body = NULL; int n_att_usable; + char top_header[BOUNDARYSIZE+200]; + engine_filter_t filter; + struct databuf_s sigbuffer; memset (sink, 0, sizeof *sink); + memset (hashsink, 0, sizeof *hashsink); + memset (&sigbuffer, 0, sizeof sigbuffer); protocol = check_protocol (protocol); if (protocol == PROTOCOL_UNKNOWN) @@ -1056,6 +1145,12 @@ if (!attach) return -1; + /* Prepare the signing. */ + if (engine_create_filter (&filter, collect_signature, &sigbuffer)) + goto failure; + if (engine_sign_start (filter, protocol)) + goto failure; + /* Get the attachment info and the body. */ body = mapi_get_body (message, NULL); if (body && !*body) @@ -1073,60 +1168,66 @@ /* Write the top header. */ generate_boundary (boundary); - rc = write_multistring (sink, - "MIME-Version: 1.0\r\n" - "Content-Type: multipart/signed;\r\n" - "\tprotocol=\"application/", - (protocol == PROTOCOL_OPENPGP - ? "pgp-signature" - : "pkcs7-signature"), - "\";\r\n\tboundary=\"", - boundary, - "\"\r\n", - NULL); - if (rc) + create_top_signing_header (top_header, sizeof top_header, + protocol, boundary, "xxx"); + if ((rc = write_string (sink, top_header))) goto failure; - + + /* Create the inner boundary if we have a body and at least one + attachment or more than one attachment. */ if ((body && n_att_usable) || n_att_usable > 1) - { - /* A body and at least one attachment or more than one attachment */ - generate_boundary (inner_boundary); - if ((rc = write_boundary (sink, boundary, 0))) - goto failure; - if ((rc=write_multistring (sink, - "Content-Type: multipart/mixed;\r\n", - "\tboundary=\"", inner_boundary, "\"\r\n", - NULL))) - goto failure; - } - else /* Only one part. */ + generate_boundary (inner_boundary); + else *inner_boundary = 0; + /* Write the boundary so that it is not included in the hashing. */ + if ((rc = write_boundary (sink, boundary, 0))) + goto failure; + /* Create a new sink for hashing and wire/hash our content. */ + hashsink->cb_data = filter; + hashsink->extrasink = sink; + hashsink->writefnc = sink_hashing_write; + + /* Note that OL2003 will add an extra line after the multipart + header, thus we do the same to avoid running all through an + IConverterSession first. */ + if (*inner_boundary + && (rc=write_multistring (hashsink, + "Content-Type: multipart/mixed;\r\n", + "\tboundary=\"", inner_boundary, "\"\r\n", + "\r\n", /* <-- extra line */ + NULL))) + goto failure; + + if (body) - rc = write_part (sink, body, strlen (body), - *inner_boundary? inner_boundary : boundary, NULL, 1); + rc = write_part (hashsink, body, strlen (body), + *inner_boundary? inner_boundary : NULL, NULL, 1); if (!rc && n_att_usable) - rc = write_attachments (sink, message, att_table, - *inner_boundary? inner_boundary : boundary); + rc = write_attachments (hashsink, message, att_table, + *inner_boundary? inner_boundary : NULL); if (rc) goto failure; - xfree (body); body = NULL; /* Finish the possible multipart/mixed. */ - if (*inner_boundary) - { - rc = write_boundary (sink, inner_boundary, 1); - if (rc) - goto failure; - } + if (*inner_boundary && (rc = write_boundary (hashsink, inner_boundary, 1))) + goto failure; + /* Here we are ready with the hashing. Flush the filter and wait + for the signing process to finish. */ + if ((rc = write_buffer (hashsink, NULL, 0))) + goto failure; + if ((rc = engine_wait (filter))) + goto failure; + filter = NULL; /* Not valid anymore. */ + hashsink->cb_data = NULL; /* Not needed anymore. */ + - /* Write signature attachment. We don't write it directly but use a - placeholder. */ + /* Write signature attachment. */ if ((rc = write_boundary (sink, boundary, 0))) goto failure; @@ -1137,43 +1238,88 @@ goto failure; /* If we would add "Content-Transfer-Encoding: 7bit\r\n" to this - attachment, Outlooks does not processed with sending and even - does not return any error. A wild guess is that while OL adds - this header itself, it detects that it already exists and somehow - gets into a problem. It is not a problem with the other parts, + attachment, Outlooks does not proceed with sending and even does + not return any error. A wild guess is that while OL adds this + header itself, it detects that it already exists and somehow gets + into a problem. It is not a problem with the other parts, though. Hmmm, triggered by the top levels CT protocol parameter? - Any way, it is not required that we add it as we won't hash + Anyway, it is not required that we add it as we won't hash it. */ if ((rc = write_string (sink, "\r\n"))) goto failure; - /* Let the placeholder start with the prefix of a boundary so that - it won't accidently occur in the actual content. */ - if ((rc = write_string (sink, "--=-=@SIGNATURE@\r\n\r\n"))) + /* Write the signature. We add an extra CR,LF which should not harm + and a terminating 0. */ + collect_signature (&sigbuffer, "\r\n", 3); + if ((rc = write_string (sink, sigbuffer.buf))) goto failure; + /* Write the final boundary and finish the attachment. */ if ((rc = write_boundary (sink, boundary, 1))) goto failure; + /* Fixup the micalg parameter. */ + { + HRESULT hr; + LARGE_INTEGER off; + LPSTREAM stream = sink->cb_data; + + off.QuadPart = 0; + hr = IStream_Seek (stream, off, STREAM_SEEK_SET, NULL); + if (hr) + { + log_error ("%s:%s: seeking back to the begin failed: hr=%#lx", + SRCNAME, __func__, hr); + goto failure; + } + + create_top_signing_header (top_header, sizeof top_header, + protocol, boundary, "pgp-sha1"); + + hr = IStream_Write (stream, top_header, strlen (top_header), NULL); + if (hr) + { + log_error ("%s:%s: writing fixed micalg failed: hr=%#lx", + SRCNAME, __func__, hr); + goto failure; + } + + /* Better seek again to the end. */ + off.QuadPart = 0; + hr = IStream_Seek (stream, off, STREAM_SEEK_END, NULL); + if (hr) + { + log_error ("%s:%s: seeking back to the end failed: hr=%#lx", + SRCNAME, __func__, hr); + goto failure; + } + } + + if (close_mapi_attachment (&attach, sink)) goto failure; if (finalize_message (message, att_table)) goto failure; + mapi_to_mime (message, "c:\\tmp\\x.msg"); + result = 0; /* Everything is fine, fall through the cleanup now. */ failure: + engine_cancel (filter); cancel_mapi_attachment (&attach, sink); xfree (body); mapi_release_attach_table (att_table); + xfree (sigbuffer.buf); return result; } + /* Sink write method used by mime_encrypt. */ static int sink_encryption_write (sink_t encsink, const void *data, size_t datalen) Modified: trunk/src/xmalloc.h =================================================================== --- trunk/src/xmalloc.h 2007-09-12 16:40:23 UTC (rev 176) +++ trunk/src/xmalloc.h 2007-09-13 11:53:15 UTC (rev 177) @@ -32,6 +32,7 @@ /*-- common.c --*/ void* xmalloc (size_t n); void* xcalloc (size_t m, size_t n); +void *xrealloc (void *a, size_t n); char* xstrdup (const char *s); void xfree (void *p); void out_of_core (void); From cvs at cvs.gnupg.org Thu Sep 13 22:42:33 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 13 Sep 2007 22:42:33 +0200 Subject: [svn] gpgme - r1253 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-13 22:42:04 +0200 (Thu, 13 Sep 2007) New Revision: 1253 Modified: trunk/gpgme/ChangeLog trunk/gpgme/rungpg.c Log: 2007-09-13 Marcus Brinkmann * rungpg.c (gpg_new): Handle return value of _gpgme_getenv (fixes small memory leak). Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-07 20:54:12 UTC (rev 1252) +++ trunk/gpgme/ChangeLog 2007-09-13 20:42:04 UTC (rev 1253) @@ -1,3 +1,8 @@ +2007-09-13 Marcus Brinkmann + + * rungpg.c (gpg_new): Handle return value of _gpgme_getenv (fixes + small memory leak). + 2007-09-07 Marcus Brinkmann * Makefile.am (libgpgme_qt_la_SOURCES): Move Modified: trunk/gpgme/rungpg.c =================================================================== --- trunk/gpgme/rungpg.c 2007-09-07 20:54:12 UTC (rev 1252) +++ trunk/gpgme/rungpg.c 2007-09-13 20:42:04 UTC (rev 1253) @@ -463,6 +463,8 @@ goto leave; rc = _gpgme_getenv ("DISPLAY", &dft_display); + if (rc) + goto leave; if (dft_display) { rc = add_arg (gpg, "--display"); @@ -471,8 +473,6 @@ free (dft_display); } - if (rc) - goto leave; if (isatty (1)) { @@ -489,7 +489,7 @@ if (!rc) { rc = _gpgme_getenv ("TERM", &dft_ttytype); - if (!rc) + if (rc) goto leave; rc = add_arg (gpg, "--ttytype"); From cvs at cvs.gnupg.org Fri Sep 14 00:40:51 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 14 Sep 2007 00:40:51 +0200 Subject: [svn] gpgme - r1254 - in trunk/tests: . gpgsm Message-ID: Author: marcus Date: 2007-09-14 00:40:22 +0200 (Fri, 14 Sep 2007) New Revision: 1254 Modified: trunk/tests/ChangeLog trunk/tests/gpgsm/t-verify.c Log: 2007-09-14 Marcus Brinkmann * gpgsm/t-verify.c (main): Release TEXT and SIG. Modified: trunk/tests/ChangeLog =================================================================== --- trunk/tests/ChangeLog 2007-09-13 20:42:04 UTC (rev 1253) +++ trunk/tests/ChangeLog 2007-09-13 22:40:22 UTC (rev 1254) @@ -1,3 +1,7 @@ +2007-09-14 Marcus Brinkmann + + * gpgsm/t-verify.c (main): Release TEXT and SIG. + 2007-07-12 Marcus Brinkmann * gpgsm/Makefile.am (key_id): Change := into =. Modified: trunk/tests/gpgsm/t-verify.c =================================================================== --- trunk/tests/gpgsm/t-verify.c 2007-09-13 20:42:04 UTC (rev 1253) +++ trunk/tests/gpgsm/t-verify.c 2007-09-13 22:40:22 UTC (rev 1254) @@ -147,6 +147,8 @@ "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", GPG_ERR_BAD_SIGNATURE, GPGME_VALIDITY_UNKNOWN); + gpgme_data_release (text); + gpgme_data_release (sig); gpgme_release (ctx); return 0; } From cvs at cvs.gnupg.org Fri Sep 14 00:42:27 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 14 Sep 2007 00:42:27 +0200 Subject: [svn] gpgme - r1255 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-14 00:41:54 +0200 (Fri, 14 Sep 2007) New Revision: 1255 Modified: trunk/gpgme/ChangeLog trunk/gpgme/gpgme.c Log: 2007-09-14 Marcus Brinkmann * gpgme.c (gpgme_release): Call gpgme_sig_notation_clear. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-13 22:40:22 UTC (rev 1254) +++ trunk/gpgme/ChangeLog 2007-09-13 22:41:54 UTC (rev 1255) @@ -1,3 +1,7 @@ +2007-09-14 Marcus Brinkmann + + * gpgme.c (gpgme_release): Call gpgme_sig_notation_clear. + 2007-09-13 Marcus Brinkmann * rungpg.c (gpg_new): Handle return value of _gpgme_getenv (fixes Modified: trunk/gpgme/gpgme.c =================================================================== --- trunk/gpgme/gpgme.c 2007-09-13 22:40:22 UTC (rev 1254) +++ trunk/gpgme/gpgme.c 2007-09-13 22:41:54 UTC (rev 1255) @@ -131,6 +131,7 @@ _gpgme_fd_table_deinit (&ctx->fdt); _gpgme_release_result (ctx); gpgme_signers_clear (ctx); + gpgme_sig_notation_clear (ctx); if (ctx->signers) free (ctx->signers); if (ctx->lc_ctype) From cvs at cvs.gnupg.org Fri Sep 14 13:41:43 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 14 Sep 2007 13:41:43 +0200 Subject: [svn] GnuPG - r4582 - in trunk: po tools Message-ID: Author: wk Date: 2007-09-14 13:41:14 +0200 (Fri, 14 Sep 2007) New Revision: 4582 Modified: trunk/po/ChangeLog trunk/po/de.po trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Minor translation change. Modified: trunk/po/ChangeLog =================================================================== --- trunk/po/ChangeLog 2007-09-10 16:38:04 UTC (rev 4581) +++ trunk/po/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * de.po: Chnaged translation of --honor-http-proxy. + 2007-08-29 Werner Koch * de.po: Translated the argparse.c strings. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-10 16:38:04 UTC (rev 4581) +++ trunk/po/de.po 2007-09-14 11:41:14 UTC (rev 4582) @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: gnupg-2.0.6\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-09-10 17:28+0200\n" -"PO-Revision-Date: 2007-08-29 18:51+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" +"PO-Revision-Date: 2007-09-14 13:31+0200\n" "Last-Translator: Walter Koch \n" "Language-Team: German \n" "MIME-Version: 1.0\n" @@ -7507,7 +7507,7 @@ #: sm/gpgsm.c:385 msgid "|NAME|use cipher algorithm NAME" -msgstr "|NAME|Verschl.verfahren NAME benutzen" +msgstr "|NAME|Verschl?sselungsverfahren NAME benutzen" #: sm/gpgsm.c:387 msgid "|NAME|use message digest algorithm NAME" @@ -7871,6 +7871,10 @@ msgid "Configuration for Keyservers" msgstr "Konfiguration der Schl?sselserver" +#: tools/gpgconf-comp.c:673 +msgid "|URL|use keyserver at URL" +msgstr "Benutze Schl?sselserver unter der URL" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "Erlaube PKA Zugriffe (DNS Anfragen)" @@ -7897,7 +7901,7 @@ #: tools/gpgconf-comp.c:845 msgid "use system's HTTP proxy setting" -msgstr "Einstellungen des System HTTP-Proxy benutzen" +msgstr "Benutze die HTTP Proxy Einstellung des Systems" #: tools/gpgconf-comp.c:850 msgid "Configuration of LDAP servers to use" Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-09-10 16:38:04 UTC (rev 4581) +++ trunk/tools/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * gpgconf-comp.c: Make a string translatable. + 2007-09-04 Moritz Schulte * gpgsm-gencert.sh: Use printf instead of echo. Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-09-10 16:38:04 UTC (rev 4581) +++ trunk/tools/gpgconf-comp.c 2007-09-14 11:41:14 UTC (rev 4582) @@ -670,7 +670,7 @@ GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC, "gnupg", N_("Configuration for Keyservers") }, { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, - "gnupg", "|URL|use keyserver at URL", + "gnupg", N_("|URL|use keyserver at URL"), GC_ARG_TYPE_STRING, GC_BACKEND_GPG }, { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC, "gnupg", N_("allow PKA lookups (DNS requests)"), From cvs at cvs.gnupg.org Fri Sep 14 13:42:04 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 14 Sep 2007 13:42:04 +0200 Subject: [svn] dirmngr - r269 - trunk/po Message-ID: Author: wk Date: 2007-09-14 13:41:34 +0200 (Fri, 14 Sep 2007) New Revision: 269 Modified: trunk/po/ChangeLog trunk/po/de.po Log: Minor ranslation change Modified: trunk/po/ChangeLog =================================================================== --- trunk/po/ChangeLog 2007-09-12 21:04:02 UTC (rev 268) +++ trunk/po/ChangeLog 2007-09-14 11:41:34 UTC (rev 269) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * de.po: Typo fix. + 2007-08-16 Werner Koch * de.po: Add missing strings and fix fuzzy entries. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-09-12 21:04:02 UTC (rev 268) +++ trunk/po/de.po 2007-09-14 11:41:34 UTC (rev 269) @@ -8,7 +8,7 @@ "Project-Id-Version: dirmngr 1.0.1\n" "Report-Msgid-Bugs-To: gpa-dev at gnupg.org\n" "POT-Creation-Date: 2007-08-16 15:23+0200\n" -"PO-Revision-Date: 2007-08-16 14:26+0200\n" +"PO-Revision-Date: 2007-09-14 13:18+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -841,7 +841,7 @@ #: src/dirmngr.c:175 msgid "|URL|use OCSP responder at URL" -msgstr "|URL|Benutze den OCSP Reponder mit dieser URL" +msgstr "|URL|Benutze den OCSP Responder mit dieser URL" #: src/dirmngr.c:176 msgid "|FPR|OCSP response signed by FPR" From cvs at cvs.gnupg.org Fri Sep 14 14:28:26 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 14 Sep 2007 14:28:26 +0200 Subject: [svn] gpgme - r1256 - in trunk: doc gpgme Message-ID: Author: wk Date: 2007-09-14 14:27:54 +0200 (Fri, 14 Sep 2007) New Revision: 1256 Modified: trunk/doc/ChangeLog trunk/doc/gpgme.texi trunk/gpgme/ChangeLog trunk/gpgme/data-mem.c trunk/gpgme/verify.c Log: Fixed bug in gpgme_data_relase_and_get_mem. Typo fixes. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-09-13 22:41:54 UTC (rev 1255) +++ trunk/doc/ChangeLog 2007-09-14 12:27:54 UTC (rev 1256) @@ -1,3 +1,7 @@ +2007-09-11 Werner Koch + + * gpgme.texi (I/O Callback Example): Typo fix. + 2007-08-07 Werner Koch * gpgme.texi (Verify): Describe chain_model. Modified: trunk/doc/gpgme.texi =================================================================== --- trunk/doc/gpgme.texi 2007-09-13 22:41:54 UTC (rev 1255) +++ trunk/doc/gpgme.texi 2007-09-14 12:27:54 UTC (rev 1256) @@ -5031,7 +5031,7 @@ I/O callbacks. The following example illustrates how to do that. The example uses -locking to show in which way the the callbacks and the event loop can +locking to show in which way the callbacks and the event loop can run concurrently. For the event loop, we use a fixed array. For a real-world implementation, you should use a dynamically sized structure because the number of file descriptors needed for a crypto Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-13 22:41:54 UTC (rev 1255) +++ trunk/gpgme/ChangeLog 2007-09-14 12:27:54 UTC (rev 1256) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * data-mem.c (gpgme_data_release_and_get_mem): Fix tracing bug. + 2007-09-14 Marcus Brinkmann * gpgme.c (gpgme_release): Call gpgme_sig_notation_clear. Modified: trunk/gpgme/data-mem.c =================================================================== --- trunk/gpgme/data-mem.c 2007-09-13 22:41:54 UTC (rev 1255) +++ trunk/gpgme/data-mem.c 2007-09-14 12:27:54 UTC (rev 1256) @@ -257,7 +257,14 @@ gpgme_data_release (dh); - TRACE_SUC2 ("buffer=%p, len=%u", str, *r_len); + if (r_len) + { + TRACE_SUC2 ("buffer=%p, len=%u", str, *r_len); + } + else + { + TRACE_SUC1 ("buffer=%p", str); + } return str; } Modified: trunk/gpgme/verify.c =================================================================== --- trunk/gpgme/verify.c 2007-09-13 22:41:54 UTC (rev 1255) +++ trunk/gpgme/verify.c 2007-09-14 12:27:54 UTC (rev 1256) @@ -552,7 +552,7 @@ { while (*args == ' ') args++; - if (!strncmp (args, "cm", 2) && (args[2] == ' ' || !args[2])) + if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2])) sig->chain_model = 1; } } From cvs at cvs.gnupg.org Fri Sep 14 15:38:40 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 14 Sep 2007 15:38:40 +0200 Subject: [svn] GnuPG - r4583 - in trunk: . agent common g10 sm Message-ID: Author: wk Date: 2007-09-14 15:38:36 +0200 (Fri, 14 Sep 2007) New Revision: 4583 Modified: trunk/ChangeLog trunk/agent/agent.h trunk/common/ChangeLog trunk/configure.ac trunk/g10/ChangeLog trunk/g10/gpg.c trunk/sm/ChangeLog trunk/sm/gpgsm.c Log: Print used library version with --version. Typo fixes Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/ChangeLog 2007-09-14 13:38:36 UTC (rev 4583) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * configure.ac (GNUPG_LIBASSUAN_VERSION): New. + 2007-09-10 Werner Koch Released 2.0.7. Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/agent/agent.h 2007-09-14 13:38:36 UTC (rev 4583) @@ -80,7 +80,7 @@ unsigned long max_cache_ttl; /* Default. */ unsigned long max_cache_ttl_ssh; /* for SSH. */ - /* Flag disallowin bypassing of the warning. */ + /* Flag disallowing bypassing of the warning. */ int enforce_passphrase_constraints; /* The require minmum length of a passphrase. */ unsigned int min_passphrase_len; Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/common/ChangeLog 2007-09-14 13:38:36 UTC (rev 4583) @@ -8,7 +8,7 @@ 2007-08-28 Werner Koch - * gettime.c (check_isotime, add_isotime): New. Orginally written + * gettime.c (check_isotime, add_isotime): New. Originally written for DirMngr by me. (add_days_to_isotime): New. (date2jd, jd2date, days_per_month, days_per_year): New. Taken from Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/configure.ac 2007-09-14 13:38:36 UTC (rev 4583) @@ -608,6 +608,8 @@ AM_CHECK_LIBASSUAN("$NEED_LIBASSUAN_API:1.0.1", [AC_DEFINE(HAVE_ASSUAN_SET_IO_MONITOR, 1, [Define to 1 if you have the `assuan_set_io_monitor' function.])],) + AC_DEFINE_UNQUOTED(GNUPG_LIBASSUAN_VERSION, "$libassuan_version", + [version of the libbassuan library]) fi Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/g10/ChangeLog 2007-09-14 13:38:36 UTC (rev 4583) @@ -1,3 +1,8 @@ +2007-09-14 Werner Koch + + * gpg.c (build_lib_list): New. + (my_strusage): Print lib info. + 2007-08-27 Werner Koch * trustdb.c (USE_INTERNAL_REGEX): Remove support. Modified: trunk/g10/gpg.c =================================================================== --- trunk/g10/gpg.c 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/g10/gpg.c 2007-09-14 13:38:36 UTC (rev 4583) @@ -727,6 +727,7 @@ static char *build_list( const char *text, char letter, const char *(*mapf)(int), int (*chkf)(int) ); +static char *build_lib_list (const char *text); static void set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ); static void print_mds( const char *fname, int algo ); @@ -739,7 +740,7 @@ static const char * my_strusage( int level ) { - static char *digests, *pubkeys, *ciphers, *zips; + static char *digests, *pubkeys, *ciphers, *zips, *libs; const char *p; switch( level ) { case 11: p = "gpg (GnuPG)"; @@ -807,6 +808,11 @@ check_compress_algo); p = zips; break; + case 38: + if (!libs) + libs = build_lib_list(_("Used libraries:")); + p = libs; + break; default: p = NULL; } @@ -869,6 +875,46 @@ } +static char * +build_lib_list (const char *text) +{ + struct { const char *name; const char *version; } array[3]; + int idx; + size_t n; + char *list, *p; + + if (maybe_setuid) + gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ + + idx = 0; + array[idx].name = "gcrypt"; + array[idx++].version = gcry_check_version (NULL); + array[idx].name = NULL; + array[idx++].version = NULL; + + n = strlen (text) + 1; + for (idx=0; array[idx].name; idx++) + { + n += 2 + strlen (array[idx].name); + if (array[idx].version) + n += 1 + strlen (array[idx].version) + 1; + } + n++; + list = xmalloc (n+1); + p = stpcpy (stpcpy (list, text), " "); + for (idx=0; array[idx].name; idx++) + { + if (idx) + p = stpcpy (p, ", "); + p = stpcpy (p, array[idx].name); + if (array[idx].version) + p = stpcpy (stpcpy (stpcpy (p, "("), array[idx].version), ")"); + } + strcpy (p, "\n"); + return list; +} + + static void wrong_args( const char *text) { Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/sm/ChangeLog 2007-09-14 13:38:36 UTC (rev 4583) @@ -1,3 +1,8 @@ +2007-09-14 Werner Koch + + * gpgsm.c (build_lib_list): New. + (my_strusage): Print lib info. + 2007-08-24 Werner Koch * Makefile.am (common_libs): Swap libkeybox and jnlib. Modified: trunk/sm/gpgsm.c =================================================================== --- trunk/sm/gpgsm.c 2007-09-14 11:41:14 UTC (rev 4582) +++ trunk/sm/gpgsm.c 2007-09-14 13:38:36 UTC (rev 4583) @@ -481,6 +481,7 @@ static char *build_list (const char *text, const char *(*mapf)(int), int (*chkf)(int)); +static char *build_lib_list (const char *text); static void set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd ); @@ -553,7 +554,7 @@ static const char * my_strusage( int level ) { - static char *digests, *pubkeys, *ciphers; + static char *digests, *pubkeys, *ciphers, *libs; const char *p; switch (level) @@ -593,7 +594,12 @@ digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo ); p = digests; break; - + case 38: + if (!libs) + libs = build_lib_list(_("Used libraries:")); + p = libs; + break; + default: p = NULL; break; } return p; @@ -632,7 +638,50 @@ return list; } +static char * +build_lib_list (const char *text) +{ + struct { const char *name; const char *version; } array[5]; + int idx; + size_t n; + char *list, *p; + if (maybe_setuid) + gcry_control (GCRYCTL_INIT_SECMEM, 0, 0); /* Drop setuid. */ + + idx = 0; + array[idx].name = "gcrypt"; + array[idx++].version = gcry_check_version (NULL); + array[idx].name = "ksba"; + array[idx++].version = ksba_check_version (NULL); + array[idx].name = "assuan"; + array[idx++].version = GNUPG_LIBASSUAN_VERSION; + array[idx].name = NULL; + array[idx++].version = NULL; + + n = strlen (text) + 1; + for (idx=0; array[idx].name; idx++) + { + n += 2 + strlen (array[idx].name); + if (array[idx].version) + n += 1 + strlen (array[idx].version) + 1; + } + n++; + list = xmalloc (n+1); + p = stpcpy (stpcpy (list, text), " "); + for (idx=0; array[idx].name; idx++) + { + if (idx) + p = stpcpy (p, ", "); + p = stpcpy (p, array[idx].name); + if (array[idx].version) + p = stpcpy (stpcpy (stpcpy (p, "("), array[idx].version), ")"); + } + strcpy (p, "\n"); + return list; +} + + /* Set the file pointer into binary mode if required. */ static void set_binary (FILE *fp) From cvs at cvs.gnupg.org Fri Sep 14 16:23:45 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 14 Sep 2007 16:23:45 +0200 Subject: [svn] assuan - r264 - trunk/src Message-ID: Author: marcus Date: 2007-09-14 16:23:45 +0200 (Fri, 14 Sep 2007) New Revision: 264 Modified: trunk/src/ChangeLog trunk/src/assuan-pipe-connect.c Log: 2007-09-14 Marcus Brinkmann * assuan-pipe-connect.c (do_finish) [HAVE_W32_SYSTEM]: Close ctx->pid as handle. (pipe_connect_w32): Save the spawned processes handle. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-11 10:36:23 UTC (rev 263) +++ trunk/src/ChangeLog 2007-09-14 14:23:45 UTC (rev 264) @@ -1,3 +1,9 @@ +2007-09-14 Marcus Brinkmann + + * assuan-pipe-connect.c (do_finish) [HAVE_W32_SYSTEM]: Close + ctx->pid as handle. + (pipe_connect_w32): Save the spawned processes handle. + 2007-09-11 Marcus Brinkmann * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. Modified: trunk/src/assuan-pipe-connect.c =================================================================== --- trunk/src/assuan-pipe-connect.c 2007-09-11 10:36:23 UTC (rev 263) +++ trunk/src/assuan-pipe-connect.c 2007-09-14 14:23:45 UTC (rev 264) @@ -129,11 +129,15 @@ _assuan_waitpid (ctx->pid, NULL, 0); ctx->pid =(pid_t)(-1); #endif -#endif /*!HAVE_W32_SYSTEM*/ +#else /*!HAVE_W32_SYSTEM*/ + CloseHandle ((HANDLE) ctx->pid); + ctx->pid = (pid_t) INVALID_HANDLE_VALUE; +#endif /*HAVE_W32_SYSTEM*/ } return 0; } + static void do_deinit (assuan_context_t ctx) { @@ -804,8 +808,7 @@ 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. */ + (*ctx)->pid = (pid_t) pi.hProcess; return initial_handshake (ctx); } From cvs at cvs.gnupg.org Fri Sep 14 16:25:03 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 14 Sep 2007 16:25:03 +0200 Subject: [svn] GnuPG - r4584 - trunk/agent Message-ID: Author: marcus Date: 2007-09-14 16:25:02 +0200 (Fri, 14 Sep 2007) New Revision: 4584 Modified: trunk/agent/ChangeLog trunk/agent/call-pinentry.c Log: 2007-09-14 Marcus Brinkmann * call-pinentry.c (agent_popup_message_stop): Implement kill for Windows. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-09-14 13:38:36 UTC (rev 4583) +++ trunk/agent/ChangeLog 2007-09-14 14:25:02 UTC (rev 4584) @@ -1,3 +1,8 @@ +2007-09-14 Marcus Brinkmann + + * call-pinentry.c (agent_popup_message_stop): Implement kill for + Windows. + 2007-08-28 Werner Koch * gpg-agent.c (main): Add option --faked-system-time. Modified: trunk/agent/call-pinentry.c =================================================================== --- trunk/agent/call-pinentry.c 2007-09-14 13:38:36 UTC (rev 4583) +++ trunk/agent/call-pinentry.c 2007-09-14 14:25:02 UTC (rev 4584) @@ -812,7 +812,16 @@ else if (popup_finished) ; /* Already finished and ready for joining. */ #ifdef HAVE_W32_SYSTEM -# warning need to implement a kill mechanism for pinentry + /* Older versions of assuan set PID to 0 on Windows to indicate an + invalid value. */ + else if (pid != (pid_t) INVALID_HANDLE_VALUE + && pid != 0) + { + HANDLE process = (HANDLE) pid; + + /* Arbitrary error code. */ + TerminateProcess (process, 1); + } #else else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) { /* The daemon already died. No need to send a kill. However From cvs at cvs.gnupg.org Fri Sep 14 17:21:51 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 14 Sep 2007 17:21:51 +0200 Subject: [svn] GpgOL - r178 - trunk/src Message-ID: Author: wk Date: 2007-09-14 17:21:50 +0200 (Fri, 14 Sep 2007) New Revision: 178 Modified: trunk/src/ChangeLog trunk/src/common.h trunk/src/engine-gpgme.c trunk/src/engine.c trunk/src/engine.h trunk/src/message-events.cpp trunk/src/message.cpp trunk/src/message.h trunk/src/mimemaker.c trunk/src/mimemaker.h trunk/src/mimeparser.c trunk/src/mimeparser.h Log: A lot of cleanups. removed unused all gpgme stuff. There is still a race condition soemwhere, but the basic functionality is now again complete - when using the gpgme backend. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/ChangeLog 2007-09-14 15:21:50 UTC (rev 178) @@ -1,3 +1,7 @@ +2007-09-14 Werner Koch + + * engine-gpgme.c: Rewrote most of it. + 2007-09-13 Werner Koch * common.c (xrealloc): New. Modified: trunk/src/common.h =================================================================== --- trunk/src/common.h 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/common.h 2007-09-14 15:21:50 UTC (rev 178) @@ -34,12 +34,14 @@ #endif #endif -/* Identifiers for the protocol. */ +/* Identifiers for the protocol. We use different one than those use + by gpgme. FIXME: We might want to define an unknown protocol to + non-null and define such a value also in gpgme. */ typedef enum { PROTOCOL_UNKNOWN = 0, - PROTOCOL_OPENPGP, - PROTOCOL_SMIME + PROTOCOL_OPENPGP = 1000, + PROTOCOL_SMIME = 1001 } protocol_t; Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/engine-gpgme.c 2007-09-14 15:21:50 UTC (rev 178) @@ -19,9 +19,6 @@ * 02110-1301, USA. */ -/* Please note that we assume UTF-8 strings everywhere except when - noted. */ - #include @@ -30,10 +27,9 @@ #include #include #include - -#define COBJMACROS +#include +#define WIN32_LEAN_AND_MEAN #include -#include /* For IStream. */ #include "common.h" #include "passcache.h" @@ -45,49 +41,44 @@ } while (0) -static char *debug_file = NULL; +/* Because we are using asynchronous gpgme commands, we need to have a + closure to cleanup allocated resources and run the code required + adfter gpgme finished the command (e.g. getting the signature + verification result. Thus all functions need to implement a + closure function and pass it using a closure_data_t object via the + gpgme_progress_cb hack. */ +struct closure_data_s; +typedef struct closure_data_s *closure_data_t; +struct closure_data_s +{ + void (*closure)(closure_data_t, gpgme_ctx_t, gpg_error_t); + engine_filter_t filter; + struct passphrase_cb_s pw_cb; /* Passphrase callback info. */ + int with_verify; + gpgme_data_t sigobj; +}; + + static int init_done = 0; static DWORD WINAPI waiter_thread (void *dummy); static void update_passphrase_cache (int err, struct passphrase_cb_s *pass_cb_value); -static void add_verify_attestation (gpgme_data_t at, - gpgme_ctx_t ctx, - gpgme_verify_result_t res, - const char *filename); +/* static void add_verify_attestation (gpgme_data_t at, */ +/* gpgme_ctx_t ctx, */ +/* gpgme_verify_result_t res, */ +/* const char *filename); */ static void cleanup (void) { - if (debug_file) - { - xfree (debug_file); - debug_file = NULL; - } + /* Fixme: We should stop the thread. */ } -/* Enable or disable GPGME debug mode. */ -void -op_gpgme_set_debug_mode (int val, const char *file) -{ - const char *s= "GPGME_DEBUG"; - - cleanup (); - if (val > 0) - { - debug_file = (char *)xcalloc (1, strlen (file) + strlen (s) + 2); - sprintf (debug_file, "%s=%d;%s", s, val, file); - putenv (debug_file); - } - else - putenv ("GPGME_DEBUG="); -} - - /* Cleanup static resources. */ void op_gpgme_deinit (void) @@ -132,7 +123,7 @@ HANDLE th; DWORD tid; - th = CreateThread (NULL, 64*1024, waiter_thread, NULL, 0, &tid); + th = CreateThread (NULL, 128*1024, waiter_thread, NULL, 0, &tid); if (th == INVALID_HANDLE_VALUE) log_error ("failed to start the gpgme waiter thread\n"); else @@ -144,20 +135,21 @@ } +/* The worker for the asynchronous commands. */ static DWORD WINAPI waiter_thread (void *dummy) { gpgme_ctx_t ctx; gpg_error_t err; - void *filter; - void *pass_cb; + void *a_voidptr; + closure_data_t closure_data; (void)dummy; TRACEPOINT (); for (;;) { - /* Note: We don't use hang becuase this will end up in a tight + /* Note: We don't use hang because this will end up in a tight loop and does not do a voluntary context switch. Thus we do this by ourself. Actually it would be better to start gpgme-Wait only if we really have something to do but that @@ -165,12 +157,12 @@ ctx = gpgme_wait (NULL, &err, 0); if (ctx) { - gpgme_get_progress_cb (ctx, NULL, &filter); - engine_gpgme_finished (filter, err); - gpgme_get_passphrase_cb (ctx, NULL, &pass_cb); - if (pass_cb) - update_passphrase_cache (err, (struct passphrase_cb_s *)pass_cb); - xfree (pass_cb); + gpgme_get_progress_cb (ctx, NULL, &a_voidptr); + closure_data = a_voidptr; + assert (closure_data); + assert (closure_data->closure); + closure_data->closure (closure_data, ctx, err); + xfree (closure_data); gpgme_release (ctx); } else if (err) @@ -182,53 +174,6 @@ } - -/* The read callback used by GPGME to read data from an IStream object. */ -static ssize_t -stream_read_cb (void *handle, void *buffer, size_t size) -{ - LPSTREAM stream = handle; - HRESULT hr; - ULONG nread; - - /* For EOF detection we assume that Read returns no error and thus - nread will be 0. The specs say that "Depending on the - implementation, either S_FALSE or an error code could be returned - when reading past the end of the stream"; thus we are not really - sure whether our assumption is correct. OTOH, at another place - the docuemntation says that the implementation used by - ISequentialStream exhibits the same EOF behaviour has found on - the MSDOS FAT file system. So we seem to have good karma. */ - hr = IStream_Read (stream, buffer, size, &nread); - if (hr != S_OK) - { - log_debug ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr); - errno = EIO; - return -1; - } - return nread; -} - - -/* The write callback used by GPGME to write data to an IStream object. */ -static ssize_t -stream_write_cb (void *handle, const void *buffer, size_t size) -{ - LPSTREAM stream = handle; - HRESULT hr; - ULONG nwritten; - - hr = IStream_Write (stream, buffer, size, &nwritten); - if (hr != S_OK) - { - log_debug ("%s:%s: Write failed: hr=%#lx", SRCNAME, __func__, hr); - errno = EIO; - return -1; - } - return nwritten; -} - - /* This routine should be called immediately after an operation to make sure that the passphrase cache gets updated. ERR is expected to be the error code from the gpgme operation and PASS_CB_VALUE the @@ -242,7 +187,9 @@ static void update_passphrase_cache (int err, struct passphrase_cb_s *pass_cb_value) { - if (*pass_cb_value->keyid) + if (!pass_cb_value) + return; + if (pass_cb_value->keyid && *pass_cb_value->keyid) { if (err) passcache_put (pass_cb_value->keyid, NULL, 0); @@ -272,151 +219,13 @@ res = gpgme_op_encrypt_result (ctx); if (!res) return err; - if (res->invalid_recipients != NULL) + if (res->invalid_recipients) return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); /* XXX: we need to do more here! */ return err; } -/* Encrypt the data in INBUF into a newly malloced buffer stored on - success at OUTBUF. The caller should release this buffer using - gpgme_free. The recipients are expected in the NULL terminated - array KEYS. If SIGN_KEY is not NULl, the data will also be signed - using this key. TTL is the time the passphrase should be - cached. */ -int -op_encrypt (const char *inbuf, char **outbuf, gpgme_key_t *keys, - gpgme_key_t sign_key, int ttl) -{ - struct passphrase_cb_s cb; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_error_t err; - gpgme_ctx_t ctx = NULL; - - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 0; - - *outbuf = NULL; - - op_gpgme_init (); - err = gpgme_new (&ctx); - if (err) - goto leave; - - err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); - if (err) - goto leave; - - err = gpgme_data_new (&out); - if (err) - goto leave; - - gpgme_set_textmode (ctx, 1); - gpgme_set_armor (ctx, 1); - if (sign_key) - { - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; - err = gpgme_signers_add (ctx, sign_key); - if (!err) - err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, - in, out); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - } - else - err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); - if (err) - err = check_encrypt_result (ctx, err); - else - { - /* Return the buffer but first make sure it is a string. */ - if (gpgme_data_write (out, "", 1) == 1) - { - *outbuf = gpgme_data_release_and_get_mem (out, NULL); - out = NULL; - } - } - - - leave: - if (ctx) - gpgme_release (ctx); - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - return err; -} - - - -/* Encrypt the stream INSTREAM to the OUTSTREAM for all recpients - given in the NULL terminated array KEYS. If SIGN_KEY is not NULL - the message will also be signed. */ -int -op_encrypt_stream (LPSTREAM instream, LPSTREAM outstream, gpgme_key_t *keys, - gpgme_key_t sign_key, int ttl) -{ - struct passphrase_cb_s cb; - struct gpgme_data_cbs cbs; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - cbs.write = stream_write_cb; - - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 0; - - err = gpgme_data_new_from_cbs (&in, &cbs, instream); - if (err) - goto fail; - - err = gpgme_data_new_from_cbs (&out, &cbs, outstream); - if (err) - goto fail; - - err = gpgme_new (&ctx); - if (err) - goto fail; - - gpgme_set_armor (ctx, 1); - /* FIXME: We should not hardcode always trust. */ - if (sign_key) - { - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; - err = gpgme_signers_add (ctx, sign_key); - if (!err) - err = gpgme_op_encrypt_sign (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, - in, out); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - } - else - err = gpgme_op_encrypt (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out); - if (err) - err = check_encrypt_result (ctx, err); - - fail: - if (ctx) - gpgme_release (ctx); - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - return err; -} - - /* Release an array of GPGME keys. */ static void release_key_array (gpgme_key_t *keys) @@ -546,6 +355,22 @@ } +/* Not that this closure is called in the context of the + waiter_thread. */ +static void +encrypt_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) +{ + if (cld->pw_cb.ctx) + { + /* Signing was also request; thus update the passphrase cache. */ + update_passphrase_cache (err, &cld->pw_cb); + } + if (err) + err = check_encrypt_result (ctx, err); + engine_gpgme_finished (cld->filter, err); +} + + /* Encrypt the data from INDATA to the OUTDATA object for all recpients given in the NULL terminated array KEYS. If SIGN_KEY is not NULL the message will also be signed. On termination of the @@ -556,19 +381,19 @@ just for this notification. We abuse the gpgme_set_progress_cb value for storing the pointer with the gpgme context. */ int -op_gpgme_encrypt_data (protocol_t protocol, - gpgme_data_t indata, gpgme_data_t outdata, - void *notify_data, /* FIXME: Add hwnd */ - char **recipients, gpgme_key_t sign_key, int ttl) +op_gpgme_encrypt (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data, /* FIXME: Add hwnd */ + char **recipients, gpgme_key_t sign_key, int ttl) { gpg_error_t err; - struct passphrase_cb_s cb; + closure_data_t cld; gpgme_ctx_t ctx = NULL; gpgme_key_t *keys = NULL; - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 0; + cld = xcalloc (1, sizeof *cld); + cld->closure = encrypt_closure; + cld->filter = notify_data; err = prepare_recipient_keys (&keys, recipients, NULL); if (err) @@ -577,52 +402,72 @@ err = gpgme_new (&ctx); if (err) goto leave; - if (protocol == PROTOCOL_SMIME) + gpgme_set_progress_cb (ctx, NULL, cld); + switch (protocol) { + case PROTOCOL_OPENPGP: /* Gpgme's default. */ + break; + case PROTOCOL_SMIME: err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); - if (err) - goto leave; + break; + default: + err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + break; } - gpgme_set_progress_cb (ctx, NULL, notify_data); + if (err) + goto leave; + gpgme_set_armor (ctx, 1); /* FIXME: We should not hardcode always trust. */ if (sign_key) { - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb); + cld->pw_cb.ctx = ctx; + cld->pw_cb.ttl = ttl; err = gpgme_signers_add (ctx, sign_key); if (!err) err = gpgme_op_encrypt_sign_start (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, indata, outdata); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); } else err = gpgme_op_encrypt_start (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, indata, outdata); -/* if (err) */ -/* err = check_encrypt_result (ctx, err); */ leave: - if (ctx && err) - gpgme_release (ctx); + if (err) + { + xfree (cld); + gpgme_release (ctx); + } release_key_array (keys); return err; } + + +/* Not that this closure is called in the context of the + waiter_thread. */ +static void +sign_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) +{ + update_passphrase_cache (err, &cld->pw_cb); + engine_gpgme_finished (cld->filter, err); +} + + /* Created a detached signature for INDATA and write it to OUTDATA. On termination of the signing command engine_gpgme_finished() is called with NOTIFY_DATA as the first argument. */ int -op_gpgme_sign_data (protocol_t protocol, - gpgme_data_t indata, gpgme_data_t outdata, - void *notify_data /* FIXME: Add hwnd */) +op_gpgme_sign (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data /* FIXME: Add hwnd */) { gpg_error_t err; - struct passphrase_cb_s *cb; + closure_data_t cld; gpgme_ctx_t ctx = NULL; gpgme_key_t sign_key = NULL; @@ -632,32 +477,39 @@ return gpg_error (GPG_ERR_CANCELED); } - cb = xcalloc (1, sizeof *cb); - cb->ttl = 0 /*FIXME: ttl*/; + cld = xcalloc (1, sizeof *cld); + cld->closure = sign_closure; + cld->filter = notify_data; err = gpgme_new (&ctx); if (err) goto leave; - if (protocol == PROTOCOL_SMIME) + gpgme_set_progress_cb (ctx, NULL, cld); + switch (protocol) { + case PROTOCOL_OPENPGP: /* Gpgme's default. */ + break; + case PROTOCOL_SMIME: err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); - if (err) - goto leave; + break; + default: + err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + break; } + if (err) + goto leave; - gpgme_set_progress_cb (ctx, NULL, notify_data); - gpgme_set_armor (ctx, 1); - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, cb); - cb->ctx = ctx; + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb); + cld->pw_cb.ctx = ctx; err = gpgme_signers_add (ctx, sign_key); if (!err) err = gpgme_op_sign_start (ctx, indata, outdata, GPGME_SIG_MODE_DETACH); leave: - if (ctx && err) + if (err) { - xfree (cb); + xfree (cld); gpgme_release (ctx); } gpgme_key_unref (sign_key); @@ -665,629 +517,186 @@ } - - - -/* Sign and encrypt the data in INBUF into a newly allocated buffer at - OUTBUF. Caller needs to free the returned buffer using gpgme_free. */ -int -op_sign (const char *inbuf, char **outbuf, int mode, - gpgme_key_t sign_key, int ttl) +/* Not that this closure is called in the context of the + waiter_thread. */ +static void +decrypt_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) { - struct passphrase_cb_s cb; - gpgme_error_t err; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_ctx_t ctx = NULL; + update_passphrase_cache (err, &cld->pw_cb); - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 0; - - *outbuf = NULL; - op_gpgme_init (); - - err = gpgme_new (&ctx); - if (err) - goto leave; - - err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); - if (err) - goto leave; - - err = gpgme_data_new (&out); - if (err) - goto leave; - - if (sign_key) - gpgme_signers_add (ctx, sign_key); - - if (mode == GPGME_SIG_MODE_CLEAR) - gpgme_set_textmode (ctx, 1); - gpgme_set_armor (ctx, 1); - - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; - err = gpgme_op_sign (ctx, in, out, mode); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - - if (!err) - { - /* Return the buffer but first make sure it is a string. */ - if (gpgme_data_write (out, "", 1) == 1) - { - *outbuf = gpgme_data_release_and_get_mem (out, NULL); - out = NULL; - } - } - - leave: - if (ctx) - gpgme_release (ctx); - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - return err; -} - - -/* Create a signature from INSTREAM and write it to OUTSTREAM. Use - signature mode MODE and a passphrase caching time of TTL. */ -int -op_sign_stream (LPSTREAM instream, LPSTREAM outstream, int mode, - gpgme_key_t sign_key, int ttl) -{ - struct gpgme_data_cbs cbs; - struct passphrase_cb_s cb; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - cbs.write = stream_write_cb; - - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 0; - - err = gpgme_data_new_from_cbs (&in, &cbs, instream); - if (err) - goto fail; - - err = gpgme_data_new_from_cbs (&out, &cbs, outstream); - if (err) - goto fail; - - err = gpgme_new (&ctx); - if (err) - goto fail; - - if (sign_key) - gpgme_signers_add (ctx, sign_key); - - if (mode == GPGME_SIG_MODE_CLEAR) - gpgme_set_textmode (ctx, 1); - gpgme_set_armor (ctx, 1); - - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; - err = gpgme_op_sign (ctx, in, out, mode); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - - fail: - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - if (ctx) - gpgme_release (ctx); - return err; -} - - - -/* Run the decryption. Decrypts INBUF to OUTBUF; caller needs to free - the returned result at OUTBUF using gpgme_free. the result at - OUTBUF. TTL is the time in seconds to cache a passphrase. If - FILENAME is not NULL it will be displayed along with status - outputs. If ATTESTATION is not NULL a text with the result of the - signature verification will get printed to it. */ -int -op_decrypt (const char *inbuf, char **outbuf, int ttl, const char *filename, - gpgme_data_t attestation, int preview_mode) -{ - struct passphrase_cb_s cb; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_ctx_t ctx; - gpgme_error_t err; - - *outbuf = NULL; - op_gpgme_init (); - - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 1; - - err = gpgme_new (&ctx); - if (err) - return err; - - err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); - if (err) - goto leave; - err = gpgme_data_new (&out); - if (err) - goto leave; - - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); - cb.ctx = ctx; - if (preview_mode) - err = gpgme_op_decrypt (ctx, in, out); - else - err = gpgme_op_decrypt_verify (ctx, in, out); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - - /* Act upon the result of the decryption operation. */ - if (!err && preview_mode) + if (!err && !cld->with_verify) ; else if (!err) { - /* Decryption succeeded. Store the result at OUTBUF. */ gpgme_verify_result_t res; - /* Return the buffer but first make sure it is a string. */ - if (gpgme_data_write (out, "", 1) == 1) - { - *outbuf = gpgme_data_release_and_get_mem (out, NULL); - out = NULL; - } - - /* Now check the state of any signature. */ + /* Decryption succeeded. Now check the state of the signatures. */ res = gpgme_op_verify_result (ctx); if (res && res->signatures) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && res->signatures && attestation) - add_verify_attestation (attestation, ctx, res, filename); + verify_dialog_box (gpgme_get_protocol (ctx), res, NULL); } - else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED) + else if (gpg_err_code (err) == GPG_ERR_DECRYPT_FAILED) { - /* The decryption failed. See whether we can determine the real - problem. */ + /* The decryption failed. See whether we can figure out a more + suitable error code. */ gpgme_decrypt_result_t res; + res = gpgme_op_decrypt_result (ctx); - if (res != NULL && res->recipients != NULL && - gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) - err = GPG_ERR_NO_SECKEY; - /* XXX: return the keyids */ + if (res && res->recipients + && gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) + err = gpg_error (GPG_ERR_NO_SECKEY); + /* Fixme: return the keyids */ } else { /* Decryption failed for other reasons. */ } - - /* If the callback indicated a cancel operation, set the error - accordingly. */ - if (err && (cb.opts & OPT_FLAG_CANCEL)) + /* If the passphrase callback indicated a cancel operation, change + the the error code accordingly. */ + if (err && (cld->pw_cb.opts & OPT_FLAG_CANCEL)) err = gpg_error (GPG_ERR_CANCELED); - -leave: - if (ctx) - gpgme_release (ctx); - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - return err; + + engine_gpgme_finished (cld->filter, err); } -/* Decrypt the GPGME data object IN into the data object OUT. Returns - 0 on success or an gpgme error code on failure. If FILENAME is not - NULL it will be displayed along with status outputs. If ATTESTATION - is not NULL a text with the result of the signature verification - will get printed to it. */ -static int -decrypt_stream (gpgme_protocol_t protocol, - gpgme_data_t in, gpgme_data_t out, int ttl, - const char *filename, gpgme_data_t attestation, - int preview_mode) -{ - struct passphrase_cb_s cb; - gpgme_ctx_t ctx = NULL; +/* Decrypt data from INDATA to OUTDATE. If WITH_VERIFY is set, a + signature of PGP/MIME combined message is also verified the same + way as with op_gpgme_verify. */ +int +op_gpgme_decrypt (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + void *notify_data, + int with_verify) +{ gpgme_error_t err; + closure_data_t cld; + gpgme_ctx_t ctx = NULL; - memset (&cb, 0, sizeof cb); - cb.ttl = ttl; - cb.decrypt_cmd = 1; + cld = xcalloc (1, sizeof *cld); + cld->closure = decrypt_closure; + cld->filter = notify_data; + cld->with_verify = with_verify; err = gpgme_new (&ctx); if (err) - goto fail; - - err = gpgme_set_protocol (ctx, protocol); + goto leave; + gpgme_set_progress_cb (ctx, NULL, cld); + switch (protocol) + { + case PROTOCOL_OPENPGP: /* Gpgme's default. */ + break; + case PROTOCOL_SMIME: + err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + break; + default: + err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + break; + } if (err) - goto fail; + goto leave; - /* GPGME does not support a command handler for gpgsm. Thus we - can't set the passphrase callback. */ - if (protocol != GPGME_PROTOCOL_CMS) - gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cb); + /* Note: We do no error checking for the next call because some + backends may not implement a command hanler at all. */ + gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb); + cld->pw_cb.ctx = ctx; - cb.ctx = ctx; - if (preview_mode) - err = gpgme_op_decrypt (ctx, in, out); + if (with_verify) + err = gpgme_op_decrypt_verify_start (ctx, indata, outdata); else - err = gpgme_op_decrypt_verify (ctx, in, out); - cb.ctx = NULL; - update_passphrase_cache (err, &cb); - /* Act upon the result of the decryption operation. */ - if (!err && preview_mode) - ; - else if (!err) - { - gpgme_verify_result_t res; + err = gpgme_op_decrypt_start (ctx, indata, outdata); - /* Decryption succeeded. Now check the state of the signatures. */ - res = gpgme_op_verify_result (ctx); - if (res && res->signatures) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && res->signatures && attestation) - add_verify_attestation (attestation, ctx, res, filename); - } - else if (gpgme_err_code (err) == GPG_ERR_DECRYPT_FAILED) - { - /* The decryption failed. See whether we can determine the real - problem. */ - gpgme_decrypt_result_t res; - res = gpgme_op_decrypt_result (ctx); - if (res != NULL && res->recipients != NULL && - gpgme_err_code (res->recipients->status) == GPG_ERR_NO_SECKEY) - err = GPG_ERR_NO_SECKEY; - /* XXX: return the keyids */ - } - else - { - /* Decryption failed for other reasons. */ - } - - /* If the callback indicated a cancel operation, set the error - accordingly. */ - if (err && (cb.opts & OPT_FLAG_CANCEL)) - err = gpg_error (GPG_ERR_CANCELED); - - fail: - if (ctx) - gpgme_release (ctx); - return err; -} - -/* Decrypt the stream INSTREAM directly to the stream OUTSTREAM. - Returns 0 on success or an gpgme error code on failure. If - FILENAME is not NULL it will be displayed along with status - outputs. */ -int -op_decrypt_stream (LPSTREAM instream, LPSTREAM outstream, int ttl, - const char *filename, gpgme_data_t attestation) -{ - struct gpgme_data_cbs cbs; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_error_t err; - - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - cbs.write = stream_write_cb; - - err = gpgme_data_new_from_cbs (&in, &cbs, instream); - if (!err) - err = gpgme_data_new_from_cbs (&out, &cbs, outstream); - if (!err) - err = decrypt_stream (GPGME_PROTOCOL_OpenPGP, - in, out, ttl, filename, attestation, 0); - - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); - return err; -} - - -/* Decrypt the stream INSTREAM directly to the newly allocated buffer - OUTBUF. Caller needs to free the returned buffer using gpgme_free. - Returns 0 on success or an gpgme error code on failure. If - FILENAME is not NULL it will be displayed along with status - outputs. */ -int -op_decrypt_stream_to_buffer (LPSTREAM instream, char **outbuf, int ttl, - const char *filename, gpgme_data_t attestation) -{ - struct gpgme_data_cbs cbs; - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_error_t err; - - *outbuf = NULL; - - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - - err = gpgme_data_new_from_cbs (&in, &cbs, instream); - if (!err) - err = gpgme_data_new (&out); - if (!err) - err = decrypt_stream (GPGME_PROTOCOL_OpenPGP, - in, out, ttl, filename, attestation, 0); - if (!err) + leave: + if (err) { - /* Return the buffer but first make sure it is a string. */ - if (gpgme_data_write (out, "", 1) == 1) - { - *outbuf = gpgme_data_release_and_get_mem (out, NULL); - out = NULL; - } + xfree (cld); + gpgme_release (ctx); } - - if (in) - gpgme_data_release (in); - if (out) - gpgme_data_release (out); return err; } -/* Decrypt the stream INSTREAM directly to the GPGME data object OUT. - Returns 0 on success or an gpgme error code on failure. If - FILENAME is not NULL it will be displayed along with status - outputs. */ -int -op_decrypt_stream_to_gpgme (gpgme_protocol_t protocol, - LPSTREAM instream, gpgme_data_t out, int ttl, - const char *filename, gpgme_data_t attestation, - int preview_mode) -{ - struct gpgme_data_cbs cbs; - gpgme_data_t in = NULL; - gpgme_error_t err; - - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - err = gpgme_data_new_from_cbs (&in, &cbs, instream); - if (!err) - err = decrypt_stream (protocol, - in, out, ttl, filename, attestation, preview_mode); - - if (in) - gpgme_data_release (in); - return err; -} - - -/* Verify a message in INBUF and return the new message (i.e. the one - with stripped off dash escaping) in a newly allocated buffer - OUTBUF. If OUTBUF is NULL only the verification result will be - displayed (this is suitable for PGP/MIME messages). A dialog box - will show the result of the verification. If FILENAME is not NULL - it will be displayed along with status outputs. If ATTESTATION is - not NULL a text with the result of the signature verification will - get printed to it. Caller needs to free the returned buffer at - OUTBUF using gpgme_free. */ -int -op_verify (const char *inbuf, char **outbuf, const char *filename, - gpgme_data_t attestation) +/* Not that this closure is called in the context of the + waiter_thread. */ +static void +verify_closure (closure_data_t cld, gpgme_ctx_t ctx, gpg_error_t err) { - gpgme_data_t in = NULL; - gpgme_data_t out = NULL; - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_verify_result_t res = NULL; - - if (outbuf) - *outbuf = NULL; - - op_gpgme_init (); - - err = gpgme_new (&ctx); - if (err) - goto leave; - - err = gpgme_data_new_from_mem (&in, inbuf, strlen (inbuf), 1); - if (err) - goto leave; - - err = gpgme_data_new (&out); - if (err) - goto leave; - - err = gpgme_op_verify (ctx, in, NULL, out); if (!err) { - if (outbuf) - { - /* Return the buffer but first make sure it is a string. */ - if (gpgme_data_write (out, "", 1) == 1) - { - *outbuf = gpgme_data_release_and_get_mem (out, NULL); - out = NULL; - } - } + gpgme_verify_result_t res; + res = gpgme_op_verify_result (ctx); + if (res) + verify_dialog_box (gpgme_get_protocol (ctx), res, NULL); } - if (res) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && attestation) - add_verify_attestation (attestation, ctx, res, filename); - - leave: - if (out) - gpgme_data_release (out); - if (in) - gpgme_data_release (in); - if (ctx) - gpgme_release (ctx); - return err; + gpgme_data_release (cld->sigobj); + engine_gpgme_finished (cld->filter, err); } -/* Verify a detached message where the data is to be read from the - DATA_STREAM and the signature itself is expected to be the string - SIG_STRING. FILENAME will be shown by the verification status - dialog box. If ATTESTATION is not NULL a text with the result of - the signature verification will get printed to it. */ + +/* Verify a detached message where the data is in the gpgme object + DATA and the signature given as the string SIGNATUEE. */ int -op_verify_detached_sig (LPSTREAM data_stream, - const char *sig_string, const char *filename, - gpgme_data_t attestation) +op_gpgme_verify (gpgme_protocol_t protocol, + gpgme_data_t data, const char *signature, + void *notify_data ) { - struct gpgme_data_cbs cbs; - gpgme_data_t data = NULL; - gpgme_data_t sig = NULL; - gpgme_ctx_t ctx = NULL; gpgme_error_t err; - gpgme_verify_result_t res = NULL; + closure_data_t cld; + gpgme_ctx_t ctx = NULL; + gpgme_data_t sigobj = NULL; - memset (&cbs, 0, sizeof cbs); - cbs.read = stream_read_cb; - cbs.write = stream_write_cb; + cld = xcalloc (1, sizeof *cld); + cld->closure = verify_closure; + cld->filter = notify_data; - op_gpgme_init (); - err = gpgme_new (&ctx); if (err) goto leave; - err = gpgme_data_new_from_cbs (&data, &cbs, data_stream); - if (err) - goto leave; - - err = gpgme_data_new_from_mem (&sig, sig_string, strlen (sig_string), 0); - if (err) - goto leave; - - err = gpgme_op_verify (ctx, sig, data, NULL); - if (!err) + gpgme_set_progress_cb (ctx, NULL, cld); + switch (protocol) { - res = gpgme_op_verify_result (ctx); - if (res) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && attestation) - add_verify_attestation (attestation, ctx, res, filename); + case PROTOCOL_OPENPGP: /* Gpgme's default. */ + break; + case PROTOCOL_SMIME: + err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + break; + default: + err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL); + break; } - - leave: - if (data) - gpgme_data_release (data); - if (sig) - gpgme_data_release (sig); - if (ctx) - gpgme_release (ctx); - return err; -} - -/* Verify a detached message where the data is in the string - DATA_STRING and the signature itself is expected to be the string - SIG_STRING. FILENAME will be shown by the verification status - dialog box. If ATTESTATION is not NULL a text with the result of - the signature verification will get printed to it. */ -int -op_verify_detached_sig_mem (const char *data_string, - const char *sig_string, const char *filename, - gpgme_data_t attestation) -{ - gpgme_data_t data = NULL; - gpgme_data_t sig = NULL; - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_verify_result_t res = NULL; - - op_gpgme_init (); - - err = gpgme_new (&ctx); if (err) goto leave; - err = gpgme_data_new_from_mem (&data, data_string, strlen (data_string), 0); + err = gpgme_data_new_from_mem (&sigobj, signature, strlen (signature), 0); if (err) goto leave; + cld->sigobj = sigobj; - err = gpgme_data_new_from_mem (&sig, sig_string, strlen (sig_string), 0); - if (err) - goto leave; + err = gpgme_op_verify_start (ctx, sigobj, data, NULL); - err = gpgme_op_verify (ctx, sig, data, NULL); - if (!err) + leave: + if (err) { - res = gpgme_op_verify_result (ctx); - if (res) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && attestation) - add_verify_attestation (attestation, ctx, res, filename); + gpgme_data_release (sigobj); + xfree (cld); + gpgme_release (ctx); } - - leave: - if (data) - gpgme_data_release (data); - if (sig) - gpgme_data_release (sig); - if (ctx) - gpgme_release (ctx); return err; } -/* Verify a detached message where the data is in the gpgme object - DATA and the signature is the gpgme object SIG. FILENAME will be - shown by the verification status dialog box. If ATTESTATION is not - NULL a text with the result of the signature verification will get - printed to it. */ -int -op_verify_detached_sig_gpgme (gpgme_protocol_t protocol, - gpgme_data_t data, gpgme_data_t sig, - const char *filename, gpgme_data_t attestation) -{ - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_verify_result_t res = NULL; - op_gpgme_init (); - err = gpgme_new (&ctx); - if (err) - goto leave; - err = gpgme_set_protocol (ctx, protocol); - if (err) - goto leave; - - err = gpgme_op_verify (ctx, sig, data, NULL); - if (!err) - { - res = gpgme_op_verify_result (ctx); - if (res) - verify_dialog_box (gpgme_get_protocol (ctx), res, filename); - if (res && attestation) - add_verify_attestation (attestation, ctx, res, filename); - } - - leave: - if (ctx) - gpgme_release (ctx); - return err; -} - - +#if 0 static void at_puts (gpgme_data_t a, const char *s) { @@ -1613,9 +1022,9 @@ } at_puts (a, "\n"); } +#endif - /* Try to find a key for each item in array NAMES. Items not found are stored as malloced strings in the newly allocated array UNKNOWN. @@ -1798,18 +1207,3 @@ return "????????"; } - -const char* -op_strerror (int err) -{ - return gpgme_strerror (err); -} - - -const char* -op_strsource (int err) -{ - return gpgme_strsource (err); -} - - Modified: trunk/src/engine.c =================================================================== --- trunk/src/engine.c 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/engine.c 2007-09-14 15:21:50 UTC (rev 178) @@ -27,9 +27,8 @@ #include #include #include -/*#define WIN32_LEAN_AND_MEAN uncomment it after remove LPSTREAM*/ +#define WIN32_LEAN_AND_MEAN #include -#include /* For LPSTREAM in engine-gpgme.h FIXME: Remove it. */ #include "common.h" #include "engine.h" @@ -233,7 +232,7 @@ } /* This function is called by the gpgme backend to notify a filter - object about the final status of an operation. It may not be + object about the final status of an operation. It may only be called by the engine-gpgme.c module. */ void engine_gpgme_finished (engine_filter_t filter, gpg_error_t status) @@ -295,7 +294,7 @@ engine_filter (engine_filter_t filter, const void *indata, size_t indatalen) { gpg_error_t err; - size_t nbytes; + int nbytes; log_debug ("%s:%s: enter; filter=%p\n", SRCNAME, __func__, filter); /* Our implementation is for now straightforward without any @@ -326,11 +325,11 @@ LeaveCriticalSection (&filter->out.lock); return gpg_error (GPG_ERR_EIO); } - assert (nbytes < filter->out.length && nbytes >= 0); + assert (nbytes <= filter->out.length && nbytes >= 0); if (nbytes < filter->out.length) memmove (filter->out.buffer, filter->out.buffer + nbytes, filter->out.length - nbytes); - filter->out.length =- nbytes; + filter->out.length -= nbytes; } if (!PulseEvent (filter->out.condvar)) log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__); @@ -383,6 +382,17 @@ } +/* Dummy data sink used if caller does not need an output + function. */ +static int +dummy_outfnc (void *opaque, const void *data, size_t datalen) +{ + (void)opaque; + (void)data; + return (int)datalen; +} + + /* Create a new filter object which uses OUTFNC as its data sink. If OUTFNC is called with NULL/0 for the data to be written, the function should do a flush. OUTFNC is expected to return the @@ -402,7 +412,7 @@ filter = create_filter (); filter->cb_inbound.read = filter_gpgme_read_cb; filter->cb_outbound.write = filter_gpgme_write_cb; - filter->outfnc = outfnc; + filter->outfnc = outfnc? outfnc : dummy_outfnc; filter->outfncdata = outfncdata; err = gpgme_data_new_from_cbs (&filter->indata, @@ -449,20 +459,21 @@ while (filter->out.length) { int nbytes; - TRACEPOINT (); + nbytes = filter->outfnc (filter->outfncdata, filter->out.buffer, filter->out.length); if (nbytes == -1) { log_debug ("%s:%s: error writing data\n", SRCNAME, __func__); LeaveCriticalSection (&filter->out.lock); - break; + return gpg_error (GPG_ERR_EIO); } - assert (nbytes < filter->out.length && nbytes >= 0); + + assert (nbytes <= filter->out.length && nbytes >= 0); if (nbytes < filter->out.length) memmove (filter->out.buffer, filter->out.buffer + nbytes, filter->out.length - nbytes); - filter->out.length =- nbytes; + filter->out.length -= nbytes; } if (!PulseEvent (filter->out.condvar)) log_error_w32 (-1, "%s:%s: PulseEvent(out) failed", SRCNAME, __func__); @@ -471,10 +482,10 @@ more = !filter->in.ready; LeaveCriticalSection (&filter->in.lock); if (more) - Sleep (0); + Sleep (100); } while (more); - + if (WaitForSingleObject (filter->in.ready_event, INFINITE) != WAIT_OBJECT_0) { log_error_w32 (-1, "%s:%s: WFSO failed", SRCNAME, __func__); @@ -520,30 +531,72 @@ { gpg_error_t err; - err = op_gpgme_encrypt_data (protocol, filter->indata, filter->outdata, - filter, recipients, NULL, 0); + err = op_gpgme_encrypt (protocol, filter->indata, filter->outdata, + filter, recipients, NULL, 0); return err; } -/* Start an detached signing operation. - FILTER - is an object created by engine_create_filter. The caller needs to - call engine_wait to finish the operation. A filter object may not - be reused after having been used through this function. However, - the lifetime of the filter object lasts until the final engine_wait - or engine_cancel. */ +/* Start an detached signing operation. FILTER is an object created + by engine_create_filter. The caller needs to call engine_wait to + finish the operation. A filter object may not be reused after + having been used through this function. However, the lifetime of + the filter object lasts until the final engine_wait or + engine_cancel. */ int engine_sign_start (engine_filter_t filter, protocol_t protocol) { gpg_error_t err; - err = op_gpgme_sign_data (protocol, filter->indata, filter->outdata, - filter); + err = op_gpgme_sign (protocol, filter->indata, filter->outdata, + filter); return err; } +/* Start an decrypt operation. FILTER is an object created by + engine_create_filter. The caller needs to call engine_wait to + finish the operation. A filter object may not be reused after + having been used through this function. However, the lifetime of + the filter object lasts until the final engine_wait or + engine_cancel. */ +int +engine_decrypt_start (engine_filter_t filter, protocol_t protocol, + int with_verify) +{ + gpg_error_t err; + err = op_gpgme_decrypt (protocol, filter->indata, filter->outdata, + filter, with_verify); + return err; +} +/* Start a verify operation. FILTER is an object created by + engine_create_filter; an output function is not required. SIGNATURE + is the detached signature or NULL if FILTER delivers an opaque + signature. The caller needs to call engine_wait to finish the + operation. A filter object may not be reused after having been + used through this function. However, the lifetime of the filter + object lasts until the final engine_wait or engine_cancel. */ +int +engine_verify_start (engine_filter_t filter, const char *signature, + protocol_t protocol) +{ + gpg_error_t err; + + if (!signature) + { + log_error ("%s:%s: opaque signature are not yet supported\n", + SRCNAME, __func__); + return gpg_error (GPG_ERR_NOT_SUPPORTED); + } + + err = op_gpgme_verify (protocol, filter->indata, signature, filter); + return err; +} + + + + + Modified: trunk/src/engine.h =================================================================== --- trunk/src/engine.h 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/engine.h 2007-09-14 15:21:50 UTC (rev 178) @@ -67,6 +67,10 @@ int engine_encrypt_start (engine_filter_t filter, protocol_t protocol, char **recipients); int engine_sign_start (engine_filter_t filter, protocol_t protocol); +int engine_decrypt_start (engine_filter_t filter, protocol_t protocol, + int with_verify); +int engine_verify_start (engine_filter_t filter, const char *signature, + protocol_t protocol); Modified: trunk/src/message-events.cpp =================================================================== --- trunk/src/message-events.cpp 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/message-events.cpp 2007-09-14 15:21:50 UTC (rev 178) @@ -349,11 +349,11 @@ if (SUCCEEDED (hr)) { if (m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) - rc = mime_sign_encrypt (msg, PROTOCOL_OPENPGP); + rc = message_sign_encrypt (msg, hWnd); else if (m_pExchExt->m_gpgEncrypt && !m_pExchExt->m_gpgSign) rc = message_encrypt (msg, hWnd); else if (!m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) - rc = mime_sign (msg, PROTOCOL_OPENPGP); + rc = message_sign (msg, hWnd); else rc = 0; Modified: trunk/src/message.cpp =================================================================== --- trunk/src/message.cpp 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/message.cpp 2007-09-14 15:21:50 UTC (rev 178) @@ -229,6 +229,7 @@ int i; char *inbuf; size_t inbuflen; + protocol_t protocol = PROTOCOL_UNKNOWN; int err; switch (msgtype) @@ -271,6 +272,7 @@ rawstream->Release (); if (!inbuf) return -1; + protocol = PROTOCOL_OPENPGP; } else { @@ -311,8 +313,7 @@ } } - err = mime_verify (inbuf, inbuflen, message, 0, - opt.passwd_ttl, NULL, NULL, 0); + err = mime_verify (protocol, inbuf, inbuflen, message, 0, 0); log_debug ("mime_verify returned %d", err); if (err) { @@ -347,7 +348,7 @@ LPSTREAM cipherstream; gpg_error_t err; int is_opaque = 0; - int is_smime = 0; + protocol_t protocol; switch (msgtype) { @@ -373,6 +374,7 @@ cipherstream = mapi_get_body_as_stream (message); if (!cipherstream) goto leave; + protocol = PROTOCOL_OPENPGP; } else { @@ -420,7 +422,7 @@ SRCNAME, __func__); goto leave; } - is_smime = 1; + protocol = PROTOCOL_SMIME; } else { @@ -472,6 +474,7 @@ SRCNAME, __func__); goto leave; } + protocol = PROTOCOL_OPENPGP; } cipherstream = mapi_get_attach_as_stream (message, table+part2_idx); @@ -479,8 +482,7 @@ goto leave; /* Problem getting the attachment. */ } - err = mime_decrypt (cipherstream, message, is_smime, opt.passwd_ttl, - NULL, NULL, 0); + err = mime_decrypt (protocol, cipherstream, message, 0, 0); log_debug ("mime_decrypt returned %d (%s)", err, gpg_strerror (err)); if (err) { @@ -595,183 +597,74 @@ - - - -#if 0 -/* Sign the current message. Returns 0 on success. */ -int -message_sign (LPMESSAGE message, HWND hwnd, int want_html) +static int +sign_encrypt (LPMESSAGE message, HWND hwnd, int signflag) { - HRESULT hr; - STATSTG statinfo; - LPSTREAM plaintext; - size_t plaintextlen; - char *signedtext = NULL; - int err = 0; - gpgme_key_t sign_key = NULL; - SPropValue prop; - int have_html_attach = 0; + gpg_error_t err; + char **recipients; - log_debug ("%s:%s: enter message=%p\n", SRCNAME, __func__, message); - - /* We don't sign an empty body - a signature on a zero length string - is pretty much useless. We assume that a HTML message always - comes with a text/plain alternative. */ - plaintext = mapi_get_body_as_stream (message); - if (!plaintext) - plaintextlen = 0; - else + recipients = get_recipients (message); + if (!recipients || !recipients[0]) { - hr = input->Stat (&statinfo, STATFLAG_NONAME); - if (hr) - { - log_debug ("%s:%s: Stat failed: hr=%#lx", SRCNAME, __func__, hr); - plaintext->Release (); - return gpg_error (GPG_ERR_GENERAL); - } - plaintextlen = (size_t)statinfo.cbSize.QuadPart; - } + MessageBox (hwnd, _("No recipients to encrypt to are given"), + "GpgOL", MB_ICONERROR|MB_OK); - if ( !plaintextlen && !has_attachments (message)) - { - log_debug ("%s:%s: leave (empty)", SRCNAME, __func__); - plaintext->Release (); - return 0; + err = gpg_error (GPG_ERR_GENERAL); } - - /* Pop up a dialog box to ask for the signer of the message. */ - if (signer_dialog_box (&sign_key, NULL, 0) == -1) + else { - log_debug ("%s.%s: leave (dialog failed)\n", SRCNAME, __func__); - plaintext->Release (); - return gpg_error (GPG_ERR_CANCELED); - } - - /* Sign the plaintext */ - if (plaintextlen) - { - err = op_sign (plaintext, &signedtext, - OP_SIG_CLEAR, sign_key, opt.passwd_ttl); + if (signflag) + err = mime_sign_encrypt (message, PROTOCOL_OPENPGP, recipients); + else + err = mime_encrypt (message, PROTOCOL_OPENPGP, recipients); if (err) { - MessageBox (hwnd, op_strerror (err), - _("Signing Failure"), MB_ICONERROR|MB_OK); - plaintext->Release (); - return gpg_error (GPG_ERR_GENERAL); + char buf[200]; + + snprintf (buf, sizeof buf, + _("Encryption failed (%s)"), gpg_strerror (err)); + MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK); } } + release_recipient_array (recipients); + return err; +} - - /* If those brain dead html mails are requested we now figure out - whether a HTML body is actually available and move it to an - attachment so that the code below will sign it as a regular - attachments. */ - if (want_html) - { - log_debug ("Signing HTML is not yet supported\n"); -// char *htmltext = loadBody (true); - -// if (htmltext && *htmltext) -// { -// if (!createHtmlAttachment (htmltext)) -// have_html_attach = 1; -// } -// xfree (htmltext); - /* If we got a new attachment we need to release the loaded - attachment info so that the next getAttachment call will read - fresh info. */ -// if (have_html_attach) -// free_attach_info (); - } +/* Sign the MESSAGE. */ +int +message_sign (LPMESSAGE message, HWND hwnd) +{ + gpg_error_t err; - - /* Note, there is a side-effect when we have HTML mails: The - auto-sign-attch option is ignored. I regard auto-sign-attach as a - silly option anyway. */ - if ((opt.auto_sign_attach || have_html_attach) && has_attachments ()) + err = mime_sign (message, PROTOCOL_OPENPGP); + if (err) { - unsigned int n; + char buf[200]; - n = getAttachments (); - log_debug ("%s:%s: message has %u attachments\n", SRCNAME, __func__, n); - for (unsigned int i=0; i < n; i++) - signAttachment (hwnd, i, sign_key, opt.passwd_ttl); - /* FIXME: we should throw an error if signing of any attachment - failed. */ + snprintf (buf, sizeof buf, + _("Signing failed (%s)"), gpg_strerror (err)); + MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK); } - - set_x_header (message, "GPGOL-VERSION", PACKAGE_VERSION); - - /* Now that we successfully processed the attachments, we can save - the changes to the body. */ - if (plaintextlen) - { - err = set_message_body (message, signedtext, 0); - if (err) - goto leave; - - /* In case we don't have attachments, Outlook will really insert - the following content type into the header. We use this to - declare that the encrypted content of the message is utf-8 - encoded. If we have atatchments, OUtlook has its own idea of - the content type to use. */ - prop.ulPropTag=PR_CONTENT_TYPE_A; - prop.Value.lpszA="text/plain; charset=utf-8"; - hr = HrSetOneProp (message, &prop); - if (hr) - log_error ("%s:%s: can't set content type: hr=%#lx\n", - SRCNAME, __func__, hr); - } - - hr = message->SaveChanges (KEEP_OPEN_READWRITE|FORCE_SAVE); - if (hr) - { - log_error ("%s:%s: SaveChanges(message) failed: hr=%#lx\n", - SRCNAME, __func__, hr); - err = gpg_error (GPG_ERR_GENERAL); - goto leave; - } - - leave: - xfree (signedtext); - gpgme_key_release (sign_key); - xfree (plaintext); - log_debug ("%s:%s: leave (err=%s)\n", SRCNAME, __func__, op_strerror (err)); return err; } -#endif /* Encrypt the MESSAGE. */ int message_encrypt (LPMESSAGE message, HWND hwnd) { - gpg_error_t err; - char **recipients; + return sign_encrypt (message, hwnd, 0); +} - recipients = get_recipients (message); - if (!recipients || !recipients[0]) - { - MessageBox (hwnd, _("No recipients for encrypted message given"), - "GpgOL", MB_ICONERROR|MB_OK); - err = gpg_error (GPG_ERR_GENERAL); - } - else - { - err = mime_encrypt (message, PROTOCOL_OPENPGP, recipients); - if (err) - { - char buf[200]; - - snprintf (buf, sizeof buf, - _("Encryption failed (%s)"), gpg_strerror (err)); - MessageBox (hwnd, buf, "GpgOL", MB_ICONERROR|MB_OK); - } - } - release_recipient_array (recipients); - return err; +/* Sign+Encrypt the MESSAGE. */ +int +message_sign_encrypt (LPMESSAGE message, HWND hwnd) +{ + return sign_encrypt (message, hwnd, 1); } + + + Modified: trunk/src/message.h =================================================================== --- trunk/src/message.h 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/message.h 2007-09-14 15:21:50 UTC (rev 178) @@ -26,7 +26,9 @@ int message_verify (LPMESSAGE message, msgtype_t msgtype, int force); int message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force); +int message_sign (LPMESSAGE message, HWND hwnd); int message_encrypt (LPMESSAGE message, HWND hwnd); +int message_sign_encrypt (LPMESSAGE message, HWND hwnd); #endif /*MESSAGE_H*/ Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/mimemaker.c 2007-09-14 15:21:50 UTC (rev 178) @@ -1484,7 +1484,7 @@ int -mime_sign_encrypt (LPMESSAGE message, protocol_t protocol) +mime_sign_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients) { return -1; } Modified: trunk/src/mimemaker.h =================================================================== --- trunk/src/mimemaker.h 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/mimemaker.h 2007-09-14 15:21:50 UTC (rev 178) @@ -30,7 +30,8 @@ int mime_sign (LPMESSAGE message, protocol_t protocol); int mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients); -int mime_sign_encrypt (LPMESSAGE message, protocol_t protocol); +int mime_sign_encrypt (LPMESSAGE message, protocol_t protocol, + char **recipients); #ifdef __cplusplus Modified: trunk/src/mimeparser.c =================================================================== --- trunk/src/mimeparser.c 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/mimeparser.c 2007-09-14 15:21:50 UTC (rev 178) @@ -761,7 +761,7 @@ /* This handler is called by GPGME with the decrypted plaintext. */ -static ssize_t +static int plaintext_handler (void *handle, const void *buffer, size_t size) { mime_context_t ctx = handle; @@ -895,20 +895,27 @@ + int -mime_verify (const char *message, size_t messagelen, - LPMESSAGE mapi_message, int is_smime, - int ttl, gpgme_data_t attestation, HWND hwnd, int preview_mode) +mime_verify (protocol_t protocol, const char *message, size_t messagelen, + LPMESSAGE mapi_message, HWND hwnd, int preview_mode) { gpg_error_t err = 0; mime_context_t ctx; const char *s; size_t len; + char *signature = NULL; + engine_filter_t filter = NULL; - (void)is_smime; /* Not yet used. */ - - log_debug ("%s:%s: enter", SRCNAME, __func__); - + /* Note: PROTOCOL is not used here but figured out directly while + collecting the message. Eventually it might help use setup a + proper verification context right at startup to avoid collecting + all the stuff. However there are a couple of problems with that + - for example we don't know whether gpgsm behaves correctly by + first reading all the data and only the reading the signature. I + guess it is the case but that needs to be checked first. It is + just a performance issue. */ + ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE); ctx->linebufsize = LINEBUFSIZE; ctx->hwnd = hwnd; @@ -943,54 +950,67 @@ } /* Note: the last character should be a LF, if not we ignore such an incomplete last line. */ + if (ctx->sig_data && gpgme_data_write (ctx->sig_data, "", 1) == 1) + { + signature = gpgme_data_release_and_get_mem (ctx->sig_data, NULL); + ctx->sig_data = NULL; + } - /* Now actually verify the signature. */ - if (!err && ctx->signed_data && ctx->sig_data) + if (!err && ctx->signed_data && signature) { - char *tmp; - gpgme_protocol_t xprot; - int inv_prot = 0; + gpgme_data_seek (ctx->signed_data, 0, SEEK_SET); + + if ((err=engine_create_filter (&filter, NULL, NULL))) + goto leave; + if ((err=engine_verify_start (filter, signature, ctx->protocol))) + goto leave; - gpgme_data_seek (ctx->signed_data, 0, SEEK_SET); - gpgme_data_seek (ctx->sig_data, 0, SEEK_SET); - if (ctx->protocol == PROTOCOL_OPENPGP) + /* Filter the data. */ + do { - tmp = native_to_utf8 (_("[OpenPGP signature]")); - xprot = GPGME_PROTOCOL_OpenPGP; + int nread; + char buffer[4096]; + + nread = gpgme_data_read (ctx->signed_data, buffer, sizeof buffer); + if (nread < 0) + { + err = gpg_error_from_syserror (); + log_error ("%s:%s: gpgme_data_read failed: %s", + SRCNAME, __func__, gpg_strerror (err)); + } + else if (nread) + { + TRACEPOINT(); + err = engine_filter (filter, buffer, nread); + } + else + break; /* EOF */ } - else if (ctx->protocol == PROTOCOL_SMIME) - { - tmp = native_to_utf8 (_("[S/MIME signature]")); - xprot = GPGME_PROTOCOL_CMS; - } - else - { - tmp = native_to_utf8 (_("[Unknown signature protocol]")); - inv_prot = 1; - } - - err = (inv_prot - ? gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL) - : op_verify_detached_sig_gpgme (xprot, - ctx->signed_data, ctx->sig_data, - tmp, attestation)); - log_debug ("%s:%s: checked signature: %s <%s>", - SRCNAME, __func__, gpg_strerror (err), op_strsource (err)); - xfree (tmp); + while (!err); + if (err) + goto leave; + + /* Wait for the engine to finish. */ + if ((err = engine_filter (filter, NULL, 0))) + goto leave; + if ((err = engine_wait (filter))) + goto leave; + filter = NULL; } leave: + TRACEPOINT(); + gpgme_free (signature); + engine_cancel (filter); if (ctx) { /* Cancel any left open attachment. */ finish_attachment (ctx, 1); rfc822parse_close (ctx->msg); - if (ctx->signed_data) - gpgme_data_release (ctx->signed_data); - if (ctx->sig_data) - gpgme_data_release (ctx->sig_data); + gpgme_data_release (ctx->signed_data); + gpgme_data_release (ctx->sig_data); show_mimestruct (ctx->mimestruct); while (ctx->mimestruct) { @@ -1008,27 +1028,20 @@ -/* Decrypt the PGP or S/MIME message taken from INSTREAM. If - ATTESTATION is not NULL a text with the result of the signature - verification will get printed to it. HWND is the window to be used - for message box and such. In PREVIEW_MODE no verification will be - done, no messages saved and no messages boxes will pop up. */ +/* Decrypt the PGP or S/MIME message taken from INSTREAM. HWND is the + window to be used for message box and such. In PREVIEW_MODE no + verification will be done, no messages saved and no messages boxes + will pop up. */ int -mime_decrypt (LPSTREAM instream, LPMESSAGE mapi_message, int is_smime, - int ttl, gpgme_data_t attestation, HWND hwnd, int preview_mode) +mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message, + HWND hwnd, int preview_mode) { gpg_error_t err; - struct gpgme_data_cbs cbs; - gpgme_data_t plaintext; mime_context_t ctx; - char *title; - gpgme_protocol_t proto; + engine_filter_t filter = NULL; - log_debug ("%s:%s: enter", SRCNAME, __func__); + log_debug ("%s:%s: enter (protocol=%d)", SRCNAME, __func__, protocol); - memset (&cbs, 0, sizeof cbs); - cbs.write = plaintext_handler; - ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE); ctx->linebufsize = LINEBUFSIZE; ctx->protect_mode = 1; @@ -1046,30 +1059,61 @@ goto leave; } - err = gpgme_data_new_from_cbs (&plaintext, &cbs, ctx); - if (err) + /* Prepare the decryption. */ +/* title = native_to_utf8 (_("[Encrypted S/MIME message]")); */ +/* title = native_to_utf8 (_("[Encrypted PGP/MIME message]")); */ + if ((err=engine_create_filter (&filter, plaintext_handler, ctx))) goto leave; + if ((err=engine_decrypt_start (filter, protocol, !preview_mode))) + goto leave; - if (is_smime) + + /* Filter the stream. */ + do { - proto = GPGME_PROTOCOL_CMS; - title = native_to_utf8 (_("[Encrypted S/MIME message]")); + HRESULT hr; + ULONG nread; + char buffer[4096]; + + /* For EOF detection we assume that Read returns no error and + thus nread will be 0. The specs say that "Depending on the + implementation, either S_FALSE or an error code could be + returned when reading past the end of the stream"; thus we + are not really sure whether our assumption is correct. At + another place the documentation says that the implementation + used by ISequentialStream exhibits the same EOF behaviour has + found on the MSDOS FAT file system. So we seem to have good + karma. */ + hr = IStream_Read (instream, buffer, sizeof buffer, &nread); + if (hr) + { + log_error ("%s:%s: IStream::Read failed: hr=%#lx", + SRCNAME, __func__, hr); + err = gpg_error (GPG_ERR_EIO); + } + else if (nread) + { + err = engine_filter (filter, buffer, nread); + } + else + break; /* EOF */ } - else - { - proto = GPGME_PROTOCOL_OpenPGP; - title = native_to_utf8 (_("[Encrypted PGP/MIME message]")); - } - err = op_decrypt_stream_to_gpgme (proto, instream, plaintext, ttl, title, - attestation, preview_mode); - xfree (title); - if (!err && (ctx->parser_error || ctx->line_too_long)) + while (!err); + if (err) + goto leave; + + /* Wait for the engine to finish. */ + if ((err = engine_filter (filter, NULL, 0))) + goto leave; + if ((err = engine_wait (filter))) + goto leave; + filter = NULL; + + if (ctx->parser_error || ctx->line_too_long) err = gpg_error (GPG_ERR_GENERAL); - leave: - if (plaintext) - gpgme_data_release (plaintext); + engine_cancel (filter); if (ctx) { /* Cancel any left over attachment which means that the MIME Modified: trunk/src/mimeparser.h =================================================================== --- trunk/src/mimeparser.h 2007-09-13 11:53:15 UTC (rev 177) +++ trunk/src/mimeparser.h 2007-09-14 15:21:50 UTC (rev 178) @@ -29,13 +29,12 @@ #endif -int mime_verify (const char *message, size_t messagelen, - LPMESSAGE mapi_message, int is_smime, - int ttl, - gpgme_data_t attestation, HWND hwnd, int preview_mode); -int mime_decrypt (LPSTREAM instream, LPMESSAGE mapi_message, int is_smime, - int ttl, - gpgme_data_t attestation, HWND hwnd, int preview_mode); +int mime_verify (protocol_t protocol, const char *message, size_t messagelen, + LPMESSAGE mapi_message, + HWND hwnd, int preview_mode); +int mime_decrypt (protocol_t protocol, + LPSTREAM instream, LPMESSAGE mapi_message, + HWND hwnd, int preview_mode); #ifdef __cplusplus From cvs at cvs.gnupg.org Fri Sep 14 19:23:35 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 14 Sep 2007 19:23:35 +0200 Subject: [svn] GnuPG - r4585 - trunk/scd Message-ID: Author: marcus Date: 2007-09-14 19:23:34 +0200 (Fri, 14 Sep 2007) New Revision: 4585 Modified: trunk/scd/ChangeLog trunk/scd/scdaemon.c Log: 2007-09-14 Marcus Brinkmann * scdaemon.c (main): New variable STANDARD_SOCKET, which is 1 for W32 targets. Use it for create_socket_name. Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2007-09-14 14:25:02 UTC (rev 4584) +++ trunk/scd/ChangeLog 2007-09-14 17:23:34 UTC (rev 4585) @@ -1,3 +1,8 @@ +2007-09-14 Marcus Brinkmann + + * scdaemon.c (main): New variable STANDARD_SOCKET, which is 1 for + W32 targets. Use it for create_socket_name. + 2007-08-07 Werner Koch * tlv.c, tlv.h: Move to ../common/. Modified: trunk/scd/scdaemon.c =================================================================== --- trunk/scd/scdaemon.c 2007-09-14 14:25:02 UTC (rev 4584) +++ trunk/scd/scdaemon.c 2007-09-14 17:23:34 UTC (rev 4585) @@ -310,6 +310,7 @@ int gpgconf_list = 0; const char *config_filename = NULL; int allow_coredump = 0; + int standard_socket = 0; set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -356,7 +357,12 @@ /* Set default options. */ opt.pcsc_driver = DEFAULT_PCSC_DRIVER; +#ifdef HAVE_W32_SYSTEM + standard_socket = 1; /* Under Windows we always use a standard + socket. */ +#endif + shell = getenv ("SHELL"); if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") ) csh_style = 1; @@ -621,7 +627,7 @@ back the name of that socket. */ if (multi_server) { - socket_name = create_socket_name (0, + socket_name = create_socket_name (standard_socket, "S.scdaemon", "/tmp/gpg-XXXXXX/S.scdaemon"); @@ -665,7 +671,7 @@ int i; /* Create the socket. */ - socket_name = create_socket_name (0, + socket_name = create_socket_name (standard_socket, "S.scdaemon", "/tmp/gpg-XXXXXX/S.scdaemon"); From cvs at cvs.gnupg.org Sun Sep 16 18:27:21 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Sun, 16 Sep 2007 18:27:21 +0200 Subject: [svn] GpgEX - r19 - trunk/src Message-ID: Author: marcus Date: 2007-09-16 18:27:20 +0200 (Sun, 16 Sep 2007) New Revision: 19 Modified: trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/gpgex.cc Log: 2007-09-16 Marcus Brinkmann * gpgex.cc (gpgex_t::QueryContextMenu): Implement popup menu correctly, such that the explorer can clean up correctly (in the file dialog). (gpgex_t::GetCommandString): Implement help texts. (start_help): New function. (gpgex_t::InvokeCommand): Call start_help. * Makefile.am (gpgex_LDADD): Add -loleaut32. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-11 14:53:06 UTC (rev 18) +++ trunk/src/ChangeLog 2007-09-16 16:27:20 UTC (rev 19) @@ -1,3 +1,13 @@ +2007-09-16 Marcus Brinkmann + + * gpgex.cc (gpgex_t::QueryContextMenu): Implement popup menu + correctly, such that the explorer can clean up correctly (in the + file dialog). + (gpgex_t::GetCommandString): Implement help texts. + (start_help): New function. + (gpgex_t::InvokeCommand): Call start_help. + * Makefile.am (gpgex_LDADD): Add -loleaut32. + 2007-09-11 Marcus Brinkmann * client.cc (client_t::call_assuan): Send --nohup as argument to Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-11 14:53:06 UTC (rev 18) +++ trunk/src/Makefile.am 2007-09-16 16:27:20 UTC (rev 19) @@ -37,9 +37,6 @@ main.h main.cc \ $(ICONS) -#gpgex_LDADD = $(srcdir)/gpgex.def \ -# -L . -lshell32 -lcomdlg32 -loleaut32 -ladvapi32 - libgpg-error.a: ln -sf $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a @@ -49,9 +46,13 @@ clean-local: rm -f libgpg-error.a libassuan.a +#gpgex_LDADD = $(srcdir)/gpgex.def \ +# -L . -lshell32 -lcomdlg32 -ladvapi32 + +# We need -loleaut32 for start_help() in gpgex.cc. gpgex_LDADD = $(srcdir)/gpgex.def -L . \ -lshell32 -lgdi32 -lole32 -luuid \ - ./libassuan.a ./libgpg-error.a -lws2_32 + ./libassuan.a ./libgpg-error.a -lws2_32 -loleaut32 .rc.o: $(WINDRES) -I $(srcdir) -I . `test -f '$<' || echo '$(srcdir)/'`$< $@ Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-09-11 14:53:06 UTC (rev 18) +++ trunk/src/gpgex.cc 2007-09-16 16:27:20 UTC (rev 19) @@ -31,6 +31,9 @@ #include +/* For the start_help() function. */ +#include + #include "main.h" #include "client.h" @@ -46,7 +49,8 @@ #define ID_CMD_ENCRYPT 5 #define ID_CMD_SIGN 6 #define ID_CMD_IMPORT 7 -#define ID_CMD_MAX 7 +#define ID_CMD_POPUP 8 +#define ID_CMD_MAX 8 #define ID_CMD_STR_HELP _("Help on GpgEX") #define ID_CMD_STR_DECRYPT_VERIFY _("Decrypt and verify") @@ -291,8 +295,13 @@ if (popup == NULL) return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); - res = InsertMenu (hMenu, indexMenu++, MF_BYPOSITION | MF_STRING | MF_POPUP, - (UINT) popup, _("More GpgEX options")); + MENUITEMINFO mii = { sizeof (MENUITEMINFO) }; + mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID; + mii.wID = idCmdFirst + ID_CMD_POPUP; + mii.hSubMenu = popup; + mii.dwTypeData = (CHAR *) _("More GpgEX options"); + + res = InsertMenuItem (hMenu, indexMenu++, TRUE, &mii); if (!res) { DWORD last_error = GetLastError (); @@ -364,26 +373,137 @@ gpgex_t::GetCommandString (UINT idCommand, UINT uFlags, LPUINT lpReserved, LPSTR pszName, UINT uMaxNameLen) { + const char *txt; + TRACE_BEG5 (DEBUG_CONTEXT_MENU, "gpgex_t::GetCommandString", this, "idCommand=%u, uFlags=%x, lpReserved=%lu, pszName=%p, " "uMaxNameLen=%u", idCommand, uFlags, lpReserved, pszName, uMaxNameLen); - if (idCommand != 0) + if (! (uFlags & GCS_HELPTEXT)) return TRACE_RES (E_INVALIDARG); - if (! (uFlags & GCS_HELPTEXT)) + if (idCommand > ID_CMD_MAX) return TRACE_RES (E_INVALIDARG); + switch (idCommand) + { + case ID_CMD_HELP: + txt = "Invoke the GpgEX documentation."; + break; + + case ID_CMD_DECRYPT_VERIFY: + txt = "Decrypt and verify the marked files."; + break; + + case ID_CMD_DECRYPT: + txt = "Decrypt the marked files."; + break; + + case ID_CMD_VERIFY: + txt = "Verify the marked files."; + break; + + case ID_CMD_ENCRYPT_SIGN: + txt = "Encrypt and sign the marked files."; + break; + + case ID_CMD_ENCRYPT: + txt = "Encrypt the marked files."; + break; + + case ID_CMD_SIGN: + txt = "Sign the marked files."; + break; + + case ID_CMD_IMPORT: + txt = "Import the marked files."; + break; + + case ID_CMD_POPUP: + txt = "Show more GpgEX options."; + break; + + default: + return TRACE_RES (E_INVALIDARG); + } + if (uFlags & GCS_UNICODE) - lstrcpynW ((LPWSTR) pszName, L"GpgEX help string (unicode)", uMaxNameLen); + { + /* FIXME: Convert to unicode. */ + lstrcpynW ((LPWSTR) pszName, L"(Unicode help not available yet)", + uMaxNameLen); + } else - lstrcpynA (pszName, "GpgEX help string (ASCII)", uMaxNameLen); + lstrcpynA (pszName, txt, uMaxNameLen); return TRACE_RES (S_OK); } +/* FIXME: Might be exported in a helper utility. Also, it might be + that we use KDE's help browser? */ +static void +start_help (HWND hwnd) +{ + HRESULT res; + CLSID clsid; + LPUNKNOWN browser = NULL; + IWebBrowser2 *web = NULL; + + CLSIDFromProgID (OLESTR ("InternetExplorer.Application"), &clsid); + res = CoCreateInstance (clsid, NULL, CLSCTX_SERVER, IID_IUnknown, (void **) &browser); + if (! SUCCEEDED (res)) + { + MessageBox (hwnd, "Can not open browser", "GpgEX", MB_ICONINFORMATION); + return; + } + + browser->QueryInterface (IID_IWebBrowser2, (void **) &web); + browser->Release (); + + /* FIXME: Pick a good configuration. */ + // Only for IE7? + // web->put_Resizable (VARIANT_TRUE); + web->put_ToolBar (FALSE); + web->put_AddressBar (VARIANT_FALSE); + web->put_MenuBar (VARIANT_FALSE); + web->put_StatusBar (VARIANT_FALSE); + // width, height + web->put_Visible (VARIANT_TRUE); + + /* FIXME: Replace by real URL. */ + BSTR url = SysAllocString ((const OLECHAR *) L"http://www.gpg4win.org/"); + VARIANT vars[4]; + memset (vars, 0, sizeof (vars)); + res = web->Navigate (url, vars, vars + 1, vars + 2, vars + 3); + SysFreeString (url); + if (!SUCCEEDED (res)) + { + web->Release (); + return; + } + +#if 0 + VARIANT_BOOL busy; + do + { + web->get_Busy (&busy); + Sleep (500); + } + while (busy == VARIANT_TRUE); + + + HWND hwnd = NULL; + web->get_HWND (&hwnd); +#endif + + Sleep (5000); + web->Release (); + +} + + STDMETHODIMP gpgex_t::InvokeCommand (LPCMINVOKECOMMANDINFO lpcmi) { @@ -402,38 +522,37 @@ switch (LOWORD (lpcmi->lpVerb)) { case ID_CMD_HELP: - { - string msg; - unsigned int i; - - msg = "Invoked Help on files:\n\n"; - for (i = 0; i < this->filenames.size (); i++) - msg = msg + this->filenames[i] + '\n'; - - MessageBox (lpcmi->hwnd, msg.c_str (), "GpgEX", MB_ICONINFORMATION); - } + start_help (lpcmi->hwnd); break; + case ID_CMD_DECRYPT_VERIFY: client.decrypt_verify (this->filenames); break; + case ID_CMD_DECRYPT: client.decrypt (this->filenames); break; + case ID_CMD_VERIFY: client.verify (this->filenames); break; + case ID_CMD_ENCRYPT_SIGN: client.encrypt_sign (this->filenames); break; + case ID_CMD_ENCRYPT: client.encrypt (this->filenames); break; + case ID_CMD_SIGN: client.sign (this->filenames); break; + case ID_CMD_IMPORT: client.import (this->filenames); break; + default: return TRACE_RES (E_INVALIDARG); break; From cvs at cvs.gnupg.org Mon Sep 17 11:31:20 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 11:31:20 +0200 Subject: [svn] GpgOL - r179 - branches Message-ID: Author: wk Date: 2007-09-17 11:31:01 +0200 (Mon, 17 Sep 2007) New Revision: 179 Added: branches/old-0.9-branch/ Log: Branch old code base Copied: branches/old-0.9-branch (from rev 167, trunk) From cvs at cvs.gnupg.org Mon Sep 17 12:19:39 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 12:19:39 +0200 Subject: [svn] GpgOL - r180 - in branches/old-0.9-branch: . po src Message-ID: Author: wk Date: 2007-09-17 12:19:38 +0200 (Mon, 17 Sep 2007) New Revision: 180 Modified: branches/old-0.9-branch/ChangeLog branches/old-0.9-branch/NEWS branches/old-0.9-branch/autogen.sh branches/old-0.9-branch/configure.ac branches/old-0.9-branch/po/de.po branches/old-0.9-branch/po/sv.po branches/old-0.9-branch/src/ChangeLog branches/old-0.9-branch/src/Makefile.am branches/old-0.9-branch/src/olflange.cpp branches/old-0.9-branch/src/w32-gettext.c Log: Updates to cope with the newer compiler. Print version number of gpgme. Modified: branches/old-0.9-branch/ChangeLog =================================================================== --- branches/old-0.9-branch/ChangeLog 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/ChangeLog 2007-09-17 10:19:38 UTC (rev 180) @@ -1,3 +1,7 @@ +2007-09-17 Werner Koch + + * autogen.sh: Add --force option. + 2006-12-13 Werner Koch * po/LINGUAS: Added sv. Modified: branches/old-0.9-branch/NEWS =================================================================== --- branches/old-0.9-branch/NEWS 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/NEWS 2007-09-17 10:19:38 UTC (rev 180) @@ -1,3 +1,10 @@ +NOTE: This is the old branch of gpgol. To avoid conflicts with the +rewrite the version number shall never reach 0.10.0! + +Noteworthy changes for version 0.9.92 +================================================== + + Noteworthy changes for version 0.9.91 (2006-10-13) ================================================== Modified: branches/old-0.9-branch/autogen.sh =================================================================== --- branches/old-0.9-branch/autogen.sh 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/autogen.sh 2007-09-17 10:19:38 UTC (rev 180) @@ -39,6 +39,11 @@ MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} DIE=no +FORCE= +if test x"$1" = x"--force"; then + FORCE=" --force" + shift +fi # ***** W32 build script ******* # Used to cross-compile for Windows. @@ -151,7 +156,7 @@ $AUTOHEADER echo "Running automake --gnu ..." $AUTOMAKE --gnu; -echo "Running autoconf..." -$AUTOCONF +echo "Running autoconf${FORCE} ..." +$AUTOCONF${FORCE} echo "You may now run \"./configure --enable-maintainer-mode && make\"." Modified: branches/old-0.9-branch/configure.ac =================================================================== --- branches/old-0.9-branch/configure.ac 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/configure.ac 2007-09-17 10:19:38 UTC (rev 180) @@ -16,8 +16,8 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [0.9.91]) -m4_define([my_issvn], [no]) +m4_define([my_version], [0.9.92]) +m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')])) Modified: branches/old-0.9-branch/po/de.po =================================================================== --- branches/old-0.9-branch/po/de.po 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/po/de.po 2007-09-17 10:19:38 UTC (rev 180) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol 0.9.4\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2006-08-28 15:44+0200\n" +"POT-Creation-Date: 2007-09-17 11:36+0200\n" "PO-Revision-Date: 2006-04-24 16:41+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" @@ -287,7 +287,7 @@ msgid "The default key may not contain any spaces." msgstr "Der Standardschl?ssel darf keine Leerzeichen enthalten." -#: src/olflange.cpp:750 +#: src/olflange.cpp:751 msgid "" "This version of Outlook is too old!\n" "\n" @@ -304,7 +304,7 @@ "\n" "Bitte updaten Sie auf SP2 bevor Sie versuchen eine Nachricht zu versenden." -#: src/olflange.cpp:946 +#: src/olflange.cpp:947 msgid "" "Sorry, we can only encrypt plain text messages and\n" "no RTF messages. Please make sure that only the text\n" @@ -407,11 +407,31 @@ msgid "[PGP/MIME signature]" msgstr "[PGP/MIME Signatur]" -#: src/recipient-dialog.c:410 +#: src/recipient-dialog.c:89 +msgid "Name" +msgstr "" + +#: src/recipient-dialog.c:94 +msgid "E-Mail" +msgstr "" + +#: src/recipient-dialog.c:99 +msgid "Key-Info" +msgstr "" + +#: src/recipient-dialog.c:104 +msgid "Key ID" +msgstr "" + +#: src/recipient-dialog.c:109 +msgid "Validity" +msgstr "" + +#: src/recipient-dialog.c:425 msgid "Please select at least one recipient key." msgstr "Bitte w?hlen Sie mindestens einen Empf?ngerschl?ssel." -#: src/recipient-dialog.c:411 +#: src/recipient-dialog.c:426 msgid "Recipient Dialog" msgstr "Auswahl des Empf?ngerschl?ssels" Modified: branches/old-0.9-branch/po/sv.po =================================================================== --- branches/old-0.9-branch/po/sv.po 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/po/sv.po 2007-09-17 10:19:38 UTC (rev 180) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2006-12-12 23:08+0100\n" +"POT-Creation-Date: 2007-09-17 11:36+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -15,138 +15,136 @@ "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../src/common.c:103 +#: src/common.c:103 msgid "GPG - Save decrypted attachment" msgstr "GPG - Spara dekrypterad bilaga" -#: ../src/config-dialog.c:290 +#: src/config-dialog.c:290 msgid "Select GPG Key Manager" msgstr "V?lj GPG-nyckelhanterare" -#: ../src/engine-gpgme.c:979 +#: src/engine-gpgme.c:979 msgid "Fingerprint: " msgstr "Fingeravtryck: " -#: ../src/engine-gpgme.c:1036 +#: src/engine-gpgme.c:1036 msgid "This signature is valid\n" msgstr "Den h?r signaturen ?r giltig\n" -#: ../src/engine-gpgme.c:1038 +#: src/engine-gpgme.c:1038 msgid "signature state is \"green\"\n" msgstr "signaturens tillst?nd ?r \"gr?n\"\n" -#: ../src/engine-gpgme.c:1040 +#: src/engine-gpgme.c:1040 msgid "signature state is \"red\"\n" msgstr "signaturens tillst?nd ?r \"r?d\"\n" -#: ../src/engine-gpgme.c:1044 +#: src/engine-gpgme.c:1044 msgid "Warning: One of the keys has been revoked\n" msgstr "Varning: En av nycklarna har sp?rrats\n" -#: ../src/engine-gpgme.c:1054 +#: src/engine-gpgme.c:1054 msgid "Warning: The key used to create the signature expired at: " msgstr "Varning: Nyckeln som anv?ndes f?r att skapa signaturen gick ut den: " -#: ../src/engine-gpgme.c:1060 +#: src/engine-gpgme.c:1060 msgid "Warning: At least one certification key has expired\n" msgstr "Varning: ?tminstone en certifieringsnyckel har g?tt ut\n" -#: ../src/engine-gpgme.c:1066 +#: src/engine-gpgme.c:1066 msgid "Warning: The signature expired at: " msgstr "Varning: Signaturen gick ut den: " -#: ../src/engine-gpgme.c:1072 +#: src/engine-gpgme.c:1072 msgid "Can't verify due to a missing key or certificate\n" msgstr "Kan inte validera p? grund av en saknad nyckel eller certifikat\n" -#: ../src/engine-gpgme.c:1076 +#: src/engine-gpgme.c:1076 msgid "The CRL is not available\n" msgstr "Sp?rrlistan ?r inte tillg?nglig\n" -#: ../src/engine-gpgme.c:1082 +#: src/engine-gpgme.c:1082 msgid "Available CRL is too old\n" msgstr "Tillg?nglig sp?rrlista ?r f?r gammal\n" -#: ../src/engine-gpgme.c:1087 +#: src/engine-gpgme.c:1087 msgid "A policy requirement was not met\n" msgstr "Ett policykrav matchades inte\n" -#: ../src/engine-gpgme.c:1093 +#: src/engine-gpgme.c:1093 msgid "A system error occured" msgstr "Ett systemfel intr?ffade" -#: ../src/engine-gpgme.c:1130 -msgid "WARNING: We have NO indication whether the key belongs to the person named as shown above\n" -msgstr "VARNING: Vi har INGA indikationer p? huruvida nyckeln tillh?r personen vars namn visas ovanf?r\n" +#: src/engine-gpgme.c:1130 +msgid "" +"WARNING: We have NO indication whether the key belongs to the person named " +"as shown above\n" +msgstr "" +"VARNING: Vi har INGA indikationer p? huruvida nyckeln tillh?r personen vars " +"namn visas ovanf?r\n" -#: ../src/engine-gpgme.c:1137 +#: src/engine-gpgme.c:1137 msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" msgstr "VARNING: Nyckeln TILLH?R INTE personen vars namn visas ovanf?r\n" -#: ../src/engine-gpgme.c:1141 -msgid "WARNING: It is NOT certain that the key belongs to the person named as shown above\n" -msgstr "VARNING: Det ?r INTE s?kert att nyckeln tillh?r den person vars namn visas ovanf?r\n" +#: src/engine-gpgme.c:1141 +msgid "" +"WARNING: It is NOT certain that the key belongs to the person named as shown " +"above\n" +msgstr "" +"VARNING: Det ?r INTE s?kert att nyckeln tillh?r den person vars namn visas " +"ovanf?r\n" -#. Nothing yet written to the stream. Insert the current time. -#: ../src/engine-gpgme.c:1174 +#: src/engine-gpgme.c:1174 msgid "Verification started at: " msgstr "Validering startad: " -#: ../src/engine-gpgme.c:1179 +#: src/engine-gpgme.c:1179 msgid "Verification result for: " msgstr "Valideringsresultat f?r: " -#: ../src/engine-gpgme.c:1180 +#: src/engine-gpgme.c:1180 msgid "[unnamed part]" msgstr "[ej namngiven del]" -#. We can't decide (yellow) but this is a PGP key with a -#. good signature, so we display what a PGP user -#. expects: The name, fingerprint and the key validity -#. (which is neither fully or ultimate). -#: ../src/engine-gpgme.c:1198 -#: ../src/engine-gpgme.c:1228 +#: src/engine-gpgme.c:1198 src/engine-gpgme.c:1228 msgid "Good signature from: " msgstr "Korrekt signatur fr?n: " -#: ../src/engine-gpgme.c:1205 +#: src/engine-gpgme.c:1205 msgid " aka: " msgstr "?ven k?nd som:" -#: ../src/engine-gpgme.c:1209 -#: ../src/engine-gpgme.c:1231 +#: src/engine-gpgme.c:1209 src/engine-gpgme.c:1231 msgid " created: " msgstr " skapad: " -#: ../src/engine-gpgme.c:1218 +#: src/engine-gpgme.c:1218 msgid "*BAD* signature claimed to be from: " msgstr "*FELAKTIG* signatur h?vdades komma fr?n: " -#: ../src/engine-gpgme.c:1241 +#: src/engine-gpgme.c:1241 msgid "Error checking signature" msgstr "Fel vid kontroll av signatur" -#: ../src/engine-gpgme.c:1257 +#: src/engine-gpgme.c:1257 msgid "*** Begin Notation (signature by: " msgstr "*** Notation start (signatur av: " -#: ../src/engine-gpgme.c:1277 +#: src/engine-gpgme.c:1277 msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" -#: ../src/gpgmsg.cpp:1194 +#: src/gpgmsg.cpp:1194 msgid "No valid OpenPGP data found." msgstr "Inget giltigt OpenPGP-data hittades." -#: ../src/gpgmsg.cpp:1195 -#: ../src/gpgmsg.cpp:1306 -#: ../src/gpgmsg.cpp:1320 -#: ../src/gpgmsg.cpp:1336 -#: ../src/gpgmsg.cpp:1515 +#: src/gpgmsg.cpp:1195 src/gpgmsg.cpp:1306 src/gpgmsg.cpp:1320 +#: src/gpgmsg.cpp:1336 src/gpgmsg.cpp:1515 msgid "Decryption" msgstr "Dekryptering" -#: ../src/gpgmsg.cpp:1213 +#: src/gpgmsg.cpp:1213 msgid "" "[This is a PGP/MIME message]\r\n" "\r\n" @@ -156,39 +154,40 @@ "\r\n" "[Anv?nd knappen \"Dekryptera\" i meddelandef?nstret f?r att visa inneh?llet.]" -#: ../src/gpgmsg.cpp:1271 +#: src/gpgmsg.cpp:1271 msgid "" -"Note: This is a PGP/MIME signed message. The GPGol plugin is not always able to verify such a message due to missing support in Outlook.\n" +"Note: This is a PGP/MIME signed message. The GPGol plugin is not always " +"able to verify such a message due to missing support in Outlook.\n" "\n" "(This message will be shown only once per session)" msgstr "" -"Observera: Det h?r ?r ett PGP/MIME-signerat meddelande. Insticksmodulen GPGol kan inte alltid validera ett s?dant meddelande p? grund av att st?d saknas i Outlook.\n" +"Observera: Det h?r ?r ett PGP/MIME-signerat meddelande. Insticksmodulen " +"GPGol kan inte alltid validera ett s?dant meddelande p? grund av att st?d " +"saknas i Outlook.\n" "\n" "(Det h?r meddelandet kommer endast att visas en g?ng per session)" -#: ../src/gpgmsg.cpp:1275 +#: src/gpgmsg.cpp:1275 msgid "Verification" msgstr "Validering" -#: ../src/gpgmsg.cpp:1293 +#: src/gpgmsg.cpp:1293 msgid "[This is a PGP/MIME message]" msgstr "[Det h?r ?r ett PGP/MIME-meddelande]" -#: ../src/gpgmsg.cpp:1305 -#: ../src/gpgmsg.cpp:1319 -#: ../src/gpgmsg.cpp:1335 +#: src/gpgmsg.cpp:1305 src/gpgmsg.cpp:1319 src/gpgmsg.cpp:1335 msgid "Problem decrypting PGP/MIME message" msgstr "Problem vid dekryptering av PGP/MIME-meddelande" -#: ../src/gpgmsg.cpp:1470 +#: src/gpgmsg.cpp:1470 msgid "Verification Failure" msgstr "Validering misslyckades" -#: ../src/gpgmsg.cpp:1473 +#: src/gpgmsg.cpp:1473 msgid "Decryption Failure" msgstr "Dekryptering misslyckades" -#: ../src/gpgmsg.cpp:1509 +#: src/gpgmsg.cpp:1509 msgid "" "The message text cannot be displayed.\n" "You have to save the decrypted message to view it.\n" @@ -204,7 +203,7 @@ #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it #. will be expanded to a list of atatchment names. -#: ../src/gpgmsg.cpp:1536 +#: src/gpgmsg.cpp:1536 msgid "" "Signed attachments found.\n" "\n" @@ -216,13 +215,13 @@ "@LIST@\n" "Vill du validera signaturerna?" -#: ../src/gpgmsg.cpp:1544 +#: src/gpgmsg.cpp:1544 msgid "Attachment Verification" msgstr "Validering av bilaga" #. TRANSLATORS: Keep the @LIST@ verbatim on a separate line; it #. will be expanded to a list of atatchment names. -#: ../src/gpgmsg.cpp:1565 +#: src/gpgmsg.cpp:1565 msgid "" "Encrypted attachments found.\n" "\n" @@ -234,70 +233,72 @@ "@LIST@\n" "Vill du dekryptera och spara dem?" -#: ../src/gpgmsg.cpp:1572 +#: src/gpgmsg.cpp:1572 msgid "Attachment Decryption" msgstr "Dekryptering av bilaga" -#: ../src/gpgmsg.cpp:1641 +#: src/gpgmsg.cpp:1641 msgid "Signing Failure" msgstr "Signering misslyckades" -#: ../src/gpgmsg.cpp:1809 +#: src/gpgmsg.cpp:1809 msgid "" -"The configured default encryption key is not available or does not unambigiously specify a key. Please fix this in the option dialog.\n" +"The configured default encryption key is not available or does not " +"unambigiously specify a key. Please fix this in the option dialog.\n" "\n" "This message won't be be encrypted to this key!" msgstr "" -"Den konfigurerade standardkrypteringsnyckeln ?r inte tillg?nglig eller anger inte uttryckligen en nyckel. R?tta till det h?r i inst?llningarna.\n" +"Den konfigurerade standardkrypteringsnyckeln ?r inte tillg?nglig eller anger " +"inte uttryckligen en nyckel. R?tta till det h?r i inst?llningarna.\n" "\n" "Det h?r meddelandet kommer inte att krypteras med den h?r nyckeln!" -#: ../src/gpgmsg.cpp:1813 +#: src/gpgmsg.cpp:1813 msgid "Encryption" msgstr "Kryptering" -#: ../src/gpgmsg.cpp:1856 +#: src/gpgmsg.cpp:1856 msgid "Encryption Failure" msgstr "Kryptering misslyckades" -#: ../src/gpgmsg.cpp:1910 -#: ../src/gpgmsg.cpp:3276 +#: src/gpgmsg.cpp:1910 src/gpgmsg.cpp:3276 msgid "Attachment Encryption Failure" msgstr "Kryptering av bilaga misslyckades" -#: ../src/gpgmsg.cpp:2683 +#: src/gpgmsg.cpp:2683 msgid "Attachment Verification Failure" msgstr "Validering av bilaga misslyckades" -#: ../src/gpgmsg.cpp:2866 -#: ../src/gpgmsg.cpp:2915 +#: src/gpgmsg.cpp:2866 src/gpgmsg.cpp:2915 msgid "Attachment Decryption Failure" msgstr "Dekryptering av bilaga misslyckades" -#: ../src/gpgmsg.cpp:3085 +#: src/gpgmsg.cpp:3085 msgid "Attachment Signing Failure" msgstr "Signering av bilaga misslyckades" -#: ../src/olflange-dlgs.cpp:183 +#: src/olflange-dlgs.cpp:183 msgid "The default key may not contain any spaces." msgstr "Standardnyckeln f?r inte inneh?lla n?gra blanksteg." -#: ../src/olflange.cpp:751 +#: src/olflange.cpp:751 msgid "" "This version of Outlook is too old!\n" "\n" -"At least versions of Outlook 2003 older than SP2 exhibit crashes when sending messages and messages might get stuck in the outgoing queue.\n" +"At least versions of Outlook 2003 older than SP2 exhibit crashes when " +"sending messages and messages might get stuck in the outgoing queue.\n" "\n" "Please update at least to SP2 before trying to send a message" msgstr "" "Den h?r versionen av Outlook ?r f?r gammal!\n" "\n" -"?tminstone versioner av Outlook 2003 ?ldre ?n SP2 kraschar n?r meddelanden skickas och meddelanden kan fastna i utg?ende postk?.\n" +"?tminstone versioner av Outlook 2003 ?ldre ?n SP2 kraschar n?r meddelanden " +"skickas och meddelanden kan fastna i utg?ende postk?.\n" "\n" "Uppdatera ?tminstone till SP2 innan du f?rs?ker skicka ett meddelande" # A bit unclear in the original text -#: ../src/olflange.cpp:947 +#: src/olflange.cpp:947 msgid "" "Sorry, we can only encrypt plain text messages and\n" "no RTF messages. Please make sure that only the text\n" @@ -307,73 +308,67 @@ "och inte RTF-meddelanden. Se till att endast textformatet\n" "har valts i inst?llningarna." -#: ../src/olflange.cpp:1337 +#: src/olflange.cpp:1337 msgid "&Decrypt and verify message" msgstr "&Dekryptera och validera meddelandet" -#: ../src/olflange.cpp:1375 +#: src/olflange.cpp:1375 msgid "GPG &encrypt message" msgstr "GPG-&kryptera meddelandet" -#: ../src/olflange.cpp:1381 +#: src/olflange.cpp:1381 msgid "GPG &sign message" msgstr "GPG-&signera meddelandet" -#: ../src/olflange.cpp:1427 +#: src/olflange.cpp:1427 msgid "GPG Key &Manager" msgstr "GPG-nyckel&hanterare" -#: ../src/olflange.cpp:1559 +#: src/olflange.cpp:1559 msgid "Could not start Key-Manager" msgstr "Kunde inte starta nyckelhanteraren" -#: ../src/olflange.cpp:1605 +#: src/olflange.cpp:1605 msgid "Decrypt and verify the message." msgstr "Dekryptera och validera meddelandet." -#: ../src/olflange.cpp:1613 +#: src/olflange.cpp:1613 msgid "Select this option to encrypt the message." msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." -#: ../src/olflange.cpp:1619 +#: src/olflange.cpp:1619 msgid "Select this option to sign the message." msgstr "V?lj det h?r alternativet f?r att signera meddelandet." -#: ../src/olflange.cpp:1628 -#: ../src/olflange.cpp:1689 -#: ../src/olflange.cpp:1771 +#: src/olflange.cpp:1628 src/olflange.cpp:1689 src/olflange.cpp:1771 msgid "Open GPG Key Manager" msgstr "?ppna GPG-nyckelhanteraren" -#: ../src/olflange.cpp:1658 -#: ../src/olflange.cpp:1722 +#: src/olflange.cpp:1658 src/olflange.cpp:1722 msgid "Decrypt message and verify signature" msgstr "Dekryptera meddelandet och validera signaturen" -#: ../src/olflange.cpp:1669 -#: ../src/olflange.cpp:1740 +#: src/olflange.cpp:1669 src/olflange.cpp:1740 msgid "Encrypt message with GPG" msgstr "Kryptera meddelandet med GPG" -#: ../src/olflange.cpp:1678 -#: ../src/olflange.cpp:1755 +#: src/olflange.cpp:1678 src/olflange.cpp:1755 msgid "Sign message with GPG" msgstr "Signera meddelandet med GPG" -#: ../src/passphrase-dialog.c:85 +#: src/passphrase-dialog.c:85 msgid "No key hint given." msgstr "Inget nyckeltips angivet." -#: ../src/passphrase-dialog.c:330 -#: ../src/passphrase-dialog.c:458 +#: src/passphrase-dialog.c:330 src/passphrase-dialog.c:458 msgid "Invalid passphrase; please try again..." msgstr "Ogiltig l?senfras; f?rs?k igen..." -#: ../src/passphrase-dialog.c:357 +#: src/passphrase-dialog.c:357 msgid "Select Signing Key" msgstr "V?lj signeringsnyckel" -#: ../src/pgpmime.c:485 +#: src/pgpmime.c:485 msgid "" "Error creating file\n" "Please select another one" @@ -381,109 +376,107 @@ "Fel vid skapande av fil\n" "V?lj en annan" -#: ../src/pgpmime.c:487 -#: ../src/pgpmime.c:638 +#: src/pgpmime.c:487 src/pgpmime.c:638 msgid "I/O-Error" msgstr "In-/Ut-fel" -#: ../src/pgpmime.c:637 +#: src/pgpmime.c:637 msgid "Error writing file" msgstr "Fel vid skrivning av fil" -#: ../src/pgpmime.c:713 +#: src/pgpmime.c:713 msgid "[PGP/MIME message]" msgstr "[PGP/MIME-meddelande]" -#: ../src/pgpmime.c:733 +#: src/pgpmime.c:733 msgid "[PGP/MIME message without plain text body]" msgstr "[PGP/MIME-meddelande utan vanlig meddelandetext]" -#: ../src/pgpmime.c:808 +#: src/pgpmime.c:808 msgid "[PGP/MIME signed message without a plain text body]" msgstr "[PGP/MIME-signerat meddelande utan vanlig meddelandetext]" -#: ../src/pgpmime.c:820 +#: src/pgpmime.c:820 msgid "[PGP/MIME signature]" msgstr "[PGP/MIME-signatur]" -#: ../src/recipient-dialog.c:89 +#: src/recipient-dialog.c:89 msgid "Name" msgstr "Namn" -#: ../src/recipient-dialog.c:94 +#: src/recipient-dialog.c:94 msgid "E-Mail" msgstr "E-post" -#: ../src/recipient-dialog.c:99 +#: src/recipient-dialog.c:99 msgid "Key-Info" msgstr "Nyckelinfo" -#: ../src/recipient-dialog.c:104 +#: src/recipient-dialog.c:104 msgid "Key ID" msgstr "Nyckel-id" -#: ../src/recipient-dialog.c:109 +#: src/recipient-dialog.c:109 msgid "Validity" msgstr "Giltighet" -#: ../src/recipient-dialog.c:425 +#: src/recipient-dialog.c:425 msgid "Please select at least one recipient key." msgstr "V?lj ?tminstone en mottagarnyckel." -#: ../src/recipient-dialog.c:426 +#: src/recipient-dialog.c:426 msgid "Recipient Dialog" msgstr "Mottagardialog" -#: ../src/verify-dialog.c:125 +#: src/verify-dialog.c:125 msgid "BAD signature!" msgstr "FELAKTIG signatur!" -#: ../src/verify-dialog.c:127 +#: src/verify-dialog.c:127 msgid "Good signature" msgstr "Korrekt signatur" -#: ../src/verify-dialog.c:129 +#: src/verify-dialog.c:129 msgid "Good signature from revoked key" msgstr "Korrekt signatur fr?n sp?rrad nyckel" -#: ../src/verify-dialog.c:131 +#: src/verify-dialog.c:131 msgid "Good signature from expired key" msgstr "Korrekt signatur fr?n utg?ngen nyckel" -#: ../src/verify-dialog.c:133 +#: src/verify-dialog.c:133 msgid "Good expired signature" msgstr "Korrekt utg?ngen signatur" -#: ../src/verify-dialog.c:136 +#: src/verify-dialog.c:136 msgid "Could not check signature: missing key" msgstr "Kunde inte kontrollera signaturen: saknar nyckel" -#: ../src/verify-dialog.c:140 +#: src/verify-dialog.c:140 msgid "Verification error" msgstr "Valideringsfel" -#: ../src/verify-dialog.c:157 +#: src/verify-dialog.c:157 msgid "User-ID not found" msgstr "Anv?ndaridentiteten hittades inte" -#: ../src/verify-dialog.c:169 +#: src/verify-dialog.c:169 msgid "This may be due to a wrong option setting" msgstr "Det h?r kan bero p? en felaktig inst?llning" -#: ../src/verify-dialog.c:175 +#: src/verify-dialog.c:175 #, c-format msgid "Signature expired on %s" msgstr "Signaturen gick ut den %s" -#: ../src/verify-dialog.c:187 +#: src/verify-dialog.c:187 msgid "Signature issued by a key we do NOT trust." msgstr "Signaturen utf?rdad av en nyckel som vi INTE litar p?." -#: ../src/verify-dialog.c:194 +#: src/verify-dialog.c:194 msgid "Signature issued by a non-valid key." msgstr "Signaturen utf?rdad av en icke-giltig nyckel." -#: ../src/verify-dialog.c:216 +#: src/verify-dialog.c:216 msgid "Verification Result" msgstr "Resultat fr?n validering" - Modified: branches/old-0.9-branch/src/ChangeLog =================================================================== --- branches/old-0.9-branch/src/ChangeLog 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/src/ChangeLog 2007-09-17 10:19:38 UTC (rev 180) @@ -1,3 +1,10 @@ +2007-09-17 Werner Koch + + * Makefile.am (gpgol_LDADD): Link with winsock2. + + * w32-gettext.c: Update some LANG_ constants to cope with a new + version of the mingw tool chain. + 2007-04-10 Werner Koch * display.cpp (find_message_window): Add arg LEVEL for debugging. Modified: branches/old-0.9-branch/src/Makefile.am =================================================================== --- branches/old-0.9-branch/src/Makefile.am 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/src/Makefile.am 2007-09-17 10:19:38 UTC (rev 180) @@ -70,7 +70,7 @@ gpgol_LDADD = $(srcdir)/gpgol.def \ -L . -lgpgme -lgpg-error -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \ - -loleaut32 + -loleaut32 -lws2_32 resource.o: resource.rc versioninfo.rc gpgol-rsrcs.rc olflange-rsrcs.rc Modified: branches/old-0.9-branch/src/olflange.cpp =================================================================== --- branches/old-0.9-branch/src/olflange.cpp 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/src/olflange.cpp 2007-09-17 10:19:38 UTC (rev 180) @@ -708,6 +708,7 @@ /* Check version. */ log_debug ("GPGol: this is %s\n", PACKAGE_STRING); + log_debug ("GPGol: using gpgme %s\n", gpgme_check_version (NULL)); pEECB->GetVersion (&lBuildVersion, EECBGV_GETBUILDVERSION); pEECB->GetVersion (&lActualVersion, EECBGV_GETACTUALVERSION); pEECB->GetVersion (&lVirtualVersion, EECBGV_GETVIRTUALVERSION); Modified: branches/old-0.9-branch/src/w32-gettext.c =================================================================== --- branches/old-0.9-branch/src/w32-gettext.c 2007-09-17 09:31:01 UTC (rev 179) +++ branches/old-0.9-branch/src/w32-gettext.c 2007-09-17 10:19:38 UTC (rev 180) @@ -1,6 +1,6 @@ /* w32-gettext.h - A simple gettext implementation for Windows targets. Copyright (C) 1995,1996,1997,1999,2005 Free Software Foundation, Inc. - Copyright (C) 2005 g10 Code GmbH + Copyright (C) 2005, 2007 g10 Code GmbH This file is part of libgpg-error. @@ -521,10 +521,10 @@ # define SUBLANG_AZERI_CYRILLIC 0x02 # endif # ifndef SUBLANG_BENGALI_INDIA -# define SUBLANG_BENGALI_INDIA 0x00 +# define SUBLANG_BENGALI_INDIA 0x01 # endif # ifndef SUBLANG_BENGALI_BANGLADESH -# define SUBLANG_BENGALI_BANGLADESH 0x01 +# define SUBLANG_BENGALI_BANGLADESH 0x02 # endif # ifndef SUBLANG_CHINESE_MACAU # define SUBLANG_CHINESE_MACAU 0x05 @@ -617,17 +617,11 @@ # define SUBLANG_NEPALI_INDIA 0x02 # endif # ifndef SUBLANG_PUNJABI_INDIA -# define SUBLANG_PUNJABI_INDIA 0x00 +# define SUBLANG_PUNJABI_INDIA 0x01 # endif -# ifndef SUBLANG_PUNJABI_PAKISTAN -# define SUBLANG_PUNJABI_PAKISTAN 0x01 -# endif # ifndef SUBLANG_ROMANIAN_ROMANIA -# define SUBLANG_ROMANIAN_ROMANIA 0x00 +# define SUBLANG_ROMANIAN_ROMANIA 0x01 # endif -# ifndef SUBLANG_ROMANIAN_MOLDOVA -# define SUBLANG_ROMANIAN_MOLDOVA 0x01 -# endif # ifndef SUBLANG_SERBIAN_LATIN # define SUBLANG_SERBIAN_LATIN 0x02 # endif @@ -1055,7 +1049,6 @@ switch (sub) { case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */ - case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */ } return "pa"; case LANG_RHAETO_ROMANCE: return "rm_CH"; @@ -1063,7 +1056,6 @@ switch (sub) { case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; - case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; } return "ro"; case LANG_RUSSIAN: From cvs at cvs.gnupg.org Mon Sep 17 12:21:21 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 12:21:21 +0200 Subject: [svn] gpgme - r1257 - in trunk: . gpgme Message-ID: Author: wk Date: 2007-09-17 12:21:20 +0200 (Mon, 17 Sep 2007) New Revision: 1257 Added: trunk/README.SVN Removed: trunk/README.CVS Modified: trunk/ChangeLog trunk/configure.ac trunk/gpgme/ChangeLog trunk/gpgme/gpgme.h trunk/gpgme/rungpg.c Log: Fixed a W32bug in rungpg.c Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/ChangeLog 2007-09-17 10:21:20 UTC (rev 1257) @@ -1,3 +1,7 @@ +2007-09-17 Werner Koch + + * configure.ac: Use the svn version magic. + 2007-09-07 Marcus Brinkmann * configure.ac: Check for C++, Qt and support --enable-w32-qt. Deleted: trunk/README.CVS Added: trunk/README.SVN =================================================================== --- trunk/README.SVN 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/README.SVN 2007-09-17 10:21:20 UTC (rev 1257) @@ -0,0 +1,51 @@ +If you are building from Subversion, run the script + +./autogen.sh + +first, to make sure that you have all the necessary maintainer tools +are installed and to build the actual configuration files. If you +have just updated from SVN, you should add the option "--force" to +autogen.sh so that meta data from SVN is noticed. Then run + +./configure --enable-maintainer-mode + +followed by the usual make. + +If autogen.sh complains about insufficient versions of the required +tools, or the tools are not installed, you may use environment +variables to override the default tool names: + + AUTOMAKE_SUFFIX is used as a suffix for all tools from the automake + package. For example + AUTOMAKE_SUFFIX="-1.7" ./autogen.sh + uses "automake-1.7" and "aclocal-1.7. + AUTOMAKE_PREFIX is used as a prefix for all tools from the automake + page and may be combined with AUTOMAKE_SUFFIX. e.g.: + AUTOMAKE_PREFIX=/usr/foo/bin ./autogen.sh + uses "automake" and "aclocal" in the /usr/foo/bin + directory. + AUTOCONF_SUFFIX is used as a suffix for all tools from the automake + package + AUTOCONF_PREFIX is used as a prefix for all tools from the automake + package + GETTEXT_SUFFIX is used as a suffix for all tools from the gettext + package + GETTEXT_PREFIX is used as a prefix for all tools from the gettext + package + +It is also possible to use the variable name AUTOMAKE, AUTOCONF, +ACLOCAL, AUTOHEADER, GETTEXT and MSGMERGE to directly specify the name +of the programs to run. It is however better to use the suffix and +prefix forms as described above because that does not require +knowledge about the actual tools used by autgen.sh. + + +Please don't use autopoint, libtoolize or autoreconf unless you are +the current maintainer and want to update the standard configuration +files. All those files should be in the SVN and only updated manually +if the maintainer decides that newer versions are required. The +maintainer should also make sure that the required version of automake +et al. are properly indicated at the top of configure.ac and take care +to copy the files and not merely use symlinks. + + Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/configure.ac 2007-09-17 10:21:20 UTC (rev 1257) @@ -23,25 +23,23 @@ min_automake_version="1.9.3" # Version number: Remember to change it immediately *after* a release. -# Make sure to run "svn up" before a "make dist". -# See below for the LT versions. +# Make sure to run "svn up" and "./autogen.sh --force" +# before a "make dist". See below for the LT versions. # -# The CVS version is usually the next intended release version with -# the string "-cvs" appended. The reason for this is that tests for a +# The SVN version is usually the next intended release version with +# the string "-svnNNN" appended. The reason for this is that tests for a # specific feature can already be done under the assumption that the -# CVS version is the most recent one in a branch. To disable the CVS -# version for the real release, just comment out the my_iscvs macro. -# Note, that we are now using Subversion instead of CVS and append the -# SVN revision number to the "cvs" suffix. To make this most useful -# for snapshot releases please do an "svn up" right before recreating -# the configure script, so that a proper revision number for all files -# is available when running a "make distcheck". +# SVN version is the most recent one in a branch. To disable the SVN +# version for the real release, set the my_issvn macro to no. m4_define(my_version, [1.1.5]) -m4_define(my_iscvs, yes) -AC_INIT([gpgme], my_version[]m4_ifdef([my_iscvs], [-cvs[]m4_translit( - [$Revision$],[Ra-z $:])]), - [bug-gpgme at gnupg.org]) +m4_define(my_issvn, [yes]) +m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ + || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')])) +AC_INIT([gpgme], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), + [bug-gpgme at gnupg.org]) + + # LT Version numbers, remember to change them just *before* a release. # (Code changed: REVISION++) # (Interfaces added/removed/changed: CURRENT++, REVISION=0) @@ -59,6 +57,7 @@ ############################################## +BUILD_REVISION=svn_revision PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION @@ -577,10 +576,6 @@ GNUPG_FIX_HDR_VERSION(gpgme/gpgme.h, GPGME_VERSION) # Generate values for the DLL version info -changequote(,)dnl -BUILD_REVISION="`echo '$Revision$' | sed 's/[^0-9]//g'`" -changequote([,])dnl -test -z "$BUILD_REVISION" && BUILD_REVISION="0" if test "$have_w32_system" = yes; then BUILD_TIMESTAMP=`date --iso-8601=minutes` changequote(,)dnl Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/gpgme/ChangeLog 2007-09-17 10:21:20 UTC (rev 1257) @@ -1,3 +1,8 @@ +2007-09-17 Werner Koch + + * rungpg.c (gpg_new): Make robust against undefined ttyname or + ttytype. + 2007-09-14 Werner Koch * data-mem.c (gpgme_data_release_and_get_mem): Fix tracing bug. Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/gpgme/gpgme.h 2007-09-17 10:21:20 UTC (rev 1257) @@ -73,7 +73,7 @@ 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.5-cvs1251" +#define GPGME_VERSION "1.1.5-svn1255" Modified: trunk/gpgme/rungpg.c =================================================================== --- trunk/gpgme/rungpg.c 2007-09-14 12:27:54 UTC (rev 1256) +++ trunk/gpgme/rungpg.c 2007-09-17 10:21:20 UTC (rev 1257) @@ -483,19 +483,27 @@ rc = gpg_error_from_errno (errno); else { - rc = add_arg (gpg, "--ttyname"); - if (!rc) - rc = add_arg (gpg, dft_ttyname); - if (!rc) + if (dft_ttyname) + { + rc = add_arg (gpg, "--ttyname"); + if (!rc) + rc = add_arg (gpg, dft_ttyname); + } + else + rc = 0; + if (!rc) { rc = _gpgme_getenv ("TERM", &dft_ttytype); if (rc) goto leave; + + if (dft_ttytype) + { + rc = add_arg (gpg, "--ttytype"); + if (!rc) + rc = add_arg (gpg, dft_ttytype); + } - rc = add_arg (gpg, "--ttytype"); - if (!rc) - rc = add_arg (gpg, dft_ttytype); - free (dft_ttytype); } } From cvs at cvs.gnupg.org Mon Sep 17 15:10:55 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 15:10:55 +0200 Subject: [svn] GpgOL - r181 - in trunk: . src Message-ID: Author: wk Date: 2007-09-17 15:10:54 +0200 (Mon, 17 Sep 2007) New Revision: 181 Modified: trunk/ChangeLog trunk/autogen.sh trunk/src/ChangeLog trunk/src/olflange.cpp Log: preparing 0.9.92 Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-17 10:19:38 UTC (rev 180) +++ trunk/ChangeLog 2007-09-17 13:10:54 UTC (rev 181) @@ -1,3 +1,7 @@ +2007-09-17 Werner Koch + + * autogen.sh (FORCE): Add --force option. + 2007-08-13 Marcus Brinkmann * configure.ac (svn_revision): Update to latest version from gnupg. Modified: trunk/autogen.sh =================================================================== --- trunk/autogen.sh 2007-09-17 10:19:38 UTC (rev 180) +++ trunk/autogen.sh 2007-09-17 13:10:54 UTC (rev 181) @@ -39,6 +39,11 @@ MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} DIE=no +FORCE= +if test x"$1" = x"--force"; then + FORCE=" --force" + shift +fi # ***** W32 build script ******* # Used to cross-compile for Windows. @@ -151,7 +156,7 @@ $AUTOHEADER echo "Running automake --gnu ..." $AUTOMAKE --gnu; -echo "Running autoconf..." -$AUTOCONF +echo "Running autoconf${FORCE} ..." +$AUTOCONF${FORCE} echo "You may now run \"./configure --enable-maintainer-mode && make\"." Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-17 10:19:38 UTC (rev 180) +++ trunk/src/ChangeLog 2007-09-17 13:10:54 UTC (rev 181) @@ -1,3 +1,7 @@ +2007-09-17 Werner Koch + + * olflange.cpp: Print gpgme version. + 2007-09-14 Werner Koch * engine-gpgme.c: Rewrote most of it. Modified: trunk/src/olflange.cpp =================================================================== --- trunk/src/olflange.cpp 2007-09-17 10:19:38 UTC (rev 180) +++ trunk/src/olflange.cpp 2007-09-17 13:10:54 UTC (rev 181) @@ -434,6 +434,7 @@ if (!version_shown) { version_shown = 1; + log_debug ("%s:%s: using gpgme %s\n", gpgme_check_version (NULL)); log_debug ("%s:%s: detected Outlook build version 0x%lx (%lu.%lu)\n", SRCNAME, __func__, lBuildVersion, (lBuildVersion & EECBGV_BUILDVERSION_MAJOR_MASK) >> 16, From cvs at cvs.gnupg.org Mon Sep 17 15:24:33 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 15:24:33 +0200 Subject: [svn] gpgme - r1258 - in trunk: . gpgme Message-ID: Author: wk Date: 2007-09-17 15:24:14 +0200 (Mon, 17 Sep 2007) New Revision: 1258 Modified: trunk/NEWS trunk/configure.ac trunk/gpgme/gpgme.h Log: Bumbed version number (still svn, though) Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-17 10:21:20 UTC (rev 1257) +++ trunk/NEWS 2007-09-17 13:24:14 UTC (rev 1258) @@ -1,6 +1,7 @@ Noteworthy changes in version 1.1.6 (unreleased) ------------------------------------------------ + * Bug fixes for for W32. * Interface changes relative to the 1.1.1 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-17 10:21:20 UTC (rev 1257) +++ trunk/configure.ac 2007-09-17 13:24:14 UTC (rev 1258) @@ -31,7 +31,7 @@ # specific feature can already be done under the assumption that the # SVN version is the most recent one in a branch. To disable the SVN # version for the real release, set the my_issvn macro to no. -m4_define(my_version, [1.1.5]) +m4_define(my_version, [1.1.6]) m4_define(my_issvn, [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-17 10:21:20 UTC (rev 1257) +++ trunk/gpgme/gpgme.h 2007-09-17 13:24:14 UTC (rev 1258) @@ -73,7 +73,7 @@ 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.5-svn1255" +#define GPGME_VERSION "1.1.6-svn1257" From cvs at cvs.gnupg.org Mon Sep 17 15:17:29 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 15:17:29 +0200 Subject: [svn] GpgOL - r183 - tags Message-ID: Author: wk Date: 2007-09-17 15:17:06 +0200 (Mon, 17 Sep 2007) New Revision: 183 Added: tags/gpgol-0.9.92/ Log: Release Copied: tags/gpgol-0.9.92 (from rev 182, branches/old-0.9-branch) From cvs at cvs.gnupg.org Mon Sep 17 15:13:30 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 17 Sep 2007 15:13:30 +0200 Subject: [svn] GpgOL - r182 - in branches/old-0.9-branch: . po Message-ID: Author: wk Date: 2007-09-17 15:13:29 +0200 (Mon, 17 Sep 2007) New Revision: 182 Modified: branches/old-0.9-branch/ChangeLog branches/old-0.9-branch/NEWS branches/old-0.9-branch/configure.ac branches/old-0.9-branch/po/de.po Log: preparing 0.9.92 Modified: branches/old-0.9-branch/ChangeLog =================================================================== --- branches/old-0.9-branch/ChangeLog 2007-09-17 13:10:54 UTC (rev 181) +++ branches/old-0.9-branch/ChangeLog 2007-09-17 13:13:29 UTC (rev 182) @@ -1,5 +1,9 @@ 2007-09-17 Werner Koch + Released 0.9.92. + + * po/de.po: Add missing translations. + * autogen.sh: Add --force option. 2006-12-13 Werner Koch Modified: branches/old-0.9-branch/NEWS =================================================================== --- branches/old-0.9-branch/NEWS 2007-09-17 13:10:54 UTC (rev 181) +++ branches/old-0.9-branch/NEWS 2007-09-17 13:13:29 UTC (rev 182) @@ -1,10 +1,15 @@ NOTE: This is the old branch of gpgol. To avoid conflicts with the -rewrite the version number shall never reach 0.10.0! +rewrite the version number shall never reach 0.10.0! There is enough +number space: The next number after 0.9.99 is 0.9.100 ;-) -Noteworthy changes for version 0.9.92 +Noteworthy changes for version 0.9.92 (2007-09-17) ================================================== +* Fixed a few minor problems. +* Localized key selection dialog. + + Noteworthy changes for version 0.9.91 (2006-10-13) ================================================== Modified: branches/old-0.9-branch/configure.ac =================================================================== --- branches/old-0.9-branch/configure.ac 2007-09-17 13:10:54 UTC (rev 181) +++ branches/old-0.9-branch/configure.ac 2007-09-17 13:13:29 UTC (rev 182) @@ -17,7 +17,7 @@ # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. m4_define([my_version], [0.9.92]) -m4_define([my_issvn], [yes]) +m4_define([my_issvn], [no]) m4_define([svn_revision], m4_esyscmd([echo -n $((svn info 2>/dev/null \ || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q}')])) Modified: branches/old-0.9-branch/po/de.po =================================================================== --- branches/old-0.9-branch/po/de.po 2007-09-17 13:10:54 UTC (rev 181) +++ branches/old-0.9-branch/po/de.po 2007-09-17 13:13:29 UTC (rev 182) @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: GPGol 0.9.4\n" +"Project-Id-Version: GPGol 0.9.92\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" "POT-Creation-Date: 2007-09-17 11:36+0200\n" -"PO-Revision-Date: 2006-04-24 16:41+0200\n" +"PO-Revision-Date: 2007-09-17 15:04+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -409,23 +409,23 @@ #: src/recipient-dialog.c:89 msgid "Name" -msgstr "" +msgstr "Name" #: src/recipient-dialog.c:94 msgid "E-Mail" -msgstr "" +msgstr "E-Mail" #: src/recipient-dialog.c:99 msgid "Key-Info" -msgstr "" +msgstr "Schl?ssel-Info" #: src/recipient-dialog.c:104 msgid "Key ID" -msgstr "" +msgstr "Schl?ssel-ID" #: src/recipient-dialog.c:109 msgid "Validity" -msgstr "" +msgstr "G?ltigkeit" #: src/recipient-dialog.c:425 msgid "Please select at least one recipient key." From cvs at cvs.gnupg.org Tue Sep 18 13:38:23 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 18 Sep 2007 13:38:23 +0200 Subject: [svn] pinentry - r168 - in trunk: . doc gtk+-2 pinentry Message-ID: Author: wk Date: 2007-09-18 13:38:21 +0200 (Tue, 18 Sep 2007) New Revision: 168 Modified: trunk/ChangeLog trunk/doc/pinentry.texi trunk/gtk+-2/pinentry-gtk-2.c trunk/pinentry/pinentry.c trunk/pinentry/pinentry.h Log: Add quality bar to the GTK-2 version. Doesn't look very pretty yet. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-07-09 07:36:40 UTC (rev 167) +++ trunk/ChangeLog 2007-09-18 11:38:21 UTC (rev 168) @@ -1,3 +1,11 @@ +2007-09-18 Werner Koch + + * pinentry/pinentry.h (struct pinentry): Add member QUALITY_BAR + and CTX_ASSUAN. + * pinentry/pinentry.c (cmd_setqualitybar): New. + (copy_and_escape): New. + (pinentry_inq_quality): New. + 2007-07-09 Werner Koch * doc/pinentry.texi: Fixed direntry syntax. Modified: trunk/doc/pinentry.texi =================================================================== --- trunk/doc/pinentry.texi 2007-07-09 07:36:40 UTC (rev 167) +++ trunk/doc/pinentry.texi 2007-09-18 11:38:21 UTC (rev 168) @@ -276,6 +276,18 @@ S: OK @end example + at item Enable a passphrase quality indicator +Adds a quality indicator to the GETPIN window. This indicator is +updated as the passphrase is typed. The clients needs to implement an +inquiry named "QUALITY" which gets passed the current passpharse +(percent-plus escaped) and should send back a string with a single +numerical vauelue between -100 and 100. Negative values will be +displayed in red. + at example + C: SETQUALITYBAR + S: OK + at end example + @item Ask for a PIN The meat of this tool is to ask for a passphrase of PIN, it is done with this command: Modified: trunk/gtk+-2/pinentry-gtk-2.c =================================================================== --- trunk/gtk+-2/pinentry-gtk-2.c 2007-07-09 07:36:40 UTC (rev 167) +++ trunk/gtk+-2/pinentry-gtk-2.c 2007-09-18 11:38:21 UTC (rev 168) @@ -1,6 +1,6 @@ /* pinentry-gtk-2.c Copyright (C) 1999 Robert Bihlmeyer - Copyright (C) 2001, 2002 g10 Code GmbH + Copyright (C) 2001, 2002, 2007 g10 Code GmbH Copyright (C) 2004 by Albrecht Dre? pinentry-gtk-2 is a pinentry application for the Gtk+-2 widget set. @@ -56,6 +56,7 @@ static int confirm_yes; static GtkWidget *entry; +static GtkWidget *qualitybar; static GtkWidget *insure; static GtkWidget *time_out; @@ -181,6 +182,49 @@ } +/* Handler called for "changed". We use it to update the quality + indicator. */ +static void +changed_text_handler (GtkWidget *widget) +{ + char textbuf[50]; + const char *s; + int length; + int percent; + GdkColor color = { 0, 0, 0, 0}; + + if (!qualitybar || !pinentry->quality_bar) + return; + + s = gtk_secure_entry_get_text (GTK_SECURE_ENTRY (widget)); + if (!s) + s = ""; + length = strlen (s); + percent = length? pinentry_inq_quality (pinentry, s, length) : 0; + if (!length) + { + *textbuf = 0; + color.red = 0xffff; + } + else if (percent < 0) + { + snprintf (textbuf, sizeof textbuf, "(%d%%)", -percent); + color.red = 0xffff; + percent = -percent; + } + else + { + snprintf (textbuf, sizeof textbuf, "%d%%", percent); + color.green = 0xffff; + } + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (qualitybar), + (double)percent/100.0); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), textbuf); + gtk_widget_modify_bg (qualitybar, GTK_STATE_PRELIGHT, &color); +} + + + static GtkWidget * create_window (int confirm_mode) { @@ -237,7 +281,7 @@ g_free (msg); gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); - gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0); } if (pinentry->error && !confirm_mode) { @@ -251,7 +295,17 @@ gtk_box_pack_start (GTK_BOX (box), w, TRUE, FALSE, 0); gtk_widget_modify_fg (w, GTK_STATE_NORMAL, &color); } - + + if (pinentry->quality_bar) + { + qualitybar = gtk_progress_bar_new(); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), "foo"); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (qualitybar), 0.0); + gtk_box_pack_start (GTK_BOX (box), qualitybar, TRUE, FALSE, 0); + } + else + qualitybar = NULL; + ebox = gtk_hbox_new (FALSE, HIG_SMALL); gtk_box_pack_start (GTK_BOX(box), ebox, FALSE, FALSE, 0); @@ -264,10 +318,13 @@ g_free (msg); gtk_box_pack_start (GTK_BOX (ebox), w, FALSE, FALSE, 0); } + entry = gtk_secure_entry_new (); gtk_widget_set_size_request (entry, 200, -1); g_signal_connect (G_OBJECT (entry), "activate", G_CALLBACK (enter_callback), entry); + g_signal_connect (G_OBJECT (entry), "changed", + G_CALLBACK (changed_text_handler), entry); gtk_box_pack_start (GTK_BOX (ebox), entry, TRUE, TRUE, 0); gtk_widget_grab_focus (entry); gtk_widget_show (entry); Modified: trunk/pinentry/pinentry.c =================================================================== --- trunk/pinentry/pinentry.c 2007-07-09 07:36:40 UTC (rev 167) +++ trunk/pinentry/pinentry.c 2007-09-18 11:38:21 UTC (rev 168) @@ -1,5 +1,5 @@ /* pinentry.c - The PIN entry support library - Copyright (C) 2002, 2003 g10 Code GmbH + Copyright (C) 2002, 2003, 2007 g10 Code GmbH This file is part of PINENTRY. @@ -69,11 +69,13 @@ 0, /* Result. */ 0, /* Locale error flag. */ 0, /* One-button flag. */ + 0, /* Quality-Bar flag. */ PINENTRY_COLOR_DEFAULT, 0, PINENTRY_COLOR_DEFAULT, PINENTRY_COLOR_DEFAULT, - 0 + 0, + NULL /* Assuan context. */ }; @@ -208,6 +210,111 @@ } #endif + +/* Copy TEXT or TEXTLEN to BUFFER and escape as required. Return a + pointer to the end of the new buffer. Note that BUFFER must be + large enough to keep the entire text; allocataing it 3 times of + TEXTLEN is sufficient. */ +static char * +copy_and_escape (char *buffer, const void *text, size_t textlen) +{ + int i; + const unsigned char *s = (unsigned char *)text; + char *p = buffer; + + for (i=0; i < textlen; i++) + { + if (s[i] < ' ' || s[i] == '+') + { + snprintf (p, 4, "%%%02X", s[i]); + p += 3; + } + else if (s[i] == ' ') + *p++ = '+'; + else + *p++ = s[i]; + } + return p; +} + + + +/* Run a quality inquiry for PASSPHRASE of LENGTH. (We need LENGTH + because not all backends might be able to return a proper + C-string.). Returns: A value between -100 and 100 to give an + estimate of the passphrase's quality. Negative values are use if + the caller won't even accept that passphrase. Note that we expect + just one data line which should not be escaped in any represent a + numeric signed decimal value. Extra data is currently ignored but + should not be send at all. */ +int +pinentry_inq_quality (pinentry_t pin, const char *passphrase, size_t length) +{ + ASSUAN_CONTEXT ctx = pin->ctx_assuan; + const char prefix[] = "INQUIRE QUALITY "; + char *command; + char *line; + size_t linelen; + int gotvalue = 0; + int value = 0; + int rc; + + if (!ctx) + return 0; /* Can't run the callback. */ + + if (length > 300) + length = 300; /* Limit so that it definitely fits into an Assuan + line. */ + + command = secmem_malloc (strlen (prefix) + 3*length + 1); + if (!command) + return 0; + strcpy (command, prefix); + copy_and_escape (command + strlen(command), passphrase, length); + rc = assuan_write_line (ctx, command); + secmem_free (command); + if (rc) + { + fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc); + return 0; + } + + for (;;) + { + do + { + rc = assuan_read_line (ctx, &line, &linelen); + if (rc) + { + fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc); + return 0; + } + } + 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' + && (!line[3] || line[3] == ' ')) + break; /* CAN command received*/ + if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' + && (!line[3] || line[3] == ' ')) + break; /* ERR command received*/ + if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue) + continue; + gotvalue = 1; + value = atoi (line+2); + } + if (value < -100) + value = -100; + else if (value > 100) + value = 100; + + return value; +} + + + /* Try to make room for at least LEN bytes in the pinentry. Returns new buffer on success and 0 on failure or when the old buffer is sufficient. */ @@ -638,7 +745,16 @@ } + static int +cmd_setqualitybar (ASSUAN_CONTEXT ctx, char *line) +{ + pinentry.quality_bar = 1; + return 0; +} + + +static int cmd_getpin (ASSUAN_CONTEXT ctx, char *line) { int result; @@ -654,8 +770,9 @@ } pinentry.locale_err = 0; pinentry.one_button = 0; - + pinentry.ctx_assuan = ctx; result = (*pinentry_cmd_handler) (&pinentry); + pinentry.ctx_assuan = NULL; if (pinentry.error) { free (pinentry.error); @@ -664,6 +781,8 @@ if (set_prompt) pinentry.prompt = NULL; + pinentry.quality_bar = 0; /* Reset it after the command. */ + if (result < 0) { if (pinentry.pin) @@ -704,6 +823,7 @@ int result; pinentry.one_button = !!strstr (line, "--one-button"); + pinentry.quality_bar = 0; pinentry.locale_err = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) @@ -726,6 +846,7 @@ int result; pinentry.one_button = 1; + pinentry.quality_bar = 0; pinentry.locale_err = 0; result = (*pinentry_cmd_handler) (&pinentry); if (pinentry.error) @@ -759,6 +880,7 @@ { "GETPIN", 0, cmd_getpin }, { "CONFIRM", 0, cmd_confirm }, { "MESSAGE", 0, cmd_message }, + { "SETQUALITYBAR", 0, cmd_setqualitybar }, { NULL } }; int i, j, rc; Modified: trunk/pinentry/pinentry.h =================================================================== --- trunk/pinentry/pinentry.h 2007-07-09 07:36:40 UTC (rev 167) +++ trunk/pinentry/pinentry.h 2007-09-18 11:38:21 UTC (rev 168) @@ -91,12 +91,21 @@ dismiss button is required. */ int one_button; + /* If this is set, a passphrase quality indicator is shown. There + will also be an inquiry back to the caller to get an indication + of the quality for the passphrase entered so far. */ + int quality_bar; + /* For the curses pinentry, the color of error messages. */ pinentry_color_t color_fg; int color_fg_bright; pinentry_color_t color_bg; pinentry_color_t color_so; int color_so_bright; + + /* Fo the quality indicator we need to do an inquiry. Thus we need + to save the assuan ctx. */ + void *ctx_assuan; }; typedef struct pinentry *pinentry_t; @@ -124,6 +133,11 @@ Return NULL on error. */ char *pinentry_local_to_utf8 (char *lc_ctype, char *text, int secure); + +/* Run a quality inquiry for PASSPHRASE of LENGTH. */ +int pinentry_inq_quality (pinentry_t pin, + const char *passphrase, size_t length); + /* Try to make room for at least LEN bytes for the pin in the pinentry PIN. Returns new buffer on success and 0 on failure. */ char *pinentry_setbufferlen (pinentry_t pin, int len); From cvs at cvs.gnupg.org Tue Sep 18 13:40:11 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 18 Sep 2007 13:40:11 +0200 Subject: [svn] GnuPG - r4586 - trunk/agent Message-ID: Author: wk Date: 2007-09-18 13:40:09 +0200 (Tue, 18 Sep 2007) New Revision: 4586 Modified: trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/call-pinentry.c trunk/agent/command.c trunk/agent/genkey.c Log: Support the SETQUALITYBAR command of recent pinentries. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-09-14 17:23:34 UTC (rev 4585) +++ trunk/agent/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) @@ -1,3 +1,14 @@ +2007-09-18 Werner Koch + + * agent.h (struct pin_entry_info_s): Add element WITH_QUALITYBAR. + * genkey.c (check_passphrase_constraints): New arg SILENT. + Changed all callers. + (agent_protect_and_store, agent_genkey): Enable qualitybar. + * call-pinentry.c (agent_askpin): Send that option. + (unescape_passphrase_string): New. + (inq_quality): New. + (estimate_passphrase_quality): New. + 2007-09-14 Marcus Brinkmann * call-pinentry.c (agent_popup_message_stop): Implement kill for Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2007-09-14 17:23:34 UTC (rev 4585) +++ trunk/agent/agent.h 2007-09-18 11:40:09 UTC (rev 4586) @@ -169,6 +169,7 @@ int max_digits; /* max. number of allowed digits allowed*/ int max_tries; int failed_tries; + int with_qualitybar; /* Set if the quality bar should be displayed. */ int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */ void *check_cb_arg; /* optional argument which might be of use in the CB */ const char *cb_errtext; /* used by the cb to displaye a specific error */ @@ -269,7 +270,7 @@ membuf_t *outbuf); /*-- genkey.c --*/ -int check_passphrase_constraints (ctrl_t ctrl, const char *pw); +int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent); int agent_genkey (ctrl_t ctrl, const char *keyparam, size_t keyparmlen, membuf_t *outbuf); int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey); Modified: trunk/agent/call-pinentry.c =================================================================== --- trunk/agent/call-pinentry.c 2007-09-14 17:23:34 UTC (rev 4585) +++ trunk/agent/call-pinentry.c 2007-09-18 11:40:09 UTC (rev 4586) @@ -413,6 +413,106 @@ } +/* Return a new malloced string by unescaping the string S. Escaping + is percent escaping and '+'/space mapping. A binary Nul will + silently be replaced by a 0xFF. Function returns NULL to indicate + an out of memory status. PArsing stops at the end of the string or + a white space character. */ +static char * +unescape_passphrase_string (const unsigned char *s) +{ + char *buffer, *d; + + buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1); + if (!buffer) + return NULL; + while (*s && !spacep (s)) + { + if (*s == '%' && s[1] && s[2]) + { + s++; + *d = xtoi_2 (s); + if (!*d) + *d = '\xff'; + d++; + s += 2; + } + else if (*s == '+') + { + *d++ = ' '; + s++; + } + else + *d++ = *s++; + } + *d = 0; + return buffer; +} + + +/* Estimate the quality of the passphrase PW and return a value in the + range 0..100. */ +static int +estimate_passphrase_quality (const char *pw) +{ + int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3; + int length; + const char *s; + + if (goodlength < 1) + return 0; + + for (length = 0, s = pw; *s; s++) + if (!spacep (s)) + length ++; + + if (length > goodlength) + return 100; + return ((length*10) / goodlength)*10; +} + + +/* Handle the QUALITY inquiry. */ +static int +inq_quality (void *opaque, const char *line) +{ + assuan_context_t ctx = opaque; + char *pin; + int rc; + int percent; + char numbuf[20]; + + if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7])) + { + line += 7; + while (*line == ' ') + line++; + + pin = unescape_passphrase_string (line); + if (!pin) + rc = gpg_error_from_syserror (); + else + { + percent = estimate_passphrase_quality (pin); + if (check_passphrase_constraints (NULL, pin, 1)) + percent = -percent; + snprintf (numbuf, sizeof numbuf, "%d", percent); + rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); + xfree (pin); + } + } + else + { + log_error ("unsupported inquiry `%s' from pinentry\n", line); + rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE); + } + + return rc; +} + + + + /* Call the Entry and ask for the PIN. We do check for a valid PIN number here and repeat it as long as we have invalid formed @@ -463,6 +563,16 @@ if (rc) return unlock_pinentry (rc); + /* If a passphrase quality indicator has been requested and a + minimum passphrase length has not been disabled, send the command + to the pinentry. */ + if (pininfo->with_qualitybar && opt.min_passphrase_len ) + { + rc = assuan_transact (entry_ctx, "SETQUALITYBAR", + NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return unlock_pinentry (rc); + } if (initial_errtext) { @@ -497,7 +607,7 @@ } rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, - NULL, NULL, NULL, NULL); + inq_quality, entry_ctx, NULL, NULL); /* Most pinentries out in the wild return the old Assuan error code for canceled which gets translated to an assuan Cancel error and not to the code for a user cancel. Fix this here. */ Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2007-09-14 17:23:34 UTC (rev 4585) +++ trunk/agent/command.c 2007-09-18 11:40:09 UTC (rev 4586) @@ -912,7 +912,7 @@ } while (!rc && opt_check - && check_passphrase_constraints (ctrl, response)); + && check_passphrase_constraints (ctrl, response, 0)); if (!rc) { Modified: trunk/agent/genkey.c =================================================================== --- trunk/agent/genkey.c 2007-09-14 17:23:34 UTC (rev 4585) +++ trunk/agent/genkey.c 2007-09-18 11:40:09 UTC (rev 4586) @@ -168,9 +168,10 @@ /* Check whether the passphrase PW is suitable. Returns 0 if the passphrase is suitable and true if it is not and the user should be - asked to provide a different one. */ + asked to provide a different one. If SILENT is set, no message are + displayed. */ int -check_passphrase_constraints (ctrl_t ctrl, const char *pw) +check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent) { gpg_error_t err; unsigned int minlen = opt.min_passphrase_len; @@ -181,7 +182,12 @@ if (utf8_charcount (pw) < minlen ) { - char *desc = xtryasprintf + char *desc; + + if (silent) + return gpg_error (GPG_ERR_INV_PASSPHRASE); + + desc = xtryasprintf ( ngettext ("Warning: You have entered a passphrase that%%0A" "is obviously not secure. A passphrase should%%0A" "be at least %u character long.", @@ -198,7 +204,12 @@ if (nonalpha_count (pw) < minnonalpha ) { - char *desc = xtryasprintf + char *desc; + + if (silent) + return gpg_error (GPG_ERR_INV_PASSPHRASE); + + desc = xtryasprintf ( ngettext ("Warning: You have entered a passphrase that%%0A" "is obviously not secure. A passphrase should%%0A" "contain at least %u digit or special character.", @@ -226,6 +237,9 @@ "is obviously not secure. A passphrase may not%0A" "be a known term or match certain pattern."); + if (silent) + return gpg_error (GPG_ERR_INV_PASSPHRASE); + err = take_this_one_anyway (ctrl, desc); if (err) return err; @@ -242,6 +256,9 @@ "Please confirm that you do not want to " "have any protection on your key.")); + if (silent) + return gpg_error (GPG_ERR_INV_PASSPHRASE); + err = take_this_one_anyway2 (ctrl, desc, _("Yes, protection is not needed")); if (err) @@ -296,6 +313,7 @@ pi2 = pi + (sizeof *pi + 100); pi->max_length = 100; pi->max_tries = 3; + pi->with_qualitybar = 1; pi2->max_length = 100; pi2->max_tries = 3; pi2->check_cb = reenter_compare_cb; @@ -306,7 +324,7 @@ initial_errtext = NULL; if (!rc) { - if (check_passphrase_constraints (ctrl, pi->pin)) + if (check_passphrase_constraints (ctrl, pi->pin, 0)) { pi->failed_tries = 0; pi2->failed_tries = 0; @@ -417,6 +435,7 @@ pi2 = pi + (sizeof *pi + 100); pi->max_length = 100; pi->max_tries = 3; + pi->with_qualitybar = 1; pi2->max_length = 100; pi2->max_tries = 3; pi2->check_cb = reenter_compare_cb; @@ -427,7 +446,7 @@ initial_errtext = NULL; if (!rc) { - if (check_passphrase_constraints (ctrl, pi->pin)) + if (check_passphrase_constraints (ctrl, pi->pin, 0)) { pi->failed_tries = 0; pi2->failed_tries = 0; From cvs at cvs.gnupg.org Tue Sep 18 19:45:39 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 18 Sep 2007 19:45:39 +0200 Subject: [svn] pinentry - r169 - in trunk: . qt Message-ID: Author: wk Date: 2007-09-18 19:45:38 +0200 (Tue, 18 Sep 2007) New Revision: 169 Modified: trunk/ChangeLog trunk/NEWS trunk/qt/main.cpp trunk/qt/pinentrydialog.cpp trunk/qt/pinentrydialog.h trunk/qt/secqlineedit.cpp trunk/qt/secqlineedit.h Log: Implemented quality bar for QT. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/ChangeLog 2007-09-18 17:45:38 UTC (rev 169) @@ -1,5 +1,12 @@ 2007-09-18 Werner Koch + * qt/secqlineedit.h (SecQLineEdit): New signal textModified. + * qt/secqlineedit.cpp (finishChange): Emit it. + * qt/pinentrydialog.cpp (setPinentryInfo): New. + (PinEntryDialog): Add arg ENABLE_QUALITY_BAR. + * qt/pinentrydialog.h (setPinentryInfo): New. + (PinEntryDialog): Add arg ENABLE_QUALITY_BAR. + * pinentry/pinentry.h (struct pinentry): Add member QUALITY_BAR and CTX_ASSUAN. * pinentry/pinentry.c (cmd_setqualitybar): New. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/NEWS 2007-09-18 17:45:38 UTC (rev 169) @@ -1,7 +1,10 @@ Noteworthy changes in version 0.7.4 ------------------------------------------------ +* Pinentry-gtk-2 and pinentry-qt now support a simple passphrase + quality indicator. + Noteworthy changes in version 0.7.3 (2007-07-06) ------------------------------------------------ Modified: trunk/qt/main.cpp =================================================================== --- trunk/qt/main.cpp 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/qt/main.cpp 2007-09-18 17:45:38 UTC (rev 169) @@ -68,8 +68,9 @@ if (pe->parent_wid) parent = new ForeignWidget (pe->parent_wid); - PinEntryDialog pinentry (parent, 0, true); + PinEntryDialog pinentry (parent, NULL, true, !!pe->quality_bar); + pinentry.setPinentryInfo (pe); pinentry.setPrompt (QString::fromUtf8 (pe->prompt)); pinentry.setDescription (QString::fromUtf8 (pe->description)); /* If we reuse the same dialog window. */ Modified: trunk/qt/pinentrydialog.cpp =================================================================== --- trunk/qt/pinentrydialog.cpp 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/qt/pinentrydialog.cpp 2007-09-18 17:45:38 UTC (rev 169) @@ -1,5 +1,6 @@ /* pinentrydialog.cpp - A secure KDE dialog for PIN entry. Copyright (C) 2002 Klar?lvdalens Datakonsult AB + Copyright (C) 2007 g10 Code GmbH Written by Steffen Hansen . This program is free software; you can redistribute it and/or @@ -17,16 +18,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ + #include #include #include #include +#include #include "secqlineedit.h" #include "pinentrydialog.h" +#include "pinentry.h" -PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, bool modal ) +PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, + bool modal, bool enable_quality_bar ) : QDialog( parent, name, modal ), _grabbed( false ) { QBoxLayout* top = new QVBoxLayout( this, 6 ); @@ -41,6 +46,16 @@ _error = new QLabel( this ); labelLayout->addWidget( _error ); + if (enable_quality_bar) + { + _quality_bar = new QProgressBar (this); + _quality_bar->setCenterIndicator (true); + labelLayout->addWidget ( _quality_bar ); + _have_quality_bar = true; + } + else + _have_quality_bar = false; + _desc = new QLabel( this ); labelLayout->addWidget( _desc ); @@ -67,12 +82,12 @@ this, SIGNAL( accepted() ) ); connect( _cancel, SIGNAL( clicked() ), this, SIGNAL( rejected() ) ); - + connect( _edit, SIGNAL( textModified(const SecQString&) ), + this, SLOT( updateQuality(const SecQString&) ) ); connect (this, SIGNAL (accepted ()), this, SLOT (accept ())); connect (this, SIGNAL (rejected ()), this, SLOT (reject ())); - _edit->setFocus(); } @@ -103,6 +118,42 @@ QDialog::keyPressEvent( e ); } + +void PinEntryDialog::updateQuality( const SecQString & txt ) +{ + char *pin; + int length; + int percent; + QPalette pal; + + if (!_have_quality_bar || !_pinentry_info) + return; + pin = (char*)txt.utf8(); + length = strlen (pin); + percent = length? pinentry_inq_quality (_pinentry_info, pin, length) : 0; + ::secmem_free (pin); + if (!length) + { + _quality_bar->reset (); + } + else + { + pal = _quality_bar->palette (); + if (percent < 0) + { + pal.setColor (QColorGroup::Highlight, QColor("red")); + percent = -percent; + } + else + { + pal.setColor (QColorGroup::Highlight, QColor("green")); + } + _quality_bar->setPalette (pal); + _quality_bar->setProgress (percent); + } +} + + void PinEntryDialog::setDescription( const QString& txt ) { _desc->setText( txt ); @@ -117,7 +168,8 @@ void PinEntryDialog::setError( const QString& txt ) { - if( !txt.isNull() )_icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Critical ) ); + if ( !txt.isNull() ) + _icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Critical ) ); _error->setText( txt ); } @@ -155,3 +207,9 @@ { _cancel->setText( txt ); } + + +void PinEntryDialog::setPinentryInfo (pinentry_t peinfo ) +{ + _pinentry_info = peinfo; +} Modified: trunk/qt/pinentrydialog.h =================================================================== --- trunk/qt/pinentrydialog.h 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/qt/pinentrydialog.h 2007-09-18 17:45:38 UTC (rev 169) @@ -21,9 +21,11 @@ #define __PINENTRYDIALOG_H__ #include +#include "pinentry.h" class QLabel; class QPushButton; +class QProgressBar; class SecQLineEdit; class SecQString; @@ -36,7 +38,8 @@ Q_PROPERTY( QString prompt READ prompt WRITE setPrompt ) public: friend class PinEntryController; // TODO: remove when assuan lets me use Qt eventloop. - PinEntryDialog( QWidget* parent = 0, const char* name = 0, bool modal = false ); + PinEntryDialog( QWidget* parent = 0, const char* name = 0, + bool modal = false, bool enable_quality_bar = false ); void setDescription( const QString& ); QString description() const; @@ -53,6 +56,11 @@ void setOkText( const QString& ); void setCancelText( const QString& ); + void setPinentryInfo (pinentry_t); + +public slots: + void updateQuality(const SecQString &); + signals: void accepted(); void rejected(); @@ -67,10 +75,13 @@ QLabel* _desc; QLabel* _error; QLabel* _prompt; + QProgressBar* _quality_bar; SecQLineEdit* _edit; QPushButton* _ok; QPushButton* _cancel; bool _grabbed; + bool _have_quality_bar; + pinentry_t _pinentry_info; }; Modified: trunk/qt/secqlineedit.cpp =================================================================== --- trunk/qt/secqlineedit.cpp 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/qt/secqlineedit.cpp 2007-09-18 17:45:38 UTC (rev 169) @@ -288,6 +288,9 @@ the Return or Enter key is pressed the returnPressed() signal is emitted. + When the text changes the textModified() signal is emitted in all + cases. + By default, SecQLineEdits have a frame as specified by the Windows and Motif style guides; you can turn it off by calling setFrame(FALSE). @@ -1845,6 +1848,7 @@ textDirty = FALSE; emit q->textChanged( text ); } + emit q->textModified( text ); #if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( q, 0, QAccessible::ValueChanged ); #endif Modified: trunk/qt/secqlineedit.h =================================================================== --- trunk/qt/secqlineedit.h 2007-09-18 11:38:21 UTC (rev 168) +++ trunk/qt/secqlineedit.h 2007-09-18 17:45:38 UTC (rev 169) @@ -184,6 +184,7 @@ signals: void textChanged( const SecQString &); + void textModified( const SecQString &); void returnPressed(); void lostFocus(); void selectionChanged(); From cvs at cvs.gnupg.org Tue Sep 18 19:52:39 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 18 Sep 2007 19:52:39 +0200 Subject: [svn] pinentry - r170 - trunk/gtk+-2 Message-ID: Author: wk Date: 2007-09-18 19:52:39 +0200 (Tue, 18 Sep 2007) New Revision: 170 Modified: trunk/gtk+-2/pinentry-gtk-2.c Log: Removed test code. Modified: trunk/gtk+-2/pinentry-gtk-2.c =================================================================== --- trunk/gtk+-2/pinentry-gtk-2.c 2007-09-18 17:45:38 UTC (rev 169) +++ trunk/gtk+-2/pinentry-gtk-2.c 2007-09-18 17:52:39 UTC (rev 170) @@ -299,7 +299,7 @@ if (pinentry->quality_bar) { qualitybar = gtk_progress_bar_new(); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), "foo"); + gtk_progress_bar_set_text (GTK_PROGRESS_BAR (qualitybar), ""); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (qualitybar), 0.0); gtk_box_pack_start (GTK_BOX (box), qualitybar, TRUE, FALSE, 0); } From cvs at cvs.gnupg.org Fri Sep 21 16:02:57 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 21 Sep 2007 16:02:57 +0200 Subject: [svn] GpgOL - r185 - trunk/src Message-ID: Author: wk Date: 2007-09-21 16:02:48 +0200 (Fri, 21 Sep 2007) New Revision: 185 Modified: trunk/src/ChangeLog trunk/src/ext-commands.cpp trunk/src/item-events.cpp trunk/src/item-events.h trunk/src/mapihelp.cpp trunk/src/mapihelp.h trunk/src/message-events.cpp trunk/src/message-events.h trunk/src/message.cpp trunk/src/message.h trunk/src/mimemaker.c trunk/src/mimeparser.c trunk/src/olflange.cpp trunk/src/user-events.cpp Log: Cleanups and played with ietm infos. An ECF file is now required. Extra/Show crypt Info shows the structure of the message. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/ChangeLog 2007-09-21 14:02:48 UTC (rev 185) @@ -1,3 +1,15 @@ +2007-09-21 Werner Koch + + * mimeparser.c (build_mimeinfo): New. + (finish_message): Store the mime structure. + * mapihelp.cpp (mapi_get_message_class): New. + (mapi_get_sig_status): New. + (get_gpgolprotectiv_tag, get_gpgolsigstatus_tag) + (get_gpgolattachtype_tag): Factored code out to ... + (create_gpgol_tag): .. New. + (get_gpgolmimeinfo_tag): New. + (mapi_get_mime_info): New. + 2007-09-20 Werner Koch * user-events.cpp, user-events.h: New. Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/ext-commands.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -412,8 +412,9 @@ if (FAILED (pEECB->GetWindow (&hWnd))) hWnd = NULL; - log_debug ("%s:%s: commandID=%u (%#x) hwnd=%p\n", - SRCNAME, __func__, nCommandID, nCommandID, hWnd); + log_debug ("%s:%s: commandID=%u (%#x) context=%s hwnd=%p\n", + SRCNAME, __func__, nCommandID, nCommandID, + ext_context_name (m_lContext), hWnd); if (nCommandID == SC_CLOSE && m_lContext == EECONTEXT_READNOTEMESSAGE) { @@ -470,34 +471,37 @@ log_debug ("%s:%s: command Forward called\n", SRCNAME, __func__); return S_FALSE; /* Pass it on. */ } - else if (nCommandID == m_nCmdEncrypt + else if (nCommandID == m_nCmdDecrypt && m_lContext == EECONTEXT_READNOTEMESSAGE) { hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message); if (SUCCEEDED (hr)) { -// GpgMsg *m = CreateGpgMsg (message); -// m->setExchangeCallback ((void*)pEECB); -// m->decrypt (hWnd, 0); -// delete m; + message_decrypt (message, m_pExchExt->getMsgtype (pEECB), 1); } ul_release (message); ul_release (mdb); } - else if (nCommandID == m_nCmdShowInfo + else if (nCommandID == m_nCmdCheckSig && m_lContext == EECONTEXT_READNOTEMESSAGE) { - MessageBox (NULL, - _("Here you should see crypto related info"), - "GpgOL", MB_ICONINFORMATION|MB_OK); + hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message); + if (SUCCEEDED (hr)) + { + message_verify (message, m_pExchExt->getMsgtype (pEECB), 1); + } + else + log_debug_w32 (hr, "%s:%s: CmdCheckSig failed", SRCNAME, __func__); + ul_release (message); + ul_release (mdb); } - else if (nCommandID == m_nCmdCheckSig + else if (nCommandID == m_nCmdShowInfo && m_lContext == EECONTEXT_READNOTEMESSAGE) { hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message); if (SUCCEEDED (hr)) { - message_verify (message, m_pExchExt->getMsgtype (pEECB), 1); + message_show_info (message, hWnd); } ul_release (message); ul_release (mdb); Modified: trunk/src/item-events.cpp =================================================================== --- trunk/src/item-events.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/item-events.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -30,6 +30,9 @@ #include "common.h" #include "olflange-def.h" #include "olflange.h" +#include "message.h" +#include "mapihelp.h" +#include "display.h" #include "item-events.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ @@ -37,12 +40,29 @@ } while (0) +/* Wrapper around UlRelease with error checking. */ +/* FIXME: Duplicated code. */ +static void +ul_release (LPVOID punk) +{ + ULONG res; + + if (!punk) + return; + res = UlRelease (punk); +// log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res); +} + + + /* Our constructor. */ GpgolItemEvents::GpgolItemEvents (GpgolExt *pParentInterface) { m_pExchExt = pParentInterface; m_ref = 0; + m_processed = false; + m_wasencrypted = false; } @@ -76,9 +96,20 @@ displayed. */ STDMETHODIMP -GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK peecb) +GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK eecb) { - log_debug ("%s:%s: received", SRCNAME, __func__); + LPMDB mdb = NULL; + LPMESSAGE message = NULL; + + log_debug ("%s:%s: received\n", SRCNAME, __func__); + + m_wasencrypted = false; + eecb->GetObject (&mdb, (LPMAPIPROP *)&message); + if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb))) + m_processed = TRUE; + ul_release (message); + ul_release (mdb); + return S_FALSE; } @@ -99,9 +130,22 @@ The same return values as for OnOpen may be used.. */ STDMETHODIMP -GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK peecb, ULONG flags) +GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK eecb, ULONG flags) { log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags); + + /* If the message has been processed by is (i.e. in OnOpen), we now + use our own display code. */ + if (!flags && m_processed) + { + HWND hwnd = NULL; + + if (FAILED (eecb->GetWindow (&hwnd))) + hwnd = NULL; + if (message_display_handler (eecb, hwnd)) + m_wasencrypted = true; + } + return S_FALSE; } @@ -114,9 +158,10 @@ E_ABORT - Abort the close operation and don't dismiss the window. */ STDMETHODIMP -GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK peecb, ULONG save_options) +GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK eecb, ULONG save_options) { log_debug ("%s:%s: received, options=%#lx", SRCNAME, __func__, save_options); + return S_FALSE; } @@ -124,8 +169,61 @@ /* This is the corresponding Complete method for OnClose. See OnOpenComplete for a description. */ STDMETHODIMP -GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK peecb, ULONG flags) +GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK eecb, ULONG flags) { log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags); + + if (m_wasencrypted) + { + /* Delete any body parts so that encrypted stuff won't show up + in the clear. */ + HRESULT hr; + LPMESSAGE message = NULL; + LPMDB mdb = NULL; + + log_debug ("%s:%s: deleting body properties", SRCNAME, __func__); + hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message); + if (SUCCEEDED (hr)) + { + SPropTagArray proparray; + int anyokay = 0; + + proparray.cValues = 1; + proparray.aulPropTag[0] = PR_BODY; + hr = message->DeleteProps (&proparray, NULL); + if (hr) + log_debug_w32 (hr, "%s:%s: deleting PR_BODY failed", + SRCNAME, __func__); + else + anyokay++; + + proparray.cValues = 1; + proparray.aulPropTag[0] = PR_BODY_HTML; + message->DeleteProps (&proparray, NULL); + if (hr) + log_debug_w32 (hr, "%s:%s: deleting PR_BODY_HTML failed", + SRCNAME, __func__); + else + anyokay++; + + if (anyokay) + { + hr = message->SaveChanges (KEEP_OPEN_READWRITE); + if (hr) + log_error_w32 (hr, "%s:%s: SaveChanges failed", + SRCNAME, __func__); + } + + m_wasencrypted = false; + + } + else + log_debug_w32 (hr, "%s:%s: error getting message", + SRCNAME, __func__); + + ul_release (message); + ul_release (mdb); + } + return S_FALSE; } Modified: trunk/src/item-events.h =================================================================== --- trunk/src/item-events.h 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/item-events.h 2007-09-21 14:02:48 UTC (rev 185) @@ -38,6 +38,8 @@ private: GpgolExt *m_pExchExt; ULONG m_ref; + bool m_processed; /* The message has been porcessed by us. */ + bool m_wasencrypted; /* The original message was encrypted. */ public: STDMETHODIMP QueryInterface (REFIID riid, LPVOID FAR *ppvObj); Modified: trunk/src/mapihelp.cpp =================================================================== --- trunk/src/mapihelp.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/mapihelp.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -94,9 +94,9 @@ } -/* Return the property tag for GpgOL Attach Type. */ -int -get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag) +/* Helper to create a named property. */ +static ULONG +create_gpgol_tag (LPMESSAGE message, wchar_t *name, const char *func) { HRESULT hr; LPSPropTagArray proparr = NULL; @@ -108,17 +108,28 @@ memset (&mnid, 0, sizeof mnid); mnid.lpguid = &guid; mnid.ulKind = MNID_STRING; - mnid.Kind.lpwstrName = L"GpgOL Attach Type"; + mnid.Kind.lpwstrName = name; pmnid = &mnid; hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr); - if (FAILED (hr)) + if (FAILED (hr) || !(proparr->aulPropTag[0] & 0xFFFF0000) ) { - log_error ("%s:%s: can't map %s property: hr=%#lx\n", - SRCNAME, __func__, "GpgOL Attach Type", hr); - return -1; + log_error ("%s:%s: can't map GpgOL property: hr=%#lx\n", + SRCNAME, func, hr); + return 0; } - *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_LONG); + return (proparr->aulPropTag[0] & 0xFFFF0000); +} + + + +/* Return the property tag for GpgOL Attach Type. */ +int +get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag) +{ + if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Attach Type", __func__))) + return -1; + *r_tag |= PT_LONG; return 0; } @@ -127,27 +138,9 @@ int get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag) { - HRESULT hr; - LPSPropTagArray proparr = NULL; - MAPINAMEID mnid, *pmnid; - /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties. */ - GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06, - 0x1b, 0x03, 0x10, 0x04}}; - - memset (&mnid, 0, sizeof mnid); - mnid.lpguid = &guid; - mnid.ulKind = MNID_STRING; - mnid.Kind.lpwstrName = L"GpgOL Sig Status"; - pmnid = &mnid; - hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr); - if (FAILED (hr)) - { - log_error ("%s:%s: can't map %s property: hr=%#lx\n", - SRCNAME, __func__, "GpgOL Sig Status", hr); - return -1; - } - - *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_STRING8); + if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Sig Status", __func__))) + return -1; + *r_tag |= PT_STRING8; return 0; } @@ -156,27 +149,20 @@ int get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag) { - HRESULT hr; - LPSPropTagArray proparr = NULL; - MAPINAMEID mnid, *pmnid; - /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties. */ - GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06, - 0x1b, 0x03, 0x10, 0x04}}; + if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Protect IV", __func__))) + return -1; + *r_tag |= PT_BINARY; + return 0; +} - memset (&mnid, 0, sizeof mnid); - mnid.lpguid = &guid; - mnid.ulKind = MNID_STRING; - mnid.Kind.lpwstrName = L"GpgOL Protect IV"; - pmnid = &mnid; - hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr); - if (FAILED (hr)) - { - log_error ("%s:%s: can't map %s property: hr=%#lx\n", - SRCNAME, __func__, "GpgOL Protect IV", hr); - return -1; - } - - *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_BINARY); + +/* Return the property tag for GpgOL MIME structure. */ +int +get_gpgolmimeinfo_tag (LPMESSAGE message, ULONG *r_tag) +{ + if (!(*r_tag = create_gpgol_tag (message, L"GpgOL MIME Info", __func__))) + return -1; + *r_tag |= PT_STRING8; return 0; } @@ -617,6 +603,40 @@ } +/* Return the message class. This function will never return NULL so + it is onlyuseful for debugging. Caller needs to releasse the + returned string. */ +char * +mapi_get_message_class (LPMESSAGE message) +{ + HRESULT hr; + LPSPropValue propval = NULL; + char *retstr; + + if (!message) + return xstrdup ("[No message]"); + + hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval); + if (FAILED (hr)) + { + log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n", + SRCNAME, __func__, hr); + return xstrdup (hr == MAPI_E_NOT_FOUND? + "[No message class property]": + "[Error getting message class property]"); + } + + if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 ) + retstr = xstrdup (propval->Value.lpszA); + else + retstr = xstrdup ("[Invalid message class property]"); + + MAPIFreeBuffer (propval); + return retstr; +} + + + /* Return the message type. This function knows only about our own message types. Returns MSGTYPE_UNKNOWN for any MESSAGE we have no special support for. */ @@ -1336,6 +1356,33 @@ } +/* Return the signature status as an allocated string. Will never + return NULL. */ +char * +mapi_get_sig_status (LPMESSAGE msg) +{ + HRESULT hr; + LPSPropValue propval = NULL; + ULONG tag; + char *retstr; + + if (get_gpgolsigstatus_tag (msg, &tag) ) + return xstrdup ("[Error getting tag for sig status]"); + hr = HrGetOneProp ((LPMAPIPROP)msg, tag, &propval); + if (FAILED (hr)) + return xstrdup (""); + if (PROP_TYPE (propval->ulPropTag) == PT_STRING8) + retstr = xstrdup (propval->Value.lpszA); + else + retstr = xstrdup ("[Sig status has an invalid type]"); + + MAPIFreeBuffer (propval); + return retstr; +} + + + + /* Set the signature status property to STATUS_STRING. There are a few special values: @@ -1369,6 +1416,33 @@ } +/* Return the MIME info as an allocated string. Will never return + NULL. */ +char * +mapi_get_mime_info (LPMESSAGE msg) +{ + HRESULT hr; + LPSPropValue propval = NULL; + ULONG tag; + char *retstr; + + if (get_gpgolmimeinfo_tag (msg, &tag) ) + return xstrdup ("[Error getting tag for MIME info]"); + hr = HrGetOneProp ((LPMAPIPROP)msg, tag, &propval); + if (FAILED (hr)) + return xstrdup (""); + if (PROP_TYPE (propval->ulPropTag) == PT_STRING8) + retstr = xstrdup (propval->Value.lpszA); + else + retstr = xstrdup ("[MIME info has an invalid type]"); + + MAPIFreeBuffer (propval); + return retstr; +} + + + + /* Helper for mapi_get_msg_content_type() */ static int get_message_content_type_cb (void *dummy_arg, @@ -1531,8 +1605,6 @@ if (r_protected) *r_protected = 0; - mapi_release_attach_table (mapi_create_attach_table (message, 0)); - if (get_gpgolattachtype_tag (message, &moss_tag) ) return NULL; Modified: trunk/src/mapihelp.h =================================================================== --- trunk/src/mapihelp.h 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/mapihelp.h 2007-09-21 14:02:48 UTC (rev 185) @@ -87,10 +87,12 @@ int get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag); int get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag); int get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag); +int get_gpgolmimeinfo_tag (LPMESSAGE message, ULONG *r_tag); int mapi_set_header (LPMESSAGE msg, const char *name, const char *val); int mapi_change_message_class (LPMESSAGE message); +char *mapi_get_message_class (LPMESSAGE message); msgtype_t mapi_get_message_type (LPMESSAGE message); int mapi_to_mime (LPMESSAGE message, const char *filename); @@ -108,8 +110,12 @@ int mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item); int mapi_has_sig_status (LPMESSAGE msg); int mapi_test_sig_status (LPMESSAGE msg); +char *mapi_get_sig_status (LPMESSAGE msg); + int mapi_set_sig_status (LPMESSAGE message, const char *status_string); +char *mapi_get_mime_info (LPMESSAGE msg); + char *mapi_get_message_content_type (LPMESSAGE message, char **r_protocol, char **r_smtype); Modified: trunk/src/message-events.cpp =================================================================== --- trunk/src/message-events.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/message-events.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -71,9 +71,10 @@ { m_pExchExt = pParentInterface; m_lRef = 0; - m_bOnSubmitActive = FALSE; - m_want_html = FALSE; - m_processed = FALSE; + m_bOnSubmitActive = false; + m_want_html = false; + m_processed = false; + m_wasencrypted = false; } @@ -109,61 +110,17 @@ LPMESSAGE message = NULL; log_debug ("%s:%s: received\n", SRCNAME, __func__); - eecb->GetObject (&mdb, (LPMAPIPROP *)&message); - switch (m_pExchExt->getMsgtype (eecb)) + + m_wasencrypted = false; + if (opt.preview_decrypt) { - case MSGTYPE_UNKNOWN: - break; - case MSGTYPE_GPGOL: - log_debug ("%s:%s: ignoring unknown message of original SMIME class\n", - SRCNAME, __func__); - break; - case MSGTYPE_GPGOL_MULTIPART_SIGNED: - log_debug ("%s:%s: processing multipart signed message\n", - SRCNAME, __func__); - m_processed = TRUE; - message_verify (message, m_pExchExt->getMsgtype (eecb), 0); - break; - case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED: - log_debug ("%s:%s: processing multipart encrypted message\n", - SRCNAME, __func__); - m_processed = TRUE; - message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0); - /* Hmmm, we might want to abort it and run our own inspector - instead. */ - break; - case MSGTYPE_GPGOL_OPAQUE_SIGNED: - log_debug ("%s:%s: processing opaque signed message\n", - SRCNAME, __func__); - m_processed = TRUE; - message_verify (message, m_pExchExt->getMsgtype (eecb), 0); - break; - case MSGTYPE_GPGOL_CLEAR_SIGNED: - log_debug ("%s:%s: processing clear signed pgp message\n", - SRCNAME, __func__); - m_processed = TRUE; - message_verify (message, m_pExchExt->getMsgtype (eecb), 0); - break; - case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED: - log_debug ("%s:%s: processing opaque encrypted message\n", - SRCNAME, __func__); - m_processed = TRUE; - message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0); - /* Hmmm, we might want to abort it and run our own inspector - instead. */ - break; - case MSGTYPE_GPGOL_PGP_MESSAGE: - log_debug ("%s:%s: processing pgp message\n", SRCNAME, __func__); - m_processed = TRUE; - message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0); - /* Hmmm, we might want to abort it and run our own inspector - instead. */ - break; + eecb->GetObject (&mdb, (LPMAPIPROP *)&message); + if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb))) + m_processed = true; + ul_release (message); + ul_release (mdb); } - ul_release (message); - ul_release (mdb); - return S_FALSE; } @@ -178,51 +135,17 @@ /* If the message has been processed by is (i.e. in OnRead), we now use our own display code. */ - if (m_processed) + if (!flags && m_processed) { - HRESULT hr; HWND hwnd = NULL; - LPMESSAGE message = NULL; - LPMDB mdb = NULL; if (FAILED (eecb->GetWindow (&hwnd))) hwnd = NULL; - hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message); - if (SUCCEEDED (hr)) - { - int ishtml, wasprotected; - char *body; - - /* If the message was protected we don't allow a fallback to - the OOM display methods. */ - body = mapi_get_gpgol_body_attachment (message, NULL, - &ishtml, &wasprotected); - if (body) - update_display (hwnd, wasprotected? NULL: eecb, ishtml, body); - else - update_display (hwnd, NULL, 0, - _("[Crypto operation failed - " - "can't show the body of the message]")); - put_outlook_property (eecb, "EncryptedStatus", "MyStatus"); - - } - ul_release (message); - ul_release (mdb); + if (message_display_handler (eecb, hwnd)) + m_wasencrypted = true; } -#if 1 - { - HWND hWnd = NULL; - - if (FAILED (eecb->GetWindow (&hWnd))) - hWnd = NULL; - else - log_window_hierarchy (hWnd, "%s:%s:%d: Windows hierarchy:", - SRCNAME, __func__, __LINE__); - } -#endif - return S_FALSE; } @@ -345,7 +268,7 @@ if (FAILED(eecb->GetWindow (&hWnd))) hWnd = NULL; - /* Get the object and call the encryption or signing fucntion. */ + /* Get the object and call the encryption or signing function. */ HRESULT hr = eecb->GetObject (&pMDB, (LPMAPIPROP *)&msg); if (SUCCEEDED (hr)) { Modified: trunk/src/message-events.h =================================================================== --- trunk/src/message-events.h 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/message-events.h 2007-09-21 14:02:48 UTC (rev 185) @@ -40,9 +40,10 @@ ULONG m_lContext; BOOL m_bOnSubmitActive; GpgolExt* m_pExchExt; - BOOL m_bWriteFailed; - BOOL m_want_html; /* Encryption of HTML is desired. */ - BOOL m_processed; /* The message has been porcessed by us. */ + bool m_bWriteFailed; + bool m_want_html; /* Encryption of HTML is desired. */ + bool m_processed; /* The message has been porcessed by us. */ + bool m_wasencrypted; /* The original message was encrypted. */ public: STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppvObj); Modified: trunk/src/message.cpp =================================================================== --- trunk/src/message.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/message.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -31,6 +31,7 @@ #include "mapihelp.h" #include "mimeparser.h" #include "mimemaker.h" +#include "display.h" #include "message.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ @@ -38,6 +39,144 @@ } while (0) +static void +ul_release (LPVOID punk) +{ + ULONG res; + + if (!punk) + return; + res = UlRelease (punk); +// log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res); +} + + +/* A helper function used by OnRead and OnOpen to dispatch the + message. Returns true if the message has been processed. */ +bool +message_incoming_handler (LPMESSAGE message, msgtype_t msgtype) +{ + bool retval = false; + + switch (msgtype) + { + case MSGTYPE_UNKNOWN: + break; + case MSGTYPE_GPGOL: + log_debug ("%s:%s: ignoring unknown message of original SMIME class\n", + SRCNAME, __func__); + break; + case MSGTYPE_GPGOL_MULTIPART_SIGNED: + log_debug ("%s:%s: processing multipart signed message\n", + SRCNAME, __func__); + retval = true; + message_verify (message, msgtype, 0); + break; + case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED: + log_debug ("%s:%s: processing multipart encrypted message\n", + SRCNAME, __func__); + retval = true; + message_decrypt (message, msgtype, 0); + break; + case MSGTYPE_GPGOL_OPAQUE_SIGNED: + log_debug ("%s:%s: processing opaque signed message\n", + SRCNAME, __func__); + retval = true; + message_verify (message, msgtype, 0); + break; + case MSGTYPE_GPGOL_CLEAR_SIGNED: + log_debug ("%s:%s: processing clear signed pgp message\n", + SRCNAME, __func__); + retval = true; + message_verify (message, msgtype, 0); + break; + case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED: + log_debug ("%s:%s: processing opaque encrypted message\n", + SRCNAME, __func__); + retval = true; + message_decrypt (message, msgtype, 0); + break; + case MSGTYPE_GPGOL_PGP_MESSAGE: + log_debug ("%s:%s: processing pgp message\n", SRCNAME, __func__); + retval = true; + message_decrypt (message, msgtype, 0); + break; + } + + return retval; +} + + +/* Common Code ise by OnReadComplete and OnOpenComplete to display a + modified message. Returns true if the message was encrypted. */ +bool +message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd) +{ + HRESULT hr; + LPMESSAGE message = NULL; + LPMDB mdb = NULL; + int ishtml, wasprotected = false; + char *body; + + hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message); + if (SUCCEEDED (hr)) + { + /* If the message was protected we don't allow a fallback to the + OOM display methods. */ + body = mapi_get_gpgol_body_attachment (message, NULL, + &ishtml, &wasprotected); + if (body) + update_display (hwnd, wasprotected? NULL: eecb, ishtml, body); + else + update_display (hwnd, NULL, 0, + _("[Crypto operation failed - " + "can't show the body of the message]")); + xfree (body); + + /* put_outlook_property (eecb, "EncryptedStatus", "MyStatus"); */ + } + else + log_debug_w32 (hr, "%s:%s: error getting message", SRCNAME, __func__); + + ul_release (message); + ul_release (mdb); + + return !!wasprotected; +} + + +/* Display some information about MESSAGE. */ +void +message_show_info (LPMESSAGE message, HWND hwnd) +{ + char *msgcls = mapi_get_message_class (message); + char *sigstat = mapi_get_sig_status (message); + char *mimeinfo = mapi_get_mime_info (message); + size_t buflen; + char *buffer; + + buflen = strlen (msgcls) + strlen (sigstat) + strlen (mimeinfo) + 200; + buffer = (char*)xmalloc (buflen+1); + snprintf (buffer, buflen, + _("Message class: %s\n" + "Sig Status : %s\n" + "Structure of the message:\n" + "%s"), + msgcls, + sigstat, + mimeinfo); + + MessageBox (hwnd, buffer, _("GpgOL - Message Information"), + MB_ICONINFORMATION|MB_OK); + xfree (buffer); + xfree (mimeinfo); + xfree (sigstat); + xfree (msgcls); +} + + + + /* Convert the clear signed message from INPUT into a PS?MIME signed message and return it in a new allocated buffer. OUTPUTLEN received the valid length of that buffer; the buffer is guarnateed Modified: trunk/src/message.h =================================================================== --- trunk/src/message.h 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/message.h 2007-09-21 14:02:48 UTC (rev 185) @@ -23,6 +23,11 @@ #define MESSAGE_H +bool message_incoming_handler (LPMESSAGE message, msgtype_t msgtype); +bool message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd); +void message_show_info (LPMESSAGE message, HWND hwnd); + + int message_verify (LPMESSAGE message, msgtype_t msgtype, int force); int message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force); Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/mimemaker.c 2007-09-21 14:02:48 UTC (rev 185) @@ -1401,7 +1401,6 @@ /* Write the top header. */ generate_boundary (boundary); - TRACEPOINT (); if ((rc=write_multistring (sink, "MIME-Version: 1.0\r\n" "Content-Type: multipart/encrypted;\r\n" @@ -1410,7 +1409,6 @@ NULL))) goto failure; - TRACEPOINT (); /* Write the PGP/MIME encrypted part. */ if ((rc = write_boundary (sink, boundary, 0))) goto failure; @@ -1429,11 +1427,9 @@ "\r\n", NULL))) goto failure; - TRACEPOINT (); /* Create a new sink for encrypting the following stuff. */ encsink->cb_data = filter; encsink->writefnc = sink_encryption_write; - TRACEPOINT (); if ((body && n_att_usable) || n_att_usable > 1) { @@ -1448,8 +1444,6 @@ else /* Only one part. */ *inner_boundary = 0; - TRACEPOINT (); - if (body) rc = write_part (encsink, body, strlen (body), *inner_boundary? inner_boundary : NULL, NULL, 1); @@ -1458,7 +1452,6 @@ *inner_boundary? inner_boundary : NULL); if (rc) goto failure; - TRACEPOINT (); xfree (body); body = NULL; @@ -1476,27 +1469,19 @@ filter = NULL; /* Not valid anymore. */ encsink->cb_data = NULL; /* Not needed anymore. */ - TRACEPOINT (); - /* Write the final boundary and finish the attachment. */ if ((rc = write_boundary (sink, boundary, 1))) goto failure; - TRACEPOINT (); - if (close_mapi_attachment (&attach, sink)) goto failure; - TRACEPOINT (); - if (finalize_message (message, att_table)) goto failure; result = 0; /* Everything is fine, fall through the cleanup now. */ - TRACEPOINT (); failure: - TRACEPOINT (); engine_cancel (filter); cancel_mapi_attachment (&attach, sink); xfree (body); Modified: trunk/src/mimeparser.c =================================================================== --- trunk/src/mimeparser.c 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/mimeparser.c 2007-09-21 14:02:48 UTC (rev 185) @@ -216,7 +216,6 @@ } - /* Start a new atatchment. With IS_BODY set, the attachment is actually the body part of the message which is treated in a special way. */ @@ -506,9 +505,88 @@ } +/* Create the MIME info string. This is a LF delimited string + with one line per MIME part. Each line is formatted this way: + LEVEL:ENCINFO:SIGINFO:CT:CHARSET:FILENAME + + LEVEL is the nesting level with 0 as the top (rfc822 header) + ENCINFO is one of + p PGP/MIME encrypted + s S/MIME encryptyed + SIGINFO is one of + pX PGP/MIME signed (also used for clearsigned) + sX S/MIME signed + With X being: + ? unklnown status + - Bad signature + ~ Good signature but with some problems + ! Good signature + CT ist the content type of this part + CHARSET is the charset used for this part + FILENAME is the file name. +*/ +static char * +build_mimeinfo (mimestruct_item_t mimestruct) +{ + mimestruct_item_t ms; + size_t buflen, n; + char *buffer, *p; + char numbuf[20]; + + /* FIXME: We need to escape stuff so that there are no colons. */ + for (buflen=0, ms = mimestruct; ms; ms = ms->next) + { + buflen += sizeof numbuf; + buflen += strlen (ms->content_type); + buflen += ms->charset? strlen (ms->charset) : 0; + buflen += ms->filename? strlen (ms->filename) : 0; + buflen += 20; + } + + p = buffer = xmalloc (buflen+1); + for (ms=mimestruct; ms; ms = ms->next) + { + snprintf (p, buflen, "%d:::%s:%s:%s:\n", + ms->level, ms->content_type, + ms->charset? ms->charset : "", + ms->filename? ms->filename : ""); + n = strlen (p); + assert (n < buflen); + buflen -= n; + p += n; + } + + return buffer; +} + + static int -finish_message (LPMESSAGE message) +finish_message (LPMESSAGE message, gpg_error_t err, + mimestruct_item_t mimestruct) { + HRESULT hr; + SPropValue prop; + + if (get_gpgolmimeinfo_tag (message, &prop.ulPropTag) ) + return -1; + prop.Value.lpszA = build_mimeinfo (mimestruct); + hr = IMessage_SetProps (message, 1, &prop, NULL); + xfree (prop.Value.lpszA); + if (hr) + { + log_error_w32 (hr, "%s:%s: error setting the mime info", + SRCNAME, __func__); + return -1; + } + + hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE); + if (hr) + { + log_error_w32 (hr, "%s:%s: SaveChanges to the message failed", + SRCNAME, __func__); + return -1; + } + return 0; } @@ -888,21 +966,6 @@ -static void -show_mimestruct (mimestruct_item_t mimestruct) -{ - mimestruct_item_t ms; - - for (ms = mimestruct; ms; ms = ms->next) - log_debug ("MIMESTRUCT: %*s%s cs=%s fn=%s\n", - ms->level*2, "", ms->content_type, - ms->charset? ms->charset : "[none]", - ms->filename? ms->filename : "[none]"); -} - - - - int mime_verify (protocol_t protocol, const char *message, size_t messagelen, LPMESSAGE mapi_message, HWND hwnd, int preview_mode) @@ -988,7 +1051,6 @@ } else if (nread) { - TRACEPOINT(); err = engine_filter (filter, buffer, nread); } else @@ -1008,7 +1070,6 @@ leave: - TRACEPOINT(); gpgme_free (signature); engine_cancel (filter); if (ctx) @@ -1018,7 +1079,7 @@ rfc822parse_close (ctx->msg); gpgme_data_release (ctx->signed_data); gpgme_data_release (ctx->sig_data); - show_mimestruct (ctx->mimestruct); + finish_message (mapi_message, err, ctx->mimestruct); while (ctx->mimestruct) { mimestruct_item_t tmp = ctx->mimestruct->next; @@ -1029,8 +1090,6 @@ } symenc_close (ctx->symenc); xfree (ctx); - if (!err) - finish_message (mapi_message); } return err; } @@ -1136,7 +1195,7 @@ gpgme_data_release (ctx->signed_data); if (ctx->sig_data) gpgme_data_release (ctx->sig_data); - show_mimestruct (ctx->mimestruct); + finish_message (mapi_message, err, ctx->mimestruct); while (ctx->mimestruct) { mimestruct_item_t tmp = ctx->mimestruct->next; @@ -1147,8 +1206,6 @@ } symenc_close (ctx->symenc); xfree (ctx); - if (!err) - finish_message (mapi_message); } return err; } Modified: trunk/src/olflange.cpp =================================================================== --- trunk/src/olflange.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/olflange.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -204,7 +204,7 @@ return E_ACCESSDENIED; } - strcpy (szEntry, "GPGol - The GPG Outlook Plugin"); + strcpy (szEntry, "GpgOL - The GnuPG Outlook Plugin"); dwTemp = strlen (szEntry) + 1; RegSetValueEx (hkey, NULL, 0, REG_SZ, (BYTE*)szEntry, dwTemp); Modified: trunk/src/user-events.cpp =================================================================== --- trunk/src/user-events.cpp 2007-09-20 13:37:50 UTC (rev 184) +++ trunk/src/user-events.cpp 2007-09-21 14:02:48 UTC (rev 185) @@ -115,6 +115,7 @@ SRCNAME, __func__, msgclass); } } + } /* I assume this is called from Outlook for all object changes. From cvs at cvs.gnupg.org Fri Sep 21 16:08:38 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 21 Sep 2007 16:08:38 +0200 Subject: [svn] GpgEX - r20 - trunk/src Message-ID: Author: wk Date: 2007-09-21 16:08:29 +0200 (Fri, 21 Sep 2007) New Revision: 20 Modified: trunk/src/ChangeLog trunk/src/registry.c Log: Made registry based homedir work. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-16 16:27:20 UTC (rev 19) +++ trunk/src/ChangeLog 2007-09-21 14:08:29 UTC (rev 20) @@ -1,3 +1,8 @@ +2007-09-21 Werner Koch + + * registry.c (default_homedir): Make registry works. Reported by + Marc Mutz. + 2007-09-16 Marcus Brinkmann * gpgex.cc (gpgex_t::QueryContextMenu): Implement popup menu Modified: trunk/src/registry.c =================================================================== --- trunk/src/registry.c 2007-09-16 16:27:20 UTC (rev 19) +++ trunk/src/registry.c 2007-09-21 14:08:29 UTC (rev 20) @@ -250,7 +250,7 @@ tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir"); - if (tmp && *tmp) + if (tmp && !*tmp) { free (tmp); tmp = NULL; From cvs at cvs.gnupg.org Mon Sep 24 11:50:14 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 24 Sep 2007 11:50:14 +0200 Subject: [svn] assuan - r265 - trunk/src Message-ID: Author: marcus Date: 2007-09-24 11:50:01 +0200 (Mon, 24 Sep 2007) New Revision: 265 Modified: trunk/src/ChangeLog trunk/src/assuan-uds.c Log: 2007-09-24 Marcus Brinkmann * assuan-uds.c (uds_reader) [HAVE_W32_SYSTEM]: Do not touch the UDS structure in the context. Reported by Frank Osterfeld. (uds_writer): Clarify code. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-14 14:23:45 UTC (rev 264) +++ trunk/src/ChangeLog 2007-09-24 09:50:01 UTC (rev 265) @@ -1,3 +1,9 @@ +2007-09-24 Marcus Brinkmann + + * assuan-uds.c (uds_reader) [HAVE_W32_SYSTEM]: Do not touch the + UDS structure in the context. Reported by Frank Osterfeld. + (uds_writer): Clarify code. + 2007-09-14 Marcus Brinkmann * assuan-pipe-connect.c (do_finish) [HAVE_W32_SYSTEM]: Close Modified: trunk/src/assuan-uds.c =================================================================== --- trunk/src/assuan-uds.c 2007-09-14 14:23:45 UTC (rev 264) +++ trunk/src/assuan-uds.c 2007-09-24 09:50:01 UTC (rev 265) @@ -70,9 +70,9 @@ static ssize_t uds_reader (assuan_context_t ctx, void *buf, size_t buflen) { +#ifndef HAVE_W32_SYSTEM int len = ctx->uds.buffersize; -#ifndef HAVE_W32_SYSTEM if (!ctx->uds.bufferallocated) { ctx->uds.buffer = xtrymalloc (2048); @@ -139,12 +139,6 @@ #endif /*USE_DESCRIPTOR_PASSING*/ } -#else /*HAVE_W32_SYSTEM*/ - - len = recvfrom (HANDLE2SOCKET(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. */ @@ -157,6 +151,9 @@ assert (ctx->uds.bufferoffset <= ctx->uds.bufferallocated); return len; +#else /*HAVE_W32_SYSTEM*/ + return recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL); +#endif /*HAVE_W32_SYSTEM*/ } @@ -179,14 +176,13 @@ iovec.iov_len = buflen; len = _assuan_simple_sendmsg (ctx, &msg); + + return len; #else /*HAVE_W32_SYSTEM*/ - int len; - - len = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0, - (struct sockaddr *)&ctx->serveraddr, - sizeof (struct sockaddr_in)); + return sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0, + (struct sockaddr *)&ctx->serveraddr, + sizeof (struct sockaddr_in)); #endif /*HAVE_W32_SYSTEM*/ - return len; } From cvs at cvs.gnupg.org Tue Sep 25 17:08:26 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 25 Sep 2007 17:08:26 +0200 Subject: [svn] gpgme - r1259 - in trunk: assuan gpgme Message-ID: Author: wk Date: 2007-09-25 17:08:14 +0200 (Tue, 25 Sep 2007) New Revision: 1259 Modified: trunk/assuan/ChangeLog trunk/assuan/assuan.h trunk/gpgme/gpgme.h Log: Fixed a name clash under W32 Modified: trunk/assuan/ChangeLog =================================================================== --- trunk/assuan/ChangeLog 2007-09-17 13:24:14 UTC (rev 1258) +++ trunk/assuan/ChangeLog 2007-09-25 15:08:14 UTC (rev 1259) @@ -1,3 +1,8 @@ +2007-09-25 Werner Koch + + * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add + new wrappers. + 2007-09-03 Marcus Brinkmann * assuan.h [_ASSUAN_EXT_SYM_PREFIX]: Add missing symbol renames Modified: trunk/assuan/assuan.h =================================================================== --- trunk/assuan/assuan.h 2007-09-17 13:24:14 UTC (rev 1258) +++ trunk/assuan/assuan.h 2007-09-25 15:08:14 UTC (rev 1259) @@ -185,6 +185,8 @@ #define _assuan_set_default_log_stream \ _ASSUAN_PREFIX(_assuan_set_default_log_stream) #define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror) +#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r) +#define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource) #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) Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-17 13:24:14 UTC (rev 1258) +++ trunk/gpgme/gpgme.h 2007-09-25 15:08:14 UTC (rev 1259) @@ -73,7 +73,7 @@ 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.6-svn1257" +#define GPGME_VERSION "1.1.6-svn1258" From cvs at cvs.gnupg.org Tue Sep 25 17:10:03 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 25 Sep 2007 17:10:03 +0200 Subject: [svn] assuan - r266 - in trunk: . doc src Message-ID: Author: wk Date: 2007-09-25 17:09:54 +0200 (Tue, 25 Sep 2007) New Revision: 266 Modified: trunk/NEWS trunk/configure.ac trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-socket.c trunk/src/assuan.h Log: Fixed a name clash in internal symbols used only under W32. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/NEWS 2007-09-25 15:09:54 UTC (rev 266) @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.0.4 +------------------------------------------------ + + Noteworthy changes in version 1.0.3 (2007-08-24) ------------------------------------------------ Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/configure.ac 2007-09-25 15:09:54 UTC (rev 266) @@ -24,7 +24,7 @@ # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.0.3]) +m4_define([my_version], [1.0.4]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \ Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/doc/assuan.texi 2007-09-25 15:09:54 UTC (rev 266) @@ -1518,7 +1518,7 @@ @end deftypefun - at deftypefun int assuan_get_active_fds (@w{assuan_context_t @var{ctx}}, @w{int @var{what}}, @w{int *@var{fdarray}}, @w{int @var{fdarraysize}}) + at deftypefun int assuan_get_active_fds (@w{assuan_context_t @var{ctx}}, @w{int @var{what}}, @w{assuan_fd_t *@var{fdarray}}, @w{int @var{fdarraysize}}) Return all active file descriptors for the context @var{ctx}. This function can be used to select on the file descriptors and to call Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/src/ChangeLog 2007-09-25 15:09:54 UTC (rev 266) @@ -1,3 +1,8 @@ +2007-09-25 Werner Koch + + * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add + wrappers for these new internal functions. + 2007-09-24 Marcus Brinkmann * assuan-uds.c (uds_reader) [HAVE_W32_SYSTEM]: Do not touch the @@ -10,6 +15,10 @@ ctx->pid as handle. (pipe_connect_w32): Save the spawned processes handle. +2007-09-13 Werner Koch + + * assuan-socket.c (_assuan_close): Add inactive debug outputs. + 2007-09-11 Marcus Brinkmann * assuan.h: Use _WIN32 instead of HAVE_W32_SYSTEM. Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/src/assuan-socket.c 2007-09-25 15:09:54 UTC (rev 266) @@ -43,13 +43,21 @@ int _assuan_close (assuan_fd_t fd) { -#ifndef HAVE_W32_SYSTEM - return close (fd); -#else +#ifdef HAVE_W32_SYSTEM int rc = closesocket (HANDLE2SOCKET(fd)); +/* if (rc) */ +/* _assuan_log_printf ("_assuan_close(%p): closesocket failed: %d/%ld\n", */ +/* fd, rc, WSAGetLastError ()); */ if (rc && WSAGetLastError () == WSAENOTSOCK) - rc = CloseHandle (fd); + { + rc = CloseHandle (fd); +/* if (rc) */ +/* _assuan_log_printf ("_assuan_close(%p): CloseHandle failed: %d\n", */ +/* fd, rc ); */ + } return rc; +#else + return close (fd); #endif } Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-09-24 09:50:01 UTC (rev 265) +++ trunk/src/assuan.h 2007-09-25 15:09:54 UTC (rev 266) @@ -159,6 +159,8 @@ #define _assuan_set_default_log_stream \ _ASSUAN_PREFIX(_assuan_set_default_log_stream) #define _assuan_w32_strerror _ASSUAN_PREFIX(_assuan_w32_strerror) +#define _assuan_gpg_strerror_r _ASSUAN_PREFIX(_assuan_gpg_strerror_r) +#define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource) #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) From cvs at cvs.gnupg.org Tue Sep 25 18:34:14 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 25 Sep 2007 18:34:14 +0200 Subject: [svn] gpgme - r1260 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-25 18:34:02 +0200 (Tue, 25 Sep 2007) New Revision: 1260 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/kdpipeiodevice.h trunk/gpgme/w32-qt-io.cpp Log: 2007-09-25 Marcus Brinkmann * kdpipeiodevice.h: Use namespace _gpgme_. * kdpipeiodevice.cpp: Use namespace _gpgme_. [Q_OS_WIN32 && NOMINMAX]: Do not define NOMINMAX again. * w32-qt-io.cpp: Change namespace of KDPipeIODevice to _gpgme_::KDPipeIODevice. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-25 15:08:14 UTC (rev 1259) +++ trunk/gpgme/ChangeLog 2007-09-25 16:34:02 UTC (rev 1260) @@ -1,3 +1,11 @@ +2007-09-25 Marcus Brinkmann + + * kdpipeiodevice.h: Use namespace _gpgme_. + * kdpipeiodevice.cpp: Use namespace _gpgme_. + [Q_OS_WIN32 && NOMINMAX]: Do not define NOMINMAX again. + * w32-qt-io.cpp: Change namespace of KDPipeIODevice to + _gpgme_::KDPipeIODevice. + 2007-09-17 Werner Koch * rungpg.c (gpg_new): Make robust against undefined ttyname or Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-09-25 15:08:14 UTC (rev 1259) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-09-25 16:34:02 UTC (rev 1260) @@ -26,7 +26,9 @@ #include #ifdef Q_OS_WIN32 -# define NOMINMAX +# ifndef NOMINMAX +# define NOMINMAX +# endif # include # include #else @@ -34,6 +36,8 @@ # include #endif +using namespace _gpgme_; + #ifndef KDAB_CHECK_THIS # define KDAB_CHECK_CTOR (void)1 # define KDAB_CHECK_DTOR KDAB_CHECK_CTOR Modified: trunk/gpgme/kdpipeiodevice.h =================================================================== --- trunk/gpgme/kdpipeiodevice.h 2007-09-25 15:08:14 UTC (rev 1259) +++ trunk/gpgme/kdpipeiodevice.h 2007-09-25 16:34:02 UTC (rev 1260) @@ -26,6 +26,8 @@ //#include "checker.h" +namespace _gpgme_ { + class KDPipeIODevice : public QIODevice { Q_OBJECT //KDAB_MAKE_CHECKABLE( KDPipeIODevice ) Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-25 15:08:14 UTC (rev 1259) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-25 16:34:02 UTC (rev 1260) @@ -53,9 +53,12 @@ #endif #endif +using _gpgme_::KDPipeIODevice; + /* This file is an ugly hack to get GPGME working with Qt on Windows targets. On Windows, you can not select() on file descriptors. + The only way to check if there is something to read is to read something. This means that GPGME can not let Qt check for data without letting Qt also handle the data on Windows targets. From cvs at cvs.gnupg.org Tue Sep 25 18:35:45 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 25 Sep 2007 18:35:45 +0200 Subject: [svn] gpgme - r1261 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-25 18:35:36 +0200 (Tue, 25 Sep 2007) New Revision: 1261 Modified: trunk/gpgme/ChangeLog trunk/gpgme/conversion.c trunk/gpgme/keylist.c Log: 2007-09-25 Marcus Brinkmann * conversion.c, keylist.c: Include . Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-25 16:34:02 UTC (rev 1260) +++ trunk/gpgme/ChangeLog 2007-09-25 16:35:36 UTC (rev 1261) @@ -1,5 +1,7 @@ 2007-09-25 Marcus Brinkmann + * conversion.c, keylist.c: Include . + * kdpipeiodevice.h: Use namespace _gpgme_. * kdpipeiodevice.cpp: Use namespace _gpgme_. [Q_OS_WIN32 && NOMINMAX]: Do not define NOMINMAX again. Modified: trunk/gpgme/conversion.c =================================================================== --- trunk/gpgme/conversion.c 2007-09-25 16:34:02 UTC (rev 1260) +++ trunk/gpgme/conversion.c 2007-09-25 16:35:36 UTC (rev 1261) @@ -25,6 +25,8 @@ #include #include +/* Solaris 8 needs sys/types.h before time.h. */ +#include #include #include Modified: trunk/gpgme/keylist.c =================================================================== --- trunk/gpgme/keylist.c 2007-09-25 16:34:02 UTC (rev 1260) +++ trunk/gpgme/keylist.c 2007-09-25 16:35:36 UTC (rev 1261) @@ -25,6 +25,8 @@ #include #include #include +/* Solaris 8 needs sys/types.h before time.h. */ +#include #include #include #include From cvs at cvs.gnupg.org Thu Sep 27 07:17:53 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 27 Sep 2007 07:17:53 +0200 Subject: [svn] gpg-error - r198 - in trunk: . src Message-ID: Author: wk Date: 2007-09-27 07:17:43 +0200 (Thu, 27 Sep 2007) New Revision: 198 Modified: trunk/ChangeLog trunk/NEWS trunk/src/err-codes.h.in trunk/src/err-sources.h.in Log: new codes Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-08-23 17:46:39 UTC (rev 197) +++ trunk/ChangeLog 2007-09-27 05:17:43 UTC (rev 198) @@ -1,3 +1,8 @@ +2007-09-27 Werner Koch + + * src/err-sources.h.in (GPG_ERR_SOURCE_GPA): New. + * src/err-codes.h.in (GPG_ERR_UNFINISHED): New. + 2007-08-03 Marcus Brinkmann * configure.ac: Call AM_PROG_CC_C_O. Allow --disable-languages. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-08-23 17:46:39 UTC (rev 197) +++ trunk/NEWS 2007-09-27 05:17:43 UTC (rev 198) @@ -1,7 +1,12 @@ Noteworthy changes in version 1.6 ---------------------------------------------- + * Interface changes relative to the 1.4 release: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + GPG_ERR_UNFINISHED NEW + GPG_ERR_SOURCE_GPA NEW + Noteworthy changes in version 1.5 (2006-11-30) ---------------------------------------------- Modified: trunk/src/err-codes.h.in =================================================================== --- trunk/src/err-codes.h.in 2007-08-23 17:46:39 UTC (rev 197) +++ trunk/src/err-codes.h.in 2007-09-27 05:17:43 UTC (rev 198) @@ -205,8 +205,10 @@ 173 GPG_ERR_LOCKED Locked 174 GPG_ERR_UNKNOWN_OPTION Unknown option 175 GPG_ERR_UNKNOWN_COMMAND Unknown command -# 176 to 199 are free to be used. +# 176 to 198 are free to be used. + +199 GPG_ERR_UNFINISHED Operation not yet finished 200 GPG_ERR_BUFFER_TOO_SHORT Buffer too short # Error codes pertaining to S-expressions. Modified: trunk/src/err-sources.h.in =================================================================== --- trunk/src/err-sources.h.in 2007-08-23 17:46:39 UTC (rev 197) +++ trunk/src/err-sources.h.in 2007-09-27 05:17:43 UTC (rev 198) @@ -41,8 +41,9 @@ 9 GPG_ERR_SOURCE_KSBA KSBA 10 GPG_ERR_SOURCE_DIRMNGR Dirmngr 11 GPG_ERR_SOURCE_GSTI GSTI +12 GPG_ERR_SOURCE_GPA GPA -# 11 to 30 are free to be used. +# 13 to 30 are free to be used. 31 GPG_ERR_SOURCE_ANY Any source 32 GPG_ERR_SOURCE_USER_1 User defined source 1 From cvs at cvs.gnupg.org Thu Sep 27 13:06:32 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 13:06:32 +0200 Subject: [svn] gpgme - r1262 - in trunk: . assuan gpgme Message-ID: Author: marcus Date: 2007-09-27 13:06:23 +0200 (Thu, 27 Sep 2007) New Revision: 1262 Modified: trunk/ChangeLog trunk/assuan/assuan-pipe-connect.c trunk/gpgme/rungpg.c Log: 2007-09-27 Marcus Brinkmann * assuan-pipe-connect.c (pipe_connect_gpgme): New function, use it if _ASSUAN_IN_GPGME_BUILD_ASSUAN. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-25 16:35:36 UTC (rev 1261) +++ trunk/ChangeLog 2007-09-27 11:06:23 UTC (rev 1262) @@ -1,3 +1,8 @@ +2007-09-27 Marcus Brinkmann + + * assuan-pipe-connect.c (pipe_connect_gpgme): New function, use it + if _ASSUAN_IN_GPGME_BUILD_ASSUAN. + 2007-09-17 Werner Koch * configure.ac: Use the svn version magic. Modified: trunk/assuan/assuan-pipe-connect.c =================================================================== --- trunk/assuan/assuan-pipe-connect.c 2007-09-25 16:35:36 UTC (rev 1261) +++ trunk/assuan/assuan-pipe-connect.c 2007-09-27 11:06:23 UTC (rev 1262) @@ -550,6 +550,108 @@ +#ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN + +#define pipe_connect pipe_connect_gpgme + +/* From GPGME priv-io.h */ +struct spawn_fd_item_s +{ + int fd; + int dup_to; +}; + +/* W32 version of the pipe connection code. */ +static assuan_error_t +pipe_connect_gpgme (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 pid; +int rp[2]; + int wp[2]; + char mypidstr[50]; + struct spawn_fd_item_s child_fds[3]; /* stdin, stdout, terminating -1 */ + + if (!ctx || !name || !argv || !argv[0]) + return _assuan_error (ASSUAN_Invalid_Value); + + /* Actually, GPGME does this for us. But we plan to reuse this code + in the generic assuan. */ + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + /* Create the two pipes. */ + if (_gpgme_io_pipe (rp, 0)) + return _assuan_error (ASSUAN_General_Error); + + if (_gpgme_io_pipe (wp, 1)) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + err = _assuan_new_context (ctx); + if (err) + { + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + _gpgme_io_close (wp[0]); + _gpgme_io_close (wp[1]); + 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 to mypidstr. 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. */ + + /* Parent list is same as client list. Note that GPGME will dup nul + to stderr even if the caller wants to inherit the handle for + it. */ + /* Server stdout is its write end of our read pipe. */ + child_fds[0].fd = rp[1]; + child_fds[0].dup_to = 1; + /* Server stdin is its read end of our write pipe. */ + child_fds[1].fd = wp[0]; + child_fds[1].dup_to = 0; + child_fds[2].fd = -1; + + /* Start the process. */ + pid = _gpgme_io_spawn (name, argv, child_fds, child_fds); + if (pid == -1) + { + _assuan_log_printf ("CreateProcess failed: %s\n", strerror (errno)); + _gpgme_io_close (rp[0]); + _gpgme_io_close (rp[1]); + _gpgme_io_close (wp[0]); + _gpgme_io_close (wp[1]); + return _assuan_error (ASSUAN_General_Error); + } + + /* ERR contains the PID. */ + (*ctx)->pid = 0; /* We don't use the PID. */ + + /* FIXME: Should be done by GPGME. */ + CloseHandle ((HANDLE) pid); /* We don't need to wait for the process. */ + + return initial_handshake (ctx); +} + +#else #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. */ @@ -648,9 +750,8 @@ filedes[1] = handle_to_fd (w); return 0; } -#endif /*HAVE_W32_SYSTEM*/ +#endif /* HAVE_W32_SYSTEM */ - #ifdef HAVE_W32_SYSTEM #define pipe_connect pipe_connect_w32 /* W32 version of the pipe connection code. */ @@ -832,6 +933,7 @@ return initial_handshake (ctx); } #endif /*HAVE_W32_SYSTEM*/ +#endif /* !_ASSUAN_IN_GPGME_BUILD_ASSUAN */ /* Connect to a server over a pipe, creating the assuan context and Modified: trunk/gpgme/rungpg.c =================================================================== --- trunk/gpgme/rungpg.c 2007-09-25 16:35:36 UTC (rev 1261) +++ trunk/gpgme/rungpg.c 2007-09-27 11:06:23 UTC (rev 1262) @@ -1263,6 +1263,7 @@ /* build the fd list for the child */ n = 0; + /* The status fd is never dup'ed, so do not include it in the list. */ if (gpg->colon.fnc) { fd_child_list[n].fd = gpg->colon.fd[1]; From cvs at cvs.gnupg.org Thu Sep 27 13:44:54 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 13:44:54 +0200 Subject: [svn] gpgme - r1263 - in trunk: assuan gpgme Message-ID: Author: marcus Date: 2007-09-27 13:44:45 +0200 (Thu, 27 Sep 2007) New Revision: 1263 Modified: trunk/assuan/assuan-pipe-connect.c trunk/gpgme/ChangeLog trunk/gpgme/posix-io.c trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-io.c trunk/gpgme/w32-qt-io.cpp Log: 2007-09-27 Marcus Brinkmann * assuan-pipe-connect.c (pipe_connect_gpgme): Fix last change. gpgme/ 2007-09-27 Marcus Brinkmann * w32-glib-io.c (_gpgme_io_pipe), w32-qt-io.c (_gpgme_io_pipe), w32-io.c (_gpgme_io_pipe), posix-io.c (_gpgme_io_pipe): Fix debug output. Modified: trunk/assuan/assuan-pipe-connect.c =================================================================== --- trunk/assuan/assuan-pipe-connect.c 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/assuan/assuan-pipe-connect.c 2007-09-27 11:44:45 UTC (rev 1263) @@ -571,7 +571,7 @@ { assuan_error_t err; int pid; -int rp[2]; + int rp[2]; int wp[2]; char mypidstr[50]; struct spawn_fd_item_s child_fds[3]; /* stdin, stdout, terminating -1 */ @@ -586,10 +586,10 @@ sprintf (mypidstr, "%lu", (unsigned long)getpid ()); /* Create the two pipes. */ - if (_gpgme_io_pipe (rp, 0)) + if (_gpgme_io_pipe (rp, 1)) return _assuan_error (ASSUAN_General_Error); - if (_gpgme_io_pipe (wp, 1)) + if (_gpgme_io_pipe (wp, 0)) { _gpgme_io_close (rp[0]); _gpgme_io_close (rp[1]); @@ -706,7 +706,7 @@ #ifdef HAVE_W32_SYSTEM -/* Create pipe where one end end is inheritable. */ +/* Create pipe where one end is inheritable. */ static int create_inheritable_pipe (int filedes[2], int for_write) { Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/gpgme/ChangeLog 2007-09-27 11:44:45 UTC (rev 1263) @@ -1,3 +1,9 @@ +2007-09-27 Marcus Brinkmann + + * w32-glib-io.c (_gpgme_io_pipe), w32-qt-io.c (_gpgme_io_pipe), + w32-io.c (_gpgme_io_pipe), posix-io.c (_gpgme_io_pipe): Fix debug + output. + 2007-09-25 Marcus Brinkmann * conversion.c, keylist.c: Include . Modified: trunk/gpgme/posix-io.c =================================================================== --- trunk/gpgme/posix-io.c 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/gpgme/posix-io.c 2007-09-27 11:44:45 UTC (rev 1263) @@ -118,7 +118,7 @@ int err; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", - inherit_idx, inherit_idx ? "writing" : "reading"); + inherit_idx, inherit_idx ? "reading" : "writing"); err = pipe (filedes); if (err < 0) Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/gpgme/w32-glib-io.c 2007-09-27 11:44:45 UTC (rev 1263) @@ -221,7 +221,7 @@ GIOChannel *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", - inherit_idx, inherit_idx ? "writing" : "reading"); + inherit_idx, inherit_idx ? "reading" : "writing"); #define PIPEBUF_SIZE 4096 if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/gpgme/w32-io.c 2007-09-27 11:44:45 UTC (rev 1263) @@ -805,7 +805,7 @@ SECURITY_ATTRIBUTES sec_attr; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", - inherit_idx, inherit_idx ? "writing" : "reading"); + inherit_idx, inherit_idx ? "reading" : "writing"); memset (&sec_attr, 0, sizeof (sec_attr)); sec_attr.nLength = sizeof (sec_attr); Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-27 11:06:23 UTC (rev 1262) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-27 11:44:45 UTC (rev 1263) @@ -194,7 +194,7 @@ QIODevice *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", - inherit_idx, inherit_idx ? "writing" : "reading"); + inherit_idx, inherit_idx ? "reading" : "writing"); #define PIPEBUF_SIZE 4096 if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) From cvs at cvs.gnupg.org Thu Sep 27 13:55:27 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 13:55:27 +0200 Subject: [svn] gpgme - r1264 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-27 13:55:18 +0200 (Thu, 27 Sep 2007) New Revision: 1264 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.h Log: 2007-09-27 Marcus Brinkmann * kdpipeiodevice.h: Fix last change. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 11:44:45 UTC (rev 1263) +++ trunk/gpgme/ChangeLog 2007-09-27 11:55:18 UTC (rev 1264) @@ -1,5 +1,7 @@ 2007-09-27 Marcus Brinkmann + * kdpipeiodevice.h: Fix last change. + * w32-glib-io.c (_gpgme_io_pipe), w32-qt-io.c (_gpgme_io_pipe), w32-io.c (_gpgme_io_pipe), posix-io.c (_gpgme_io_pipe): Fix debug output. Modified: trunk/gpgme/kdpipeiodevice.h =================================================================== --- trunk/gpgme/kdpipeiodevice.h 2007-09-27 11:44:45 UTC (rev 1263) +++ trunk/gpgme/kdpipeiodevice.h 2007-09-27 11:55:18 UTC (rev 1264) @@ -64,5 +64,7 @@ Private * d; }; +} /* namespace _gpgme_ */ + #endif /* __KDTOOLSCORE_KDPIPEIODEVICE_H__ */ From cvs at cvs.gnupg.org Thu Sep 27 14:17:34 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 14:17:34 +0200 Subject: [svn] gpgme - r1265 - in trunk: . doc gpgme Message-ID: Author: marcus Date: 2007-09-27 14:17:24 +0200 (Thu, 27 Sep 2007) New Revision: 1265 Modified: trunk/ChangeLog trunk/doc/ChangeLog trunk/doc/gpgme.texi trunk/gpgme/ChangeLog trunk/gpgme/gpgme.c trunk/gpgme/gpgme.h Log: doc/ 2007-09-27 Marcus Brinkmann * gpgme.texi (Protocols and Engines): Document GPGME_PROTOCOL_UNKNOWN. gpgme/ 2007-09-27 Marcus Brinkmann * gpgme.h (gpgme_protocol_t): Add GPGME_PROTOCOL_UNKNOWN. * gpgme.c (gpgme_get_protocol_name): Implement support for GPGME_PROTOCOL_UNKNOWN. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) @@ -1,5 +1,7 @@ 2007-09-27 Marcus Brinkmann + * assuan-pipe-connect.c (pipe_connect_gpgme): Fix last change. + * assuan-pipe-connect.c (pipe_connect_gpgme): New function, use it if _ASSUAN_IN_GPGME_BUILD_ASSUAN. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/doc/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) @@ -1,3 +1,7 @@ +2007-09-27 Marcus Brinkmann + + * gpgme.texi (Protocols and Engines): Document GPGME_PROTOCOL_UNKNOWN. + 2007-09-11 Werner Koch * gpgme.texi (I/O Callback Example): Typo fix. Modified: trunk/doc/gpgme.texi =================================================================== --- trunk/doc/gpgme.texi 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/doc/gpgme.texi 2007-09-27 12:17:24 UTC (rev 1265) @@ -748,6 +748,12 @@ @item GPGME_PROTOCOL_CMS This specifies the Cryptographic Message Syntax. + + at item GPGME_PROTOCOL_UNKNOWN +Reserved for future extension. You may use this to indicate that the +used protocol is not known to the application. Currently, + at acronym{GPGME} does not accept this value in any operation, though, +except for @code{gpgme_get_protocol_name}. @end table @end deftp Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/gpgme/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) @@ -1,5 +1,9 @@ 2007-09-27 Marcus Brinkmann + * gpgme.h (gpgme_protocol_t): Add GPGME_PROTOCOL_UNKNOWN. + * gpgme.c (gpgme_get_protocol_name): Implement support for + GPGME_PROTOCOL_UNKNOWN. + * kdpipeiodevice.h: Fix last change. * w32-glib-io.c (_gpgme_io_pipe), w32-qt-io.c (_gpgme_io_pipe), Modified: trunk/gpgme/gpgme.c =================================================================== --- trunk/gpgme/gpgme.c 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/gpgme/gpgme.c 2007-09-27 12:17:24 UTC (rev 1265) @@ -208,6 +208,9 @@ case GPGME_PROTOCOL_CMS: return "CMS"; + case GPGME_PROTOCOL_UNKNOWN: + return "unknown"; + default: return NULL; } Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-27 11:55:18 UTC (rev 1264) +++ trunk/gpgme/gpgme.h 2007-09-27 12:17:24 UTC (rev 1265) @@ -300,7 +300,8 @@ typedef enum { GPGME_PROTOCOL_OpenPGP = 0, /* The default mode. */ - GPGME_PROTOCOL_CMS = 1 + GPGME_PROTOCOL_CMS = 1, + GPGME_PROTOCOL_UNKNOWN = 255 } gpgme_protocol_t; From cvs at cvs.gnupg.org Thu Sep 27 15:02:04 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 15:02:04 +0200 Subject: [svn] gpgme - r1266 - in trunk: . assuan gpgme tests tests/gpg Message-ID: Author: marcus Date: 2007-09-27 15:01:54 +0200 (Thu, 27 Sep 2007) New Revision: 1266 Modified: trunk/ChangeLog trunk/assuan/assuan-pipe-connect.c trunk/gpgme/ChangeLog trunk/gpgme/gpgme.h trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-io.c trunk/gpgme/w32-qt-io.cpp trunk/tests/ChangeLog trunk/tests/gpg/Makefile.am trunk/tests/gpg/t-support.h trunk/tests/gpg/t-wait.c trunk/tests/t-engine-info.c Log: 2007-09-27 Marcus Brinkmann * assuan-pipe-connect.c (pipe_connect_gpgme): Do not close process handle here. Use this function also on Unix systems. gpgme/ 2007-09-27 Marcus Brinkmann * w32-glib-io.c (_gpgme_io_spawn), w32-qt-io.cpp (_gpgme_io_spawn), w32-io.c (_gpgme_io_spawn): Close the process handle, return 0. tests/ 2007-09-27 Marcus Brinkmann * t-engine-info.c (check_engine_info): Fix debug output. * gpg/Makefile.am (tests_unix): New variable. (TESTS): Use it. * gpg/t-support.h (passphrase_cb) [HAVE_W32_SYSTEM]: Use WriteFile instead of write. * gpg/t-wait.c [HAVE_W32_SYSTEM]: Define sleep as _sleep. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/ChangeLog 2007-09-27 13:01:54 UTC (rev 1266) @@ -1,5 +1,8 @@ 2007-09-27 Marcus Brinkmann + * assuan-pipe-connect.c (pipe_connect_gpgme): Do not close process + handle here. Use this function also on Unix systems. + * assuan-pipe-connect.c (pipe_connect_gpgme): Fix last change. * assuan-pipe-connect.c (pipe_connect_gpgme): New function, use it Modified: trunk/assuan/assuan-pipe-connect.c =================================================================== --- trunk/assuan/assuan-pipe-connect.c 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/assuan/assuan-pipe-connect.c 2007-09-27 13:01:54 UTC (rev 1266) @@ -181,6 +181,8 @@ } +#ifndef _ASSUAN_IN_GPGME_BUILD_ASSUAN + #ifndef HAVE_W32_SYSTEM #define pipe_connect pipe_connect_unix /* Unix version of the pipe connection code. We use an extra macro to @@ -365,6 +367,7 @@ return initial_handshake (ctx); } #endif /*!HAVE_W32_SYSTEM*/ +#endif /* _ASSUAN_IN_GPGME_BUILD_ASSUAN */ #ifndef HAVE_W32_SYSTEM @@ -550,6 +553,7 @@ + #ifdef _ASSUAN_IN_GPGME_BUILD_ASSUAN #define pipe_connect pipe_connect_gpgme @@ -570,7 +574,7 @@ void *atforkvalue) { assuan_error_t err; - int pid; + int res; int rp[2]; int wp[2]; char mypidstr[50]; @@ -631,8 +635,8 @@ child_fds[2].fd = -1; /* Start the process. */ - pid = _gpgme_io_spawn (name, argv, child_fds, child_fds); - if (pid == -1) + res = _gpgme_io_spawn (name, argv, child_fds, child_fds); + if (res == -1) { _assuan_log_printf ("CreateProcess failed: %s\n", strerror (errno)); _gpgme_io_close (rp[0]); @@ -642,12 +646,8 @@ return _assuan_error (ASSUAN_General_Error); } - /* ERR contains the PID. */ (*ctx)->pid = 0; /* We don't use the PID. */ - /* FIXME: Should be done by GPGME. */ - CloseHandle ((HANDLE) pid); /* We don't need to wait for the process. */ - return initial_handshake (ctx); } Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/gpgme/ChangeLog 2007-09-27 13:01:54 UTC (rev 1266) @@ -1,5 +1,9 @@ 2007-09-27 Marcus Brinkmann + * w32-glib-io.c (_gpgme_io_spawn), + w32-qt-io.cpp (_gpgme_io_spawn), w32-io.c (_gpgme_io_spawn): Close + the process handle, return 0. + * gpgme.h (gpgme_protocol_t): Add GPGME_PROTOCOL_UNKNOWN. * gpgme.c (gpgme_get_protocol_name): Implement support for GPGME_PROTOCOL_UNKNOWN. Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/gpgme/gpgme.h 2007-09-27 13:01:54 UTC (rev 1266) @@ -73,7 +73,7 @@ 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.6-svn1258" +#define GPGME_VERSION "1.1.6-svn1264" Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/gpgme/w32-glib-io.c 2007-09-27 13:01:54 UTC (rev 1266) @@ -576,7 +576,11 @@ (int) GetLastError ()); TRACE_SUC1 ("process=%p", pi.hProcess); - return 0; + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (0); } Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/gpgme/w32-io.c 2007-09-27 13:01:54 UTC (rev 1266) @@ -1156,7 +1156,11 @@ (int) GetLastError ()); TRACE_SUC1 ("process=%p", pi.hProcess); - return handle_to_pid (pi.hProcess); + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (0); } Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-27 13:01:54 UTC (rev 1266) @@ -525,7 +525,11 @@ (int) GetLastError ()); TRACE_SUC1 ("process=%p", pi.hProcess); - return 0; + + /* We don't need to wait for the process. */ + CloseHandle (pi.hProcess); + + return TRACE_SYSRES (0); } Modified: trunk/tests/ChangeLog =================================================================== --- trunk/tests/ChangeLog 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/tests/ChangeLog 2007-09-27 13:01:54 UTC (rev 1266) @@ -1,3 +1,11 @@ +2007-09-27 Marcus Brinkmann + + * t-engine-info.c (check_engine_info): Fix debug output. + * gpg/Makefile.am (tests_unix): New variable. + (TESTS): Use it. + * gpg/t-support.h (passphrase_cb) [HAVE_W32_SYSTEM]: Use WriteFile instead of write. + * gpg/t-wait.c [HAVE_W32_SYSTEM]: Define sleep as _sleep. + 2007-09-14 Marcus Brinkmann * gpgsm/t-verify.c (main): Release TEXT and SIG. Modified: trunk/tests/gpg/Makefile.am =================================================================== --- trunk/tests/gpg/Makefile.am 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/tests/gpg/Makefile.am 2007-09-27 13:01:54 UTC (rev 1266) @@ -25,12 +25,18 @@ # The keylist tests must come after the import and the edit test. noinst_HEADERS = t-support.h -TESTS = t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \ - t-decrypt t-verify t-decrypt-verify t-sig-notation \ - t-export t-import t-trustlist t-eventloop t-edit \ - t-keylist t-keylist-sig t-thread1 t-wait t-encrypt-large \ - t-file-name +if HAVE_W32_SYSTEM +tests_unix = +else +tests_unix = t-eventloop t-thread1 +endif + +TESTS = t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \ + t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \ + t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \ + t-encrypt-large t-file-name $(tests_unix) + CLEANFILES = secring.gpg pubring.gpg trustdb.gpg DISTCLEANFILES = pubring.gpg~ random_seed gpg.conf Modified: trunk/tests/gpg/t-support.h =================================================================== --- trunk/tests/gpg/t-support.h 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/tests/gpg/t-support.h 2007-09-27 13:01:54 UTC (rev 1266) @@ -24,6 +24,10 @@ #include #include +#ifdef HAVE_W32_SYSTEM +#include +#endif + #include #ifndef DIM @@ -65,7 +69,13 @@ passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd) { +#ifdef HAVE_W32_SYSTEM + DWORD written; + WriteFile ((HANDLE) fd, "abc\n", 4, &written, 0); +#else write (fd, "abc\n", 4); +#endif + return 0; } Modified: trunk/tests/gpg/t-wait.c =================================================================== --- trunk/tests/gpg/t-wait.c 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/tests/gpg/t-wait.c 2007-09-27 13:01:54 UTC (rev 1266) @@ -1,6 +1,6 @@ /* t-wait.c - Regression test. Copyright (C) 2000 Werner Koch (dd9jn) - Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH This file is part of GPGME. @@ -29,6 +29,10 @@ #include #include +#ifdef HAVE_W32_SYSTEM +#define sleep _sleep +#endif + #include #include "t-support.h" Modified: trunk/tests/t-engine-info.c =================================================================== --- trunk/tests/t-engine-info.c 2007-09-27 12:17:24 UTC (rev 1265) +++ trunk/tests/t-engine-info.c 2007-09-27 13:01:54 UTC (rev 1266) @@ -1,5 +1,5 @@ /* t-engine-info.c - Regression test for gpgme_get_engine_info. - Copyright (C) 2003, 2004 g10 Code GmbH + Copyright (C) 2003, 2004, 2007 g10 Code GmbH This file is part of GPGME. @@ -54,13 +54,13 @@ } if (strcmp (info->file_name, file_name)) { - fprintf (stderr, "Unexpected file name to executable %s (expected %s instead)", + fprintf (stderr, "Unexpected file name to executable %s (expected %s instead)\n", info->file_name, file_name); exit (1); } if (strcmp (info->req_version, req_version)) { - fprintf (stderr, "Unexpected required version %s (expected %s instead)", + fprintf (stderr, "Unexpected required version %s (expected %s instead)\n", info->req_version, req_version); exit (1); } From cvs at cvs.gnupg.org Thu Sep 27 16:00:34 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 27 Sep 2007 16:00:34 +0200 Subject: [svn] gpg-error - r199 - in trunk: . src Message-ID: Author: marcus Date: 2007-09-27 16:00:25 +0200 (Thu, 27 Sep 2007) New Revision: 199 Modified: trunk/ChangeLog trunk/src/Makefile.am Log: 2007-09-27 Marcus Brinkmann * src/Makefile.am (%.o): Replace pattern rule with suffix rule. (SUFFIXES): New variable. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-27 05:17:43 UTC (rev 198) +++ trunk/ChangeLog 2007-09-27 14:00:25 UTC (rev 199) @@ -1,3 +1,8 @@ +2007-09-27 Marcus Brinkmann + + * src/Makefile.am (%.o): Replace pattern rule with suffix rule. + (SUFFIXES): New variable. + 2007-09-27 Werner Koch * src/err-sources.h.in (GPG_ERR_SOURCE_GPA): New. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-09-27 05:17:43 UTC (rev 198) +++ trunk/src/Makefile.am 2007-09-27 14:00:25 UTC (rev 199) @@ -54,7 +54,9 @@ `echo $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) | \ sed -e 's/-I/--include-dir /g;s/-D/--define /g'` -%.o : %.rc +SUFFIXES = rc + +.rc.o: $(LTRCCOMPILE) -i $< -o $@ gpg_error_res = versioninfo.o From cvs at cvs.gnupg.org Fri Sep 28 00:21:20 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 28 Sep 2007 00:21:20 +0200 Subject: [svn] gpgme - r1267 - trunk/gpgme Message-ID: Author: marcus Date: 2007-09-28 00:21:10 +0200 (Fri, 28 Sep 2007) New Revision: 1267 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/kdpipeiodevice.moc trunk/gpgme/w32-qt-io.cpp Log: 2007-09-28 Marcus Brinkmann * kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New versions from Frank Osterfeld. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 13:01:54 UTC (rev 1266) +++ trunk/gpgme/ChangeLog 2007-09-27 22:21:10 UTC (rev 1267) @@ -1,3 +1,8 @@ +2007-09-28 Marcus Brinkmann + + * kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New + versions from Frank Osterfeld. + 2007-09-27 Marcus Brinkmann * w32-glib-io.c (_gpgme_io_spawn), Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-09-27 13:01:54 UTC (rev 1266) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-09-27 22:21:10 UTC (rev 1267) @@ -51,7 +51,7 @@ const bool ALLOW_QIODEVICE_BUFFERING = true; // comment to get trace output: -#define qDebug if(1){}else qDebug +//#define qDebug if(1){}else qDebug namespace { class Reader : public QThread { @@ -81,7 +81,7 @@ return true; return false; } - + Q_SIGNALS: void readyRead(); @@ -188,7 +188,8 @@ Writer::~Writer() {} -class KDPipeIODevice::Private { +class KDPipeIODevice::Private : public QObject { +Q_OBJECT friend class ::KDPipeIODevice; KDPipeIODevice * const q; public: @@ -196,6 +197,11 @@ ~Private(); bool doOpen( int, Qt::HANDLE, OpenMode ); + bool startReaderThread(); + bool startWriterThread(); + void stopThreads(); + bool triedToStartReader; + bool triedToStartWriter; private: int fd; @@ -205,19 +211,18 @@ }; KDPipeIODevice::Private::Private( KDPipeIODevice * qq ) - : q( qq ), + : QObject( qq ), q( qq ), fd( -1 ), handle( 0 ), reader( 0 ), - writer( 0 ) + writer( 0 ), + triedToStartReader( false ), triedToStartWriter( false ) { } - KDPipeIODevice::Private::~Private() {} - KDPipeIODevice::KDPipeIODevice( QObject * p ) : QIODevice( p ), d( new Private( this ) ) { @@ -267,6 +272,36 @@ } +bool KDPipeIODevice::Private::startReaderThread() +{ + if ( triedToStartReader ) + return true; + triedToStartReader = true; + if ( reader && !reader->isRunning() && !reader->isFinished() ) { + LOCKED( reader ); + + reader->start( QThread::HighestPriority ); + if ( !reader->hasStarted.wait( &reader->mutex, 1000 ) ) + return false; + } + return true; +} + +bool KDPipeIODevice::Private::startWriterThread() +{ + if ( triedToStartWriter ) + return true; + triedToStartWriter = true; + if ( writer && !writer->isRunning() && !writer->isFinished() ) { + LOCKED( writer ); + + writer->start( QThread::HighestPriority ); + if ( !writer->hasStarted.wait( &writer->mutex, 1000 ) ) + return false; + } + return true; +} + bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) { if ( q->isOpen() || fd_ < 0 ) @@ -288,19 +323,15 @@ if ( mode_ & ReadOnly ) { reader_.reset( new Reader( fd_, handle_ ) ); - LOCKED( reader_ ); - reader_->start( QThread::HighestPriority ); - if ( !reader_->hasStarted.wait( &reader_->mutex, 1000 ) ) - return false; - connect( reader_.get(), SIGNAL(readyRead()), q, SIGNAL(readyRead()), Qt::QueuedConnection ); + qDebug( "KDPipeIODevice::doOpen: created reader for fd %d", fd_ ); + connect( reader_.get(), SIGNAL(readyRead()), q, +SIGNAL(readyRead()), Qt::QueuedConnection ); } if ( mode_ & WriteOnly ) { writer_.reset( new Writer( fd_, handle_ ) ); - LOCKED( writer_ ); - writer_->start( QThread::HighestPriority ); - if ( !writer_->hasStarted.wait( &writer_->mutex, 1000 ) ) - return false; - connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection ); + qDebug( "KDPipeIODevice::doOpen: created writer for fd %d", fd_ ); + connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), +Qt::QueuedConnection ); } // commit to *this: @@ -310,7 +341,6 @@ writer = writer_.release(); q->setOpenMode( mode_|Unbuffered ); - return true; } @@ -318,18 +348,24 @@ return d->fd; } + Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS; return d->handle; } qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS; const qint64 base = QIODevice::bytesAvailable(); + if ( !d->triedToStartReader ) { + d->startReaderThread(); + return base; + } if ( d->reader ) synchronized( d->reader ) return base + d->reader->bytesInBuffer(); return base; } qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS; + d->startWriterThread(); const qint64 base = QIODevice::bytesToWrite(); if ( d->writer ) synchronized( d->writer ) return base + d->writer->bytesInBuffer(); @@ -337,7 +373,8 @@ } bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS; - if ( QIODevice::canReadLine() ) + d->startReaderThread(); + if ( QIODevice::canReadLine() ) return true; if ( d->reader ) synchronized( d->reader ) return d->reader->bufferContains( '\n' ); @@ -349,8 +386,9 @@ } bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS; + d->startReaderThread(); if ( !QIODevice::atEnd() ) { - qDebug( "KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", static_cast(bytesAvailable()) ); + qDebug( "%p: KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", this, static_cast(bytesAvailable()) ); return false; } if ( !isOpen() ) @@ -361,14 +399,15 @@ const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty(); if ( !eof ) { if ( !d->reader->error && !d->reader->eof ) - qDebug( "KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof" ); + qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof", this ); if ( !d->reader->bufferEmpty() ) - qDebug( "KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()" ); + qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()", this ); } return eof; } bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS; + d->startWriterThread(); Writer * const w = d->writer; if ( !w ) return true; @@ -377,6 +416,7 @@ } bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS; + d->startReaderThread(); if ( ALLOW_QIODEVICE_BUFFERING ) { if ( bytesAvailable() > 0 ) return true; @@ -389,18 +429,22 @@ } qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS; + qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize ); - qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld", data, maxSize ); + if ( maxSize == 0 ) + return 0; + d->startReaderThread(); Reader * const r = d->reader; assert( r ); + //assert( r->isRunning() ); // wrong (might be eof, error) assert( data || maxSize == 0 ); assert( maxSize >= 0 ); if ( r->eofShortCut ) { - qDebug( "KDPipeIODevice::readData: hit eofShortCut, returning 0" ); + qDebug( "%p: KDPipeIODevice::readData: hit eofShortCut, returning 0", this ); return 0; } @@ -414,31 +458,31 @@ LOCKED( r ); if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? - qDebug( "KDPipeIODevice::readData: waiting for bufferNotEmptyCondition" ); + qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition", this ); r->bufferNotEmptyCondition.wait( &r->mutex ); } if ( r->bufferEmpty() ) { - qDebug( "KDPipeIODevice::readData: got empty buffer, signal eof" ); + qDebug( "%p: KDPipeIODevice::readData: got empty buffer, signal eof", this ); // woken with an empty buffer must mean either EOF or error: assert( r->eof || r->error ); r->eofShortCut = true; return r->eof ? 0 : -1 ; } - qDebug( "KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", maxSize ); + qDebug( "%p: KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", this, maxSize ); const qint64 bytesRead = r->readData( data, maxSize ); - qDebug( "KDPipeIODevice::readData: read %lld bytes", bytesRead ); + qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead ); + qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data ); return bytesRead; } qint64 Reader::readData( char * data, qint64 maxSize ) { - qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ; if ( numRead > maxSize ) numRead = maxSize; - qDebug( "KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", + qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", this, data, maxSize, rptr, wptr, bytesInBuffer(), numRead ); std::memcpy( data, buffer + rptr, numRead ); @@ -446,7 +490,7 @@ rptr = ( rptr + numRead ) % sizeof buffer ; if ( !bufferFull() ) { - qDebug( "KDPipeIODevice::readData: signal bufferNotFullCondition" ); + qDebug( "%p: KDPipeIODevice::readData: signal bufferNotFullCondition", this ); bufferNotFullCondition.wakeAll(); } @@ -454,7 +498,7 @@ } qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS; - + d->startWriterThread(); Writer * const w = d->writer; assert( w ); @@ -476,7 +520,6 @@ } qint64 Writer::writeData( const char * data, qint64 size ) { - assert( bufferEmpty() ); if ( size > static_cast( sizeof buffer ) ) @@ -492,40 +535,47 @@ return size; } -void KDPipeIODevice::close() { KDAB_CHECK_THIS; +void KDPipeIODevice::Private::stopThreads() +{ + if ( triedToStartWriter ) + { + if ( writer && q->bytesToWrite() > 0 ) + q->waitForBytesWritten( -1 ); - if ( !isOpen() ) - return; - - // tell clients we're about to close: - emit aboutToClose(); - - if ( d->writer && bytesToWrite() > 0 ) - waitForBytesWritten( -1 ); - - assert( bytesToWrite() == 0 ); - - if ( Reader * & r = d->reader ) { + assert( q->bytesToWrite() == 0 ); + } + if ( Reader * & r = reader ) { synchronized( r ) { // tell thread to cancel: r->cancel = true; // and wake it, so it can terminate: r->bufferNotFullCondition.wakeAll(); } - r->wait(); - delete r; r = 0; } - if ( Writer * & w = d->writer ) { + if ( Writer * & w = writer ) { synchronized( w ) { // tell thread to cancel: w->cancel = true; // and wake it, so it can terminate: w->bufferNotEmptyCondition.wakeAll(); } - w->wait(); - delete w; w = 0; } +} +void KDPipeIODevice::close() { KDAB_CHECK_THIS; + + if ( !isOpen() ) + return; + + // tell clients we're about to close: + emit aboutToClose(); + d->stopThreads(); + +#define waitAndDelete( t ) if ( t ) { t->wait(); delete t; t = 0; } + waitAndDelete( d->writer ); + waitAndDelete( d->reader ); +#undef waitAndDelete + #ifdef Q_OS_WIN32 CloseHandle( d->handle ); #else @@ -544,19 +594,19 @@ // too bad QThread doesn't have that itself; a signal isn't enough hasStarted.wakeAll(); - qDebug( "Reader::run: started" ); + qDebug( "%p: Reader::run: started", this ); while ( true ) { while ( !cancel && bufferFull() ) { bufferNotEmptyCondition.wakeAll(); - qDebug( "Reader::run: buffer is full, going to sleep" ); + qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); bufferNotFullCondition.wait( &mutex ); - qDebug( "Reader::run: woke up" ); + qDebug( "%p: Reader::run: woke up", this ); } if ( cancel ) { - qDebug( "Reader::run: detected cancel" ); + qDebug( "%p: Reader::run: detected cancel", this ); goto leave; } @@ -567,11 +617,11 @@ if ( numBytes > sizeof buffer - wptr ) numBytes = sizeof buffer - wptr; - qDebug( "Reader::run: rptr=%d, wptr=%d -> numBytes=%d", rptr, wptr, numBytes ); + qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes ); assert( numBytes > 0 ); - qDebug( "Reader::run: trying to read %d bytes", numBytes ); + qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes ); #ifdef Q_OS_WIN32 DWORD numRead; mutex.unlock(); @@ -580,10 +630,10 @@ if ( !ok ) { errorCode = static_cast( GetLastError() ); if ( errorCode == ERROR_BROKEN_PIPE ) { - qDebug( "Reader::run: got eof" ); + qDebug( "%p: Reader::run: got eof (broken pipe)", this ); eof = true; } else { - qDebug( "Reader::run: got error: %d", errorCode ); + qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode ); error = true; } goto leave; @@ -599,32 +649,33 @@ if ( numRead < 0 ) { errorCode = errno; error = true; - qDebug( "Reader::run: got error: %d", errorCode ); + qDebug( "%p: Reader::run: got error: %d", this, errorCode ); goto leave; } #endif - qDebug( "Reader::run: read %ld bytes", static_cast(numRead) ); + qDebug( "%p: Reader::run: read %ld bytes", this, static_cast(numRead) ); + qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, fd, buffer ); if ( numRead == 0 ) { - qDebug( "Reader::run: eof detected" ); + qDebug( "%p: Reader::run: eof detected", this ); eof = true; goto leave; } if ( cancel ) { - qDebug( "Reader::run: detected cancel" ); + qDebug( "%p: Reader::run: detected cancel", this ); goto leave; } - qDebug( "Reader::run: buffer before: rptr=%4d, wptr=%4d", rptr, wptr ); + qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); wptr = ( wptr + numRead ) % sizeof buffer; - qDebug( "Reader::run: buffer after: rptr=%4d, wptr=%4d", rptr, wptr ); + qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr ); if ( !bufferEmpty() ) { - qDebug( "Reader::run: buffer no longer empty, waking everyone" ); + qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); bufferNotEmptyCondition.wakeAll(); emit readyRead(); } } leave: - qDebug( "Reader::run: terminating" ); + qDebug( "%p: Reader::run: terminating", this ); bufferNotEmptyCondition.wakeAll(); emit readyRead(); } @@ -636,25 +687,25 @@ // too bad QThread doesn't have that itself; a signal isn't enough hasStarted.wakeAll(); - qDebug( "Writer::run: started" ); + qDebug( "%p: Writer::run: started", this ); while ( true ) { while ( !cancel && bufferEmpty() ) { bufferEmptyCondition.wakeAll(); - qDebug( "Writer::run: buffer is empty, going to sleep" ); + qDebug( "%p: Writer::run: buffer is empty, going to sleep", this ); bufferNotEmptyCondition.wait( &mutex ); - qDebug( "Writer::run: woke up" ); + qDebug( "%p: Writer::run: woke up", this ); } if ( cancel ) { - qDebug( "Writer::run: detected cancel" ); + qDebug( "%p: Writer::run: detected cancel", this ); goto leave; } assert( numBytesInBuffer > 0 ); - qDebug( "Writer::run: Trying to write %u bytes", numBytesInBuffer ); + qDebug( "%p: Writer::run: Trying to write %u bytes", this, numBytesInBuffer ); qint64 totalWritten = 0; do { mutex.unlock(); @@ -663,7 +714,7 @@ if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) { mutex.lock(); errorCode = static_cast( GetLastError() ); - qDebug( "Writer::run: got error code: %d", errorCode ); + qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); error = true; goto leave; } @@ -676,7 +727,7 @@ if ( numWritten < 0 ) { mutex.lock(); errorCode = errno; - qDebug( "Writer::run: got error code: %d", errorCode ); + qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); error = true; goto leave; } @@ -685,14 +736,14 @@ mutex.lock(); } while ( totalWritten < numBytesInBuffer ); - qDebug( "Writer::run: wrote %lld bytes", totalWritten ); + qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten ); numBytesInBuffer = 0; bufferEmptyCondition.wakeAll(); emit bytesWritten( totalWritten ); } leave: - qDebug( "Writer::run: terminating" ); + qDebug( "%p: Writer::run: terminating", this ); numBytesInBuffer = 0; bufferEmptyCondition.wakeAll(); emit bytesWritten( 0 ); Modified: trunk/gpgme/kdpipeiodevice.moc =================================================================== --- trunk/gpgme/kdpipeiodevice.moc 2007-09-27 13:01:54 UTC (rev 1266) +++ trunk/gpgme/kdpipeiodevice.moc 2007-09-27 22:21:10 UTC (rev 1267) @@ -1,8 +1,8 @@ /**************************************************************************** ** Meta object code from reading C++ file 'kdpipeiodevice.cpp' ** -** Created: Mon Aug 27 15:17:18 2007 -** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0) +** Created: Wed Sep 26 11:05:05 2007 +** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ @@ -10,7 +10,7 @@ #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'kdpipeiodevice.cpp' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 59 -#error "This file was generated using the moc from 4.3.0. It" +#error "This file was generated using the moc from 4.3.1. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif @@ -130,3 +130,45 @@ void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 0, _a); } +static const uint qt_meta_data_KDPipeIODevice__Private[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + + 0 // eod +}; + +static const char qt_meta_stringdata_KDPipeIODevice__Private[] = { + "KDPipeIODevice::Private\0" +}; + +const QMetaObject KDPipeIODevice::Private::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_KDPipeIODevice__Private, + qt_meta_data_KDPipeIODevice__Private, 0 } +}; + +const QMetaObject *KDPipeIODevice::Private::metaObject() const +{ + return &staticMetaObject; +} + +void *KDPipeIODevice::Private::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice__Private)) + return static_cast(const_cast< Private*>(this)); + return QObject::qt_metacast(_clname); +} + +int KDPipeIODevice::Private::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-27 13:01:54 UTC (rev 1266) +++ trunk/gpgme/w32-qt-io.cpp 2007-09-27 22:21:10 UTC (rev 1267) @@ -82,12 +82,20 @@ really nice callback interfaces to let the user control all this at a per-context level. */ - -#define MAX_SLAFD 256 +#define MAX_SLAFD 50000 -QIODevice *iodevice_table[MAX_SLAFD]; +struct DeviceEntry { + DeviceEntry() : iodev( 0 ), actual_fd( -1 ), refCount( 1 ) {} + QIODevice* iodev; + int actual_fd; + mutable int refCount; + void ref() const { ++refCount; } + int unref() const { return --refCount; } +}; +DeviceEntry* iodevice_table[MAX_SLAFD]; + static QIODevice * find_channel (int fd, int create) { @@ -95,13 +103,16 @@ return NULL; if (create && !iodevice_table[fd]) - iodevice_table[fd] = new KDPipeIODevice - (fd, QIODevice::ReadOnly|QIODevice::Unbuffered); - - return iodevice_table[fd]; + { + DeviceEntry* entry = new DeviceEntry; + entry->actual_fd = fd; + entry->iodev = new KDPipeIODevice + (fd, QIODevice::ReadWrite|QIODevice::Unbuffered); + iodevice_table[fd] = entry; + } + return iodevice_table[fd] ? iodevice_table[fd]->iodev : 0; } - /* 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. */ @@ -232,7 +243,9 @@ /* Now we have a pipe with the right end inheritable. The other end should have a giochannel. */ + chan = find_channel (filedes[1 - inherit_idx], 1); + if (!chan) { int saved_errno = errno; @@ -248,7 +261,6 @@ chan); } - int _gpgme_io_close (int fd) { @@ -270,16 +282,29 @@ } /* Then do the close. */ - chan = iodevice_table[fd]; - if (chan) - { - chan->close(); - delete chan; - iodevice_table[fd] = NULL; + + DeviceEntry* const entry = iodevice_table[fd]; + if ( entry ) + { + assert( entry->refCount > 0 ); + const int actual_fd = entry->actual_fd; + assert( actual_fd > 0 ); + if ( !entry->unref() ) { + entry->iodev->close(); + delete entry->iodev; + delete entry; + for ( int i = 0; i < MAX_SLAFD; ++i ) { + if ( iodevice_table[i] == entry ) + iodevice_table[i] = 0; + } } + + if ( fd != actual_fd ) + _close( fd ); + } else _close (fd); - + return 0; } @@ -334,7 +359,7 @@ /* The leading double-quote. */ n++; while (*p) - { + { /* An extra one for each literal that must be escaped. */ if (*p == '\\' || *p == '"') n++; @@ -586,13 +611,6 @@ } -int -_gpgme_io_dup (int fd) -{ - return _dup (fd); -} - - /* Look up the qiodevice for file descriptor FD. */ extern "C" void * @@ -610,3 +628,16 @@ return NULL; } + +int +_gpgme_io_dup (int fd) +{ + const int new_fd = _dup( fd ); + iodevice_table[new_fd] = iodevice_table[fd]; + if ( iodevice_table[new_fd] ) + iodevice_table[new_fd]->ref(); + else + find_channel( new_fd, /*create=*/1 ); + return new_fd; +} + From cvs at cvs.gnupg.org Fri Sep 28 18:24:03 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 28 Sep 2007 18:24:03 +0200 Subject: [svn] gpgme - r1268 - trunk/gpgme Message-ID: Author: wk Date: 2007-09-28 18:23:53 +0200 (Fri, 28 Sep 2007) New Revision: 1268 Modified: trunk/gpgme/ChangeLog trunk/gpgme/engine-gpgsm.c trunk/gpgme/gpgme.h trunk/gpgme/posix-io.c trunk/gpgme/priv-io.h trunk/gpgme/rungpg.c trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-io.c trunk/gpgme/wait.c Log: Fixed the external event loop for glib. Add a bit more tracing. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/ChangeLog 2007-09-28 16:23:53 UTC (rev 1268) @@ -1,3 +1,23 @@ +2007-09-28 Werner Koch + + * w32-glib-io.c (find_channel): Add a new primary flag. + (_gpgme_io_close): Close channel only if primary. + (_gpgme_io_dup): Put newfd into the table as shallow copy. + + * priv-io.h (struct io_select_fd_s): Remove member FROZEN. + * w32-io.c (_gpgme_io_select): Ditto. + * w32-glib-io.c (_gpgme_io_select): Ditto. + + * posix-io.c (_gpgme_io_select): Ditto. + * rungpg.c (read_status): Ditto. + * wait.c (fd_table_put): Ditto. + + * rungpg.c (gpg_io_event): Add tracing. + (start): Use gpg_io_event for sending the start event. + * engine-gpgsm.c (gpgsm_io_event): Add tracing. + (start): Use gpgsm_io_event for sending the start event. + * wait.c (_gpgme_add_io_cb, _gpgme_run_io_cb): Add tracing. + 2007-09-28 Marcus Brinkmann * kdpipeiodevice.moc, w32-qt-io.cpp, kdpipeiodevice.cpp: New Modified: trunk/gpgme/engine-gpgsm.c =================================================================== --- trunk/gpgme/engine-gpgsm.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/engine-gpgsm.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -96,6 +96,11 @@ typedef struct engine_gpgsm *engine_gpgsm_t; + +static void gpgsm_io_event (void *engine, + gpgme_event_io_t type, void *type_data); + + static char * gpgsm_get_version (const char *file_name) @@ -846,10 +851,10 @@ gpgsm->colon.any = 0; err = gpgsm->colon.fnc (gpgsm->colon.fnc_value, NULL); } - _gpgme_io_close (gpgsm->status_cb.fd); TRACE2 (DEBUG_CTX, "gpgme:status_handler", gpgsm, "fd 0x%x: OK line - final status: %s", fd, err ? gpg_strerror (err) : "ok"); + _gpgme_io_close (gpgsm->status_cb.fd); return err; } else if (linelen > 2 @@ -963,15 +968,17 @@ { gpgme_error_t err; + TRACE_BEG2 (DEBUG_ENGINE, "engine-gpgsm:add_io_cb", gpgsm, + "fd %d, dir %d", iocbd->fd, iocbd->dir); err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv, iocbd->fd, iocbd->dir, handler, iocbd->data, &iocbd->tag); if (err) - return err; + return TRACE_ERR (err); if (!iocbd->dir) /* FIXME Kludge around poll() problem. */ err = _gpgme_io_set_nonblocking (iocbd->fd); - return err; + return TRACE_ERR (err); } @@ -1020,7 +1027,7 @@ 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); + gpgsm_io_event (gpgsm, GPGME_EVENT_START, NULL); return err; } @@ -1713,6 +1720,9 @@ { engine_gpgsm_t gpgsm = engine; + TRACE3 (DEBUG_ENGINE, "gpgme:gpgsm_io_event", gpgsm, + "event %p, type %d, type_data %p", + gpgsm->io_cbs.event, type, type_data); if (gpgsm->io_cbs.event) (*gpgsm->io_cbs.event) (gpgsm->io_cbs.event_priv, type, type_data); } Modified: trunk/gpgme/gpgme.h =================================================================== --- trunk/gpgme/gpgme.h 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/gpgme.h 2007-09-28 16:23:53 UTC (rev 1268) @@ -73,7 +73,7 @@ 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.6-svn1264" +#define GPGME_VERSION "1.1.6-svn1258" Modified: trunk/gpgme/posix-io.c =================================================================== --- trunk/gpgme/posix-io.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/posix-io.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -393,9 +393,7 @@ { if (fds[i].fd == -1) continue; - if (fds[i].frozen) - TRACE_ADD1 (dbg_help, "f0x%x ", fds[i].fd); - else if (fds[i].for_read) + if (fds[i].for_read) { assert (!FD_ISSET (fds[i].fd, &readfds)); FD_SET (fds[i].fd, &readfds); Modified: trunk/gpgme/priv-io.h =================================================================== --- trunk/gpgme/priv-io.h 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/priv-io.h 2007-09-28 16:23:53 UTC (rev 1268) @@ -37,7 +37,6 @@ int for_read; int for_write; int signaled; - int frozen; void *opaque; }; Modified: trunk/gpgme/rungpg.c =================================================================== --- trunk/gpgme/rungpg.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/rungpg.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -136,6 +136,9 @@ { engine_gpg_t gpg = engine; + TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg, + "event %p, type %d, type_data %p", + gpg->io_cbs.event, type, type_data); if (gpg->io_cbs.event) (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data); } @@ -1044,7 +1047,6 @@ gpg->fd_data_map[gpg->cmd.linked_idx].fd; fds.for_read = 1; fds.for_write = 0; - fds.frozen = 0; fds.opaque = NULL; do { @@ -1354,7 +1356,7 @@ } } - (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL); + gpg_io_event (gpg, GPGME_EVENT_START, NULL); /* fixme: check what data we can release here */ return 0; Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/w32-glib-io.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -78,7 +78,11 @@ #define MAX_SLAFD 256 -GIOChannel *giochannel_table[MAX_SLAFD]; +static struct +{ + GIOChannel *chan; + int primary; /* Set if CHAN is the one we used to create the channel. */ +} giochannel_table[MAX_SLAFD]; static GIOChannel * @@ -87,14 +91,15 @@ if (fd < 0 || fd >= MAX_SLAFD) return NULL; - if (create && !giochannel_table[fd]) + if (create && !giochannel_table[fd].chan) { - giochannel_table[fd] = g_io_channel_win32_new_fd (fd); - g_io_channel_set_encoding (giochannel_table[fd], NULL, NULL); - g_io_channel_set_buffered (giochannel_table[fd], FALSE); + giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd); + giochannel_table[fd].primary = 1; + g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL); + g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE); } - return giochannel_table[fd]; + return giochannel_table[fd].chan; } @@ -279,7 +284,6 @@ int _gpgme_io_close (int fd) { - GIOChannel *chan; TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); if (fd < 0 || fd >= MAX_SLAFD) @@ -297,16 +301,19 @@ } /* Then do the close. */ - chan = giochannel_table[fd]; - if (chan) + if (giochannel_table[fd].chan) { - g_io_channel_shutdown (chan, 1, NULL); - g_io_channel_unref (chan); - giochannel_table[fd] = NULL; + if (giochannel_table[fd].primary) + { + g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL); + g_io_channel_unref (giochannel_table[fd].chan); + } + giochannel_table[fd].chan = NULL; } else _close (fd); + TRACE_SUC (); return 0; } @@ -621,14 +628,21 @@ any = 0; for (i = 0; i < nfds; i++) { + GIOChannel *chan = NULL; + if (fds[i].fd == -1) continue; - if (fds[i].frozen) - TRACE_ADD1 (dbg_help, "f0x%x ", fds[i].fd); + + if ((fds[i].for_read || fds[i].for_write) + && !(chan = find_channel (fds[i].fd, 0))) + { + TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd); + TRACE_END (dbg_help, "]"); + assert (!"see log file"); + } else if (fds[i].for_read ) { - GIOChannel *chan = find_channel (fds[i].fd, 0); - assert (chan); + assert(chan); g_io_channel_win32_make_pollfd (chan, G_IO_IN, pollfds + npollfds); pollfds_map[npollfds] = i; TRACE_ADD2 (dbg_help, "r0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); @@ -637,8 +651,7 @@ } else if (fds[i].for_write) { - GIOChannel *chan = find_channel (fds[i].fd, 0); - assert (chan); + assert(chan); g_io_channel_win32_make_pollfd (chan, G_IO_OUT, pollfds + npollfds); pollfds_map[npollfds] = i; TRACE_ADD2 (dbg_help, "w0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); @@ -711,5 +724,45 @@ int _gpgme_io_dup (int fd) { - return _dup (fd); + int newfd; + GIOChannel *chan; + + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd); + + newfd =_dup (fd); + if (newfd == -1) + return TRACE_SYSRES (-1); + if (newfd < 0 || newfd >= MAX_SLAFD) + { + /* New fd won't fit into our table. */ + _close (newfd); + errno = EIO; + return TRACE_SYSRES (-1); + } + + chan = find_channel (fd, 0); + if (!chan) + { + /* No channel exists for the original fd, thus we create one for + our new fd. */ + if ( !find_channel (newfd, 1) ) + { + _close (newfd); + errno = EIO; + return TRACE_SYSRES (-1); + } + } + else + { + /* There is already a channel for the original one. Copy that + channel into a new table entry unless we already did so. */ + if ( !giochannel_table[newfd].chan) + { + giochannel_table[newfd].chan = chan; + giochannel_table[newfd].primary = 0; + } + assert (giochannel_table[newfd].chan == chan); + } + + return TRACE_SYSRES (newfd); } Modified: trunk/gpgme/w32-io.c =================================================================== --- trunk/gpgme/w32-io.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/w32-io.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -1192,9 +1192,7 @@ fds[i].signaled = 0; if (fds[i].for_read || fds[i].for_write) { - if (fds[i].frozen) - TRACE_ADD1 (dbg_help, "f0x%x ", fds[i].fd); - else if (fds[i].for_read) + if (fds[i].for_read) { struct reader_context_s *ctx = find_reader (fds[i].fd,1); Modified: trunk/gpgme/wait.c =================================================================== --- trunk/gpgme/wait.c 2007-09-27 22:21:10 UTC (rev 1267) +++ trunk/gpgme/wait.c 2007-09-28 16:23:53 UTC (rev 1268) @@ -82,7 +82,6 @@ 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; @@ -136,6 +135,9 @@ return err; } + TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx, + "fd %d, dir=%d -> tag=%p", fd, dir, tag); + *r_tag = tag; return 0; } @@ -189,6 +191,7 @@ int nr; struct io_select_fd_s fds; + TRACE0 (DEBUG_CTX, "_gpgme_run_io_cb", item, "need to check"); fds = *an_fds; fds.signaled = 0; /* Just give it a quick poll. */ @@ -202,5 +205,7 @@ return 0; } + TRACE2 (DEBUG_CTX, "_gpgme_run_io_cb", item, "handler (%p, %d)", + item->handler_value, an_fds->fd); return item->handler (item->handler_value, an_fds->fd); } From cvs at cvs.gnupg.org Fri Sep 28 19:30:21 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 28 Sep 2007 19:30:21 +0200 Subject: [svn] gpgme - r1269 - trunk/gpgme Message-ID: Author: wk Date: 2007-09-28 19:30:11 +0200 (Fri, 28 Sep 2007) New Revision: 1269 Modified: trunk/gpgme/ChangeLog trunk/gpgme/engine-gpgsm.c trunk/gpgme/w32-glib-io.c Log: Fixed a problem in the W32 gpgme->gpgsm communication. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-28 16:23:53 UTC (rev 1268) +++ trunk/gpgme/ChangeLog 2007-09-28 17:30:11 UTC (rev 1269) @@ -1,5 +1,9 @@ 2007-09-28 Werner Koch + * engine-gpgsm.c (iocb_data_t): Add SERVER_FD_STR. + (gpgsm_new): Set it. + (gpgsm_set_fd): Use it. + * w32-glib-io.c (find_channel): Add a new primary flag. (_gpgme_io_close): Close channel only if primary. (_gpgme_io_dup): Put newfd into the table as shallow copy. Modified: trunk/gpgme/engine-gpgsm.c =================================================================== --- trunk/gpgme/engine-gpgsm.c 2007-09-28 16:23:53 UTC (rev 1268) +++ trunk/gpgme/engine-gpgsm.c 2007-09-28 17:30:11 UTC (rev 1269) @@ -49,10 +49,13 @@ typedef struct { int fd; /* FD we talk about. */ - int server_fd; /* Server FD for this connection. */ + 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. */ + char server_fd_str[15]; /* Same as SERVER_FD but as a string. We + need this because _gpgme_io_fdstr can't + be used on a closed descriptor. */ } iocb_data_t; @@ -351,14 +354,17 @@ gpgsm->input_cb.dir = 0; gpgsm->input_cb.tag = 0; gpgsm->input_cb.server_fd = -1; + *gpgsm->input_cb.server_fd_str = 0; gpgsm->output_cb.fd = -1; gpgsm->output_cb.dir = 1; gpgsm->output_cb.tag = 0; gpgsm->output_cb.server_fd = -1; + *gpgsm->output_cb.server_fd_str = 0; gpgsm->message_cb.fd = -1; gpgsm->message_cb.dir = 0; gpgsm->message_cb.tag = 0; gpgsm->message_cb.server_fd = -1; + *gpgsm->message_cb.server_fd_str = 0; gpgsm->status.fnc = 0; gpgsm->colon.fnc = 0; @@ -381,6 +387,9 @@ } gpgsm->input_cb.fd = fds[1]; gpgsm->input_cb.server_fd = fds[0]; + _gpgme_io_fd2str (gpgsm->input_cb.server_fd_str, + sizeof gpgsm->input_cb.server_fd_str, + gpgsm->input_cb.server_fd); if (_gpgme_io_pipe (fds, 1) < 0) { @@ -389,6 +398,9 @@ } gpgsm->output_cb.fd = fds[0]; gpgsm->output_cb.server_fd = fds[1]; + _gpgme_io_fd2str (gpgsm->output_cb.server_fd_str, + sizeof gpgsm->output_cb.server_fd_str, + gpgsm->output_cb.server_fd); if (_gpgme_io_pipe (fds, 0) < 0) { @@ -397,6 +409,9 @@ } gpgsm->message_cb.fd = fds[1]; gpgsm->message_cb.server_fd = fds[0]; + _gpgme_io_fd2str (gpgsm->message_cb.server_fd_str, + sizeof gpgsm->message_cb.server_fd_str, + gpgsm->message_cb.server_fd); child_fds[0] = gpgsm->input_cb.server_fd; child_fds[1] = gpgsm->output_cb.server_fd; @@ -672,7 +687,6 @@ char *which; iocb_data_t *iocb_data; int dir; - int fd; switch (fd_type) { @@ -718,16 +732,13 @@ goto leave_set_fd; } } -#endif - fd = iocb_data->server_fd; - -#if USE_DESCRIPTOR_PASSING - err = assuan_sendfd (gpgsm->assuan_ctx, fd); + err = assuan_sendfd (gpgsm->assuan_ctx, iocb_data->server_fd); if (err) goto leave_set_fd; - _gpgme_io_close (fd); + _gpgme_io_close (iocb_data->server_fd); + iocb_data->server_fd = -1; if (opt) snprintf (line, COMMANDLINELEN, "%s FD %s", which, opt); @@ -735,9 +746,11 @@ snprintf (line, COMMANDLINELEN, "%s FD", which); #else if (opt) - snprintf (line, COMMANDLINELEN, "%s FD=%i %s", which, fd, opt); + snprintf (line, COMMANDLINELEN, "%s FD=%s %s", + which, iocb_data->server_fd_str, opt); else - snprintf (line, COMMANDLINELEN, "%s FD=%i", which, fd); + snprintf (line, COMMANDLINELEN, "%s FD=%s", + which, iocb_data->server_fd_str); #endif err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL); @@ -747,9 +760,12 @@ if (err) { _gpgme_io_close (iocb_data->fd); - _gpgme_io_close (iocb_data->server_fd); iocb_data->fd = -1; - iocb_data->server_fd = -1; + if (iocb_data->server_fd != -1) + { + _gpgme_io_close (iocb_data->server_fd); + iocb_data->server_fd = -1; + } } #endif Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-28 16:23:53 UTC (rev 1268) +++ trunk/gpgme/w32-glib-io.c 2007-09-28 17:30:11 UTC (rev 1269) @@ -125,6 +125,8 @@ int _gpgme_io_fd2str (char *buf, int buflen, int fd) { + TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd); + TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd)); return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (fd)); }