From cvs at cvs.gnupg.org Mon Oct 1 16:44:56 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 01 Oct 2007 16:44:56 +0200 Subject: [svn] assuan - r267 - in trunk: . doc src Message-ID: Author: wk Date: 2007-10-01 16:44:46 +0200 (Mon, 01 Oct 2007) New Revision: 267 Modified: trunk/NEWS trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-defs.h trunk/src/assuan-io-pth.c trunk/src/assuan-io.c trunk/src/assuan-logging.c trunk/src/assuan-socket-connect.c trunk/src/assuan-socket-server.c trunk/src/assuan-socket.c trunk/src/assuan.h Log: Add socket wrapper API. Changed the ABI ofthe W32 socket emulation. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/NEWS 2007-10-01 14:44:46 UTC (rev 267) @@ -1,7 +1,10 @@ Noteworthy changes in version 1.0.4 ------------------------------------------------ + * New socket wrapper fucntions to support Unix domain sockets under + Windows. + Noteworthy changes in version 1.0.3 (2007-08-24) ------------------------------------------------ Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/doc/assuan.texi 2007-10-01 14:44:46 UTC (rev 267) @@ -118,6 +118,7 @@ * Server code:: How to develop an Assuan server. * External I/O Loop:: How to use external I/O event loops. * Utilities:: Utility functions. +* Socket wrappers:: Socket wrapper functions. Miscellaneous @@ -1580,6 +1581,72 @@ @end deftypefun + at c + at c S O C K E T W R A P P E R S + at c + at node Socket wrappers + at chapter Socket wrapper functions + + at noindent +It is sometimes useful to support Unix domain sockets on Windows. To do +this in a portable way, Assuan provides a set of wrapper functions which +may be used on any system but will enhance Windows to support these +socket types. The actual implementation is based on local TCP sockets +and fully transparent for the client. Server code needs to utilize two +extra functions to check the permissions. + + + at deftypefun int assuan_sock_close (@w{assuan_fd_t @var{fd}}) + +Wrapper for close which does a closesocket on Windows if needed. + at end deftypefun + + at deftypefun assuan_fd_t assuan_sock_new (@w{int @var{domain}}, @w{int @var{type}}, @w{int @var{proto}}); + +Wrapper around socket. + at end deftypefun + + at deftypefun int assuan_sock_connect (@w{assuan_fd_t @var{sockfd}}, @ + @w{struct sockaddr *@var{addr}}, @ + @w{int @var{addrlen}}) + +Wrapper around connect. For Unix domain sockets under Windows this +function also does a write immediatley after the the connect to send the +nonce as read from the socket's file. + at end deftypefun + + + at deftypefun int assuan_sock_bind ( @ + @w{assuan_fd_t @var{sockfd}}, @ + @w{struct sockaddr *@var{addr}}, @ + @w{int @var{addrlen}}) + +Wrapper around bind. Under Windows this creates a file and writes the +port number and a random nonce to this file. + at end deftypefun + + at deftypefun int assuan_sock_get_nonce ( @ + @w{struct sockaddr *@var{addr}}, @ + @w{int @var{addrlen}}, @ + @w{assuan_sock_nonce_t *@var{nonce}}) + +This is used by the server after a bind to return the random nonce. To +keep the code readable this may also be used on POSIX system. + at end deftypefun + + at deftypefun int assuan_sock_check_nonce ( @ + @w{assuan_fd_t @var{fd}}, @ + @w{assuan_sock_nonce_t *@var{nonce}}) + +On Windows this is used by the server after an accept to read the nonce +from the client and compare it with the saved @var{nonce}. If this +function fails the server should immediatly drop the connection. To +keep the code readable this may also be used on POSIX system; it is a +dummy function then. + at end deftypefun + + + @c --------------------------------------------------------------------- @c Legal BS @c --------------------------------------------------------------------- Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/ChangeLog 2007-10-01 14:44:46 UTC (rev 267) @@ -1,3 +1,14 @@ +2007-10-01 Werner Koch + + * assuan-socket.c: Rewritten. + (assuan_sock_new, assuan_sock_connect, assuan_sock_bind) + (assuan_sock_get_nonce, assuan_sock_check_nonce): New APIs. + + * assuan-io.c (_assuan_simple_read, _assuan_simple_write): + Factored code out to ... + (_assuan_io_read, _assuan_io_write): .. new. + * assuan-io-pth.c (_assuan_io_read, _assuan_io_write): New. + 2007-09-25 Werner Koch * assuan.h (_assuan_gpg_strerror_r, _assuan_gpg_strsource): Add Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-defs.h 2007-10-01 14:44:46 UTC (rev 267) @@ -40,17 +40,6 @@ #endif #ifdef HAVE_W32_SYSTEM -#define AF_LOCAL AF_UNIX -/* We need to prefix the structure with a sockaddr_in header so we can - use it later for sendto and recvfrom. */ -struct sockaddr_un -{ - short sun_family; - unsigned short sun_port; - struct in_addr sun_addr; - char sun_path[108-2-4]; /* Path name. */ -}; - /* Not needed anymore because the current mingw32 defines this in sys/types.h */ /* typedef int ssize_t; */ @@ -296,6 +285,8 @@ ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size); ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size); +ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size); +ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size); #ifdef HAVE_W32_SYSTEM int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg); int _assuan_simple_recvmsg (assuan_context_t ctx, void *msg); @@ -307,10 +298,14 @@ /*-- assuan-socket.c --*/ int _assuan_close (assuan_fd_t fd); assuan_fd_t _assuan_sock_new (int domain, int type, int proto); -int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); int _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, + assuan_sock_nonce_t *nonce); +int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); + #ifdef HAVE_FOPENCOOKIE /* We have to implement funopen in terms of glibc's fopencookie. */ FILE *_assuan_funopen(void *cookie, Modified: trunk/src/assuan-io-pth.c =================================================================== --- trunk/src/assuan-io-pth.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-io-pth.c 2007-10-01 14:44:46 UTC (rev 267) @@ -56,15 +56,28 @@ { /* Fixme: For W32 we should better not cast the HANDLE type to int. However, this requires changes in w32pth too. */ - return pth_read ((int)ctx->inbound.fd, buffer, size); + return _assuan_io_read (ctx->inbound.fd, buffer, size); } ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) { - return pth_write ((int)ctx->outbound.fd, buffer, size); + return _assuan_io_write (ctx->outbound.fd, buffer, size); } +ssize_t +_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) +{ + return pth_read ((int)fd, buffer, size); +} + +ssize_t +_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ + return pth_write ((int)fd, buffer, size); +} + + #ifdef HAVE_W32_SYSTEM int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg) Modified: trunk/src/assuan-io.c =================================================================== --- trunk/src/assuan-io.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-io.c 2007-10-01 14:44:46 UTC (rev 267) @@ -47,7 +47,7 @@ ssize_t -_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) +_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) { #ifdef HAVE_W32_SYSTEM /* Due to the peculiarities of the W32 API we can't use read for a @@ -55,12 +55,12 @@ read if recv detects that it is not a network socket. */ int n; - n = recv (HANDLE2SOCKET(ctx->inbound.fd), buffer, size, 0); + n = recv (HANDLE2SOCKET(fd), buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nread = 0; - n = ReadFile (ctx->inbound.fd, buffer, size, &nread, NULL); + n = ReadFile (fd, buffer, size, &nread, NULL); if (!n) { switch (GetLastError()) @@ -75,25 +75,33 @@ } return n; #else /*!HAVE_W32_SYSTEM*/ - return read (ctx->inbound.fd, buffer, size); + return read (fd, buffer, size); #endif /*!HAVE_W32_SYSTEM*/ } + ssize_t -_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +_assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) { + return _assuan_io_read (ctx->inbound.fd, buffer, size); +} + + +ssize_t +_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ #ifdef HAVE_W32_SYSTEM /* Due to the peculiarities of the W32 API we can't use write for a network socket and thus we try to use send first and fallback to write if send detects that it is not a network socket. */ int n; - n = send (HANDLE2SOCKET(ctx->outbound.fd), buffer, size, 0); + n = send (HANDLE2SOCKET(fd), buffer, size, 0); if (n == -1 && WSAGetLastError () == WSAENOTSOCK) { DWORD nwrite; - n = WriteFile (ctx->outbound.fd, buffer, size, &nwrite, NULL); + n = WriteFile (fd, buffer, size, &nwrite, NULL); if (!n) { switch (GetLastError ()) @@ -109,11 +117,18 @@ } return n; #else /*!HAVE_W32_SYSTEM*/ - return write (ctx->outbound.fd, buffer, size); + return write (fd, buffer, size); #endif /*!HAVE_W32_SYSTEM*/ } +ssize_t +_assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) +{ + return _assuan_io_write (ctx->outbound.fd, buffer, size); +} + + #ifdef HAVE_W32_SYSTEM int _assuan_simple_sendmsg (assuan_context_t ctx, void *msg) Modified: trunk/src/assuan-logging.c =================================================================== --- trunk/src/assuan-logging.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-logging.c 2007-10-01 14:44:46 UTC (rev 267) @@ -118,8 +118,8 @@ /* Dump a possibly binary string (used for debugging). Distinguish ascii text from binary and print it accordingly. This function - takes FILE pointer arg becuase logging may be enabled on a per - context basis. */ + takes FILE pointer arg because logging may be enabled on a per + context basis. */ void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length) { Modified: trunk/src/assuan-socket-connect.c =================================================================== --- trunk/src/assuan-socket-connect.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-socket-connect.c 2007-10-01 14:44:46 UTC (rev 267) @@ -137,7 +137,6 @@ srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; len = SUN_LEN (&srvr_addr); - if ( _assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1 ) { _assuan_log_printf ("can't connect to `%s': %s\n", Modified: trunk/src/assuan-socket-server.c =================================================================== --- trunk/src/assuan-socket-server.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-socket-server.c 2007-10-01 14:44:46 UTC (rev 267) @@ -131,7 +131,7 @@ } /* Initialize a server using the already accepted socket FD. This - fucntion is deprecated. */ + function is deprecated. */ int assuan_init_connected_socket_server (assuan_context_t *r_ctx, assuan_fd_t fd) { Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan-socket.c 2007-10-01 14:44:46 UTC (rev 267) @@ -19,13 +19,19 @@ #include #include +#include #ifdef HAVE_W32_SYSTEM +#define WIN32_LEAN_AND_MEAN #include +#include #include #else #include #include #endif +#include +#include +#include #include "assuan-defs.h" /* Hacks for Slowaris. */ @@ -40,20 +46,89 @@ # define AF_LOCAL AF_UNIX #endif +#ifdef HAVE_W32_SYSTEM +#ifndef S_IRGRP +# define S_IRGRP 0 +# define S_IWGRP 0 +#endif +#endif + + +#ifdef HAVE_W32_SYSTEM +/* W32: Fill BUFFER with LENGTH bytes of random. Returns -1 on + failure, 0 on success. */ +static int +get_nonce (char *buffer, size_t nbytes) +{ + HCRYPTPROV prov; + int ret = -1; + + if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) ) + errno = ENODEV; + else + { + if (!CryptGenRandom (prov, nbytes, buffer)) + errno = ENODEV; + else + ret = 0; + CryptReleaseContext (prov, 0); + } + return ret; +} + + +/* W32: The buffer for NONCE needs to be at least 16 bytes. Returns 0 on + success. */ +static int +read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) +{ + FILE *fp; + char buffer[50], *p; + size_t nread; + int aval; + + fp = fopen (fname, "rb"); + if (!fp) + return -1; + nread = fread (buffer, 1, sizeof buffer - 1, fp); + fclose (fp); + if (!nread) + { + errno = ENOFILE; + return -1; + } + buffer[nread] = 0; + aval = atoi (buffer); + if (aval < 1 || aval > 65535) + { + errno = EINVAL; + return -1; + } + *port = (unsigned int)aval; + for (p=buffer; nread && *p != '\n'; p++, nread--) + ; + if (*p != '\n' || nread != 17) + { + errno = EINVAL; + return -1; + } + p++; nread--; + memcpy (nonce, p, 16); + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + + int _assuan_close (assuan_fd_t fd) { #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); -/* if (rc) */ -/* _assuan_log_printf ("_assuan_close(%p): CloseHandle failed: %d\n", */ -/* fd, rc ); */ } return rc; #else @@ -64,16 +139,16 @@ /* Return a new socket. Note that under W32 we consider a socket the same as an System Handle; all functions using such a handle know - about this dual use and act accordingly. */ + about this dual use and act accordingly. */ assuan_fd_t _assuan_sock_new (int domain, int type, int proto) { -#ifndef HAVE_W32_SYSTEM - return socket (domain, type, proto); -#else +#ifdef HAVE_W32_SYSTEM if (domain == AF_UNIX || domain == AF_LOCAL) domain = AF_INET; return SOCKET2HANDLE(socket (domain, type, proto)); +#else + return socket (domain, type, proto); #endif } @@ -81,78 +156,242 @@ int _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) { -#ifndef HAVE_W32_SYSTEM - return connect (sockfd, addr, addrlen); -#else - struct sockaddr_in myaddr; - struct sockaddr_un * unaddr; - FILE * fp; - int port = 0; +#ifdef HAVE_W32_SYSTEM + if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) + { + struct sockaddr_in myaddr; + struct sockaddr_un *unaddr; + unsigned short port; + char nonce[16]; + int ret; + + unaddr = (struct sockaddr_un *)addr; + if (read_port_and_nonce (unaddr->sun_path, &port, nonce)) + return -1; + + myaddr.sin_family = AF_INET; + myaddr.sin_port = htons (port); + myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - unaddr = (struct sockaddr_un *)addr; - fp = fopen (unaddr->sun_path, "rb"); - if (!fp) - return -1; - fscanf (fp, "%d", &port); - fclose (fp); - /* XXX: set errno in this case */ - if (port < 0 || port > 65535) - return -1; + /* Set return values. */ + unaddr->sun_family = myaddr.sin_family; + unaddr->sun_port = myaddr.sin_port; + unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; - myaddr.sin_family = AF_INET; - myaddr.sin_port = port; - myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - /* we need this later. */ - unaddr->sun_family = myaddr.sin_family; - unaddr->sun_port = myaddr.sin_port; - unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; - - return connect (HANDLE2SOCKET(sockfd), (struct sockaddr *)&myaddr, sizeof myaddr); + ret = connect (HANDLE2SOCKET(sockfd), + (struct sockaddr *)&myaddr, sizeof myaddr); + if (!ret) + { + /* Send the nonce. */ + ret = _assuan_io_write (sockfd, nonce, 16); + if (ret >= 0 && ret != 16) + { + errno = EIO; + ret = -1; + } + } + return ret; + } + else + return connect (HANDLE2SOCKET (sockfd), addr, addrlen); +#else + return connect (sockfd, addr, addrlen); #endif } int -_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr * addr, int addrlen) +_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) { -#ifndef HAVE_W32_SYSTEM - return bind (sockfd, addr, addrlen); -#else +#ifdef HAVE_W32_SYSTEM if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) { struct sockaddr_in myaddr; - struct sockaddr_un * unaddr; - FILE * fp; + struct sockaddr_un *unaddr; + int filefd; + FILE *fp; int len = sizeof myaddr; int rc; + char nonce[16]; + if (get_nonce (nonce, 16)) + return -1; + + unaddr = (struct sockaddr_un *)addr; + myaddr.sin_port = 0; myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - rc = bind (HANDLE2SOCKET(sockfd), (struct sockaddr *)&myaddr, len); + filefd = open (unaddr->sun_path, + (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), + (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)); + if (filefd == -1) + { + if (errno == EEXIST) + errno = WSAEADDRINUSE; + return -1; + } + fp = fdopen (filefd, "wb"); + if (!fp) + { + int save_e = errno; + close (filefd); + errno = save_e; + return -1; + } + + rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len); + if (!rc) + rc = getsockname (HANDLE2SOCKET (sockfd), + (struct sockaddr *)&myaddr, &len); if (rc) - return rc; - rc = getsockname (HANDLE2SOCKET(sockfd), - (struct sockaddr *)&myaddr, &len); - if (rc) - return rc; + { + int save_e = errno; + fclose (fp); + remove (unaddr->sun_path); + errno = save_e; + return rc; + } + fprintf (fp, "%d\n", ntohs (myaddr.sin_port)); + fwrite (nonce, 16, 1, fp); + fclose (fp); + + return 0; + } + else + return bind (HANDLE2SOCKET(sockfd), addr, addrlen); +#else + return bind (sockfd, addr, addrlen); +#endif +} + + +int +_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, + assuan_sock_nonce_t *nonce) +{ +#ifdef HAVE_W32_SYSTEM + if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) + { + struct sockaddr_un *unaddr; + unsigned short port; + + if (sizeof nonce->nonce != 16) + { + errno = EINVAL; + return -1; + } + nonce->length = 16; unaddr = (struct sockaddr_un *)addr; - fp = fopen (unaddr->sun_path, "wb"); - if (!fp) + if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce)) return -1; - fprintf (fp, "%d", myaddr.sin_port); - fclose (fp); + } + else + { + nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */ + nonce->nonce[0] = 42; + } +#else + (void)addr; + (void)addrlen; + nonce->length = 0; +#endif + return 0; +} + + +int +_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) +{ +#ifdef HAVE_W32_SYSTEM + char buffer[16], *p; + size_t nleft, n; - /* we need this later. */ - unaddr->sun_family = myaddr.sin_family; - unaddr->sun_port = myaddr.sin_port; - unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; + if (sizeof nonce->nonce != 16) + { + errno = EINVAL; + return -1; + } + + if (nonce->length == 42 && nonce->nonce[0] == 42) + return 0; /* Not a Unix domain socket. */ + + if (nonce->length != 16) + { + errno = EINVAL; + return -1; + } - return 0; + p = buffer; + nleft = 16; + while (nleft) + { + n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft); + if (n < 0 && errno == EINTR) + ; + else if (n < 0 && errno == EAGAIN) + Sleep (100); + else if (n < 0) + return -1; + else if (!n) + { + errno = EIO; + return -1; + } + else + { + p += n; + nleft -= n; + } } - return bind (HANDLE2SOCKET(sockfd), addr, addrlen); + if (memcmp (buffer, nonce->nonce, 16)) + { + errno = EACCES; + return -1; + } +#else + (void)fd; + (void)nonce; #endif + return 0; } + +/* Public API. */ +int +assuan_sock_close (assuan_fd_t fd) +{ + return _assuan_close (fd); +} + +assuan_fd_t +assuan_sock_new (int domain, int type, int proto) +{ + return _assuan_sock_new (domain, type, proto); +} + +int +assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) +{ + return _assuan_sock_connect (sockfd, addr, addrlen); +} + +int +assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen) +{ + return _assuan_sock_bind (sockfd, addr, addrlen); +} + +int +assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, + assuan_sock_nonce_t *nonce) +{ + return _assuan_sock_get_nonce (addr, addrlen, nonce); +} + +int +assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) +{ + return _assuan_sock_check_nonce (fd, nonce); +} Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-09-25 15:09:54 UTC (rev 266) +++ trunk/src/assuan.h 2007-10-01 14:44:46 UTC (rev 267) @@ -23,19 +23,29 @@ #include #include #include +#ifndef _ASSUAN_NO_SOCKET_WRAPPER +#ifdef _WIN32 +#include +#else +#include +#endif +#endif /*!_ASSUAN_NO_SOCKET_WRAPPER*/ - /* To use this file with libraries the following macros are useful: #define _ASSUAN_EXT_SYM_PREFIX _foo_ - This prefixes all external symbols with "_foo_". + This prefixes all external symbols with "_foo_". #define _ASSUAN_ONLY_GPG_ERRORS - If this is defined all old-style Assuan error codes are made - inactive as well as other dereacted stuff. + If this is defined all old-style Assuan error codes are made + inactive as well as other deprecated stuff. + #define _ASSUAN_NO_SOCKET_WRAPPER + + Do not include the definitions for the socket wrapper feature. + The follwing macros are used internally in the implementation of libassuan: @@ -132,6 +142,12 @@ #define assuan_pipe_connect2 _ASSUAN_PREFIX(assuan_pipe_connect2) #define assuan_set_assuan_log_prefix \ _ASSUAN_PREFIX(assuan_set_assuan_log_prefix) +#define assuan_sock_close _ASSUAN_PREFIX(assuan_sock_close) +#define assuan_sock_new _ASSUAN_PREFIX(assuan_sock_new) +#define assuan_sock_connect _ASSUAN_PREFIX(assuan_sock_connect) +#define assuan_sock_bind _ASSUAN_PREFIX(assuan_sock_bind) +#define assuan_sock_get_nonce _ASSUAN_PREFIX(assuan_sock_get_nonce) +#define assuan_sock_check_nonce _ASSUAN_PREFIX(assuan_sock_check_nonce) /* And now the internal functions, argh... */ @@ -144,8 +160,8 @@ _ASSUAN_PREFIX(_assuan_register_std_commands) #define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read) #define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) -#define _assuan_simple_read _ASSUAN_PREFIX(_assuan_simple_read) -#define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) +#define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read) +#define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write) #define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context) #define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context) #define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc) @@ -162,10 +178,6 @@ #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) -#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) @@ -173,6 +185,12 @@ #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_sock_close _ASSUAN_PREFIX(_assuan_close) +#define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new) +#define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect) +#define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) +#define _assuan_sock_get_nonce _ASSUAN_PREFIX(_assuan_sock_get_nonce) +#define _assuan_sock_check_nonce _ASSUAN_PREFIX(_assuan_sock_check_nonce) #endif /*_ASSUAN_EXT_SYM_PREFIX*/ @@ -357,13 +375,45 @@ actually is a plain pointer). This is required to eventually support 64 bit Windows systems. */ #ifdef _WIN32 -typedef void * assuan_fd_t; +typedef void *assuan_fd_t; #define ASSUAN_INVALID_FD ((void*)(-1)) #else typedef int assuan_fd_t; #define ASSUAN_INVALID_FD (-1) #endif + +/* Assuan features an emulation of Unix domain sockets based on a + local TCP connections. To implement access permissions based on + file permissions a nonce is used which is expected by th server as + the first bytes received. This structure is used by the server to + save the nonce created initially by bind. On POSIX systems this is + a dummy operation. */ +struct assuan_sock_nonce_s +{ + size_t length; +#ifdef _WIN32 + char nonce[16]; +#endif +}; +typedef struct assuan_sock_nonce_s assuan_sock_nonce_t; + +/* Define the Unix domain socket structure for Windows. */ +#if defined(_WIN32) && !defined(_ASSUAN_NO_SOCKET_WRAPPER) +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif +#define EADDRINUSE WSAEADDRINUSE +struct sockaddr_un +{ + short sun_family; + unsigned short sun_port; + struct in_addr sun_addr; + char sun_path[108-2-4]; +}; +#endif + + /*-- assuan-handler.c --*/ int assuan_register_command (assuan_context_t ctx, const char *cmd_string, @@ -498,6 +548,7 @@ assuan_error_t assuan_sendfd (assuan_context_t ctx, assuan_fd_t fd); assuan_error_t assuan_receivefd (assuan_context_t ctx, assuan_fd_t *fd); + /*-- assuan-util.c --*/ void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), void *(*new_realloc_func)(void *p, size_t n), @@ -563,6 +614,21 @@ string, i.e. "" */ const char *assuan_get_assuan_log_prefix (void); + +/*-- assuan-socket.c --*/ + +/* These are socket wrapper functions to support an emulation of Unix + domain sockets on Windows W32. */ +int assuan_sock_close (assuan_fd_t fd); +assuan_fd_t assuan_sock_new (int domain, int type, int proto); +int assuan_sock_connect (assuan_fd_t sockfd, + struct sockaddr *addr, int addrlen); +int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen); +int assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, + assuan_sock_nonce_t *nonce); +int assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); + + #ifdef __cplusplus } #endif From cvs at cvs.gnupg.org Mon Oct 1 16:49:06 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 01 Oct 2007 16:49:06 +0200 Subject: [svn] GnuPG - r4587 - in trunk: . agent common g10 jnlib po scd tools Message-ID: Author: wk Date: 2007-10-01 16:48:39 +0200 (Mon, 01 Oct 2007) New Revision: 4587 Modified: trunk/ChangeLog trunk/NEWS trunk/agent/ChangeLog trunk/agent/agent.h trunk/agent/command-ssh.c trunk/agent/command.c trunk/agent/gpg-agent.c trunk/common/ChangeLog trunk/common/homedir.c trunk/common/sysutils.h trunk/configure.ac trunk/g10/server.c trunk/jnlib/ChangeLog trunk/jnlib/w32-afunix.c trunk/jnlib/w32-afunix.h trunk/po/be.po trunk/po/ca.po trunk/po/cs.po trunk/po/da.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/scd/ChangeLog trunk/scd/scdaemon.c trunk/scd/scdaemon.h trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c Log: Use Assuan socket wrapper calls. Made socket servers secure under Windows. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,7 @@ +2007-10-01 Werner Koch + + * configure.ac: Require assuan 1.0.4. + 2007-09-14 Werner Koch * configure.ac (GNUPG_LIBASSUAN_VERSION): New. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/NEWS 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,7 +1,11 @@ Noteworthy changes in version 2.0.8 ------------------------------------------------ + * Make sure that under Windows the file permissions of the socket are + taken into account. This required a change of our the socket + emulation code; thus old GnuPG modules can't be used anymore. + Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/agent/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,17 @@ +2007-10-01 Werner Koch + + * agent.h (struct server_control_s): Remove unused CONNECTION_FD. + + * gpg-agent.c: Remove w32-afunix.h. Include mkdtemp.h. + (socket_nonce, socket_nonce_ssh): New. + (create_server_socket): Use assuan socket wrappers. Remove W32 + specific stuff. Save the server nonce. + (check_nonce): New. + (start_connection_thread, start_connection_thread_ssh): Call it. + (handle_connections): Change args to gnupg_fd_t. + * command.c (start_command_handler): Change LISTEN_FD to gnupg_fd_t. + * command-ssh.c (start_command_handler_ssh): Ditto. + 2007-09-18 Werner Koch * agent.h (struct pin_entry_info_s): Add element WITH_QUALITYBAR. Modified: trunk/agent/agent.h =================================================================== --- trunk/agent/agent.h 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/agent/agent.h 2007-10-01 14:48:39 UTC (rev 4587) @@ -32,7 +32,8 @@ #include #include "../common/util.h" #include "../common/errors.h" -#include "membuf.h" +#include "../common/membuf.h" +#include "../common/sysutils.h" /* (gnupg_fd_t) */ /* To convey some special hash algorithms we use algorithm numbers reserved for application use. */ @@ -131,7 +132,7 @@ /* Private data used to fire up the connection thread. We use this structure do avoid an extra allocation for just a few bytes. */ struct { - int fd; + gnupg_fd_t fd; } thread_startup; /* Private data of the server (command.c). */ @@ -140,8 +141,6 @@ /* Private data of the SCdaemon (call-scd.c). */ struct scd_local_s *scd_local; - int connection_fd; /* -1 or an identifier for the current connection. */ - char *display; char *ttyname; char *ttytype; @@ -209,10 +208,10 @@ gpg_error_t agent_write_status (ctrl_t ctrl, const char *keyword, ...); void bump_key_eventcounter (void); void bump_card_eventcounter (void); -void start_command_handler (ctrl_t, int, int); +void start_command_handler (ctrl_t, gnupg_fd_t, gnupg_fd_t); /*-- command-ssh.c --*/ -void start_command_handler_ssh (ctrl_t, int); +void start_command_handler_ssh (ctrl_t, gnupg_fd_t); /*-- findkey.c --*/ int agent_write_private_key (const unsigned char *grip, Modified: trunk/agent/command-ssh.c =================================================================== --- trunk/agent/command-ssh.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/agent/command-ssh.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -2818,15 +2818,12 @@ /* Start serving client on SOCK_CLIENT. */ void -start_command_handler_ssh (ctrl_t ctrl, int sock_client) +start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client) { estream_t stream_sock; gpg_error_t err; int ret; - /* Setup control structure. */ - ctrl->connection_fd = sock_client; - /* Because the ssh protocol does not send us information about the the current TTY setting, we resort here to use those from startup or those explictly set. */ @@ -2843,7 +2840,7 @@ /* Create stream from socket. */ - stream_sock = es_fdopen (sock_client, "r+"); + stream_sock = es_fdopen (FD2INT(sock_client), "r+"); if (!stream_sock) { err = gpg_error_from_syserror (); Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/agent/command.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -1544,12 +1544,12 @@ control structure for this connection; it has only the basic intialization. */ void -start_command_handler (ctrl_t ctrl, int listen_fd, int fd) +start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd) { int rc; assuan_context_t ctx; - if (listen_fd == -1 && fd == -1) + if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD) { int filedes[2]; @@ -1557,14 +1557,13 @@ filedes[1] = 1; rc = assuan_init_pipe_server (&ctx, filedes); } - else if (listen_fd != -1) + else if (listen_fd != GNUPG_INVALID_FD) { rc = assuan_init_socket_server_ext (&ctx, listen_fd, 0); } else { rc = assuan_init_socket_server_ext (&ctx, fd, 2); - ctrl->connection_fd = fd; } if (rc) { Modified: trunk/agent/gpg-agent.c =================================================================== --- trunk/agent/gpg-agent.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/agent/gpg-agent.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -40,13 +40,11 @@ #define JNLIB_NEED_LOG_LOGV #include "agent.h" -#include /* Malloc hooks */ +#include /* Malloc hooks and socket wrappers. */ #include "i18n.h" +#include "mkdtemp.h" /* Gnulib replacement. */ #include "sysutils.h" -#ifdef HAVE_W32_SYSTEM -# include "../jnlib/w32-afunix.h" -#endif #include "setenv.h" #include "gc-opt-flags.h" @@ -207,6 +205,12 @@ /* Name of the communication socket used for ssh-agent-emulation. */ static char *socket_name_ssh; +/* We need to keep track of the server's nonces (these are dummies for + POSIX systems). */ +static assuan_sock_nonce_t socket_nonce; +static assuan_sock_nonce_t socket_nonce_ssh; + + /* Default values for options passed to the pinentry. */ static char *default_display; static char *default_ttyname; @@ -236,13 +240,15 @@ static char *create_socket_name (int use_standard_socket, char *standard_name, char *template); -static int create_server_socket (int is_standard_name, char *name); +static gnupg_fd_t create_server_socket (int is_standard_name, char *name, + assuan_sock_nonce_t *nonce); static void create_directories (void); static void agent_init_default_ctrl (ctrl_t ctrl); static void agent_deinit_default_ctrl (ctrl_t ctrl); -static void handle_connections (int listen_fd, int listen_fd_ssh); +static void handle_connections (gnupg_fd_t listen_fd, + gnupg_fd_t listen_fd_ssh); static int check_for_running_agent (int silent, int mode); /* Pth wrapper function definitions. */ @@ -845,7 +851,7 @@ agent_exit (1); } agent_init_default_ctrl (ctrl); - start_command_handler (ctrl, -1, -1); + start_command_handler (ctrl, GNUPG_INVALID_FD, GNUPG_INVALID_FD); agent_deinit_default_ctrl (ctrl); xfree (ctrl); } @@ -853,8 +859,8 @@ ; /* NOTREACHED */ else { /* Regular server mode */ - int fd; - int fd_ssh; + gnupg_fd_t fd; + gnupg_fd_t fd_ssh; pid_t pid; /* Remove the DISPLAY variable so that a pinentry does not @@ -878,11 +884,13 @@ "S.gpg-agent.ssh", "/tmp/gpg-XXXXXX/S.gpg-agent.ssh"); - fd = create_server_socket (standard_socket, socket_name); + fd = create_server_socket (standard_socket, socket_name, + &socket_nonce); if (opt.ssh_support) - fd_ssh = create_server_socket (standard_socket, socket_name_ssh); + fd_ssh = create_server_socket (standard_socket, socket_name_ssh, + &socket_nonce_ssh); else - fd_ssh = -1; + fd_ssh = GNUPG_INVALID_FD; /* If we are going to exec a program in the parent, we record the PID, so that the child may check whether the program is @@ -1079,8 +1087,8 @@ } #endif /*!HAVE_W32_SYSTEM*/ - handle_connections (fd, opt.ssh_support ? fd_ssh : -1); - close (fd); + handle_connections (fd, opt.ssh_support ? fd_ssh : GNUPG_INVALID_FD); + assuan_sock_close (fd); } return 0; @@ -1109,8 +1117,6 @@ static void agent_init_default_ctrl (ctrl_t ctrl) { - ctrl->connection_fd = -1; - /* Note we ignore malloc errors because we can't do much about it and the request will fail anyway shortly after this initialization. */ @@ -1269,20 +1275,17 @@ /* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates whether a non-random socket is used. Returns the file descriptor or terminates the process in case of an error. */ -static int -create_server_socket (int is_standard_name, char *name) +static gnupg_fd_t +create_server_socket (int is_standard_name, char *name, + assuan_sock_nonce_t *nonce) { struct sockaddr_un *serv_addr; socklen_t len; - int fd; + gnupg_fd_t fd; int rc; -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) + fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0); + if (fd == ASSUAN_INVALID_FD) { log_error (_("can't create socket: %s\n"), strerror (errno)); agent_exit (2); @@ -1291,43 +1294,32 @@ serv_addr = xmalloc (sizeof (*serv_addr)); memset (serv_addr, 0, sizeof *serv_addr); serv_addr->sun_family = AF_UNIX; - assert (strlen (name) + 1 < sizeof (serv_addr->sun_path)); + if (strlen (name) + 1 >= sizeof (serv_addr->sun_path)) + { + log_error (_("socket name `%s' is too long\n"), name); + agent_exit (2); + } strcpy (serv_addr->sun_path, name); len = (offsetof (struct sockaddr_un, sun_path) + strlen (serv_addr->sun_path) + 1); -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); - if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE) - { - if (!check_for_running_agent (1, 1)) - { - log_error (_("a gpg-agent is already running - " - "not starting a new one\n")); - *name = 0; /* Inhibit removal of the socket by cleanup(). */ - close (fd); - agent_exit (2); - } - - remove (name); - rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); - } -#else - rc = bind (fd, (struct sockaddr*) serv_addr, len); + rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len); if (is_standard_name && rc == -1 && errno == EADDRINUSE) { if (!check_for_running_agent (1, 1)) { log_error (_("a gpg-agent is already running - " - "not starting a new one\n")); + "not starting a new one\n")); *name = 0; /* Inhibit removal of the socket by cleanup(). */ - close (fd); + assuan_sock_close (fd); agent_exit (2); } remove (name); - rc = bind (fd, (struct sockaddr*) serv_addr, len); + rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len); } -#endif + if (rc != -1 + && (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce))) + log_error (_("error getting nonce for the socket\n")); if (rc == -1) { /* We use gpg_strerror here because it allows us to get strings @@ -1336,16 +1328,16 @@ serv_addr->sun_path, gpg_strerror (gpg_error_from_errno (errno))); - close (fd); + assuan_sock_close (fd); if (is_standard_name) *name = 0; /* Inhibit removal of the socket by cleanup(). */ agent_exit (2); } - if (listen (fd, 5 ) == -1) + if (listen (FD2INT(fd), 5 ) == -1) { log_error (_("listen() failed: %s\n"), strerror (errno)); - close (fd); + assuan_sock_close (fd); agent_exit (2); } @@ -1538,21 +1530,42 @@ } +/* Check the nonce on a new connection. This is a NOP unless we we + are using our Unix domain socket emulation under Windows. */ +static int +check_nonce (ctrl_t ctrl, assuan_sock_nonce_t *nonce) +{ + if (assuan_sock_check_nonce (ctrl->thread_startup.fd, nonce)) + { + log_info (_("error reading nonce on fd %d: %s\n"), + FD2INT(ctrl->thread_startup.fd), strerror (errno)); + assuan_sock_close (ctrl->thread_startup.fd); + xfree (ctrl); + return -1; + } + else + return 0; +} + + /* This is the standard connection thread's main function. */ static void * start_connection_thread (void *arg) { ctrl_t ctrl = arg; + if (check_nonce (ctrl, &socket_nonce)) + return NULL; + agent_init_default_ctrl (ctrl); if (opt.verbose) log_info (_("handler 0x%lx for fd %d started\n"), - (long)pth_self (), ctrl->thread_startup.fd); + (long)pth_self (), FD2INT(ctrl->thread_startup.fd)); - start_command_handler (ctrl, -1, ctrl->thread_startup.fd); + start_command_handler (ctrl, GNUPG_INVALID_FD, ctrl->thread_startup.fd); if (opt.verbose) log_info (_("handler 0x%lx for fd %d terminated\n"), - (long)pth_self (), ctrl->thread_startup.fd); + (long)pth_self (), FD2INT(ctrl->thread_startup.fd)); agent_deinit_default_ctrl (ctrl); xfree (ctrl); @@ -1566,15 +1579,18 @@ { ctrl_t ctrl = arg; + if (check_nonce (ctrl, &socket_nonce_ssh)) + return NULL; + agent_init_default_ctrl (ctrl); if (opt.verbose) log_info (_("ssh handler 0x%lx for fd %d started\n"), - (long)pth_self (), ctrl->thread_startup.fd); + (long)pth_self (), FD2INT(ctrl->thread_startup.fd)); start_command_handler_ssh (ctrl, ctrl->thread_startup.fd); if (opt.verbose) log_info (_("ssh handler 0x%lx for fd %d terminated\n"), - (long)pth_self (), ctrl->thread_startup.fd); + (long)pth_self (), FD2INT(ctrl->thread_startup.fd)); agent_deinit_default_ctrl (ctrl); xfree (ctrl); @@ -1585,7 +1601,7 @@ /* Connection handler loop. Wait for connection requests and spawn a thread after accepting a connection. */ static void -handle_connections (int listen_fd, int listen_fd_ssh) +handle_connections (gnupg_fd_t listen_fd, gnupg_fd_t listen_fd_ssh) { pth_attr_t tattr; pth_event_t ev, time_ev; @@ -1595,7 +1611,7 @@ socklen_t plen; fd_set fdset, read_fdset; int ret; - int fd; + gnupg_fd_t fd; int nfd; tattr = pth_attr_new(); @@ -1620,13 +1636,13 @@ time_ev = NULL; FD_ZERO (&fdset); - FD_SET (listen_fd, &fdset); - nfd = listen_fd; - if (listen_fd_ssh != -1) + FD_SET (FD2INT (listen_fd), &fdset); + nfd = FD2INT (listen_fd); + if (listen_fd_ssh != GNUPG_INVALID_FD) { - FD_SET (listen_fd_ssh, &fdset); - if (listen_fd_ssh > nfd) - nfd = listen_fd_ssh; + FD_SET ( FD2INT(listen_fd_ssh), &fdset); + if (FD2INT (listen_fd_ssh) > nfd) + nfd = FD2INT (listen_fd_ssh); } for (;;) @@ -1701,13 +1717,14 @@ new thread. Thus we need to block those signals. */ pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); - if (FD_ISSET (listen_fd, &read_fdset)) + if (FD_ISSET (FD2INT (listen_fd), &read_fdset)) { ctrl_t ctrl; plen = sizeof paddr; - fd = pth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); - if (fd == -1) + fd = INT2FD (pth_accept (FD2INT(listen_fd), + (struct sockaddr *)&paddr, &plen)); + if (fd == GNUPG_INVALID_FD) { log_error ("accept failed: %s\n", strerror (errno)); } @@ -1715,14 +1732,14 @@ { log_error ("error allocating connection control data: %s\n", strerror (errno) ); - close (fd); + assuan_sock_close (fd); } else { char threadname[50]; snprintf (threadname, sizeof threadname-1, - "conn fd=%d (gpg)", fd); + "conn fd=%d (gpg)", FD2INT(fd)); threadname[sizeof threadname -1] = 0; pth_attr_set (tattr, PTH_ATTR_NAME, threadname); ctrl->thread_startup.fd = fd; @@ -1730,20 +1747,22 @@ { log_error ("error spawning connection handler: %s\n", strerror (errno) ); - close (fd); + assuan_sock_close (fd); xfree (ctrl); } } - fd = -1; + fd = GNUPG_INVALID_FD; } - if (listen_fd_ssh != -1 && FD_ISSET (listen_fd_ssh, &read_fdset)) + if (listen_fd_ssh != GNUPG_INVALID_FD + && FD_ISSET ( FD2INT (listen_fd_ssh), &read_fdset)) { ctrl_t ctrl; plen = sizeof paddr; - fd = pth_accept (listen_fd_ssh, (struct sockaddr *)&paddr, &plen); - if (fd == -1) + fd = INT2FD(pth_accept (FD2INT(listen_fd_ssh), + (struct sockaddr *)&paddr, &plen)); + if (fd == GNUPG_INVALID_FD) { log_error ("accept failed for ssh: %s\n", strerror (errno)); } @@ -1751,7 +1770,7 @@ { log_error ("error allocating connection control data: %s\n", strerror (errno) ); - close (fd); + assuan_sock_close (fd); } else { @@ -1759,7 +1778,7 @@ agent_init_default_ctrl (ctrl); snprintf (threadname, sizeof threadname-1, - "conn fd=%d (ssh)", fd); + "conn fd=%d (ssh)", FD2INT(fd)); threadname[sizeof threadname -1] = 0; pth_attr_set (tattr, PTH_ATTR_NAME, threadname); ctrl->thread_startup.fd = fd; @@ -1767,11 +1786,11 @@ { log_error ("error spawning ssh connection handler: %s\n", strerror (errno) ); - close (fd); + assuan_sock_close (fd); xfree (ctrl); } } - fd = -1; + fd = GNUPG_INVALID_FD; } /* Restore the signal mask. */ Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/common/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,12 @@ +2007-10-01 Werner Koch + + * sysutils.h (FD2INT, INT2FD): New. + +2007-09-21 Werner Koch + + * homedir.c (default_homedir): Make registry work. Reported by + Marc Mutz. + 2007-08-29 Werner Koch * exechelp.c (gnupg_wait_process): Add arg EXITCODE. Changed all Modified: trunk/common/homedir.c =================================================================== --- trunk/common/homedir.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/common/homedir.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -143,7 +143,7 @@ tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir"); - if (tmp && *tmp) + if (tmp && !*tmp) { xfree (tmp); tmp = NULL; Modified: trunk/common/sysutils.h =================================================================== --- trunk/common/sysutils.h 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/common/sysutils.h 2007-10-01 14:48:39 UTC (rev 4587) @@ -27,9 +27,13 @@ #ifdef HAVE_W32_SYSTEM typedef void *gnupg_fd_t; #define GNUPG_INVALID_FD ((void*)(-1)) +#define INT2FD(s) ((void *)(s)) +#define FD2INT(h) ((unsigned int)(h)) #else typedef int gnupg_fd_t; #define GNUPG_INVALID_FD (-1) +#define INT2FD(s) (s) +#define FD2INT(h) (h) #endif Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/configure.ac 2007-10-01 14:48:39 UTC (rev 4587) @@ -43,7 +43,7 @@ NEED_LIBGCRYPT_VERSION=1.2.2 NEED_LIBASSUAN_API=1 -NEED_LIBASSUAN_VERSION=1.0.2 +NEED_LIBASSUAN_VERSION=1.0.4 NEED_KSBA_API=1 NEED_KSBA_VERSION=1.0.2 Modified: trunk/g10/server.c =================================================================== --- trunk/g10/server.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/g10/server.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -32,9 +32,9 @@ #include "util.h" #include "i18n.h" #include "options.h" +#include "../common/sysutils.h" - #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t)) @@ -44,7 +44,7 @@ /* Our current Assuan context. */ assuan_context_t assuan_ctx; /* File descriptor as set by the MESSAGE command. */ - int message_fd; + gnupg_fd_t message_fd; }; @@ -53,10 +53,10 @@ static void close_message_fd (ctrl_t ctrl) { - if (ctrl->server_local->message_fd != -1) + if (ctrl->server_local->message_fd != GNUPG_INVALID_FD) { - close (ctrl->server_local->message_fd); - ctrl->server_local->message_fd = -1; + assuan_sock_close (ctrl->server_local->message_fd); + ctrl->server_local->message_fd = GNUPG_INVALID_FD; } } @@ -229,27 +229,28 @@ { int rc; ctrl_t ctrl = assuan_get_pointer (ctx); - int fd = assuan_get_input_fd (ctx); - int out_fd = assuan_get_output_fd (ctx); + gnupg_fd_t fd = assuan_get_input_fd (ctx); + gnupg_fd_t out_fd = assuan_get_output_fd (ctx); FILE *out_fp = NULL; - if (fd == -1) + if (fd == GNUPG_INVALID_FD) return gpg_error (GPG_ERR_ASS_NO_INPUT); - if (out_fd != -1) + if (out_fd != GNUPG_INVALID_FD) { - out_fp = fdopen ( dup(out_fd), "w"); + out_fp = fdopen ( dup (FD2INT (out_fd)), "w"); if (!out_fp) return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed"); } - log_debug ("WARNING: The server mode work in progress and not ready for use\n"); + log_debug ("WARNING: The server mode work " + "in progress and not ready for use\n"); /* Need to dup it because it might get closed and libassuan won't know about it then. */ rc = gpg_verify (ctrl, - dup (fd), - dup (ctrl->server_local->message_fd), + dup ( FD2INT (fd)), + dup ( FD2INT (ctrl->server_local->message_fd)), out_fp); if (out_fp) @@ -326,13 +327,13 @@ cmd_message (assuan_context_t ctx, char *line) { int rc; - int fd; + gnupg_fd_t fd; ctrl_t ctrl = assuan_get_pointer (ctx); rc = assuan_command_parse_fd (ctx, line, &fd); if (rc) return rc; - if (fd == -1) + if (fd == GNUPG_INVALID_FD) return gpg_error (GPG_ERR_ASS_NO_INPUT); ctrl->server_local->message_fd = fd; return 0; @@ -488,7 +489,7 @@ goto leave; } ctrl->server_local->assuan_ctx = ctx; - ctrl->server_local->message_fd = -1; + ctrl->server_local->message_fd = GNUPG_INVALID_FD; if (DBG_ASSUAN) assuan_set_log_stream (ctx, log_get_stream ()); Modified: trunk/jnlib/ChangeLog =================================================================== --- trunk/jnlib/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/jnlib/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,9 @@ +2007-10-01 Werner Koch + + * w32-afunix.c: Only keep the client related code. + (read_port_and_nonce): New. Taken from Assuan. + (_w32_sock_connect): Rewritten. + 2007-08-29 Werner Koch * argparse.c (initialize): Make strings translatable and remove Modified: trunk/jnlib/w32-afunix.c =================================================================== --- trunk/jnlib/w32-afunix.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/jnlib/w32-afunix.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,4 +1,4 @@ -/* w32-afunix.c - AF_UNIX emulation for Windows. +/* w32-afunix.c - AF_UNIX emulation for Windows (Client only). * Copyright (C) 2004, 2006 g10 Code GmbH * * This file is part of JNLIB. @@ -17,8 +17,13 @@ * License along with this program; if not, see . */ +/* Use of this code is preprecated - you better use the sockt wrappers + from libassuan. */ + #ifdef _WIN32 #include +#include +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -27,12 +32,50 @@ #include "w32-afunix.h" -#ifndef S_IRGRP -# define S_IRGRP 0 -# define S_IWGRP 0 -#endif +/* The buffer for NONCE needs to be at least 16 bytes. Returns 0 on + success. */ +static int +read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) +{ + FILE *fp; + char buffer[50], *p; + size_t nread; + int aval; + + fp = fopen (fname, "rb"); + if (!fp) + return -1; + nread = fread (buffer, 1, sizeof buffer - 1, fp); + fclose (fp); + if (!nread) + { + errno = ENOFILE; + return -1; + } + buffer[nread] = 0; + aval = atoi (buffer); + if (aval < 1 || aval > 65535) + { + errno = EINVAL; + return -1; + } + *port = (unsigned int)aval; + for (p=buffer; nread && *p != '\n'; p++, nread--) + ; + if (*p != '\n' || nread != 17) + { + errno = EINVAL; + return -1; + } + p++; nread--; + memcpy (nonce, p, 16); + return 0; +} + + + int _w32_close (int fd) { @@ -53,97 +96,40 @@ int -_w32_sock_connect (int sockfd, struct sockaddr * addr, int addrlen) +_w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen) { struct sockaddr_in myaddr; - struct sockaddr_un * unaddr; - FILE * fp; - int port; - + struct sockaddr_un *unaddr; + unsigned short port; + char nonce[16]; + int ret; + unaddr = (struct sockaddr_un *)addr; - fp = fopen (unaddr->sun_path, "rb"); - if (!fp) + if (read_port_and_nonce (unaddr->sun_path, &port, nonce)) return -1; - fscanf (fp, "%d", &port); - fclose (fp); - - if (port < 0 || port > 65535) - { - errno = EINVAL; - return -1; - } - + myaddr.sin_family = AF_INET; - myaddr.sin_port = port; + myaddr.sin_port = htons (port); myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - /* we need this later. */ + + /* Set return values. */ unaddr->sun_family = myaddr.sin_family; unaddr->sun_port = myaddr.sin_port; unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; - return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); -} - - -int -_w32_sock_bind (int sockfd, struct sockaddr *addr, int addrlen) -{ - if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX) + ret = connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr); + if (!ret) { - struct sockaddr_in myaddr; - struct sockaddr_un *unaddr; - int filefd; - FILE *fp; - int len = sizeof myaddr; - int rc; - - unaddr = (struct sockaddr_un *)addr; - - myaddr.sin_port = 0; - myaddr.sin_family = AF_INET; - myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - filefd = open (unaddr->sun_path, - (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), - (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)); - if (filefd == -1) + /* Send the nonce. */ + ret = send (sockfd, nonce, 16, 0); + if (ret >= 0 && ret != 16) { - if (errno == EEXIST) - errno = WSAEADDRINUSE; - return -1; + errno = EIO; + ret = -1; } - fp = fdopen (filefd, "wb"); - if (!fp) - { - int save_e = errno; - close (filefd); - errno = save_e; - return -1; - } - - rc = bind (sockfd, (struct sockaddr *)&myaddr, len); - if (!rc) - rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len); - if (rc) - { - int save_e = errno; - fclose (fp); - remove (unaddr->sun_path); - errno = save_e; - return rc; - } - fprintf (fp, "%d", myaddr.sin_port); - fclose (fp); - - /* The caller expects these values. */ - unaddr->sun_family = myaddr.sin_family; - unaddr->sun_port = myaddr.sin_port; - unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr; - - return 0; } - return bind (sockfd, addr, addrlen); + return ret; } + #endif /*_WIN32*/ Modified: trunk/jnlib/w32-afunix.h =================================================================== --- trunk/jnlib/w32-afunix.h 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/jnlib/w32-afunix.h 2007-10-01 14:48:39 UTC (rev 4587) @@ -39,10 +39,11 @@ char sun_path[108-2-4]; /* Path name. */ }; + int _w32_close (int fd); int _w32_sock_new (int domain, int type, int proto); -int _w32_sock_bind (int sockfd, struct sockaddr *addr, int addrlen); int _w32_sock_connect (int sockfd, struct sockaddr *addr, int addrlen); + #endif /*W32AFUNIX_DEFS_H*/ #endif /*_WIN32*/ Modified: trunk/po/be.po =================================================================== --- trunk/po/be.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/be.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2003-10-30 16:35+0200\n" "Last-Translator: Ales Nyakhaychyk \n" "Language-Team: Belarusian \n" @@ -7509,6 +7509,10 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +msgid "|URL|use keyserver at URL" +msgstr "" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/ca.po =================================================================== --- trunk/po/ca.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/ca.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2005-02-04 02:04+0100\n" "Last-Translator: Jordi Mallach \n" "Language-Team: Catalan \n" @@ -8097,6 +8097,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "no s'ha pogut analitzar sint??cticament la URI del servidor de claus\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/cs.po =================================================================== --- trunk/po/cs.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/cs.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-11-26 09:12+0200\n" "Last-Translator: Roman Pavlik \n" "Language-Team: Czech \n" @@ -7779,6 +7779,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "nelze zpracovat URL serveru kl???\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/da.po =================================================================== --- trunk/po/da.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/da.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2003-12-03 16:11+0100\n" "Last-Translator: Birger Langkjer \n" "Language-Team: Danish \n" @@ -7663,6 +7663,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "import?r n?gler fra en n?gleserver: %s\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/el.po =================================================================== --- trunk/po/el.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/el.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2003-06-27 12:00+0200\n" "Last-Translator: Dokianakis Theofanis \n" "Language-Team: Greek \n" @@ -7951,6 +7951,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "???????? ???????????? ??? URI ??? ????????? ????????\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/eo.po =================================================================== --- trunk/po/eo.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/eo.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2002-04-14 14:33+0100\n" "Last-Translator: Edmund GRIMLEY EVANS \n" "Language-Team: Esperanto \n" @@ -7897,6 +7897,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "ne povis analizi URI de ?losilservilo\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/es.po =================================================================== --- trunk/po/es.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/es.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2007-08-16 11:35+0200\n" "Last-Translator: Jaime Su?rez \n" "Language-Team: Spanish \n" @@ -7825,6 +7825,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "no se puede interpretar la URL del servidor de claves\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/et.po =================================================================== --- trunk/po/et.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/et.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-17 11:04+0300\n" "Last-Translator: Toomas Soome \n" "Language-Team: Estonian \n" @@ -7856,6 +7856,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "ei saa parsida v?tmeserveri URI\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/fi.po =================================================================== --- trunk/po/fi.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/fi.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-16 22:40+0300\n" "Last-Translator: Tommi Vainikainen \n" "Language-Team: Finnish \n" @@ -7935,6 +7935,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "avainpalvelimen URI:i?? ei voi j??sent????\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/fr.po =================================================================== --- trunk/po/fr.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/fr.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2005-06-28 00:24+0200\n" "Last-Translator: Ga?l Qu?ri \n" "Language-Team: French \n" @@ -7983,6 +7983,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "impossible d'interpr?ter l'URL du serveur de cl?s\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/gl.po =================================================================== --- trunk/po/gl.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/gl.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2003-12-04 11:39+0100\n" "Last-Translator: Jacobo Tarrio \n" "Language-Team: Galician \n" @@ -7946,6 +7946,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "non se puido analisa-lo URI do servidor de chaves\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/hu.po =================================================================== --- trunk/po/hu.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/hu.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-19 21:53+0200\n" "Last-Translator: Nagy Ferenc L?szl? \n" "Language-Team: Hungarian \n" @@ -7897,6 +7897,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "?rtelmezhetetlen a kulcsszerver URI-ja!\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/id.po =================================================================== --- trunk/po/id.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/id.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: gnupg-id\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-17 16:32+0700\n" "Last-Translator: Tedi Heriyanto \n" "Language-Team: Indonesian \n" @@ -7899,6 +7899,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "tidak dapat memparsing URI keyserver\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/it.po =================================================================== --- trunk/po/it.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/it.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-16 17:01+0200\n" "Last-Translator: Marco d'Itri \n" "Language-Team: Italian \n" @@ -7945,6 +7945,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "impossibile fare il parsing dell'URI del keyserver\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/ja.po =================================================================== --- trunk/po/ja.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/ja.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-11-23 11:14+0900\n" "Last-Translator: IIDA Yosiaki \n" "Language-Team: Japanese \n" @@ -7713,6 +7713,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "????????????URL??????????\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/nb.po =================================================================== --- trunk/po/nb.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/nb.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2006-06-13 20:31+0200\n" "Last-Translator: Trond Endrest?l \n" "Language-Team: Norwegian Bokm?l \n" @@ -7582,6 +7582,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "kunne ikke parse n?kkelserverens URL\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/pl.po =================================================================== --- trunk/po/pl.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/pl.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-06-23 15:54+0200\n" "Last-Translator: Janusz A. Urbanowicz \n" "Language-Team: Polish \n" @@ -7942,6 +7942,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "niezrozuma?y URI serwera kluczy\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/pt.po =================================================================== --- trunk/po/pt.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/pt.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: gnupg\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2007-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2002-09-13 18:26+0100\n" "Last-Translator: Pedro Morais \n" "Language-Team: pt \n" @@ -7911,6 +7911,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "n?o consegui processar a URI do servidor de chaves\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/pt_BR.po =================================================================== --- trunk/po/pt_BR.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/pt_BR.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2007-08-16 11:35+0200\n" "Last-Translator:\n" "Language-Team: ?\n" @@ -7863,6 +7863,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "imposs?vel escrever para o chaveiro: %s\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/ro.po =================================================================== --- trunk/po/ro.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/ro.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2005-05-31 22:00-0500\n" "Last-Translator: Laurentiu Buzdugan \n" "Language-Team: Romanian \n" @@ -7806,6 +7806,12 @@ msgid "Configuration for Keyservers" msgstr "" +# +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "nu am putut interpreta URL-ul serverului de chei\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/ru.po =================================================================== --- trunk/po/ru.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/ru.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2006-11-07 19:31+0300\n" "Last-Translator: Maxim Britov \n" "Language-Team: Russian \n" @@ -7667,6 +7667,11 @@ msgid "Configuration for Keyservers" msgstr "???????????????????????? ???????????????? ????????????" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "???? ???????? ???????????????????????????????? URL ?????????????? ????????????\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/sk.po =================================================================== --- trunk/po/sk.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/sk.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2004-07-20 15:52+0200\n" "Last-Translator: Michal Majer \n" "Language-Team: Slovak \n" @@ -7917,6 +7917,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "nemo?no pou?i? URI servera k???ov - chyba anal?zy URI\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/sv.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2007-02-17 13:13+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -7880,6 +7880,11 @@ msgid "Configuration for Keyservers" msgstr "Konfiguration f??r nyckelservrar" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "kunde inte tolka url till nyckelserver\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "till??t PKA-uppslag (DNS-f??rfr??gningar)" Modified: trunk/po/tr.po =================================================================== --- trunk/po/tr.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/tr.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2006-11-04 03:45+0200\n" "Last-Translator: Nilg??n Belma Bug??ner \n" "Language-Team: Turkish \n" @@ -7755,6 +7755,11 @@ msgid "Configuration for Keyservers" msgstr "Anahtar sunucular i??in yap??land??rma" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "anahtar sunucusunun adresi ????z??mlenemedi\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "PKA aramalar??na izin verilir (DNS istekleri)" Modified: trunk/po/zh_CN.po =================================================================== --- trunk/po/zh_CN.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/zh_CN.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2006-07-02 10:58+0800\n" "Last-Translator: Meng Jie \n" "Language-Team: Chinese (simplified) \n" @@ -7615,6 +7615,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "??????????????????????????? URL\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/po/zh_TW.po =================================================================== --- trunk/po/zh_TW.po 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/po/zh_TW.po 2007-10-01 14:48:39 UTC (rev 4587) @@ -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-09-10 17:28+0200\n" +"POT-Creation-Date: 2007-09-14 13:27+0200\n" "PO-Revision-Date: 2005-07-29 09:49+0800\n" "Last-Translator: Jedi \n" "Language-Team: Chinese (traditional) \n" @@ -7655,6 +7655,11 @@ msgid "Configuration for Keyservers" msgstr "" +#: tools/gpgconf-comp.c:673 +#, fuzzy +msgid "|URL|use keyserver at URL" +msgstr "??????????????????????????? URI\n" + #: tools/gpgconf-comp.c:676 msgid "allow PKA lookups (DNS requests)" msgstr "" Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/scd/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,10 @@ +2007-10-01 Werner Koch + + * scdaemon.c (create_server_socket): Use Assuan socket wrappers + and remove Windows specific code. + (socket_nonce): New. + (start_connection_thread): Check nonce. + 2007-09-14 Marcus Brinkmann * scdaemon.c (main): New variable STANDARD_SOCKET, which is 1 for Modified: trunk/scd/scdaemon.c =================================================================== --- trunk/scd/scdaemon.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/scd/scdaemon.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -47,9 +47,6 @@ #include "i18n.h" #include "sysutils.h" #include "app-common.h" -#ifdef HAVE_W32_SYSTEM -#include "../jnlib/w32-afunix.h" -#endif #include "ccid-driver.h" #include "mkdtemp.h" #include "gc-opt-flags.h" @@ -170,6 +167,9 @@ /* Name of the communication socket */ static char *socket_name; +/* We need to keep track of the server's nonces (these are dummies for + POSIX systems). */ +static assuan_sock_nonce_t socket_nonce; /* Debug flag to disable the ticker. The ticker is in fact not disabled but it won't perform any ticker specific actions. */ @@ -179,7 +179,8 @@ static char *create_socket_name (int use_standard_socket, char *standard_name, char *template); -static int create_server_socket (int is_standard_name, const char *name); +static gnupg_fd_t create_server_socket (int is_standard_name, const char *name, + assuan_sock_nonce_t *nonce); static void *start_connection_thread (void *arg); static void handle_connections (int listen_fd); @@ -631,7 +632,7 @@ "S.scdaemon", "/tmp/gpg-XXXXXX/S.scdaemon"); - fd = create_server_socket (0, socket_name); + fd = FD2INT(create_server_socket (0, socket_name, &socket_nonce)); } tattr = pth_attr_new(); @@ -646,7 +647,7 @@ strerror (errno) ); scd_exit (2); } - ctrl->thread_startup.fd = -1; + ctrl->thread_startup.fd = GNUPG_INVALID_FD; if ( !pth_spawn (tattr, start_connection_thread, ctrl) ) { log_error ("error spawning pipe connection handler: %s\n", @@ -667,15 +668,17 @@ else { /* Regular server mode */ int fd; +#ifndef HAVE_W32_SYSTEM pid_t pid; int i; +#endif /* Create the socket. */ socket_name = create_socket_name (standard_socket, "S.scdaemon", "/tmp/gpg-XXXXXX/S.scdaemon"); - fd = create_server_socket (0, socket_name); + fd = FD2INT (create_server_socket (0, socket_name, &socket_nonce)); fflush (NULL); @@ -936,20 +939,17 @@ /* Create a Unix domain socket with NAME. IS_STANDARD_NAME indicates whether a non-random socket is used. Returns the file descriptor or terminates the process in case of an error. */ -static int -create_server_socket (int is_standard_name, const char *name) +static gnupg_fd_t +create_server_socket (int is_standard_name, const char *name, + assuan_sock_nonce_t *nonce) { struct sockaddr_un *serv_addr; socklen_t len; - int fd; + gnupg_fd_t fd; int rc; -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) + fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0); + if (fd == GNUPG_INVALID_FD) { log_error (_("can't create socket: %s\n"), strerror (errno)); scd_exit (2); @@ -963,33 +963,27 @@ len = (offsetof (struct sockaddr_un, sun_path) + strlen (serv_addr->sun_path) + 1); -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len); - if (is_standard_name && rc == -1 ) - { - remove (name); - rc = bind (fd, (struct sockaddr*) serv_addr, len); - } -#else - rc = bind (fd, (struct sockaddr*) serv_addr, len); + rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len); if (is_standard_name && rc == -1 && errno == EADDRINUSE) { remove (name); - rc = bind (fd, (struct sockaddr*) serv_addr, len); + rc = assuan_sock_bind (fd, (struct sockaddr*) serv_addr, len); } -#endif - if (rc == -1) + if (rc != -1 + && (rc=assuan_sock_get_nonce ((struct sockaddr*)serv_addr, len, nonce))) + log_error (_("error getting nonce for the socket\n")); + if (rc == -1) { log_error (_("error binding socket to `%s': %s\n"), serv_addr->sun_path, strerror (errno)); - close (fd); + assuan_sock_close (fd); scd_exit (2); } - if (listen (fd, 5 ) == -1) + if (listen (FD2INT(fd), 5 ) == -1) { log_error (_("listen() failed: %s\n"), strerror (errno)); - close (fd); + assuan_sock_close (fd); scd_exit (2); } @@ -1007,20 +1001,31 @@ { ctrl_t ctrl = arg; + if (assuan_sock_check_nonce (ctrl->thread_startup.fd, &socket_nonce)) + { + log_info (_("error reading nonce on fd %d: %s\n"), + FD2INT(ctrl->thread_startup.fd), strerror (errno)); + assuan_sock_close (ctrl->thread_startup.fd); + xfree (ctrl); + return NULL; + } + scd_init_default_ctrl (ctrl); if (opt.verbose) - log_info (_("handler for fd %d started\n"), ctrl->thread_startup.fd); + log_info (_("handler for fd %d started\n"), + FD2INT(ctrl->thread_startup.fd)); - scd_command_handler (ctrl, ctrl->thread_startup.fd); + scd_command_handler (ctrl, FD2INT(ctrl->thread_startup.fd)); if (opt.verbose) - log_info (_("handler for fd %d terminated\n"), ctrl->thread_startup.fd); + log_info (_("handler for fd %d terminated\n"), + FD2INT (ctrl->thread_startup.fd)); /* If this thread is the pipe connection thread, flag that a shutdown is required. With the next ticker event and given that no other connections are running the shutdown will then happen. */ - if (ctrl->thread_startup.fd == -1) + if (ctrl->thread_startup.fd == GNUPG_INVALID_FD) shutdown_pending = 1; scd_deinit_default_ctrl (ctrl); @@ -1166,7 +1171,7 @@ snprintf (threadname, sizeof threadname-1, "conn fd=%d", fd); threadname[sizeof threadname -1] = 0; pth_attr_set (tattr, PTH_ATTR_NAME, threadname); - ctrl->thread_startup.fd = fd; + ctrl->thread_startup.fd = INT2FD (fd); if (!pth_spawn (tattr, start_connection_thread, ctrl)) { log_error ("error spawning connection handler: %s\n", Modified: trunk/scd/scdaemon.h =================================================================== --- trunk/scd/scdaemon.h 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/scd/scdaemon.h 2007-10-01 14:48:39 UTC (rev 4587) @@ -30,8 +30,8 @@ #include #include "../common/util.h" #include "../common/errors.h" +#include "../common/sysutils.h" - /* To convey some special hash algorithms we use algorithm numbers reserved for application use. */ #ifndef GCRY_MD_USER @@ -91,7 +91,7 @@ /* Private data used to fire up the connection thread. We use this structure do avoid an extra allocation for just a few bytes. */ struct { - int fd; + gnupg_fd_t fd; } thread_startup; /* Local data of the server; used only in command.c. */ Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/tools/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) @@ -1,3 +1,12 @@ +2007-10-01 Werner Koch + + * gpg-connect-agent.c (do_sendfd): Use INT2FD for assuan_sendfd. + +2007-09-26 Werner Koch + + * gpg-connect-agent.c (main): Print the first response from the + server. + 2007-09-14 Werner Koch * gpgconf-comp.c: Make a string translatable. Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-09-18 11:40:09 UTC (rev 4586) +++ trunk/tools/gpg-connect-agent.c 2007-10-01 14:48:39 UTC (rev 4587) @@ -29,9 +29,9 @@ #include "i18n.h" #include "../common/util.h" #include "../common/asshelp.h" +#include "../common/sysutils.h" - /* Constants to identify the commands and options. */ enum cmd_and_opt_values { @@ -244,7 +244,7 @@ log_error ("file `%s' opened in \"%s\" mode, fd=%d\n", name, mode, fd); - rc = assuan_sendfd (ctx, fd); + rc = assuan_sendfd (ctx, INT2FD (fd) ); if (rc) log_error ("sednig descriptor %d failed: %s\n", fd, gpg_strerror (rc)); fclose (fp); @@ -360,6 +360,16 @@ } else ctx = start_agent (); + + /* See whether there is a line pending from the server (in case + assuan did not run the initial handshaking). */ + if (assuan_pending_line (ctx)) + { + rc = read_and_print_response (ctx); + if (rc) + log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) ); + } + line = NULL; linesize = 0; for (;;) From cvs at cvs.gnupg.org Tue Oct 2 10:44:30 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 02 Oct 2007 10:44:30 +0200 Subject: [svn] assuan - r268 - in trunk: doc src Message-ID: Author: wk Date: 2007-10-02 10:44:21 +0200 (Tue, 02 Oct 2007) New Revision: 268 Modified: trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-defs.h trunk/src/assuan-io.c trunk/src/assuan-socket-server.c trunk/src/assuan-socket.c trunk/src/assuan.h Log: Add new API assuan_set_sock_nonce. Fixed a blocking problem on Windows. Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/doc/assuan.texi 2007-10-02 08:44:21 UTC (rev 268) @@ -920,6 +920,21 @@ @end deftypefun @noindent +On the Windows platform the following function needs to be called after +assuan_init_socket_server_ext: + + at deftypefun void assuan_set_sock_nonce ( @ + @w{assuan_context_t @var{ctx}}, @ + @w{assuan_sock_nonce_t *@var{nonce}}) + +Save a copy of @var{nonce} in context @var{ctx}. This should be used to +register the server's nonce with a context established by +assuan_init_socket_server. It is actually only needed for Windows but +it does not harm to use it on other systems as well. + at end deftypefun + + + at noindent After error checking, the implemented assuan commands are registered with the server. @@ -938,6 +953,7 @@ @} @end example + @deftypefun assuan_error_t assuan_register_command (@w{assuan_context_t @var{ctx}}, @w{const char *@var{cmd_string}}, @w{int (*@var{handler}) (assuan_context_t, char *)}) This registers the command named @var{cmd_string} with the Assuan @@ -1642,7 +1658,7 @@ from the client and compare it with the saved @var{nonce}. If this function fails the server should immediatly drop the connection. To keep the code readable this may also be used on POSIX system; it is a -dummy function then. +dummy function then. See also @code{assuan_set_sock_nonce}. @end deftypefun Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/ChangeLog 2007-10-02 08:44:21 UTC (rev 268) @@ -1,5 +1,16 @@ +2007-10-02 Werner Koch + + * assuan-io.c (_assuan_io_read) [W32]: Map WSAEWOULDBLOCK to EAGAIN. + * assuan-socket.c (_assuan_sock_check_nonce): N needs to be signed. + + * assuan-defs.h (struct assuan_context_s): Add LISTEN_NONCE. + * assuan-socket-server.c (assuan_set_sock_nonce): New. + (accept_connection): Check the nonce. + 2007-10-01 Werner Koch + * assuan.h (ASSUAN_INT2FD, ASSUAN_FD2INT): New. + * assuan-socket.c: Rewritten. (assuan_sock_new, assuan_sock_connect, assuan_sock_bind) (assuan_sock_get_nonce, assuan_sock_check_nonce): New APIs. Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/assuan-defs.h 2007-10-02 08:44:21 UTC (rev 268) @@ -136,6 +136,7 @@ pid_t pid; /* The pid of the peer. */ assuan_fd_t listen_fd; /* The fd we are listening on (used by socket servers) */ + assuan_sock_nonce_t listen_nonce; /* Used with LISTEN_FD. */ assuan_fd_t connected_fd; /* helper */ struct { @@ -186,8 +187,8 @@ /* If set, this is called right before logging an I/O line. With DIRECTION set to 1 it is called for an output oeration; 0 means an input operation. If bit 0 is set in the return value, the - logging of the will be suppressed. With bit 1 set, the entire - line will be ignored. */ + logging of the line will be suppressed. With bit 1 set, the + entire line will be ignored. */ unsigned int (*io_monitor)(assuan_context_t ctx, int direction, const char *line, Modified: trunk/src/assuan-io.c =================================================================== --- trunk/src/assuan-io.c 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/assuan-io.c 2007-10-02 08:44:21 UTC (rev 268) @@ -56,22 +56,33 @@ int n; n = recv (HANDLE2SOCKET(fd), buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) + if (n == -1) { - DWORD nread = 0; - - n = ReadFile (fd, buffer, size, &nread, NULL); - if (!n) + switch (WSAGetLastError ()) { - switch (GetLastError()) - { - case ERROR_BROKEN_PIPE: errno = EPIPE; break; - default: errno = EIO; - } - n = -1; + case WSAENOTSOCK: + { + DWORD nread = 0; + + n = ReadFile (fd, buffer, size, &nread, NULL); + if (!n) + { + switch (GetLastError()) + { + case ERROR_BROKEN_PIPE: errno = EPIPE; break; + default: errno = EIO; + } + n = -1; + } + else + n = (int)nread; + } + break; + + case WSAEWOULDBLOCK: errno = EAGAIN; break; + case ERROR_BROKEN_PIPE: errno = EPIPE; break; + default: errno = EIO; break; } - else - n = (int)nread; } return n; #else /*!HAVE_W32_SYSTEM*/ Modified: trunk/src/assuan-socket-server.c =================================================================== --- trunk/src/assuan-socket-server.c 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/assuan-socket-server.c 2007-10-02 08:44:21 UTC (rev 268) @@ -1,5 +1,5 @@ /* assuan-socket-server.c - Assuan socket based server - * Copyright (C) 2002 Free Software Foundation, Inc. + * Copyright (C) 2002, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -98,6 +98,12 @@ ctx->os_errno = errno; return _assuan_error (ASSUAN_Accept_Failed); } + if (_assuan_sock_check_nonce (fd, &ctx->listen_nonce)) + { + _assuan_close (fd); + ctx->os_errno = EACCES; + return _assuan_error (ASSUAN_Accept_Failed); + } ctx->connected_fd = fd; return accept_connection_bottom (ctx); @@ -190,3 +196,14 @@ *r_ctx = ctx; return rc; } + + +/* Save a copy of NONCE in context CTX. This should be used to + register the server's nonce with an context established by + assuan_init_socket_server. */ +void +assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce) +{ + if (ctx && nonce) + ctx->listen_nonce = *nonce; +} Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/assuan-socket.c 2007-10-02 08:44:21 UTC (rev 268) @@ -32,6 +32,8 @@ #include #include #include +#include + #include "assuan-defs.h" /* Hacks for Slowaris. */ @@ -306,7 +308,8 @@ { #ifdef HAVE_W32_SYSTEM char buffer[16], *p; - size_t nleft, n; + size_t nleft; + int n; if (sizeof nonce->nonce != 16) { Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-10-01 14:44:46 UTC (rev 267) +++ trunk/src/assuan.h 2007-10-02 08:44:21 UTC (rev 268) @@ -377,9 +377,13 @@ #ifdef _WIN32 typedef void *assuan_fd_t; #define ASSUAN_INVALID_FD ((void*)(-1)) +#define ASSUAN_INT2FD(s) ((void *)(s)) +#define ASSUAN_FD2INT(h) ((unsigned int)(h)) #else typedef int assuan_fd_t; #define ASSUAN_INVALID_FD (-1) +#define ASSUAN_INT2FD(s) ((s)) +#define ASSUAN_FD2INT(h) ((h)) #endif @@ -475,6 +479,7 @@ assuan_fd_t fd) _ASSUAN_DEPRECATED; int assuan_init_socket_server_ext (assuan_context_t *r_ctx, assuan_fd_t fd, unsigned int flags); +void assuan_set_sock_nonce (assuan_context_t ctx, assuan_sock_nonce_t *nonce); /*-- assuan-pipe-connect.c --*/ assuan_error_t assuan_pipe_connect (assuan_context_t *ctx, From cvs at cvs.gnupg.org Tue Oct 2 14:02:19 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 02 Oct 2007 14:02:19 +0200 Subject: [svn] gpgme - r1270 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-02 14:02:08 +0200 (Tue, 02 Oct 2007) New Revision: 1270 Modified: trunk/gpgme/ChangeLog trunk/gpgme/engine-gpgsm.c trunk/gpgme/priv-io.h trunk/gpgme/w32-glib-io.c trunk/gpgme/w32-qt-io.cpp Log: 2007-10-02 Marcus Brinkmann * priv-io.h, engine-gpgsm.c: Add comments. * w32-qt-io.cpp (_gpgme_io_select): Remove code handling frozen FDs. * w32-glib-io.c (_gpgme_io_close): Always dereference the channel, even if not primary. (_gpgme_io_dup): Acquire a reference. Replace unused implementation by assertion. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-09-28 17:30:11 UTC (rev 1269) +++ trunk/gpgme/ChangeLog 2007-10-02 12:02:08 UTC (rev 1270) @@ -1,3 +1,12 @@ +2007-10-02 Marcus Brinkmann + + * priv-io.h, engine-gpgsm.c: Add comments. + * w32-qt-io.cpp (_gpgme_io_select): Remove code handling frozen FDs. + * w32-glib-io.c (_gpgme_io_close): Always dereference the channel, + even if not primary. + (_gpgme_io_dup): Acquire a reference. Replace unused + implementation by assertion. + 2007-09-28 Werner Koch * engine-gpgsm.c (iocb_data_t): Add SERVER_FD_STR. Modified: trunk/gpgme/engine-gpgsm.c =================================================================== --- trunk/gpgme/engine-gpgsm.c 2007-09-28 17:30:11 UTC (rev 1269) +++ trunk/gpgme/engine-gpgsm.c 2007-10-02 12:02:08 UTC (rev 1270) @@ -54,7 +54,7 @@ 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 + need this because _gpgme_io_fd2str can't be used on a closed descriptor. */ } iocb_data_t; @@ -530,8 +530,9 @@ #endif leave: - /* Close the server ends of the pipes. Our ends are closed in - gpgsm_release(). */ + /* Close the server ends of the pipes (because of this, we must use + the stored server_fd_str in the function start). Our ends are + closed in gpgsm_release(). */ #if !USE_DESCRIPTOR_PASSING if (gpgsm->input_cb.server_fd != -1) _gpgme_io_close (gpgsm->input_cb.server_fd); @@ -1013,11 +1014,15 @@ if (nfds < 1) return gpg_error (GPG_ERR_GENERAL); /* FIXME */ - /* We duplicate the file descriptor, so we can close it without - disturbing assuan. Alternatively, we could special case - status_fd and register/unregister it manually as needed, but this - increases code duplication and is more complicated as we can not - use the close notifications etc. */ + /* We "duplicate" the file descriptor, so we can close it here (we + can't close fdlist[0], as that is closed by libassuan, and + closing it here might cause libassuan to close some unrelated FD + later). Alternatively, we could special case status_fd and + register/unregister it manually as needed, but this increases + code duplication and is more complicated as we can not use the + close notifications etc. A third alternative would be to let + Assuan know that we closed the FD, but that complicates the + Assuan interface. */ gpgsm->status_cb.fd = _gpgme_io_dup (fdlist[0]); if (gpgsm->status_cb.fd < 0) Modified: trunk/gpgme/priv-io.h =================================================================== --- trunk/gpgme/priv-io.h 2007-09-28 17:30:11 UTC (rev 1269) +++ trunk/gpgme/priv-io.h 2007-10-02 12:02:08 UTC (rev 1270) @@ -64,7 +64,13 @@ line that the child process expects. */ int _gpgme_io_fd2str (char *buf, int buflen, int fd); -/* Like dup(). */ +/* Duplicate a file descriptor. This is more restrictive than dup(): + it assumes that the resulting file descriptors are essentially + co-equal (for example, no private offset), which is true for pipes + and sockets (but not files) under Unix with the standard dup() + function. Basically, this function is used to reference count the + status output file descriptor shared between GPGME and libassuan + (in engine-gpgsm.c). */ int _gpgme_io_dup (int fd); #endif /* IO_H */ Modified: trunk/gpgme/w32-glib-io.c =================================================================== --- trunk/gpgme/w32-glib-io.c 2007-09-28 17:30:11 UTC (rev 1269) +++ trunk/gpgme/w32-glib-io.c 2007-10-02 12:02:08 UTC (rev 1270) @@ -81,7 +81,23 @@ static struct { GIOChannel *chan; - int primary; /* Set if CHAN is the one we used to create the channel. */ + /* The boolean PRIMARY is true if this file descriptor caused the + allocation of CHAN. Only then should CHAN be destroyed when this + FD is closed. This, together with the fact that dup'ed file + descriptors are closed before the file descriptors from which + they are dup'ed are closed, ensures that CHAN is always valid, + and shared among all file descriptors refering to the same + underlying object. + + The logic behind this is that there is only one reason for us to + dup file descriptors anyway: to allow simpler book-keeping of + file descriptors shared between GPGME and libassuan, which both + want to close something. Using the same channel for these + duplicates works just fine (and in fact, using different channels + does not work because the W32 backend in glib does not support + that: One would end up with several competing reader/writer + threads. */ + int primary; } giochannel_table[MAX_SLAFD]; @@ -306,10 +322,11 @@ if (giochannel_table[fd].chan) { if (giochannel_table[fd].primary) - { - g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL); - g_io_channel_unref (giochannel_table[fd].chan); - } + g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL); + else + _close (fd); + + g_io_channel_unref (giochannel_table[fd].chan); giochannel_table[fd].chan = NULL; } else @@ -731,40 +748,24 @@ TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd); - newfd =_dup (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. */ + /* New FD won't fit into our table. */ _close (newfd); errno = EIO; return TRACE_SYSRES (-1); } + assert (giochannel_table[newfd].chan == NULL); 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); - } + assert (chan); + g_io_channel_ref (chan); + giochannel_table[newfd].chan = chan; + giochannel_table[newfd].primary = 0; + return TRACE_SYSRES (newfd); } Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-09-28 17:30:11 UTC (rev 1269) +++ trunk/gpgme/w32-qt-io.cpp 2007-10-02 12:02:08 UTC (rev 1270) @@ -1,4 +1,4 @@ -/* w32-glib-io.c - W32 Glib I/O functions +/* w32-qt-io.c - W32 Glib I/O functions Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH @@ -583,13 +583,8 @@ { fds[i].signaled = 0; } - else if (fds[i].frozen) + else if (fds[i].for_read) { - 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 ; From cvs at cvs.gnupg.org Tue Oct 2 17:56:46 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 02 Oct 2007 17:56:46 +0200 Subject: [svn] gpgme - r1271 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-02 17:56:37 +0200 (Tue, 02 Oct 2007) New Revision: 1271 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/kdpipeiodevice.moc trunk/gpgme/w32-qt-io.cpp Log: 2007-10-02 Marcus Brinkmann * kdpipeiodevice.cpp, kdpipeiodevice.moc: New versions. * w32-qt-io.cpp (_gpgme_io_fd2str): Print actual_fd if available. (_gpgme_io_dup): Only acquire a reference, do not actually dup. Submitted by Frank Osterfeld. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-10-02 12:02:08 UTC (rev 1270) +++ trunk/gpgme/ChangeLog 2007-10-02 15:56:37 UTC (rev 1271) @@ -1,5 +1,10 @@ 2007-10-02 Marcus Brinkmann + * kdpipeiodevice.cpp, kdpipeiodevice.moc: New versions. + * w32-qt-io.cpp (_gpgme_io_fd2str): Print actual_fd if available. + (_gpgme_io_dup): Only acquire a reference, do not actually dup. + Submitted by Frank Osterfeld. + * priv-io.h, engine-gpgsm.c: Add comments. * w32-qt-io.cpp (_gpgme_io_select): Remove code handling frozen FDs. * w32-glib-io.c (_gpgme_io_close): Always dereference the channel, Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-10-02 12:02:08 UTC (rev 1270) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-10-02 15:56:37 UTC (rev 1271) @@ -82,6 +82,8 @@ return false; } + void notifyReadyRead(); + Q_SIGNALS: void readyRead(); @@ -96,11 +98,15 @@ QWaitCondition bufferNotFullCondition; QWaitCondition bufferNotEmptyCondition; QWaitCondition hasStarted; + QWaitCondition readyReadSentCondition; + QWaitCondition notInReadDataCondition; bool cancel; bool eof; bool error; bool eofShortCut; int errorCode; + bool inReadData; + private: unsigned int rptr, wptr; char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state @@ -120,7 +126,8 @@ error( false ), eofShortCut( false ), errorCode( 0 ), - rptr( 0 ), wptr( 0 ) + rptr( 0 ), wptr( 0 ), + inReadData( false ) { } @@ -203,6 +210,9 @@ bool triedToStartReader; bool triedToStartWriter; +public Q_SLOTS: + void emitReadyRead(); + private: int fd; Qt::HANDLE handle; @@ -221,7 +231,9 @@ } -KDPipeIODevice::Private::~Private() {} +KDPipeIODevice::Private::~Private() { + qDebug( "KDPipeIODevice::~Private(): Destroying %p", this ); +} KDPipeIODevice::KDPipeIODevice( QObject * p ) : QIODevice( p ), d( new Private( this ) ) @@ -302,6 +314,21 @@ return true; } +void KDPipeIODevice::Private::emitReadyRead() +{ + static int s_counter = 0; + const int counter = s_counter++; + QPointer thisPointer( this ); + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d", this, counter ); + emit q->readyRead(); + if ( !thisPointer ) + return; + LOCKED( reader ); + reader->readyReadSentCondition.wakeAll(); + qDebug( "KDPipeIODevice::Private::emitReadyRead %p leaving %d", this, counter ); + +} + bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) { if ( q->isOpen() || fd_ < 0 ) @@ -323,13 +350,13 @@ if ( mode_ & ReadOnly ) { reader_.reset( new Reader( fd_, handle_ ) ); - qDebug( "KDPipeIODevice::doOpen: created reader for fd %d", fd_ ); - connect( reader_.get(), SIGNAL(readyRead()), q, -SIGNAL(readyRead()), Qt::QueuedConnection ); + qDebug( "KDPipeIODevice::doOpen (%p): created reader (%p) for fd %d", this, reader_.get(), fd_ ); + connect( reader_.get(), SIGNAL(readyRead()), this, SLOT(emitReadyRead()), +Qt::QueuedConnection ); } if ( mode_ & WriteOnly ) { writer_.reset( new Writer( fd_, handle_ ) ); - qDebug( "KDPipeIODevice::doOpen: created writer for fd %d", fd_ ); + qDebug( "KDPipeIODevice::doOpen (%p): created writer (%p) for fd %d", this, writer_.get(), fd_ ); connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection ); } @@ -412,6 +439,8 @@ if ( !w ) return true; LOCKED( w ); + qDebug( "KDPipeIODevice::waitForBytesWritten (%p,w=%p): entered locked area", this, w +); return w->bufferEmpty() || w->error || w->bufferEmptyCondition.wait( &w->mutex, msecs ) ; } @@ -428,17 +457,24 @@ return r->bytesInBuffer() != 0 || r->eof || r->error || r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ; } +template +class TemporaryValue { +public: + TemporaryValue( T& var_, const T& tv ) : var( var_ ), oldValue( var_ ) { var = tv; } + ~TemporaryValue() { var = oldValue; } +private: + T& var; + const T oldValue; +}; + qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS; qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, 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 ); @@ -455,10 +491,14 @@ 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? + const TemporaryValue tmp( d->reader->inReadData, true ); + assert( d->reader->inReadData ); + while ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition", this ); + r->readyReadSentCondition.wakeAll(); + r->notInReadDataCondition.wakeAll(); r->bufferNotEmptyCondition.wait( &r->mutex ); } @@ -467,6 +507,7 @@ // woken with an empty buffer must mean either EOF or error: assert( r->eof || r->error ); r->eofShortCut = true; + r->notInReadDataCondition.wakeAll(); return r->eof ? 0 : -1 ; } @@ -474,6 +515,7 @@ const qint64 bytesRead = r->readData( data, maxSize ); qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead ); qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data ); + r->notInReadDataCondition.wakeAll(); return bytesRead; } @@ -508,9 +550,12 @@ LOCKED( w ); - while ( !w->error && !w->bufferEmpty() ) + while ( !w->error && !w->bufferEmpty() ) { + qDebug( "%p: KDPipeIODevice::writeData: wait for empty buffer", this ); w->bufferEmptyCondition.wait( &w->mutex ); + qDebug( "%p: KDPipeIODevice::writeData: empty buffer signaled", this ); + } if ( w->error ) return -1; @@ -529,10 +574,10 @@ numBytesInBuffer = size; - if ( !bufferEmpty() ) + if ( !bufferEmpty() ) { bufferNotEmptyCondition.wakeAll(); - - return size; + } + return size; } void KDPipeIODevice::Private::stopThreads() @@ -550,6 +595,7 @@ r->cancel = true; // and wake it, so it can terminate: r->bufferNotFullCondition.wakeAll(); + r->readyReadSentCondition.wakeAll(); } } if ( Writer * & w = writer ) { @@ -563,7 +609,7 @@ } void KDPipeIODevice::close() { KDAB_CHECK_THIS; - + qDebug( "KDPipeIODevice::close(%p)", this ); if ( !isOpen() ) return; @@ -571,12 +617,14 @@ emit aboutToClose(); d->stopThreads(); -#define waitAndDelete( t ) if ( t ) { t->wait(); delete t; t = 0; } +#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* t2 = t; t = 0; delete t2; } + qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer ); waitAndDelete( d->writer ); + qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader ); waitAndDelete( d->reader ); #undef waitAndDelete - #ifdef Q_OS_WIN32 + qDebug( "Closing handle" ); CloseHandle( d->handle ); #else ::close( d->fd ); @@ -598,18 +646,27 @@ while ( true ) { - while ( !cancel && bufferFull() ) { - bufferNotEmptyCondition.wakeAll(); - qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); + if ( !bufferFull() && !bufferEmpty() ) { + qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); + notifyReadyRead(); + } + + while ( !cancel && bufferFull() ) { + bufferNotEmptyCondition.wakeAll(); + notifyReadyRead(); + if ( !bufferFull() ) + break; + qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); bufferNotFullCondition.wait( &mutex ); qDebug( "%p: Reader::run: woke up", this ); } - + if ( cancel ) { qDebug( "%p: Reader::run: detected cancel", this ); goto leave; } + if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty rptr = wptr = 0; @@ -630,9 +687,11 @@ if ( !ok ) { errorCode = static_cast( GetLastError() ); if ( errorCode == ERROR_BROKEN_PIPE ) { + assert( numRead == 0 ); qDebug( "%p: Reader::run: got eof (broken pipe)", this ); eof = true; } else { + assert( numRead == 0 ); qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode ); error = true; } @@ -668,16 +727,33 @@ qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); wptr = ( wptr + numRead ) % sizeof buffer; qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr ); - if ( !bufferEmpty() ) { - qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); - bufferNotEmptyCondition.wakeAll(); - emit readyRead(); - } } leave: - qDebug( "%p: Reader::run: terminating", this ); + qDebug( "%p: Reader::run: terminating: loop while not canceled and not empty", this ); + while ( !cancel && !bufferEmpty() ) { + notifyReadyRead(); + } + notifyReadyRead(); + qDebug( "%p: Reader::run: terminated", this ); +} + +void Reader::notifyReadyRead() +{ + qDebug( "notifyReadyRead" ); + if ( cancel ) + return; bufferNotEmptyCondition.wakeAll(); + if ( inReadData ) { + qDebug( "notifyReadyRead: inReadData: waiting" ); + notInReadDataCondition.wait( &mutex ); + } + if ( cancel || ( !eof && !error && bufferEmpty() ) ) + return; + qDebug( "readyReadData: actually emit signal" ); emit readyRead(); + bufferNotEmptyCondition.wakeAll(); + readyReadSentCondition.wait( &mutex ); + bufferNotEmptyCondition.wakeAll(); } void Writer::run() { @@ -692,9 +768,11 @@ while ( true ) { while ( !cancel && bufferEmpty() ) { - bufferEmptyCondition.wakeAll(); + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); + bufferEmptyCondition.wakeAll(); + emit bytesWritten( 0 ); qDebug( "%p: Writer::run: buffer is empty, going to sleep", this ); - bufferNotEmptyCondition.wait( &mutex ); + bufferNotEmptyCondition.wait( &mutex ); qDebug( "%p: Writer::run: woke up", this ); } @@ -707,10 +785,12 @@ qDebug( "%p: Writer::run: Trying to write %u bytes", this, numBytesInBuffer ); qint64 totalWritten = 0; - do { - mutex.unlock(); + do { + mutex.unlock(); #ifdef Q_OS_WIN32 - DWORD numWritten; + DWORD numWritten; + qDebug( "%p (fd=%d): Writer::run: buffer before WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, buffer ); + qDebug( "%p (fd=%d): Writer::run: Going into WriteFile", this, fd ); if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) { mutex.lock(); errorCode = static_cast( GetLastError() ); @@ -732,6 +812,8 @@ goto leave; } #endif + qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, +buffer ); totalWritten += numWritten; mutex.lock(); } while ( totalWritten < numBytesInBuffer ); @@ -739,12 +821,15 @@ qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten ); numBytesInBuffer = 0; + + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); bufferEmptyCondition.wakeAll(); emit bytesWritten( totalWritten ); } leave: qDebug( "%p: Writer::run: terminating", this ); numBytesInBuffer = 0; + qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this ); bufferEmptyCondition.wakeAll(); emit bytesWritten( 0 ); } Modified: trunk/gpgme/kdpipeiodevice.moc =================================================================== --- trunk/gpgme/kdpipeiodevice.moc 2007-10-02 12:02:08 UTC (rev 1270) +++ trunk/gpgme/kdpipeiodevice.moc 2007-10-02 15:56:37 UTC (rev 1271) @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'kdpipeiodevice.cpp' ** -** Created: Wed Sep 26 11:05:05 2007 +** Created: Mon Oct 1 16:08:44 2007 ** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1) ** ** WARNING! All changes made in this file will be lost! @@ -136,15 +136,18 @@ 1, // revision 0, // classname 0, 0, // classinfo - 0, 0, // methods + 1, 10, // methods 0, 0, // properties 0, 0, // enums/sets + // slots: signature, parameters, type, tag, flags + 25, 24, 24, 24, 0x0a, + 0 // eod }; static const char qt_meta_stringdata_KDPipeIODevice__Private[] = { - "KDPipeIODevice::Private\0" + "KDPipeIODevice::Private\0\0emitReadyRead()\0" }; const QMetaObject KDPipeIODevice::Private::staticMetaObject = { @@ -170,5 +173,11 @@ _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: emitReadyRead(); break; + } + _id -= 1; + } return _id; } Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-10-02 12:02:08 UTC (rev 1270) +++ trunk/gpgme/w32-qt-io.cpp 2007-10-02 15:56:37 UTC (rev 1271) @@ -117,9 +117,11 @@ 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) +_gpgme_io_fd2str (char *buf, int buflen, int fd_) { - return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (fd)); + const int actual_fd = iodevice_table[fd_] ? iodevice_table[fd_]->actual_fd : fd_; + return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (actual_fd)); + // return snprintf (buf, buflen, "%d", fd); } @@ -627,6 +629,14 @@ int _gpgme_io_dup (int fd) { + DeviceEntry* const existing = iodevice_table[fd]; + if ( existing ) + existing->ref(); + else + find_channel( fd, /*create=*/1 ); + return fd; + +#if 0 const int new_fd = _dup( fd ); iodevice_table[new_fd] = iodevice_table[fd]; if ( iodevice_table[new_fd] ) @@ -634,5 +644,6 @@ else find_channel( new_fd, /*create=*/1 ); return new_fd; +#endif } From cvs at cvs.gnupg.org Tue Oct 2 18:31:09 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 02 Oct 2007 18:31:09 +0200 Subject: [svn] GnuPG - r4588 - in trunk: agent scd tools Message-ID: Author: wk Date: 2007-10-02 18:30:58 +0200 (Tue, 02 Oct 2007) New Revision: 4588 Modified: trunk/agent/ChangeLog trunk/agent/command.c trunk/scd/ChangeLog trunk/scd/command.c trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c trunk/tools/no-libgcrypt.c Log: Extended gpg-connect-agent. New "GETINFO pid" command for scdaemon and gpg-agent. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/agent/ChangeLog 2007-10-02 16:30:58 UTC (rev 4588) @@ -1,3 +1,7 @@ +2007-10-02 Werner Koch + + * command.c (cmd_getinfo): Add "pid" subcommand. + 2007-10-01 Werner Koch * agent.h (struct server_control_s): Remove unused CONNECTION_FD. Modified: trunk/agent/command.c =================================================================== --- trunk/agent/command.c 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/agent/command.c 2007-10-02 16:30:58 UTC (rev 4588) @@ -1344,6 +1344,7 @@ Supported values for WHAT are: version - Return the version of the program. + pid - Return the process id of the server. socket_name - Return the name of the socket. ssh_socket_name - Return the name of the ssh socket. @@ -1358,6 +1359,13 @@ const char *s = VERSION; rc = assuan_send_data (ctx, s, strlen (s)); } + else if (!strcmp (line, "pid")) + { + char numbuf[50]; + + snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); + rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); + } else if (!strcmp (line, "socket_name")) { const char *s = get_agent_socket_name (); Modified: trunk/scd/ChangeLog =================================================================== --- trunk/scd/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/scd/ChangeLog 2007-10-02 16:30:58 UTC (rev 4588) @@ -1,3 +1,7 @@ +2007-10-02 Werner Koch + + * command.c (cmd_getinfo): Add "pid" subcommand. + 2007-10-01 Werner Koch * scdaemon.c (create_server_socket): Use Assuan socket wrappers Modified: trunk/scd/command.c =================================================================== --- trunk/scd/command.c 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/scd/command.c 2007-10-02 16:30:58 UTC (rev 4588) @@ -1452,6 +1452,7 @@ Supported values of WHAT are: version - Return the version of the program. + pid - Return the process id of the server. socket_name - Return the name of the socket. @@ -1476,6 +1477,13 @@ const char *s = VERSION; rc = assuan_send_data (ctx, s, strlen (s)); } + else if (!strcmp (line, "pid")) + { + char numbuf[50]; + + snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); + rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); + } else if (!strcmp (line, "socket_name")) { const char *s = scd_get_socket_name (); Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/tools/ChangeLog 2007-10-02 16:30:58 UTC (rev 4588) @@ -1,3 +1,13 @@ +2007-10-02 Werner Koch + + * no-libgcrypt.c (gcry_malloc_secure): New. + + * gpg-connect-agent.c (set_var, set_int_var, get_var) + (substitute_line, show_variables, assign_variable) + (do_open, do_close, do_showopen): New. + (main): Add new commands /nosubst, /subst, /let, /showvar, /open, + /close and /showopen. + 2007-10-01 Werner Koch * gpg-connect-agent.c (do_sendfd): Use INT2FD for assuan_sendfd. Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/tools/gpg-connect-agent.c 2007-10-02 16:30:58 UTC (rev 4588) @@ -30,8 +30,8 @@ #include "../common/util.h" #include "../common/asshelp.h" #include "../common/sysutils.h" +#include "../common/membuf.h" - /* Constants to identify the commands and options. */ enum cmd_and_opt_values { @@ -82,6 +82,7 @@ const char *raw_socket; /* Name of socket to connect in raw mode. */ int exec; /* Run the pgm given on the command line. */ unsigned int connect_flags; /* Flags used for connecting. */ + int enable_varsubst; /* Set if variable substitution is enabled. */ } opt; @@ -101,7 +102,31 @@ static definq_t *definq_list_tail = &definq_list; +/* Variable definitions and glovbal table. */ +struct variable_s +{ + struct variable_s *next; + char *value; /* Malloced value - always a string. */ + char name[1]; /* Name of the variable. */ +}; +typedef struct variable_s *variable_t; +static variable_t variable_table; + +/* This is used to store the pid of the server. */ +static pid_t server_pid = (pid_t)(-1); + + +/* A list of open file descriptors. */ +static struct +{ + int inuse; +#ifdef HAVE_W32_SYSTEM + HANDLE handle; +#endif +} open_fd_table[256]; + + /*-- local prototypes --*/ static int read_and_print_response (assuan_context_t ctx); static assuan_context_t start_agent (void); @@ -139,7 +164,163 @@ return p; } + +static void +set_var (const char *name, const char *value) +{ + variable_t var; + for (var = variable_table; var; var = var->next) + if (!strcmp (var->name, name)) + break; + if (!var) + { + var = xmalloc (sizeof *var + strlen (name)); + var->value = NULL; + strcpy (var->name, name); + var->next = variable_table; + variable_table = var; + } + xfree (var->value); + var->value = value? xstrdup (value) : NULL; +} + + +static void +set_int_var (const char *name, int value) +{ + char numbuf[35]; + + snprintf (numbuf, sizeof numbuf, "%d", value); + set_var (name, numbuf); +} + +/* Return the value of a variable. That value is valid until a + variable of the name is changed. Return NULL if not found. */ +static const char * +get_var (const char *name) +{ + variable_t var; + + for (var = variable_table; var; var = var->next) + if (!strcmp (var->name, name)) + break; + if (!var || !var->value) + return NULL; + return var->value; +} + + + +/* Substitute variables in LINE and return a new allocated buffer if + required. The function might modify LINE if the expanded version + fits into it. */ +static char * +substitute_line (char *buffer) +{ + char *line = buffer; + char *p, *pend; + const char *value; + size_t valuelen, n; + char *result = NULL; + + while (*line) + { + p = strchr (line, '$'); + if (!p) + return result; /* No more variables. */ + + if (p[1] == '$') /* Escaped dollar sign. */ + { + memmove (p, p+1, strlen (p+1)+1); + line = p + 1; + continue; + } + for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++) + ; + if (*pend) + { + int save = *pend; + *pend = 0; + value = get_var (p+1); + *pend = save; + } + else + value = get_var (p+1); + if (!value) + value = ""; + valuelen = strlen (value); + if (valuelen <= pend - p) + { + memcpy (p, value, valuelen); + p += valuelen; + n = pend - p; + if (n) + memmove (p, p+n, strlen (p+n)+1); + line = p; + } + else + { + char *src = result? result : buffer; + char *dst; + + dst = xmalloc (strlen (src) + valuelen + 1); + n = p - src; + memcpy (dst, src, n); + memcpy (dst + n, value, valuelen); + n += valuelen; + strcpy (dst + n, pend); + line = dst + n; + free (result); + result = dst; + } + } + return result; +} + + + +static void +assign_variable (char *line) +{ + char *name, *p, *tmp; + + /* Get the name. */ + name = line; + for (p=name; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + if (!*p) + set_var (name, NULL); /* Remove variable. */ + else + { + tmp = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmp) + { + set_var (name, tmp); + xfree (tmp); + } + else + set_var (name, p); + } +} + + +static void +show_variables (void) +{ + variable_t var; + + for (var = variable_table; var; var = var->next) + if (var->value) + printf ("%-20s %s\n", var->name, var->value); +} + + /* Store an inquire response pattern. Note, that this function may change the content of LINE. We assume that leading white spaces are already removed. */ @@ -246,7 +427,7 @@ rc = assuan_sendfd (ctx, INT2FD (fd) ); if (rc) - log_error ("sednig descriptor %d failed: %s\n", fd, gpg_strerror (rc)); + log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc)); fclose (fp); } @@ -258,6 +439,200 @@ } +static void +do_open (char *line) +{ + FILE *fp; + char *varname, *name, *mode, *p; + int fd; + +#ifdef HAVE_W32_SYSTEM + if (server_pid == (pid_t)(-1)) + { + log_error ("the pid of the server is unknown\n"); + log_info ("use command \"/serverpid\" first\n"); + return; + } +#endif + + /* Get variable name. */ + varname = line; + for (p=varname; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + /* Get file name. */ + name = p; + for (p=name; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + /* Get mode. */ + mode = p; + if (!*mode) + mode = "r"; + else + { + for (p=mode; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + } + + /* Open and send. */ + fp = fopen (name, mode); + if (!fp) + { + log_error ("can't open `%s' in \"%s\" mode: %s\n", + name, mode, strerror (errno)); + return; + } + fd = fileno (fp); + if (fd >= 0 && fd < DIM (open_fd_table)) + { + open_fd_table[fd].inuse = 1; +#ifdef HAVE_W32_SYSTEM + { + HANDLE prochandle, handle, newhandle; + + handle = (void*)_get_osfhandle (fd); + + prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid); + if (!prochandle) + { + log_error ("failed to open the server process\n"); + close (fd); + return; + } + + if (!DuplicateHandle (GetCurrentProcess(), handle, + prochandle, &newhandle, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + log_error ("failed to duplicate the handle\n"); + close (fd); + CloseHandle (prochandle); + return; + } + CloseHandle (prochandle); + open_fd_table[fd].handle = newhandle; + } + if (opt.verbose) + log_info ("file `%s' opened in \"%s\" mode, fd=%d (libc=%d)\n", + name, mode, (int)open_fd_table[fd].handle, fd); + set_int_var (varname, (int)open_fd_table[fd].handle); +#else + if (opt.verbose) + log_info ("file `%s' opened in \"%s\" mode, fd=%d\n", + name, mode, fd); + set_int_var (varname, fd); +#endif + } + else + { + log_error ("can't put fd %d into table\n", fd); + close (fd); + } +} + + +static void +do_close (char *line) +{ + int fd = atoi (line); + +#ifdef HAVE_W32_SYSTEM + int i; + + for (i=0; i < DIM (open_fd_table); i++) + if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd) + break; + if (i < DIM (open_fd_table)) + fd = i; + else + { + log_error ("given fd (system handle) has not been opened\n"); + return; + } +#endif + + if (fd < 0 || fd >= DIM (open_fd_table)) + { + log_error ("invalid fd\n"); + return; + } + + if (!open_fd_table[fd].inuse) + { + log_error ("given fd has not been opened\n"); + return; + } +#ifdef HAVE_W32_SYSTEM + CloseHandle (open_fd_table[fd].handle); /* Close duped handle. */ +#endif + close (fd); + open_fd_table[fd].inuse = 0; +} + + +static void +do_showopen (void) +{ + int i; + + for (i=0; i < DIM (open_fd_table); i++) + if (open_fd_table[i].inuse) + { +#ifdef HAVE_W32_SYSTEM + printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i); +#else + printf ("%-15d\n", i); +#endif + } +} + + + +static int +getinfo_pin_cb (void *opaque, const void *buffer, size_t length) +{ + membuf_t *mb = opaque; + put_membuf (mb, buffer, length); + return 0; +} + +/* Get the pid of the server and store it locally. */ +static void +do_serverpid (assuan_context_t ctx) +{ + int rc; + membuf_t mb; + char *buffer; + + init_membuf (&mb, 100); + rc = assuan_transact (ctx, "GETINFO pid", getinfo_pin_cb, &mb, + NULL, NULL, NULL, NULL); + put_membuf (&mb, "", 1); + buffer = get_membuf (&mb, NULL); + if (rc || !buffer) + log_error ("command \"%s\" failed: %s\n", + "GETINFO pid", gpg_strerror (rc)); + else + { + server_pid = (pid_t)strtoul (buffer, NULL, 10); + if (opt.verbose) + log_info ("server's PID is %lu\n", (unsigned long)server_pid); + } + xfree (buffer); +} + + /* gpg-connect-agent's entry point. */ int main (int argc, char **argv) @@ -266,6 +641,7 @@ int no_more_options = 0; assuan_context_t ctx; char *line, *p; + char *tmpline; size_t linesize; int rc; @@ -406,8 +782,16 @@ *p++ = 0; while (spacep (p)) p++; - if (!strcmp (cmd, "definqfile")) + if (!strcmp (cmd, "let")) { + assign_variable (p); + } + else if (!strcmp (cmd, "showvar")) + { + show_variables (); + } + else if (!strcmp (cmd, "definqfile")) + { add_definq (p, 0); } else if (!strcmp (cmd, "definqprog")) @@ -424,7 +808,14 @@ } else if (!strcmp (cmd, "echo")) { - puts (p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + puts (tmpline); + xfree (tmpline); + } + else + puts (p); } else if (!strcmp (cmd, "sendfd")) { @@ -436,6 +827,22 @@ do_recvfd (ctx, p); continue; } + else if (!strcmp (cmd, "open")) + { + do_open (p); + } + else if (!strcmp (cmd, "close")) + { + do_close (p); + } + else if (!strcmp (cmd, "showopen")) + { + do_showopen (); + } + else if (!strcmp (cmd, "serverpid")) + { + do_serverpid (ctx); + } else if (!strcmp (cmd, "hex")) opt.hex = 1; else if (!strcmp (cmd, "nohex")) @@ -444,11 +851,17 @@ opt.decode = 1; else if (!strcmp (cmd, "nodecode")) opt.decode = 0; + else if (!strcmp (cmd, "subst")) + opt.enable_varsubst = 1; + else if (!strcmp (cmd, "nosubst")) + opt.enable_varsubst = 0; else if (!strcmp (cmd, "help")) { puts ( "Available commands:\n" "/echo ARGS Echo ARGS.\n" +"/let NAME VALUE Set variable NAME to VALUE.\n" +"/showvar Show all variables.\n" "/definqfile NAME FILE\n" " Use content of FILE for inquiries with NAME.\n" " NAME may be \"*\" to match any inquiry.\n" @@ -458,9 +871,14 @@ "/showdef Print all definitions.\n" "/cleardef Delete all definitions.\n" "/sendfd FILE MODE Open FILE and pass descriptor to server.\n" -"/recvfd Receive FD from server and print. \n" +"/recvfd Receive FD from server and print.\n" +"/open VAR FILE MODE Open FILE and assign the descrptor to VAR.\n" +"/close FD Close file with descriptor FD.\n" +"/showopen Show descriptors of all open files.\n" +"/serverpid Retrieve the pid of the server.\n" "/[no]hex Enable hex dumping of received data lines.\n" "/[no]decode Enable decoding of received data lines.\n" +"/[no]subst Enable varibale substitution.\n" "/help Print this help."); } else @@ -468,8 +886,15 @@ continue; } - - rc = assuan_write_line (ctx, line); + + tmpline = opt.enable_varsubst? substitute_line (line) : NULL; + if (tmpline) + { + rc = assuan_write_line (ctx, tmpline); + xfree (tmpline); + } + else + rc = assuan_write_line (ctx, line); if (rc) { log_info (_("sending line failed: %s\n"), gpg_strerror (rc) ); Modified: trunk/tools/no-libgcrypt.c =================================================================== --- trunk/tools/no-libgcrypt.c 2007-10-01 14:48:39 UTC (rev 4587) +++ trunk/tools/no-libgcrypt.c 2007-10-02 16:30:58 UTC (rev 4588) @@ -38,6 +38,12 @@ } void * +gcry_malloc_secure (size_t n) +{ + return malloc (n); +} + +void * gcry_xmalloc (size_t n) { void *p = malloc (n); From cvs at cvs.gnupg.org Tue Oct 2 23:46:38 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 02 Oct 2007 23:46:38 +0200 Subject: [svn] GnuPG - r4589 - trunk/tools Message-ID: Author: wk Date: 2007-10-02 23:46:29 +0200 (Tue, 02 Oct 2007) New Revision: 4589 Modified: trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c Log: Add commands /run and /bye so that we can better automate tests. Also add option --run. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-02 16:30:58 UTC (rev 4588) +++ trunk/tools/ChangeLog 2007-10-02 21:46:29 UTC (rev 4589) @@ -7,6 +7,7 @@ (do_open, do_close, do_showopen): New. (main): Add new commands /nosubst, /subst, /let, /showvar, /open, /close and /showopen. + (main): New commands /run and /bye. 2007-10-01 Werner Koch Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-02 16:30:58 UTC (rev 4588) +++ trunk/tools/gpg-connect-agent.c 2007-10-02 21:46:29 UTC (rev 4589) @@ -40,6 +40,7 @@ oVerbose = 'v', oRawSocket = 'S', oExec = 'E', + oRun = 'r', oNoVerbose = 500, oHomedir, @@ -63,7 +64,7 @@ { oExec, "exec", 0, N_("run the Assuan server given on the command line")}, { oNoExtConnect, "no-ext-connect", 0, N_("do not use extended connect mode")}, - + { oRun, "run", 2, N_("|FILE|run commands from FILE on startup")}, /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, { oHomedir, "homedir", 2, "@" }, @@ -128,7 +129,7 @@ /*-- local prototypes --*/ -static int read_and_print_response (assuan_context_t ctx); +static int read_and_print_response (assuan_context_t ctx, int *r_goterr); static assuan_context_t start_agent (void); @@ -644,6 +645,9 @@ char *tmpline; size_t linesize; int rc; + int cmderr; + const char *opt_run = NULL; + FILE *script_fp = NULL; set_strusage (my_strusage); log_set_prefix ("gpg-connect-agent", 1); @@ -675,6 +679,7 @@ case oRawSocket: opt.raw_socket = pargs.r.ret_str; break; case oExec: opt.exec = 1; break; case oNoExtConnect: opt.connect_flags &= ~(1); break; + case oRun: opt_run = pargs.r.ret_str; break; default: pargs.err = 2; break; } @@ -699,6 +704,14 @@ log_info (_("option \"%s\" ignored due to \"%s\"\n"), "--raw-socket", "--exec"); + if (opt_run && !(script_fp = fopen (opt_run, "r"))) + { + log_error ("cannot open run file `%s': %s\n", + opt_run, strerror (errno)); + exit (1); + } + + if (opt.exec) { int no_close[3]; @@ -741,11 +754,12 @@ assuan did not run the initial handshaking). */ if (assuan_pending_line (ctx)) { - rc = read_and_print_response (ctx); + rc = read_and_print_response (ctx, &cmderr); if (rc) log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) ); } + line = NULL; linesize = 0; for (;;) @@ -754,14 +768,32 @@ size_t maxlength; maxlength = 2048; - n = read_line (stdin, &line, &linesize, &maxlength); + n = read_line (script_fp? script_fp:stdin, &line, &linesize, &maxlength); if (n < 0) { log_error (_("error reading input: %s\n"), strerror (errno)); + if (script_fp) + { + fclose (script_fp); + script_fp = NULL; + log_error ("stopping script execution\n"); + continue; + } exit (1); } if (!n) - break; /* EOF */ + { + /* EOF */ + if (script_fp) + { + fclose (script_fp); + script_fp = NULL; + if (opt.verbose) + log_info ("end of script\n"); + continue; + } + break; + } if (!maxlength) { log_error (_("line too long - skipped\n")); @@ -855,6 +887,42 @@ opt.enable_varsubst = 1; else if (!strcmp (cmd, "nosubst")) opt.enable_varsubst = 0; + else if (!strcmp (cmd, "run")) + { + char *p2; + for (p2=p; *p2 && !spacep (p2); p2++) + ; + if (*p2) + *p2++ = 0; + while (spacep (p2)) + p++; + if (*p2) + { + log_error ("syntax error in run command\n"); + if (script_fp) + { + fclose (script_fp); + script_fp = NULL; + } + } + else if (script_fp) + { + log_error ("cannot nest run commands - stop\n"); + fclose (script_fp); + script_fp = NULL; + } + else if (!(script_fp = fopen (p, "r"))) + { + log_error ("cannot open run file `%s': %s\n", + p, strerror (errno)); + } + else if (opt.verbose) + log_info ("running commands from `%s'\n", p); + } + else if (!strcmp (cmd, "bye")) + { + break; + } else if (!strcmp (cmd, "help")) { puts ( @@ -879,6 +947,8 @@ "/[no]hex Enable hex dumping of received data lines.\n" "/[no]decode Enable decoding of received data lines.\n" "/[no]subst Enable varibale substitution.\n" +"/run FILE Run commands from FILE.\n" +"/bye Terminate gpg-connect-agent.\n" "/help Print this help."); } else @@ -887,6 +957,9 @@ continue; } + if (opt.verbose && script_fp) + puts (line); + tmpline = opt.enable_varsubst? substitute_line (line) : NULL; if (tmpline) { @@ -903,9 +976,16 @@ if (*line == '#' || !*line) continue; /* Don't expect a response for a comment line. */ - rc = read_and_print_response (ctx); + rc = read_and_print_response (ctx, &cmderr); if (rc) log_info (_("receiving line failed: %s\n"), gpg_strerror (rc) ); + if ((rc || cmderr) && script_fp) + { + log_error ("stopping script execution\n"); + fclose (script_fp); + script_fp = NULL; + } + /* FIXME: If the last command was BYE or the server died for some other reason, we won't notice until we get the next @@ -1010,9 +1090,10 @@ /* Read all response lines from server and print them. Returns 0 on - success or an assuan error code. */ + success or an assuan error code. Set R_GOTERR to true if the + command did not returned OK. */ static int -read_and_print_response (assuan_context_t ctx) +read_and_print_response (assuan_context_t ctx, int *r_goterr) { char *line; size_t linelen; @@ -1020,6 +1101,7 @@ int i, j; int need_lf = 0; + *r_goterr = 0; for (;;) { do @@ -1132,6 +1214,7 @@ { fwrite (line, linelen, 1, stdout); putchar ('\n'); + *r_goterr = 1; return 0; } else if (linelen >= 7 From cvs at cvs.gnupg.org Wed Oct 3 12:49:00 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 03 Oct 2007 12:49:00 +0200 Subject: [svn] GpgEX - r21 - trunk/src Message-ID: Author: marcus Date: 2007-10-03 12:48:48 +0200 (Wed, 03 Oct 2007) New Revision: 21 Modified: trunk/src/ChangeLog trunk/src/client.cc Log: 2007-10-03 Marcus Brinkmann * client.cc (percent_escape, escape): New functions. (client_t::call_assuan): Fix INPUT command. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-21 14:08:29 UTC (rev 20) +++ trunk/src/ChangeLog 2007-10-03 10:48:48 UTC (rev 21) @@ -1,3 +1,8 @@ +2007-10-03 Marcus Brinkmann + + * client.cc (percent_escape, escape): New functions. + (client_t::call_assuan): Fix INPUT command. + 2007-09-21 Werner Koch * registry.c (default_homedir): Make registry works. Reported by Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-09-21 14:08:29 UTC (rev 20) +++ trunk/src/client.cc 2007-10-03 10:48:48 UTC (rev 21) @@ -61,6 +61,73 @@ } +#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a')) + +/* Percent-escape the string STR by replacing colons with '%3a'. If + EXTRA is not NULL all characters in it are also escaped. */ +static char * +percent_escape (const char *str, const char *extra) +{ + int i, j; + char *ptr; + + if (!str) + return NULL; + + for (i=j=0; str[i]; i++) + if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i]))) + j++; + ptr = (char *) malloc (i + 2 * j + 1); + i = 0; + while (*str) + { +#if 0 + /* FIXME: Work around a bug in Kleo. */ + if (*str == ':') + { + ptr[i++] = '%'; + ptr[i++] = '3'; + ptr[i++] = 'a'; + } + else +#endif + if (*str == '%') + { + ptr[i++] = '%'; + ptr[i++] = '2'; + ptr[i++] = '5'; + } + else if (extra && strchr (extra, *str)) + { + ptr[i++] = '%'; + ptr[i++] = tohex_lower ((*str >> 4) & 15); + ptr[i++] = tohex_lower (*str & 15); + } + else + ptr[i++] = *str; + str++; + } + ptr[i] = '\0'; + + return ptr; +} + + +static string +escape (string str) +{ + char *arg_esc = percent_escape (str.c_str (), "+= "); + + if (arg_esc == NULL) + throw std::bad_alloc (); + + string res = arg_esc; + free (arg_esc); + + return res; +} + + bool client_t::call_assuan (const char *cmd, vector &filenames) { @@ -90,7 +157,7 @@ /* 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"; + msg = "INPUT FILE=" + escape (filenames[i]); (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ()); From cvs at cvs.gnupg.org Thu Oct 4 14:24:38 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 04 Oct 2007 14:24:38 +0200 Subject: [svn] assuan - r269 - trunk/src Message-ID: Author: wk Date: 2007-10-04 14:24:29 +0200 (Thu, 04 Oct 2007) New Revision: 269 Modified: trunk/src/ChangeLog trunk/src/assuan-buffer.c trunk/src/assuan-socket-connect.c trunk/src/mkerrors Log: Better error mapping. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-02 08:44:21 UTC (rev 268) +++ trunk/src/ChangeLog 2007-10-04 12:24:29 UTC (rev 269) @@ -1,3 +1,8 @@ +2007-10-04 Werner Koch + + * mkerrors: Map EAGAIN to GPG_ERR_EAGAIN for read and write + errors. + 2007-10-02 Werner Koch * assuan-io.c (_assuan_io_read) [W32]: Map WSAEWOULDBLOCK to EAGAIN. Modified: trunk/src/assuan-buffer.c =================================================================== --- trunk/src/assuan-buffer.c 2007-10-02 08:44:21 UTC (rev 268) +++ trunk/src/assuan-buffer.c 2007-10-04 12:24:29 UTC (rev 269) @@ -133,10 +133,11 @@ if (rc) { if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", - assuan_get_assuan_log_prefix (), + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", + assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (int)ctx->inbound.fd, strerror (errno)); + return _assuan_error (ASSUAN_Read_Error); } if (!nread) Modified: trunk/src/assuan-socket-connect.c =================================================================== --- trunk/src/assuan-socket-connect.c 2007-10-02 08:44:21 UTC (rev 268) +++ trunk/src/assuan-socket-connect.c 2007-10-04 12:24:29 UTC (rev 269) @@ -85,7 +85,7 @@ /* Make a connection to the Unix domain socket NAME and return a new Assuan context in CTX. SERVER_PID is currently not used but may become handy in the future. With flags set to 1 sendmsg and - recvmesg are used. */ + recvmsg are used. */ assuan_error_t assuan_socket_connect_ext (assuan_context_t *r_ctx, const char *name, pid_t server_pid, Modified: trunk/src/mkerrors =================================================================== --- trunk/src/mkerrors 2007-10-02 08:44:21 UTC (rev 268) +++ trunk/src/mkerrors 2007-10-04 12:24:29 UTC (rev 269) @@ -93,6 +93,9 @@ switch (errno) { case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break; + case EAGAIN: + n = (6 | (1 << 15)); + break; default: n = 270; /*GPG_ERR_ASS_READ_ERROR*/ break; } break; @@ -101,6 +104,9 @@ switch (errno) { case 0: n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break; + case EAGAIN: + n = (6 | (1 << 15)); + break; default: n = 271; /*GPG_ERR_ASS_WRITE_ERROR*/ break; } break; @@ -114,7 +120,9 @@ an error is indeed returned. */ n = 16381; /*GPG_ERR_MISSING_ERRNO*/ break; - case ENOMEM: n = (1 << 15) | 86; break; + case ENOMEM: + n = (86 | (1 << 15)); + break; default: n = 16382; /*GPG_ERR_UNKNOWN_ERRNO*/ break; From cvs at cvs.gnupg.org Thu Oct 4 16:10:07 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 04 Oct 2007 16:10:07 +0200 Subject: [svn] gpgme - r1272 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-04 16:09:58 +0200 (Thu, 04 Oct 2007) New Revision: 1272 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/kdpipeiodevice.h trunk/gpgme/kdpipeiodevice.moc trunk/gpgme/w32-qt-io.cpp Log: 2007-10-04 Marcus Brinkmann * kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc, w32-qt-io.cpp: New versions from Frank Osterfeld. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-10-02 15:56:37 UTC (rev 1271) +++ trunk/gpgme/ChangeLog 2007-10-04 14:09:58 UTC (rev 1272) @@ -1,3 +1,8 @@ +2007-10-04 Marcus Brinkmann + + * kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc, + w32-qt-io.cpp: New versions from Frank Osterfeld. + 2007-10-02 Marcus Brinkmann * kdpipeiodevice.cpp, kdpipeiodevice.moc: New versions. Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-10-02 15:56:37 UTC (rev 1271) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-10-04 14:09:58 UTC (rev 1272) @@ -99,14 +99,14 @@ QWaitCondition bufferNotEmptyCondition; QWaitCondition hasStarted; QWaitCondition readyReadSentCondition; - QWaitCondition notInReadDataCondition; + QWaitCondition blockedConsumerIsDoneCondition; bool cancel; bool eof; bool error; bool eofShortCut; int errorCode; - bool inReadData; - + bool consumerBlocksOnUs; + private: unsigned int rptr, wptr; char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state @@ -127,7 +127,7 @@ eofShortCut( false ), errorCode( 0 ), rptr( 0 ), wptr( 0 ), - inReadData( false ) + consumerBlocksOnUs( false ) { } @@ -226,13 +226,13 @@ handle( 0 ), reader( 0 ), writer( 0 ), - triedToStartReader( false ), triedToStartWriter( false ) + triedToStartReader( false ), triedToStartWriter( false ) { } KDPipeIODevice::Private::~Private() { - qDebug( "KDPipeIODevice::~Private(): Destroying %p", this ); + qDebug( "KDPipeIODevice::~Private(): Destroying %p", q ); } KDPipeIODevice::KDPipeIODevice( QObject * p ) @@ -290,11 +290,15 @@ return true; triedToStartReader = true; if ( reader && !reader->isRunning() && !reader->isFinished() ) { + qDebug("KDPipeIODevice::Private::startReaderThread(): locking reader (CONSUMER THREAD)" ); LOCKED( reader ); - + qDebug("KDPipeIODevice::Private::startReaderThread(): locked reader (CONSUMER THREAD)" ); reader->start( QThread::HighestPriority ); - if ( !reader->hasStarted.wait( &reader->mutex, 1000 ) ) - return false; + qDebug("KDPipeIODevice::Private::startReaderThread(): waiting for hasStarted (CONSUMER THREAD)" ); + const bool hasStarted = reader->hasStarted.wait( &reader->mutex, 1000 ); + qDebug("KDPipeIODevice::Private::startReaderThread(): returned from hasStarted (CONSUMER THREAD)" ); + + return hasStarted; } return true; } @@ -320,11 +324,16 @@ const int counter = s_counter++; QPointer thisPointer( this ); qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d", this, counter ); + emit q->readyRead(); + if ( !thisPointer ) return; - LOCKED( reader ); - reader->readyReadSentCondition.wakeAll(); + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locking reader (CONSUMER THREAD)", this, counter ); + synchronized( reader ) { + qDebug( "KDPipeIODevice::Private::emitReadyRead %p, %d: locked reader (CONSUMER THREAD)", this, counter ); + reader->readyReadSentCondition.wakeAll(); + } qDebug( "KDPipeIODevice::Private::emitReadyRead %p leaving %d", this, counter ); } @@ -342,8 +351,6 @@ 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_; @@ -387,7 +394,10 @@ return base; } if ( d->reader ) - synchronized( d->reader ) return base + d->reader->bytesInBuffer(); + synchronized( d->reader ) { + const qint64 inBuffer = d->reader->bytesInBuffer(); + return base + inBuffer; + } return base; } @@ -445,6 +455,7 @@ } bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS; + qDebug( "KDPipeIODEvice::waitForReadyRead()(%p)", this); d->startReaderThread(); if ( ALLOW_QIODEVICE_BUFFERING ) { if ( bytesAvailable() > 0 ) @@ -454,7 +465,10 @@ if ( !r || r->eofShortCut ) return true; LOCKED( r ); - return r->bytesInBuffer() != 0 || r->eof || r->error || r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ; + if ( r->bytesInBuffer() != 0 || r->eof || r->error ) + return true; + assert( false ); + return r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) ; } template @@ -467,6 +481,22 @@ const T oldValue; }; + +bool KDPipeIODevice::readWouldBlock() const +{ + d->startReaderThread(); + LOCKED( d->reader ); + return d->reader->bufferEmpty() && !d->reader->eof && !d->reader->error; +} + +bool KDPipeIODevice::writeWouldBlock() const +{ + d->startWriterThread(); + LOCKED( d->writer ); + return d->writer->bufferFull() && !d->writer->error; +} + + qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS; qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize ); d->startReaderThread(); @@ -491,15 +521,17 @@ if ( bytesAvailable() > 0 ) maxSize = std::min( maxSize, bytesAvailable() ); // don't block } - + qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)" ); LOCKED( r ); - const TemporaryValue tmp( d->reader->inReadData, true ); - assert( d->reader->inReadData ); - while ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? - qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition", this ); - r->readyReadSentCondition.wakeAll(); - r->notInReadDataCondition.wakeAll(); + qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)" ); + + r->readyReadSentCondition.wakeAll(); + if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? + qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition (CONSUMER THREAD)", this ); + const TemporaryValue tmp( d->reader->consumerBlocksOnUs, true ); r->bufferNotEmptyCondition.wait( &r->mutex ); + r->blockedConsumerIsDoneCondition.wakeAll(); + qDebug( "%p: KDPipeIODevice::readData: woke up from bufferNotEmptyCondition (CONSUMER THREAD)", this ); } if ( r->bufferEmpty() ) { @@ -507,7 +539,6 @@ // woken with an empty buffer must mean either EOF or error: assert( r->eof || r->error ); r->eofShortCut = true; - r->notInReadDataCondition.wakeAll(); return r->eof ? 0 : -1 ; } @@ -515,7 +546,7 @@ const qint64 bytesRead = r->readData( data, maxSize ); qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead ); qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data ); - r->notInReadDataCondition.wakeAll(); + return bytesRead; } @@ -590,13 +621,14 @@ assert( q->bytesToWrite() == 0 ); } if ( Reader * & r = reader ) { + disconnect( r, SIGNAL( readyRead() ), this, SLOT( emitReadyRead() ) ); synchronized( r ) { // tell thread to cancel: r->cancel = true; // and wake it, so it can terminate: r->bufferNotFullCondition.wakeAll(); r->readyReadSentCondition.wakeAll(); - } + } } if ( Writer * & w = writer ) { synchronized( w ) { @@ -617,10 +649,14 @@ emit aboutToClose(); d->stopThreads(); -#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* t2 = t; t = 0; delete t2; } +#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* const t2 = t; t = 0; delete t2; } qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer ); waitAndDelete( d->writer ); qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader ); + { + LOCKED( d->reader ); + d->reader->readyReadSentCondition.wakeAll(); + } waitAndDelete( d->reader ); #undef waitAndDelete #ifdef Q_OS_WIN32 @@ -645,115 +681,102 @@ qDebug( "%p: Reader::run: started", this ); while ( true ) { - - if ( !bufferFull() && !bufferEmpty() ) { + if ( !cancel && ( eof || error ) ) { + qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error ); + notifyReadyRead(); + } else if ( !cancel && !bufferFull() && !bufferEmpty() ) { qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); notifyReadyRead(); } - while ( !cancel && bufferFull() ) { - bufferNotEmptyCondition.wakeAll(); + while ( !error && !cancel && bufferFull() ) { notifyReadyRead(); - if ( !bufferFull() ) - break; - qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); - bufferNotFullCondition.wait( &mutex ); - qDebug( "%p: Reader::run: woke up", this ); - } + if ( bufferFull() ) { + qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); + bufferNotFullCondition.wait( &mutex ); + } + } if ( cancel ) { - qDebug( "%p: Reader::run: detected cancel", this ); + qDebug( "%p: Reader::run: detected cancel", this ); goto leave; } + if ( !eof && !error ) { + if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty + rptr = wptr = 0; - 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; - unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer; - if ( numBytes > sizeof buffer - wptr ) - numBytes = sizeof buffer - wptr; + qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes ); - qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes ); + assert( numBytes > 0 ); - assert( numBytes > 0 ); - - qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes ); + qDebug( "%p: Reader::run: trying to read %d bytes", this, 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 ) { - assert( numRead == 0 ); - qDebug( "%p: Reader::run: got eof (broken pipe)", this ); - eof = true; - } else { - assert( numRead == 0 ); - qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode ); - error = true; + mutex.unlock(); + DWORD numRead; + const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 ); + mutex.lock(); + if ( !ok ) { + errorCode = static_cast( GetLastError() ); + if ( errorCode == ERROR_BROKEN_PIPE ) { + assert( numRead == 0 ); + qDebug( "%p: Reader::run: got eof (broken pipe)", this ); + eof = true; + } else { + assert( numRead == 0 ); + qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode ); + error = true; + } } - goto leave; - } #else - qint64 numRead; - mutex.unlock(); - do { - numRead = ::read( fd, buffer + wptr, numBytes ); - } while ( numRead == -1 && errno == EINTR ); - mutex.lock(); + 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( "%p: Reader::run: got error: %d", this, errorCode ); - goto leave; - } + if ( numRead < 0 ) { + errorCode = errno; + error = true; + qDebug( "%p: Reader::run: got error: %d", this, errorCode ); + } else if ( numRead == 0 ) { + qDebug( "%p: Reader::run: eof detected", this ); + eof = true; + } #endif - 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( "%p: Reader::run: eof detected", this ); - eof = true; - goto leave; - } + qDebug( "%p: Reader::run: read %ld bytes", this, static_cast(numRead) ); + qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, fd, buffer ); - if ( cancel ) { - qDebug( "%p: Reader::run: detected cancel", this ); - goto leave; - } - qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); - wptr = ( wptr + numRead ) % sizeof buffer; - qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr ); + if ( numRead > 0 ) { + qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); + wptr = ( wptr + numRead ) % sizeof buffer; + qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr ); + } + } } leave: - qDebug( "%p: Reader::run: terminating: loop while not canceled and not empty", this ); - while ( !cancel && !bufferEmpty() ) { - notifyReadyRead(); - } - notifyReadyRead(); qDebug( "%p: Reader::run: terminated", this ); } void Reader::notifyReadyRead() { - qDebug( "notifyReadyRead" ); - if ( cancel ) - return; - bufferNotEmptyCondition.wakeAll(); - if ( inReadData ) { - qDebug( "notifyReadyRead: inReadData: waiting" ); - notInReadDataCondition.wait( &mutex ); + qDebug( "notifyReadyRead: %d bytes available", bytesInBuffer() ); + assert( !cancel ); + + if ( consumerBlocksOnUs ) { + bufferNotEmptyCondition.wakeAll(); + blockedConsumerIsDoneCondition.wait( &mutex ); + return; } - if ( cancel || ( !eof && !error && bufferEmpty() ) ) - return; - qDebug( "readyReadData: actually emit signal" ); + qDebug( "notifyReadyRead: emit signal" ); emit readyRead(); - bufferNotEmptyCondition.wakeAll(); readyReadSentCondition.wait( &mutex ); - bufferNotEmptyCondition.wakeAll(); + qDebug( "notifyReadyRead: returning from waiting, leave" ); } void Writer::run() { @@ -796,7 +819,7 @@ errorCode = static_cast( GetLastError() ); qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); error = true; - goto leave; + goto leave; } #else qint64 numWritten; @@ -805,17 +828,17 @@ } while ( numWritten == -1 && errno == EINTR ); if ( numWritten < 0 ) { - mutex.lock(); + mutex.lock(); errorCode = errno; qDebug( "%p: Writer::run: got error code: %d", this, errorCode ); error = true; - goto leave; + goto leave; } #endif qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, buffer ); totalWritten += numWritten; - mutex.lock(); + mutex.lock(); } while ( totalWritten < numBytesInBuffer ); qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten ); Modified: trunk/gpgme/kdpipeiodevice.h =================================================================== --- trunk/gpgme/kdpipeiodevice.h 2007-10-02 15:56:37 UTC (rev 1271) +++ trunk/gpgme/kdpipeiodevice.h 2007-10-04 14:09:58 UTC (rev 1272) @@ -45,6 +45,9 @@ Qt::HANDLE handle() const; int descriptor() const; + bool readWouldBlock() const; + bool writeWouldBlock() const; + /* reimp */ qint64 bytesAvailable() const; /* reimp */ qint64 bytesToWrite() const; /* reimp */ bool canReadLine() const; Modified: trunk/gpgme/kdpipeiodevice.moc =================================================================== --- trunk/gpgme/kdpipeiodevice.moc 2007-10-02 15:56:37 UTC (rev 1271) +++ trunk/gpgme/kdpipeiodevice.moc 2007-10-04 14:09:58 UTC (rev 1272) @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'kdpipeiodevice.cpp' ** -** Created: Mon Oct 1 16:08:44 2007 +** Created: Tue Oct 2 19:30:13 2007 ** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1) ** ** WARNING! All changes made in this file will be lost! Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-10-02 15:56:37 UTC (rev 1271) +++ trunk/gpgme/w32-qt-io.cpp 2007-10-04 14:09:58 UTC (rev 1272) @@ -82,30 +82,29 @@ really nice callback interfaces to let the user control all this at a per-context level. */ -#define MAX_SLAFD 50000 +#define MAX_SLAFD 1024 struct DeviceEntry { - DeviceEntry() : iodev( 0 ), actual_fd( -1 ), refCount( 1 ) {} - QIODevice* iodev; - int actual_fd; + DeviceEntry() : iodev( 0 ), refCount( 1 ) {} + KDPipeIODevice* iodev; mutable int refCount; void ref() const { ++refCount; } - int unref() const { return --refCount; } + int unref() const { assert( refCount > 0 ); return --refCount; } }; DeviceEntry* iodevice_table[MAX_SLAFD]; -static QIODevice * +static KDPipeIODevice * find_channel (int fd, int create) { + assert( fd < MAX_SLAFD ); if (fd < 0 || fd >= MAX_SLAFD) return NULL; if (create && !iodevice_table[fd]) { DeviceEntry* entry = new DeviceEntry; - entry->actual_fd = fd; entry->iodev = new KDPipeIODevice (fd, QIODevice::ReadWrite|QIODevice::Unbuffered); iodevice_table[fd] = entry; @@ -117,11 +116,9 @@ 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_) +_gpgme_io_fd2str (char *buf, int buflen, int fd) { - const int actual_fd = iodevice_table[fd_] ? iodevice_table[fd_]->actual_fd : fd_; - return snprintf (buf, buflen, "%ld", (long) _get_osfhandle (actual_fd)); - // return snprintf (buf, buflen, "%d", fd); + return snprintf (buf, buflen, "%d", (long)_get_osfhandle( fd ) ); } @@ -143,7 +140,7 @@ { int saved_errno = 0; qint64 nread; - QIODevice *chan; + KDPipeIODevice *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, "buffer=%p, count=%u", buffer, count); @@ -175,7 +172,7 @@ _gpgme_io_write (int fd, const void *buffer, size_t count) { qint64 nwritten; - QIODevice *chan; + KDPipeIODevice *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, "buffer=%p, count=%u", buffer, count); TRACE_LOGBUF ((char *) buffer, count); @@ -204,7 +201,7 @@ int _gpgme_io_pipe (int filedes[2], int inherit_idx) { - QIODevice *chan; + KDPipeIODevice *chan; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", inherit_idx, inherit_idx ? "reading" : "writing"); @@ -266,7 +263,7 @@ int _gpgme_io_close (int fd) { - QIODevice *chan; + KDPipeIODevice *chan; TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd); if (fd < 0 || fd >= MAX_SLAFD) @@ -286,27 +283,19 @@ /* Then do the close. */ 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 ( entry ) { + if ( entry->unref() == 0 ) { + entry->iodev->close(); + delete entry->iodev; + delete entry; + iodevice_table[fd] = 0; } - } - - if ( fd != actual_fd ) - _close( fd ); + } else { + _close( fd ); } - else - _close (fd); + + return 0; } @@ -337,7 +326,6 @@ /* 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); } @@ -538,6 +526,7 @@ /* 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", @@ -565,8 +554,6 @@ 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; @@ -576,30 +563,32 @@ /* We only implement the special case of nonblock == true. */ assert (nonblock); - count = 0; + int count = 0; TRACE_SEQ (dbg_help, "select on [ "); - for (i = 0; i < nfds; i++) + for (int i = 0; i < nfds; i++) { if (fds[i].fd == -1) { fds[i].signaled = 0; + } + else if (fds[i].for_read ) + { + const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0); + assert (chan); + fds[i].signaled = chan->readWouldBlock() ? 0 : 1; + TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); + if ( fds[i].signaled ) + count++; } - 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); + const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0); assert (chan); - fds[i].signaled = chan->bytesToWrite() > 0 ? 0 : 1 ; + fds[i].signaled = chan->writeWouldBlock() ? 0 : 1; TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd); - count++; + if ( fds[i].signaled ) + count++; } } TRACE_END (dbg_help, "]"); @@ -629,21 +618,8 @@ int _gpgme_io_dup (int fd) { - DeviceEntry* const existing = iodevice_table[fd]; - if ( existing ) - existing->ref(); - else - find_channel( fd, /*create=*/1 ); + assert( iodevice_table[fd] ); + iodevice_table[fd]->ref(); return fd; - -#if 0 - 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; -#endif } From cvs at cvs.gnupg.org Fri Oct 5 02:21:01 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 02:21:01 +0200 Subject: [svn] gpgme - r1273 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-05 02:20:43 +0200 (Fri, 05 Oct 2007) New Revision: 1273 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp trunk/gpgme/w32-qt-io.cpp Log: 2007-10-05 Marcus Brinkmann * kdpipeiodevice.cpp, w32-qt-io.cpp: New versions from Frank Osterfeld. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-10-04 14:09:58 UTC (rev 1272) +++ trunk/gpgme/ChangeLog 2007-10-05 00:20:43 UTC (rev 1273) @@ -1,3 +1,8 @@ +2007-10-05 Marcus Brinkmann + + * kdpipeiodevice.cpp, w32-qt-io.cpp: New versions from Frank + Osterfeld. + 2007-10-04 Marcus Brinkmann * kdpipeiodevice.h, kdpipeiodevice.cpp, kdpipeiodevice.moc, Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-10-04 14:09:58 UTC (rev 1272) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-10-05 00:20:43 UTC (rev 1273) @@ -493,7 +493,7 @@ { d->startWriterThread(); LOCKED( d->writer ); - return d->writer->bufferFull() && !d->writer->error; + return !d->writer->bufferEmpty() && !d->writer->error; } @@ -684,6 +684,7 @@ if ( !cancel && ( eof || error ) ) { qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error ); notifyReadyRead(); + cancel = true; } else if ( !cancel && !bufferFull() && !bufferEmpty() ) { qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); notifyReadyRead(); Modified: trunk/gpgme/w32-qt-io.cpp =================================================================== --- trunk/gpgme/w32-qt-io.cpp 2007-10-04 14:09:58 UTC (rev 1272) +++ trunk/gpgme/w32-qt-io.cpp 2007-10-05 00:20:43 UTC (rev 1273) @@ -85,8 +85,9 @@ #define MAX_SLAFD 1024 struct DeviceEntry { - DeviceEntry() : iodev( 0 ), refCount( 1 ) {} + DeviceEntry() : iodev( 0 ), refCount( 1 ), blocking( true ) {} KDPipeIODevice* iodev; + bool blocking; mutable int refCount; void ref() const { ++refCount; } int unref() const { assert( refCount > 0 ); return --refCount; } @@ -152,7 +153,11 @@ return TRACE_SYSRES (-1); } TRACE_LOG1 ("channel %p", chan); - + if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->readWouldBlock() ) { + errno = EAGAIN; + return TRACE_SYSRES( -1 ); + } + nread = chan->read ((char *) buffer, count); if (nread < 0) { @@ -185,6 +190,11 @@ return -1; } + if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->writeWouldBlock() ) + { + errno = EAGAIN; + return TRACE_SYSRES( -1 ); + } nwritten = chan->write ((char *) buffer, count); if (nwritten < 0) @@ -323,8 +333,9 @@ int _gpgme_io_set_nonblocking (int fd) { - /* Qt always uses non-blocking IO, except for files, maybe, but who - uses that? */ + DeviceEntry* const entry = iodevice_table[fd]; + assert( entry ); + entry->blocking = false; TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd); return TRACE_SYSRES (0); } From cvs at cvs.gnupg.org Fri Oct 5 02:40:30 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 02:40:30 +0200 Subject: [svn] GpgEX - r22 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 02:40:21 +0200 (Fri, 05 Oct 2007) New Revision: 22 Modified: trunk/src/ChangeLog trunk/src/client.cc trunk/src/client.h trunk/src/gpgex.cc Log: 2007-10-05 Marcus Brinkmann * client.h (class client_t): Two new member functions create_checksums and verify_checksums. * client.cc (client_t::create_checksums, client_t::verify_checksums): New functions. (client_t::encrypt_sign, client_t::encrypt): Fix spelling. * gpgex.cc (ID_CMD_CREATE_CHECKSUMS, ID_CMD_VERIFY_CHECKSUMS, ID_CMD_STR_CREATE_CHECKSUMS, ID_CMD_STR_VERIFY_CHECKSUMS): New macros. (gpgex_t::QueryContextMenu): Add create and verify checksums menu entries. (gpgex_t::GetCommandString): Support these here as well. Translate all strings. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-03 10:48:48 UTC (rev 21) +++ trunk/src/ChangeLog 2007-10-05 00:40:21 UTC (rev 22) @@ -1,3 +1,14 @@ +2007-10-05 Marcus Brinkmann + + * client.h (class client_t): Two new member functions + create_checksums and verify_checksums. + * client.cc (client_t::create_checksums, client_t::verify_checksums): New functions. + (client_t::encrypt_sign, client_t::encrypt): Fix spelling. + * gpgex.cc (ID_CMD_CREATE_CHECKSUMS, ID_CMD_VERIFY_CHECKSUMS, + ID_CMD_STR_CREATE_CHECKSUMS, ID_CMD_STR_VERIFY_CHECKSUMS): New macros. + (gpgex_t::QueryContextMenu): Add create and verify checksums menu entries. + (gpgex_t::GetCommandString): Support these here as well. Translate all strings. + 2007-10-03 Marcus Brinkmann * client.cc (percent_escape, escape): New functions. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-03 10:48:48 UTC (rev 21) +++ trunk/src/client.cc 2007-10-05 00:40:21 UTC (rev 22) @@ -223,14 +223,14 @@ void client_t::encrypt_sign (vector &filenames) { - this->call_assuan ("ENCRPYT_SIGN", filenames); + this->call_assuan ("ENCRYPT_SIGN", filenames); } void client_t::encrypt (vector &filenames) { - this->call_assuan ("ENCRPYT", filenames); + this->call_assuan ("ENCRYPT", filenames); } @@ -246,3 +246,17 @@ { this->call_assuan ("IMPORT", filenames); } + + +void +client_t::create_checksums (vector &filenames) +{ + this->call_assuan ("CREATE_CHECKSUMS", filenames); +} + + +void +client_t::verify_checksums (vector &filenames) +{ + this->call_assuan ("VERIFY_CHECKSUMS", filenames); +} Modified: trunk/src/client.h =================================================================== --- trunk/src/client.h 2007-10-03 10:48:48 UTC (rev 21) +++ trunk/src/client.h 2007-10-05 00:40:21 UTC (rev 22) @@ -49,6 +49,8 @@ void encrypt (vector &filenames); void sign (vector &filenames); void import (vector &filenames); + void create_checksums (vector &filenames); + void verify_checksums (vector &filenames); }; #endif /* ! CLIENT_H */ Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-10-03 10:48:48 UTC (rev 21) +++ trunk/src/gpgex.cc 2007-10-05 00:40:21 UTC (rev 22) @@ -49,8 +49,10 @@ #define ID_CMD_ENCRYPT 5 #define ID_CMD_SIGN 6 #define ID_CMD_IMPORT 7 -#define ID_CMD_POPUP 8 -#define ID_CMD_MAX 8 +#define ID_CMD_CREATE_CHECKSUMS 8 +#define ID_CMD_VERIFY_CHECKSUMS 9 +#define ID_CMD_POPUP 10 +#define ID_CMD_MAX 10 #define ID_CMD_STR_HELP _("Help on GpgEX") #define ID_CMD_STR_DECRYPT_VERIFY _("Decrypt and verify") @@ -60,6 +62,8 @@ #define ID_CMD_STR_ENCRYPT _("Encrypt") #define ID_CMD_STR_SIGN _("Sign") #define ID_CMD_STR_IMPORT _("Import keys") +#define ID_CMD_STR_CREATE_CHECKSUMS _("Create checksums") +#define ID_CMD_STR_VERIFY_CHECKSUMS _("Verify checksums") /* Reset the instance between operations. */ @@ -322,20 +326,16 @@ return TRACE_RES (HRESULT_FROM_WIN32 (GetLastError ())); res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, - idCmdFirst + ID_CMD_DECRYPT_VERIFY, - ID_CMD_STR_DECRYPT_VERIFY); + idCmdFirst + ID_CMD_DECRYPT, + ID_CMD_STR_DECRYPT); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, - 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); + idCmdFirst + ID_CMD_DECRYPT_VERIFY, + ID_CMD_STR_DECRYPT_VERIFY); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, idCmdFirst + ID_CMD_ENCRYPT, @@ -346,8 +346,18 @@ ID_CMD_STR_SIGN); 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_IMPORT, ID_CMD_STR_IMPORT); if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_CREATE_CHECKSUMS, ID_CMD_STR_CREATE_CHECKSUMS); + if (res) + res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, + idCmdFirst + ID_CMD_VERIFY_CHECKSUMS, ID_CMD_STR_VERIFY_CHECKSUMS); + if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); if (res) res = InsertMenu (popup, idx++, MF_BYPOSITION | MF_STRING, @@ -389,39 +399,47 @@ switch (idCommand) { case ID_CMD_HELP: - txt = "Invoke the GpgEX documentation."; + txt = _("Invoke the GpgEX documentation."); break; case ID_CMD_DECRYPT_VERIFY: - txt = "Decrypt and verify the marked files."; + txt = _("Decrypt and verify the marked files."); break; case ID_CMD_DECRYPT: - txt = "Decrypt the marked files."; + txt = _("Decrypt the marked files."); break; case ID_CMD_VERIFY: - txt = "Verify the marked files."; + txt = _("Verify the marked files."); break; case ID_CMD_ENCRYPT_SIGN: - txt = "Encrypt and sign the marked files."; + txt = _("Encrypt and sign the marked files."); break; case ID_CMD_ENCRYPT: - txt = "Encrypt the marked files."; + txt = _("Encrypt the marked files."); break; case ID_CMD_SIGN: - txt = "Sign the marked files."; + txt = _("Sign the marked files."); break; case ID_CMD_IMPORT: - txt = "Import the marked files."; + txt = _("Import the marked files."); break; + case ID_CMD_CREATE_CHECKSUMS: + txt = _("Create checksums."); + break; + + case ID_CMD_VERIFY_CHECKSUMS: + txt = _("Verify checksums."); + break; + case ID_CMD_POPUP: - txt = "Show more GpgEX options."; + txt = _("Show more GpgEX options."); break; default: @@ -484,23 +502,8 @@ 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 (); - } @@ -553,6 +556,14 @@ client.import (this->filenames); break; + case ID_CMD_CREATE_CHECKSUMS: + client.create_checksums (this->filenames); + break; + + case ID_CMD_VERIFY_CHECKSUMS: + client.verify_checksums (this->filenames); + break; + default: return TRACE_RES (E_INVALIDARG); break; From cvs at cvs.gnupg.org Fri Oct 5 02:48:24 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 02:48:24 +0200 Subject: [svn] GpgEX - r23 - in trunk: . po Message-ID: Author: marcus Date: 2007-10-05 02:48:16 +0200 (Fri, 05 Oct 2007) New Revision: 23 Modified: trunk/ChangeLog trunk/po/de.po Log: 2007-10-05 Marcus Brinkmann * po/de.po: Update. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-05 00:40:21 UTC (rev 22) +++ trunk/ChangeLog 2007-10-05 00:48:16 UTC (rev 23) @@ -1,3 +1,7 @@ +2007-10-05 Marcus Brinkmann + + * po/de.po: Update. + 2007-09-11 Marcus Brinkmann * po/de.po: Update. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-10-05 00:40:21 UTC (rev 22) +++ trunk/po/de.po 2007-10-05 00:48:16 UTC (rev 23) @@ -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-11 16:17+0200\n" -"PO-Revision-Date: 2007-09-11 16:20+0200\n" +"POT-Creation-Date: 2007-10-05 02:37+0200\n" +"PO-Revision-Date: 2007-10-05 02:41+0200\n" "Last-Translator: Marcus Brinkmann \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -16,42 +16,97 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: src/client.cc:135 +#: src/client.cc:194 msgid "Can not access Kleopatra, see log file for details" msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei f?r Details" -#: src/gpgex.cc:51 +#: src/gpgex.cc:57 msgid "Help on GpgEX" msgstr "Hilfe zu GpgEX" -#: src/gpgex.cc:52 +#: src/gpgex.cc:58 msgid "Decrypt and verify" msgstr "Entschl?sseln und verifizieren" -#: src/gpgex.cc:53 +#: src/gpgex.cc:59 msgid "Decrypt" msgstr "Entschl?sseln" -#: src/gpgex.cc:54 +#: src/gpgex.cc:60 msgid "Verify" msgstr "Verifizieren" -#: src/gpgex.cc:55 +#: src/gpgex.cc:61 msgid "Encrypt and sign" msgstr "Verschl?sseln und verifizieren" -#: src/gpgex.cc:56 +#: src/gpgex.cc:62 msgid "Encrypt" msgstr "Verschl?sseln" -#: src/gpgex.cc:57 +#: src/gpgex.cc:63 msgid "Sign" msgstr "Signieren" -#: src/gpgex.cc:58 +#: src/gpgex.cc:64 msgid "Import keys" msgstr "Zertifikate importieren" -#: src/gpgex.cc:295 +#: src/gpgex.cc:65 +msgid "Create checksums" +msgstr "Pr?fsummen erstellen" + +#: src/gpgex.cc:66 +msgid "Verify checksums" +msgstr "Pr?fsummen verifizieren" + +#: src/gpgex.cc:306 msgid "More GpgEX options" msgstr "Mehr GpgEX Optionen" + +#: src/gpgex.cc:402 +msgid "Invoke the GpgEX documentation." +msgstr "?ffne die Dokumentation zu GpgEX" + +#: src/gpgex.cc:406 +#, fuzzy +msgid "Decrypt and verify the marked files." +msgstr "Die markierten Dateien entschl?sseln und verifizieren." + +#: src/gpgex.cc:410 +msgid "Decrypt the marked files." +msgstr "Die markierten Dateien entschl?sseln." + +#: src/gpgex.cc:414 +msgid "Verify the marked files." +msgstr "Die markierten Dateien verifizieren." + +#: src/gpgex.cc:418 +#, fuzzy +msgid "Encrypt and sign the marked files." +msgstr "Die markierten Dateien verschl?sseln und verifizieren." + +#: src/gpgex.cc:422 +msgid "Encrypt the marked files." +msgstr "Die markierten Dateien verschl?sseln." + +#: src/gpgex.cc:426 +msgid "Sign the marked files." +msgstr "Die markierten Dateien signieren." + +#: src/gpgex.cc:430 +msgid "Import the marked files." +msgstr "Die markierten Dateien importieren." + +#: src/gpgex.cc:434 +msgid "Create checksums." +msgstr "F?r die markierten Dateien Pr?fsummen erstellen." + +#: src/gpgex.cc:438 +msgid "Verify checksums." +msgstr "Die Pr?fsummen der markierten Dateien verifizieren." + +#: src/gpgex.cc:442 +#, fuzzy +msgid "Show more GpgEX options." +msgstr "Mehr GpgEX Optionen" From cvs at cvs.gnupg.org Fri Oct 5 04:29:57 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 04:29:57 +0200 Subject: [svn] GpgEX - r24 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 04:29:48 +0200 (Fri, 05 Oct 2007) New Revision: 24 Modified: trunk/src/ChangeLog trunk/src/client.cc trunk/src/gpgex.cc Log: 2007-10-05 Marcus Brinkmann * client.cc (percent_escape): Also escape ':' again. * gpgex.cc (start_help): Do not sleep. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 00:48:16 UTC (rev 23) +++ trunk/src/ChangeLog 2007-10-05 02:29:48 UTC (rev 24) @@ -1,5 +1,8 @@ 2007-10-05 Marcus Brinkmann + * client.cc (percent_escape): Also escape ':' again. + * gpgex.cc (start_help): Do not sleep. + * client.h (class client_t): Two new member functions create_checksums and verify_checksums. * client.cc (client_t::create_checksums, client_t::verify_checksums): New functions. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-05 00:48:16 UTC (rev 23) +++ trunk/src/client.cc 2007-10-05 02:29:48 UTC (rev 24) @@ -81,7 +81,6 @@ i = 0; while (*str) { -#if 0 /* FIXME: Work around a bug in Kleo. */ if (*str == ':') { @@ -90,7 +89,6 @@ ptr[i++] = 'a'; } else -#endif if (*str == '%') { ptr[i++] = '%'; Modified: trunk/src/gpgex.cc =================================================================== --- trunk/src/gpgex.cc 2007-10-05 00:48:16 UTC (rev 23) +++ trunk/src/gpgex.cc 2007-10-05 02:29:48 UTC (rev 24) @@ -502,7 +502,8 @@ return; } - Sleep (5000); + /* Do more stuff. */ + web->Release (); } From cvs at cvs.gnupg.org Fri Oct 5 11:36:20 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 05 Oct 2007 11:36:20 +0200 Subject: [svn] GpgOL - r186 - in trunk: . doc Message-ID: Author: wk Date: 2007-10-05 11:36:10 +0200 (Fri, 05 Oct 2007) New Revision: 186 Added: trunk/doc/ trunk/doc/Makefile.am trunk/doc/gpgol.texi trunk/doc/gpl.texi Modified: trunk/Makefile.am trunk/configure.ac Log: Started documentation. Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2007-09-21 14:02:48 UTC (rev 185) +++ trunk/Makefile.am 2007-10-05 09:36:10 UTC (rev 186) @@ -22,7 +22,7 @@ EXTRA_DIST = autogen.sh -SUBDIRS = src po m4 +SUBDIRS = src po m4 doc dist-hook: echo "$(VERSION)" > $(distdir)/VERSION Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-09-21 14:02:48 UTC (rev 185) +++ trunk/configure.ac 2007-10-05 09:36:10 UTC (rev 186) @@ -24,8 +24,11 @@ AC_INIT([gpgol], my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision]), [bug-gpgol at g10code.com]) +NEED_GPG_ERROR_VERSION=1.4 NEED_GPGME_API=1 NEED_GPGME_VERSION=1.1.0 +NEED_LIBASSUAN_API=1 +NEED_LIBASSUAN_VERSION=1.0.4 SVN_REVISION=svn_revision @@ -40,6 +43,9 @@ AC_GNU_SOURCE +have_gpg_error=no +have_libassuan=no + AC_SUBST(PACKAGE) AC_SUBST(PACKAGE_GT) AC_SUBST(VERSION) @@ -141,9 +147,20 @@ AM_PATH_GPGME("$NEED_GPGME_API:$NEED_GPGME_VERSION", have_gpgme=yes,have_gpgme=no) -AM_PATH_GPG_ERROR(0.5,, AC_MSG_ERROR([libgpg-error was not found])) +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_2, + [The default error source for GpgOL.]) +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 +]) + + # Note, that autogen.sh greps for the next line. AM_GNU_GETTEXT_VERSION(0.12.1) AM_GNU_GETTEXT([external]) @@ -190,6 +207,16 @@ # 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_gpgme" = "no"; then die=yes AC_MSG_NOTICE([[ @@ -200,6 +227,16 @@ *** (at least version $NEED_GPGME_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([[ *** @@ -212,6 +249,7 @@ AC_CONFIG_FILES([ Makefile src/Makefile src/versioninfo.rc +doc/Makefile po/Makefile.in m4/Makefile ]) Added: trunk/doc/Makefile.am =================================================================== --- trunk/doc/Makefile.am 2007-09-21 14:02:48 UTC (rev 185) +++ trunk/doc/Makefile.am 2007-10-05 09:36:10 UTC (rev 186) @@ -0,0 +1,19 @@ +# doc - Automake template +# Copyright (C) 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 +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +## Process this file with automake to produce Makefile.in + +DISTCLEANFILES = gpgol.cps + +info_TEXINFOS = gpgol.texi +gpgol_TEXINFOS = gpl.texi + + Added: trunk/doc/gpgol.texi =================================================================== --- trunk/doc/gpgol.texi 2007-09-21 14:02:48 UTC (rev 185) +++ trunk/doc/gpgol.texi 2007-10-05 09:36:10 UTC (rev 186) @@ -0,0 +1,231 @@ +\input texinfo + at setfilename gpgol.info + at settitle The GpgOL Technical Manual + + at dircategory GnuPG Plugin + at direntry +* gpgol: (gpgol). An Outlook Plugin for GnuPG. + at end direntry + + at include version.texi + + at c Unify some of the indices. + at syncodeindex tp fn + at syncodeindex pg fn + + at macro mycopyrightnotice +Copyright @copyright{} 2007 g10 Code GmbH + at end macro + at macro mypermissionnotice +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. The text of the license can be found in the +section entitled ``Copying''. + at end macro + + + + at ifinfo +This file documents @acronym{GpgOL}; a GnuPG plugin for Microsoft's +Outlook MUA. + +This is @cite{The GpgOL Technical Manual} for @acronym{GpgOL} version + at value{VERSION}, last updated @value{UPDATED}. + + at sp 1 + at mycopyrightnotice{} + at sp 1 + at mypermissionnotice{} + at end ifinfo + + + at iftex + at shorttitlepage The `GpgOL' Technical Manual + at titlepage + at center @titlefont{The `GpgOL'} + at sp 1 + at center @titlefont{Technical Manual} + at sp 6 + at center for version @value{VERSION} + at sp 1 + at center last updated @value{UPDATED} + at sp 1 + at author by Werner Koch, g10 Code GmbH + at email{wk@@gnupg.org} + at page + at vskip 0pt plus 1filll + at mycopyrightnotice{} + at sp 1 + at mypermissionnotice{} + at end titlepage + at summarycontents + at contents + at page + at end iftex + + + at ifnottex + at node Top + at top Main Menu +This is @cite{The GpgOL Technical Manual} for @acronym{GpgOL} version + at value{VERSION}, last updated @value{UPDATED}. + at sp 1 + at mycopyrightnotice{} + at sp 1 + at mypermissionnotice{} + at sp 1 + at end ifnottex + + + at menu +* Introduction:: How to use this manual. +* Assuan Protocol:: Description of the UI server protocol. + +Appendices + +* Copying:: The GNU General Public License says how you + can copy and share this manual. + +Indices + +* Concept Index:: Index of concepts and programs. +* Function and Data Index:: Index of functions, variables and data types. + + at end menu + + at node Introduction + at chapter Introduction +Bla bla + + + + at node Assuan Protocol + at chapter Description of the UI Server Protocol + +This section descripes the protocol used between @acronym{GpgOL} and the +User Interface Server (UI server). All cryptographic operations are +done by this server and teh server is responsible for all dialogs. If a +a server is not available, @acronym{GpgOL} can only use a very limited +internal crypto server. + +We assume that the connection has already been established; see the +Assuan manual for details. + + at menu +* ENCRYPT:: Encrypting a message. +* Miscellaneous Commands:: Commands not related to a specific operation. + at end menu + + + + at node ENCRYPT + at section Encrypting a Message + +Before encrytion can be done the recipients must be set using the +command: + + at deffn Command RECIPIENT @var{string} + +Set the recipient for the encryption. @var{string} is an RFC-2822 +recipient name. This command may or may not check the recipient for +validity right away; if it does not all recipients are expected to be +checked at the time of the @code{ENCRYPT} command. All @code{RECIPIENT} +commands are cumulative until a successful @code{ENCRYPT} command or +until a RESET command. Linefeeds are obviously not allowed in + at var{string} and should be folded into spaces (which are equivalent). + at end deffn + + at noindent +To tell the server the source and destination of the data, the next two +commands are to be used: + + at deffn Command INPUT FD=@var{n} +Set the file descriptor for the message to be encrypted to @var{n}. The +message send to the server is binary encoded. + +GpgOL is a Windows only program, thus @var{n} is not a libc file +descriptor but a regular system handle. Given that the Assuan +connection works over a socket, it is not possible to use regular +inheritance to make the file descriptor available to the server. +Thus @code{DuplicateHandle} needs to be used to duplicate a handle +to the server process. This is the reason that the server needs to +implement the @code{GETINFO pid} command. Sending this command a second +time replaces the file descriptor set by the last one. + at c If @var{n} is not given, this commands uses the + at c %last file descriptor passed to the application. + at c %@xref{fun-assuan_sendfd, ,the assuan_sendfd function,assuan,the + at c %Libassuan manual}, on how to do descriptor passing. + at end deffn + + at deffn Command OUTPUT FD=@var{n} +Set the file descriptor to be used for the output (i.e. the encrypted +message) to @var{n}. Binary encoding is expected. For details on the +file descriptor, see the @code{INPUT} command. + at end deffn + + at noindent +The setting of the recipients, the data source and destination may +happen in any order, even intermixed. If this has been done the actual +encryption operation is called using: + + at deffn Command ENCRYPT --protocol=@var{name} + +This command reads the plaintext from the file descriptor set by the + at code{INPUT} command, encrypts it and writes the ciphertext to the file +descriptor set by the @code{OUTPUT} command. The server may (and +should) overlap readind and writing. The recipients used for the +encryption are all the recipients set so far. If any recipient is not +usable the server should take appropriate measures to notify the user +about the problem and may cancel the operation by returning an error +code. The used file descriptors are a void after this command; the +recipient list is only cleared if the server returns success. + + at noindent +Because GpgOL uses a streaming mode of operation the server is not +allowed to auto select the protocol and must obey to the mandatory + at var{protocol} parameter: + + at table @code + at item OpenPGP +Use the OpenPGP protocol (RFC-2440). + at item CMS +Use the CMS (PKCS#7) protocol (RFC-3852). + at end table + + at end deffn + + + + + at node Miscellaneous Commands + at section Miscellaneous Commands + +The server needs to implement the following commands which are not +related to a specific command: + + at deffn Command GETINFO @var{what} +This is a multi purpose command, commonly used to return a variety of +information. The required subcommands as descriped by the @var{waht} +parameter are: + + at table @code + at item pid +Return the process id of the server in decimal notation using an Assuan +data line. + at end table + at end deffn + + + + + at include gpl.texi + + + at node Concept Index + at unnumbered Concept Index + at printindex cp + at node Function and Data Index + at unnumbered Function and Data Index + at printindex fn + at bye Added: trunk/doc/gpl.texi =================================================================== --- trunk/doc/gpl.texi 2007-09-21 14:02:48 UTC (rev 185) +++ trunk/doc/gpl.texi 2007-10-05 09:36:10 UTC (rev 186) @@ -0,0 +1,725 @@ + at node Copying + + at unnumbered GNU General Public License + at center Version 3, 29 June 2007 + + at c This file is intended to be included in another file. + + at display +Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + at end display + + at unnumberedsec Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program--to make sure it remains +free software for all its users. We, the Free Software Foundation, +use the GNU General Public License for most of our software; it +applies also to any other work released this way by its authors. You +can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, +receive or can get the source code. And you must show them these +terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + + at iftex + at unnumberedsec TERMS AND CONDITIONS + at end iftex + at ifinfo + at center TERMS AND CONDITIONS + at end ifinfo + + at enumerate 0 + at item Definitions. + +``This License'' refers to version 3 of the GNU General Public License. + +``Copyright'' also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +``The Program'' refers to any copyrightable work licensed under this +License. Each licensee is addressed as ``you''. ``Licensees'' and +``recipients'' may be individuals or organizations. + +To ``modify'' a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a ``modified version'' of +the earlier work or a work ``based on'' the earlier work. + +A ``covered work'' means either the unmodified Program or a work based +on the Program. + +To ``propagate'' a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To ``convey'' a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays ``Appropriate Legal Notices'' to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + at item Source Code. + +The ``source code'' for a work means the preferred form of the work for +making modifications to it. ``Object code'' means any non-source form +of a work. + +A ``Standard Interface'' means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The ``System Libraries'' of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +``Major Component'', in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The ``Corresponding Source'' for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + + at item Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + at item Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + + at item Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + at item Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + + at enumerate a + at item +The work must carry prominent notices stating that you modified it, +and giving a relevant date. + + at item +The work must carry prominent notices stating that it is released +under this License and any conditions added under section 7. This +requirement modifies the requirement in section 4 to ``keep intact all +notices''. + + at item +You must license the entire work, as a whole, under this License to +anyone who comes into possession of a copy. This License will +therefore apply, along with any applicable section 7 additional terms, +to the whole of the work, and all its parts, regardless of how they +are packaged. This License gives no permission to license the work in +any other way, but it does not invalidate such permission if you have +separately received it. + + at item +If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your work +need not make them do so. + at end enumerate + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +``aggregate'' if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + at item Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + + at enumerate a + at item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium customarily +used for software interchange. + + at item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a written +offer, valid for at least three years and valid for as long as you +offer spare parts or customer support for that product model, to give +anyone who possesses the object code either (1) a copy of the +Corresponding Source for all the software in the product that is +covered by this License, on a durable physical medium customarily used +for software interchange, for a price no more than your reasonable +cost of physically performing this conveying of source, or (2) access +to copy the Corresponding Source from a network server at no charge. + + at item +Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is +allowed only occasionally and noncommercially, and only if you +received the object code with such an offer, in accord with subsection +6b. + + at item +Convey the object code by offering access from a designated place +(gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to copy +the object code is a network server, the Corresponding Source may be +on a different server (operated by you or a third party) that supports +equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. +Regardless of what server hosts the Corresponding Source, you remain +obligated to ensure that it is available for as long as needed to +satisfy these requirements. + + at item +Convey the object code using peer-to-peer transmission, provided you +inform other peers where the object code and Corresponding Source of +the work are being offered to the general public at no charge under +subsection 6d. + + at end enumerate + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A ``User Product'' is either (1) a ``consumer product'', which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +``normally used'' refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +``Installation Information'' for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + at item Additional Terms. + +``Additional permissions'' are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + + at enumerate a + at item +Disclaiming warranty or limiting liability differently from the terms +of sections 15 and 16 of this License; or + + at item +Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices +displayed by works containing it; or + + at item +Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + + at item +Limiting the use for publicity purposes of names of licensors or +authors of the material; or + + at item +Declining to grant rights under trademark law for use of some trade +names, trademarks, or service marks; or + + at item +Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with +contractual assumptions of liability to the recipient, for any +liability that these contractual assumptions directly impose on those +licensors and authors. + at end enumerate + +All other non-permissive additional terms are considered ``further +restrictions'' within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + + at item Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + at item Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + at item Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An ``entity transaction'' is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + at item Patents. + +A ``contributor'' is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's ``contributor version''. + +A contributor's ``essential patent claims'' are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, ``control'' includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a ``patent license'' is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To ``grant'' such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. ``Knowingly relying'' means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is ``discriminatory'' if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + at item No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey +a covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree +to terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + + at item Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + at item Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If +the Program does not specify a version number of the GNU General +Public License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + at item Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + at item Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + at item Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + at iftex + at heading END OF TERMS AND CONDITIONS + at end iftex + at ifinfo + at center END OF TERMS AND CONDITIONS + at end ifinfo + at unnumberedsec How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + at smallexample + at var{one line to give the program's name and a brief idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +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 3 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, see @url{http://www.gnu.org/licenses/}. + at end smallexample + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + at smallexample + at var{program} Copyright (C) @var{year} @var{name of author} +This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. +This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. + at end smallexample + +The hypothetical commands @samp{show w} and @samp{show c} should show +the appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an ``about box''. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a ``copyright disclaimer'' for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see + at url{http://www.gnu.org/licenses/}. + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. But +first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. + + at end enumerate From cvs at cvs.gnupg.org Fri Oct 5 14:24:09 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 14:24:09 +0200 Subject: [svn] assuan - r270 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 14:24:01 +0200 (Fri, 05 Oct 2007) New Revision: 270 Modified: trunk/src/ChangeLog trunk/src/assuan-uds.c Log: 2007-10-05 Marcus Brinkmann * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: New function. (uds_reader, uds_writer) [HAVE_W32_SYSTEM]: Set errno. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-04 12:24:29 UTC (rev 269) +++ trunk/src/ChangeLog 2007-10-05 12:24:01 UTC (rev 270) @@ -1,3 +1,8 @@ +2007-10-05 Marcus Brinkmann + + * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: New function. + (uds_reader, uds_writer) [HAVE_W32_SYSTEM]: Set errno. + 2007-10-04 Werner Koch * mkerrors: Map EAGAIN to GPG_ERR_EAGAIN for read and write Modified: trunk/src/assuan-uds.c =================================================================== --- trunk/src/assuan-uds.c 2007-10-04 12:24:29 UTC (rev 269) +++ trunk/src/assuan-uds.c 2007-10-05 12:24:01 UTC (rev 270) @@ -63,6 +63,25 @@ #endif /*USE_DESCRIPTOR_PASSING*/ +#ifdef HAVE_W32_SYSTEM +int +wsa2errno (int err) +{ + switch (err) + { + case WSAENOTSOCK: + return EINVAL; + case WSAEWOULDBLOCK: + return EAGAIN; + case ERROR_BROKEN_PIPE: + return EPIPE; + default: + return EIO; + } +} +#endif + + /* Read from a unix domain socket using sendmsg. FIXME: We don't need the buffering. It is a leftover from the time @@ -152,7 +171,10 @@ return len; #else /*HAVE_W32_SYSTEM*/ - return recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL); + int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL); + if (res < 0) + errno = wsa2errno (WSAGetLastError ()); + return res; #endif /*HAVE_W32_SYSTEM*/ } @@ -179,9 +201,12 @@ return len; #else /*HAVE_W32_SYSTEM*/ - return sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0, - (struct sockaddr *)&ctx->serveraddr, - sizeof (struct sockaddr_in)); + int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0, + (struct sockaddr *)&ctx->serveraddr, + sizeof (struct sockaddr_in)); + if (res < 0) + errno = wsa2errno (WSAGetLastError ()); + return res; #endif /*HAVE_W32_SYSTEM*/ } From cvs at cvs.gnupg.org Fri Oct 5 16:40:42 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 16:40:42 +0200 Subject: [svn] GpgEX - r25 - trunk Message-ID: Author: marcus Date: 2007-10-05 16:40:33 +0200 (Fri, 05 Oct 2007) New Revision: 25 Modified: trunk/ChangeLog Log: 2007-10-05 Marcus Brinkmann * po/de.po: Fix translation. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-05 02:29:48 UTC (rev 24) +++ trunk/ChangeLog 2007-10-05 14:40:33 UTC (rev 25) @@ -1,5 +1,7 @@ 2007-10-05 Marcus Brinkmann + * po/de.po: Fix translation. + * po/de.po: Update. 2007-09-11 Marcus Brinkmann From cvs at cvs.gnupg.org Fri Oct 5 16:41:34 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 16:41:34 +0200 Subject: [svn] GpgEX - r26 - trunk/po Message-ID: Author: marcus Date: 2007-10-05 16:41:25 +0200 (Fri, 05 Oct 2007) New Revision: 26 Modified: trunk/po/de.po Log: 2007-10-05 Marcus Brinkmann * po/de.po: Fix translation. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-10-05 14:40:33 UTC (rev 25) +++ trunk/po/de.po 2007-10-05 14:41:25 UTC (rev 26) @@ -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-10-05 02:37+0200\n" -"PO-Revision-Date: 2007-10-05 02:41+0200\n" +"PO-Revision-Date: 2007-10-05 16:34+0200\n" "Last-Translator: Marcus Brinkmann \n" "Language-Team: German\n" "MIME-Version: 1.0\n" @@ -38,7 +38,7 @@ #: src/gpgex.cc:61 msgid "Encrypt and sign" -msgstr "Verschl?sseln und verifizieren" +msgstr "Verschl?sseln und signieren" #: src/gpgex.cc:62 msgid "Encrypt" From cvs at cvs.gnupg.org Fri Oct 5 17:03:54 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 17:03:54 +0200 Subject: [svn] GpgEX - r27 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 17:03:44 +0200 (Fri, 05 Oct 2007) New Revision: 27 Modified: trunk/src/ChangeLog trunk/src/main.cc Log: 2007-10-05 Marcus Brinkmann * main.cc (DllMain): Initialize winsock. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 14:41:25 UTC (rev 26) +++ trunk/src/ChangeLog 2007-10-05 15:03:44 UTC (rev 27) @@ -1,5 +1,7 @@ 2007-10-05 Marcus Brinkmann + * main.cc (DllMain): Initialize winsock. + * client.cc (percent_escape): Also escape ':' again. * gpgex.cc (start_help): Do not sleep. Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-10-05 14:41:25 UTC (rev 26) +++ trunk/src/main.cc 2007-10-05 15:03:44 UTC (rev 27) @@ -207,6 +207,12 @@ (void) TRACE0 (DEBUG_INIT, "DllMain", hinst, "reason=DLL_PROCESS_ATTACH"); + + { + WSADATA wsadat; + + WSAStartup (0x202, &wsadat); + } } else if (reason == DLL_PROCESS_DETACH) { From cvs at cvs.gnupg.org Fri Oct 5 18:01:23 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 18:01:23 +0200 Subject: [svn] assuan - r271 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 18:01:12 +0200 (Fri, 05 Oct 2007) New Revision: 271 Modified: trunk/src/ChangeLog trunk/src/assuan-buffer.c trunk/src/assuan-defs.h trunk/src/assuan-socket.c trunk/src/assuan-uds.c Log: 2007-10-05 Marcus Brinkmann * assuan-defs.h (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: Add prototype. * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: Move and rename to ... * assuan-socket.c (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: ... this. (_assuan_close, _assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind): Always set errno on error. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 12:24:01 UTC (rev 270) +++ trunk/src/ChangeLog 2007-10-05 16:01:12 UTC (rev 271) @@ -1,5 +1,11 @@ 2007-10-05 Marcus Brinkmann + * assuan-defs.h (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: Add prototype. + * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: Move and rename to ... + * assuan-socket.c (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: ... this. + (_assuan_close, _assuan_sock_new, _assuan_sock_connect, _assuan_sock_bind): + Always set errno on error. + * assuan-uds.c (wsa2errno) [HAVE_W32_SYSTEM]: New function. (uds_reader, uds_writer) [HAVE_W32_SYSTEM]: Set errno. Modified: trunk/src/assuan-buffer.c =================================================================== --- trunk/src/assuan-buffer.c 2007-10-05 12:24:01 UTC (rev 270) +++ trunk/src/assuan-buffer.c 2007-10-05 16:01:12 UTC (rev 271) @@ -51,9 +51,10 @@ return 0; /* okay */ } -/* Read an entire line. Returns 0 on success or -1 and ERRNo on +/* Read an entire line. Returns 0 on success or -1 and ERRNO on failure. EOF is indictated by setting the integer at address - R_EOF. */ + R_EOF. Note: BUF, R_NREAD and R_EOF contain a valid result even if + an error is returned. */ static int readline (assuan_context_t ctx, char *buf, size_t buflen, int *r_nread, int *r_eof) @@ -132,12 +133,23 @@ &nread, &ctx->inbound.eof); if (rc) { + int saved_errno = errno; + if (ctx->log_fp) - fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", + fprintf (ctx->log_fp, "%s[%u.%d] DBG: <- [Error: %s]\n", assuan_get_assuan_log_prefix (), (unsigned int)getpid (), (int)ctx->inbound.fd, strerror (errno)); - + + if (saved_errno == EAGAIN) + { + /* We have to save a partial line. */ + memcpy (ctx->inbound.attic.line, line, atticlen + nread); + ctx->inbound.attic.pending = 0; + ctx->inbound.attic.linelen = atticlen + nread; + } + + errno = saved_errno; return _assuan_error (ASSUAN_Read_Error); } if (!nread) Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-10-05 12:24:01 UTC (rev 270) +++ trunk/src/assuan-defs.h 2007-10-05 16:01:12 UTC (rev 271) @@ -305,8 +305,10 @@ int _assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, assuan_sock_nonce_t *nonce); int _assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce); +#ifdef HAVE_W32_SYSTEM +int _assuan_sock_wsa2errno (int err); +#endif - #ifdef HAVE_FOPENCOOKIE /* We have to implement funopen in terms of glibc's fopencookie. */ FILE *_assuan_funopen(void *cookie, Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-10-05 12:24:01 UTC (rev 270) +++ trunk/src/assuan-socket.c 2007-10-05 16:01:12 UTC (rev 271) @@ -57,8 +57,25 @@ #ifdef HAVE_W32_SYSTEM +int +_assuan_sock_wsa2errno (int err) +{ + switch (err) + { + case WSAENOTSOCK: + return EINVAL; + case WSAEWOULDBLOCK: + return EAGAIN; + case ERROR_BROKEN_PIPE: + return EPIPE; + default: + return EIO; + } +} + + /* W32: Fill BUFFER with LENGTH bytes of random. Returns -1 on - failure, 0 on success. */ + failure, 0 on success. Sets errno on failure. */ static int get_nonce (char *buffer, size_t nbytes) { @@ -81,7 +98,7 @@ /* W32: The buffer for NONCE needs to be at least 16 bytes. Returns 0 on - success. */ + success and sets errno on failure. */ static int read_port_and_nonce (const char *fname, unsigned short *port, char *nonce) { @@ -128,9 +145,14 @@ { #ifdef HAVE_W32_SYSTEM int rc = closesocket (HANDLE2SOCKET(fd)); + if (rc) + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); if (rc && WSAGetLastError () == WSAENOTSOCK) { rc = CloseHandle (fd); + if (rc) + /* FIXME. */ + errno = EIO; } return rc; #else @@ -146,9 +168,13 @@ _assuan_sock_new (int domain, int type, int proto) { #ifdef HAVE_W32_SYSTEM + int res; if (domain == AF_UNIX || domain == AF_LOCAL) domain = AF_INET; - return SOCKET2HANDLE(socket (domain, type, proto)); + res = SOCKET2HANDLE(socket (domain, type, proto)); + if (res < 0) + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); + return res; #else return socket (domain, type, proto); #endif @@ -195,7 +221,13 @@ return ret; } else - return connect (HANDLE2SOCKET (sockfd), addr, addrlen); + { + int res; + res = connect (HANDLE2SOCKET (sockfd), addr, addrlen); + if (res < 0) + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); + return res; + } #else return connect (sockfd, addr, addrlen); #endif @@ -262,7 +294,12 @@ return 0; } else - return bind (HANDLE2SOCKET(sockfd), addr, addrlen); + { + int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen); + if (res < 0) + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); + return res; + } #else return bind (sockfd, addr, addrlen); #endif Modified: trunk/src/assuan-uds.c =================================================================== --- trunk/src/assuan-uds.c 2007-10-05 12:24:01 UTC (rev 270) +++ trunk/src/assuan-uds.c 2007-10-05 16:01:12 UTC (rev 271) @@ -63,25 +63,6 @@ #endif /*USE_DESCRIPTOR_PASSING*/ -#ifdef HAVE_W32_SYSTEM -int -wsa2errno (int err) -{ - switch (err) - { - case WSAENOTSOCK: - return EINVAL; - case WSAEWOULDBLOCK: - return EAGAIN; - case ERROR_BROKEN_PIPE: - return EPIPE; - default: - return EIO; - } -} -#endif - - /* Read from a unix domain socket using sendmsg. FIXME: We don't need the buffering. It is a leftover from the time @@ -173,7 +154,7 @@ #else /*HAVE_W32_SYSTEM*/ int res = recvfrom (HANDLE2SOCKET(ctx->inbound.fd), buf, buflen, 0, NULL, NULL); if (res < 0) - errno = wsa2errno (WSAGetLastError ()); + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); return res; #endif /*HAVE_W32_SYSTEM*/ } @@ -205,7 +186,7 @@ (struct sockaddr *)&ctx->serveraddr, sizeof (struct sockaddr_in)); if (res < 0) - errno = wsa2errno (WSAGetLastError ()); + errno = _assuan_sock_wsa2errno (WSAGetLastError ()); return res; #endif /*HAVE_W32_SYSTEM*/ } From cvs at cvs.gnupg.org Fri Oct 5 18:20:01 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 05 Oct 2007 18:20:01 +0200 Subject: [svn] assuan - r272 - trunk/src Message-ID: Author: wk Date: 2007-10-05 18:19:51 +0200 (Fri, 05 Oct 2007) New Revision: 272 Modified: trunk/src/ChangeLog trunk/src/assuan-socket.c trunk/src/assuan.h Log: Map WSANOTINITIALIZED to ENOSYS. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 16:01:12 UTC (rev 271) +++ trunk/src/ChangeLog 2007-10-05 16:19:51 UTC (rev 272) @@ -1,3 +1,9 @@ +2007-10-05 Werner Koch + + * assuan-socket.c (_assuan_sock_wsa2errno): Map WSANOTINITIALISED. + (_assuan_sock_new): Use assuan_fd_t. + * assuan.h (_assuan_sock_wsa2errno): Add prefix macro. + 2007-10-05 Marcus Brinkmann * assuan-defs.h (_assuan_sock_wsa2errno) [HAVE_W32_SYSTEM]: Add prototype. Modified: trunk/src/assuan-socket.c =================================================================== --- trunk/src/assuan-socket.c 2007-10-05 16:01:12 UTC (rev 271) +++ trunk/src/assuan-socket.c 2007-10-05 16:19:51 UTC (rev 272) @@ -68,6 +68,8 @@ return EAGAIN; case ERROR_BROKEN_PIPE: return EPIPE; + case WSANOTINITIALISED: + return ENOSYS; default: return EIO; } @@ -168,11 +170,11 @@ _assuan_sock_new (int domain, int type, int proto) { #ifdef HAVE_W32_SYSTEM - int res; + assuan_fd_t res; if (domain == AF_UNIX || domain == AF_LOCAL) domain = AF_INET; res = SOCKET2HANDLE(socket (domain, type, proto)); - if (res < 0) + if (res == ASSUAN_INVALID_FD) errno = _assuan_sock_wsa2errno (WSAGetLastError ()); return res; #else Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-10-05 16:01:12 UTC (rev 271) +++ trunk/src/assuan.h 2007-10-05 16:19:51 UTC (rev 272) @@ -185,7 +185,8 @@ #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_sock_close _ASSUAN_PREFIX(_assuan_close) +#define _assuan_sock_wsa2errno _ASSUAN_PREFIX(_assuan_sock_wsa2errno) +#define _assuan_sock_close _ASSUAN_PREFIX(_assuan_sock_close) #define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new) #define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect) #define _assuan_sock_bind _ASSUAN_PREFIX(_assuan_sock_bind) From cvs at cvs.gnupg.org Fri Oct 5 18:44:18 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 18:44:18 +0200 Subject: [svn] assuan - r273 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 18:44:08 +0200 (Fri, 05 Oct 2007) New Revision: 273 Modified: trunk/src/ChangeLog trunk/src/assuan-buffer.c trunk/src/assuan-client.c trunk/src/assuan-defs.h trunk/src/assuan-handler.c trunk/src/mkerrors Log: 2007-10-05 Marcus Brinkmann * assuan-defs.h (_assuan_error_is_eagain): New prototype. * mkerrors (_assuan_error_is_eagain): New function. * assuan-handler.c (process_next): Leave on EAGAIN. * assuan-handler.c (process_request), assuan-client.c (_assuan_read_from_server), assuan-buffer.c (assuan_read_line): Busy loop over EAGAIN. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/ChangeLog 2007-10-05 16:44:08 UTC (rev 273) @@ -1,3 +1,12 @@ +2007-10-05 Marcus Brinkmann + + * assuan-defs.h (_assuan_error_is_eagain): New prototype. + * mkerrors (_assuan_error_is_eagain): New function. + * assuan-handler.c (process_next): Leave on EAGAIN. + * assuan-handler.c (process_request), + assuan-client.c (_assuan_read_from_server), + assuan-buffer.c (assuan_read_line): Busy loop over EAGAIN. + 2007-10-05 Werner Koch * assuan-socket.c (_assuan_sock_wsa2errno): Map WSANOTINITIALISED. Modified: trunk/src/assuan-buffer.c =================================================================== --- trunk/src/assuan-buffer.c 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/assuan-buffer.c 2007-10-05 16:44:08 UTC (rev 273) @@ -93,7 +93,7 @@ } -/* Function returns an Assuan error. */ +/* Function returns an Assuan error. */ assuan_error_t _assuan_read_line (assuan_context_t ctx) { @@ -245,7 +245,12 @@ if (!ctx) return _assuan_error (ASSUAN_Invalid_Value); - err = _assuan_read_line (ctx); + do + { + err = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (err)); + *line = ctx->inbound.line; *linelen = ctx->inbound.linelen; return err; Modified: trunk/src/assuan-client.c =================================================================== --- trunk/src/assuan-client.c 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/assuan-client.c 2007-10-05 16:44:08 UTC (rev 273) @@ -42,7 +42,11 @@ *off = 0; do { - rc = _assuan_read_line (ctx); + do + { + rc = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (rc)); if (rc) return rc; line = ctx->inbound.line; Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/assuan-defs.h 2007-10-05 16:44:08 UTC (rev 273) @@ -234,6 +234,8 @@ /* Map error codes as used in this implementation to the libgpg-error codes. */ assuan_error_t _assuan_error (int oldcode); +/* Check if ERR means EAGAIN. */ +int _assuan_error_is_eagain (assuan_error_t err); /* Extract the error code from A. This works for both the old and the new style error codes. This needs to be used whenever an error Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/assuan-handler.c 2007-10-05 16:44:08 UTC (rev 273) @@ -612,6 +612,8 @@ required to write full lines without blocking long after starting a partial line. */ rc = _assuan_read_line (ctx); + if (_assuan_error_is_eagain (rc)) + return 0; if (rc) return rc; if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) @@ -683,7 +685,11 @@ if (ctx->in_inquire) return _assuan_error (ASSUAN_Nested_Commands); - rc = _assuan_read_line (ctx); + do + { + rc = _assuan_read_line (ctx); + } + while (_assuan_error_is_eagain (rc)); if (rc) return rc; if (*ctx->inbound.line == '#' || !ctx->inbound.linelen) Modified: trunk/src/mkerrors =================================================================== --- trunk/src/mkerrors 2007-10-05 16:19:51 UTC (rev 272) +++ trunk/src/mkerrors 2007-10-05 16:44:08 UTC (rev 273) @@ -141,6 +141,19 @@ } +/* A small helper function to treat EAGAIN transparently to the + caller. */ +int +_assuan_error_is_eagain (assuan_error_t err) +{ + if ((!err_source && err == ASSUAN_Read_Error && errno == EAGAIN) + || (err_source && (err & ((1 << 24) - 1)) == (6 | (1 << 15)))) + return 1; + else + return 0; +} + + /** * assuan_strerror: * @err: Error code From cvs at cvs.gnupg.org Fri Oct 5 18:56:00 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 18:56:00 +0200 Subject: [svn] assuan - r274 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 18:55:51 +0200 (Fri, 05 Oct 2007) New Revision: 274 Modified: trunk/src/ChangeLog trunk/src/assuan.h Log: 2007-10-05 Marcus Brinkmann * assuan.h (_assuan_error_is_eagain): Add prefix macro. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 16:44:08 UTC (rev 273) +++ trunk/src/ChangeLog 2007-10-05 16:55:51 UTC (rev 274) @@ -1,5 +1,7 @@ 2007-10-05 Marcus Brinkmann + * assuan.h (_assuan_error_is_eagain): Add prefix macro. + * assuan-defs.h (_assuan_error_is_eagain): New prototype. * mkerrors (_assuan_error_is_eagain): New function. * assuan-handler.c (process_next): Leave on EAGAIN. Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-10-05 16:44:08 UTC (rev 273) +++ trunk/src/assuan.h 2007-10-05 16:55:51 UTC (rev 274) @@ -179,13 +179,14 @@ #define _assuan_gpg_strsource _ASSUAN_PREFIX(_assuan_gpg_strsource) #define _assuan_write_line _ASSUAN_PREFIX(_assuan_write_line) #define _assuan_error _ASSUAN_PREFIX(_assuan_error) +#define _assuan_error_is_eagain _ASSUAN_PREFIX(_assuan_error_is_eagain) #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_sock_wsa2errno _ASSUAN_PREFIX(_assuan_sock_wsa2errno) +#define _assuan_sock_wsa2errno _ASSUAN_PREFIX(_assuan_sock_wsa2errno) #define _assuan_sock_close _ASSUAN_PREFIX(_assuan_sock_close) #define _assuan_sock_new _ASSUAN_PREFIX(_assuan_sock_new) #define _assuan_sock_connect _ASSUAN_PREFIX(_assuan_sock_connect) From cvs at cvs.gnupg.org Fri Oct 5 19:30:43 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 19:30:43 +0200 Subject: [svn] dirmngr - r270 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 19:30:33 +0200 (Fri, 05 Oct 2007) New Revision: 270 Modified: trunk/src/ChangeLog trunk/src/dirmngr.c trunk/src/dirmngr.h trunk/src/server.c Log: 2007-10-05 Marcus Brinkmann * dirmngr.h: Include assuan.h. (start_command_handler): Change type of FD to assuan_fd_t. * dirmngr.c: Do not include w32-afunix.h. (socket_nonce): New global variable. (create_server_socket): Use assuan socket wrappers. Remove W32 specific stuff. Save the server nonce. (check_nonce): New function. (start_connection_thread): Call it. (handle_connections): Change args to assuan_fd_t. * server.c (start_command_handler): Change type of FD to assuan_fd_t. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-09-14 11:41:34 UTC (rev 269) +++ trunk/src/ChangeLog 2007-10-05 17:30:33 UTC (rev 270) @@ -1,3 +1,16 @@ +2007-10-05 Marcus Brinkmann + + * dirmngr.h: Include assuan.h. + (start_command_handler): Change type of FD to assuan_fd_t. + * dirmngr.c: Do not include w32-afunix.h. + (socket_nonce): New global variable. + (create_server_socket): Use assuan socket wrappers. Remove W32 + specific stuff. Save the server nonce. + (check_nonce): New function. + (start_connection_thread): Call it. + (handle_connections): Change args to assuan_fd_t. + * server.c (start_command_handler): Change type of FD to assuan_fd_t. + 2007-09-12 Marcus Brinkmann * dirmngr.c (main): Percent escape pathnames in --gpgconf-list output. Modified: trunk/src/dirmngr.c =================================================================== --- trunk/src/dirmngr.c 2007-09-14 11:41:34 UTC (rev 269) +++ trunk/src/dirmngr.c 2007-10-05 17:30:33 UTC (rev 270) @@ -42,7 +42,7 @@ #include #include -#include /* Needed for the malloc hooks */ +#include /* Needed for the malloc and socket hooks */ #define JNLIB_NEED_LOG_LOGV #include "dirmngr.h" @@ -53,8 +53,10 @@ #include "i18n.h" #ifdef HAVE_W32_SYSTEM -#include "../jnlib/w32-afunix.h" #define sleep _sleep +#define FD2INT(h) ((unsigned int) (h)) +#else +#define FD2INT(h) (h) #endif enum cmd_and_opt_values @@ -205,15 +207,24 @@ /* For the cleanup handler we need to keep track of the socket's name. */ static const char *socket_name; + +/* We need to keep track of the server's nonces (these are dummies for + POSIX systems). */ +static assuan_sock_nonce_t socket_nonce; + /* Only if this flag has been set we will remove the socket file. */ static int cleanup_socket; + /* Keep track of the current log file so that we can avoid updating the log file after a SIGHUP if it didn't changed. Malloced. */ static char *current_logfile; + /* Helper to implement --debug-level. */ static const char *debug_level; + /* Flag indicating that a shutdown has been requested. */ static volatile int shutdown_pending; + /* Counter for the active connections. */ static int active_connections; @@ -232,7 +243,7 @@ static ldap_server_t parse_ldapserver_file (const char* filename); static void free_ldapservers_list (ldap_server_t servers); static fingerprint_list_t parse_ocsp_signer (const char *string); -static void handle_connections (int listen_fd); +static void handle_connections (assuan_fd_t listen_fd); /* Pth wrapper function definitions. */ GCRY_THREAD_OPTION_PTH_IMPL; @@ -883,12 +894,12 @@ launch_reaper_thread (); cert_cache_init (); crl_cache_init (); - start_command_handler (-1); + start_command_handler (ASSUAN_INVALID_FD); shutdown_reaper (); } else if (cmd == aDaemon) { - int fd; + assuan_fd_t fd; pid_t pid; int len; struct sockaddr_un serv_addr; @@ -919,14 +930,10 @@ dirmngr_exit (1); } -#ifdef HAVE_W32_SYSTEM - fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0); -#else - fd = socket (AF_UNIX, SOCK_STREAM, 0); -#endif - if (fd == -1) + fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0); + if (fd == ASSUAN_INVALID_FD) { - log_error (_("can't create socket: %s\n"), strerror(errno) ); + log_error (_("can't create socket: %s\n"), strerror (errno)); cleanup (); dirmngr_exit (1); } @@ -935,36 +942,30 @@ serv_addr.sun_family = AF_UNIX; strcpy (serv_addr.sun_path, socket_name); len = (offsetof (struct sockaddr_un, sun_path) - + strlen(serv_addr.sun_path) + 1); + + strlen (serv_addr.sun_path) + 1); -#ifdef HAVE_W32_SYSTEM - rc = _w32_sock_bind (fd, (struct sockaddr*) &serv_addr, len); - if (rc == -1 && errno == WSAEADDRINUSE) + rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); + if (rc == -1 && errno == EADDRINUSE) { remove (socket_name); - rc = _w32_sock_bind (fd, (struct sockaddr*) &serv_addr, len); + rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); } -#else - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - if (rc == -1 && errno == EADDRINUSE) - { - remove (socket_name); - rc = bind (fd, (struct sockaddr*)&serv_addr, len); - } -#endif + if (rc != -1 + && (rc = assuan_sock_get_nonce ((struct sockaddr*) &serv_addr, len, &socket_nonce))) + log_error (_("error getting nonce for the socket\n")); if (rc == -1) { log_error (_("error binding socket to `%s': %s\n"), - serv_addr.sun_path, strerror (errno) ); - close (fd); + serv_addr.sun_path, gpg_strerror (gpg_error_from_errno (errno))); + assuan_sock_close (fd); dirmngr_exit (1); } cleanup_socket = 1; - if (listen (fd, 5 ) == -1) + if (listen (FD2INT (fd), 5) == -1) { log_error (_("listen() failed: %s\n"), strerror (errno)); - close (fd); + assuan_sock_close (fd); dirmngr_exit (1); } @@ -1064,7 +1065,7 @@ } #endif handle_connections (fd); - close (fd); + assuan_sock_close (fd); shutdown_reaper (); #ifdef HAVE_W32_SYSTEM if (opt.system_service) @@ -1694,20 +1695,40 @@ } +/* Check the nonce on a new connection. This is a NOP unless we we + are using our Unix domain socket emulation under Windows. */ +static int +check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) +{ + if (assuan_sock_check_nonce (fd, nonce)) + { + log_info (_("error reading nonce on fd %d: %s\n"), + FD2INT (fd), strerror (errno)); + assuan_sock_close (fd); + return -1; + } + else + return 0; +} + + /* Helper to call a connection's main fucntion. */ static void * start_connection_thread (void *arg) { - int fd = (int)arg; + assuan_fd_t fd = (assuan_fd_t) arg; + if (check_nonce (fd, &socket_nonce)) + return NULL; + active_connections++; if (opt.verbose) - log_info (_("handler for fd %d started\n"), fd); + log_info (_("handler for fd %d started\n"), FD2INT (fd)); start_command_handler (fd); if (opt.verbose) - log_info (_("handler for fd %d terminated\n"), fd); + log_info (_("handler for fd %d terminated\n"), FD2INT (fd)); active_connections--; return NULL; @@ -1716,7 +1737,7 @@ /* Main loop in daemon mode. */ static void -handle_connections (int listen_fd) +handle_connections (assuan_fd_t listen_fd) { pth_attr_t tattr; pth_event_t ev, time_ev; @@ -1724,7 +1745,7 @@ int signo; struct sockaddr_un paddr; socklen_t plen = sizeof( paddr ); - int fd; + assuan_fd_t fd; tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); @@ -1767,11 +1788,11 @@ if (time_ev) pth_event_concat (ev, time_ev, NULL); - fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev); + fd = (assuan_fd_t) pth_accept_ev (FD2INT (listen_fd), (struct sockaddr *)&paddr, &plen, ev); if (time_ev) pth_event_isolate (time_ev); - if (fd == -1) + if (fd == ASSUAN_INVALID_FD) { if (pth_event_occurred (ev) || (time_ev && pth_event_occurred (time_ev)) ) @@ -1814,7 +1835,7 @@ { log_error (_("error spawning connection handler: %s\n"), strerror (errno) ); - close (fd); + assuan_sock_close (fd); } /* Restore the signal mask. */ Modified: trunk/src/dirmngr.h =================================================================== --- trunk/src/dirmngr.h 2007-09-14 11:41:34 UTC (rev 269) +++ trunk/src/dirmngr.h 2007-10-05 17:30:33 UTC (rev 270) @@ -27,6 +27,7 @@ #include /* we need this for the memory function protos */ #include #include +#include /* to pass hash functions to libksba we need to cast it */ #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) @@ -172,7 +173,7 @@ ksba_cert_t get_issuing_cert_local (ctrl_t ctrl, const char *issuer); ksba_cert_t get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid); -void start_command_handler (int fd); +void start_command_handler (assuan_fd_t fd); gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...); gpg_error_t dirmngr_tick (ctrl_t ctrl); Modified: trunk/src/server.c =================================================================== --- trunk/src/server.c 2007-09-14 11:41:34 UTC (rev 269) +++ trunk/src/server.c 2007-10-05 17:30:33 UTC (rev 270) @@ -1039,7 +1039,7 @@ /* Startup the server and run the main command loop. With FD = -1 used stdin/stdout. */ void -start_command_handler (int fd) +start_command_handler (assuan_fd_t fd) { static const char hello[] = "Dirmngr " VERSION " at your service"; static char *hello_line; @@ -1060,7 +1060,7 @@ dirmngr_init_default_ctrl (ctrl); - if (fd == -1) + if (fd == ASSUAN_INVALID_FD) { int filedes[2]; From cvs at cvs.gnupg.org Fri Oct 5 19:48:21 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Fri, 05 Oct 2007 19:48:21 +0200 Subject: [svn] GpgEX - r28 - trunk/src Message-ID: Author: marcus Date: 2007-10-05 19:48:11 +0200 (Fri, 05 Oct 2007) New Revision: 28 Modified: trunk/src/ChangeLog trunk/src/main.cc Log: 2007-10-05 Marcus Brinkmann * main.cc (DllMain): Call WSACleanup. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 15:03:44 UTC (rev 27) +++ trunk/src/ChangeLog 2007-10-05 17:48:11 UTC (rev 28) @@ -1,5 +1,7 @@ 2007-10-05 Marcus Brinkmann + * main.cc (DllMain): Call WSACleanup. + * main.cc (DllMain): Initialize winsock. * client.cc (percent_escape): Also escape ':' again. Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-10-05 15:03:44 UTC (rev 27) +++ trunk/src/main.cc 2007-10-05 17:48:11 UTC (rev 28) @@ -216,6 +216,8 @@ } else if (reason == DLL_PROCESS_DETACH) { + WSACleanup (); + (void) TRACE0 (DEBUG_INIT, "DllMain", hinst, "reason=DLL_PROCESS_DETACH"); From cvs at cvs.gnupg.org Mon Oct 8 12:25:56 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 08 Oct 2007 12:25:56 +0200 Subject: [svn] dirmngr - r271 - trunk Message-ID: Author: wk Date: 2007-10-08 12:25:48 +0200 (Mon, 08 Oct 2007) New Revision: 271 Modified: trunk/ChangeLog trunk/configure.ac Log: Require libassuan 1.0.4 Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-05 17:30:33 UTC (rev 270) +++ trunk/ChangeLog 2007-10-08 10:25:48 UTC (rev 271) @@ -1,3 +1,7 @@ +2007-10-08 Werner Koch + + * configure.ac: Require libassuan 1.0.4. + 2007-09-04 Werner Koch * configure.ac: Add test for locale.h. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-10-05 17:30:33 UTC (rev 270) +++ trunk/configure.ac 2007-10-08 10:25:48 UTC (rev 271) @@ -40,7 +40,7 @@ NEED_LIBGCRYPT_VERSION=1.2.0 NEED_LIBASSUAN_API=1 -NEED_LIBASSUAN_VERSION=0.9.3 +NEED_LIBASSUAN_VERSION=1.0.4 NEED_KSBA_API=1 NEED_KSBA_VERSION=1.0.0 From cvs at cvs.gnupg.org Mon Oct 8 18:42:11 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 08 Oct 2007 18:42:11 +0200 Subject: [svn] GpgEX - r30 - in trunk: . po Message-ID: Author: marcus Date: 2007-10-08 18:42:03 +0200 (Mon, 08 Oct 2007) New Revision: 30 Modified: trunk/ChangeLog trunk/po/de.po Log: 2007-10-08 Marcus Brinkmann * po/de.po: Convert to UTF-8. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-08 16:39:03 UTC (rev 29) +++ trunk/ChangeLog 2007-10-08 16:42:03 UTC (rev 30) @@ -1,5 +1,7 @@ 2007-10-08 Marcus Brinkmann + * po/de.po: Convert to UTF-8. + * autogen.sh: Add --add-missing to automake invocation. * configure.ac (AC_CONFIG_FILES): Add doc/Makefile. * Makefile.am (SUBDIRS): Add doc. Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-10-08 16:39:03 UTC (rev 29) +++ trunk/po/de.po 2007-10-08 16:42:03 UTC (rev 30) @@ -8,17 +8,17 @@ "Project-Id-Version: gpgex 0.0.0-svn10\n" "Report-Msgid-Bugs-To: bug-gpgex at g10code.com\n" "POT-Creation-Date: 2007-10-05 02:37+0200\n" -"PO-Revision-Date: 2007-10-05 16:34+0200\n" +"PO-Revision-Date: 2007-10-08 18:34+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-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/client.cc:194 msgid "Can not access Kleopatra, see log file for details" -msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei f?r Details" +msgstr "Kann nicht auf Kleopatra zugreifen, siehe Protokolldatei f??r Details" #: src/gpgex.cc:57 msgid "Help on GpgEX" @@ -26,11 +26,11 @@ #: src/gpgex.cc:58 msgid "Decrypt and verify" -msgstr "Entschl?sseln und verifizieren" +msgstr "Entschl??sseln und verifizieren" #: src/gpgex.cc:59 msgid "Decrypt" -msgstr "Entschl?sseln" +msgstr "Entschl??sseln" #: src/gpgex.cc:60 msgid "Verify" @@ -38,11 +38,11 @@ #: src/gpgex.cc:61 msgid "Encrypt and sign" -msgstr "Verschl?sseln und signieren" +msgstr "Verschl??sseln und signieren" #: src/gpgex.cc:62 msgid "Encrypt" -msgstr "Verschl?sseln" +msgstr "Verschl??sseln" #: src/gpgex.cc:63 msgid "Sign" @@ -54,11 +54,11 @@ #: src/gpgex.cc:65 msgid "Create checksums" -msgstr "Pr?fsummen erstellen" +msgstr "Pr??fsummen erstellen" #: src/gpgex.cc:66 msgid "Verify checksums" -msgstr "Pr?fsummen verifizieren" +msgstr "Pr??fsummen verifizieren" #: src/gpgex.cc:306 msgid "More GpgEX options" @@ -66,16 +66,16 @@ #: src/gpgex.cc:402 msgid "Invoke the GpgEX documentation." -msgstr "?ffne die Dokumentation zu GpgEX" +msgstr "??ffne die Dokumentation zu GpgEX" #: src/gpgex.cc:406 #, fuzzy msgid "Decrypt and verify the marked files." -msgstr "Die markierten Dateien entschl?sseln und verifizieren." +msgstr "Die markierten Dateien entschl??sseln und verifizieren." #: src/gpgex.cc:410 msgid "Decrypt the marked files." -msgstr "Die markierten Dateien entschl?sseln." +msgstr "Die markierten Dateien entschl??sseln." #: src/gpgex.cc:414 msgid "Verify the marked files." @@ -84,11 +84,11 @@ #: src/gpgex.cc:418 #, fuzzy msgid "Encrypt and sign the marked files." -msgstr "Die markierten Dateien verschl?sseln und verifizieren." +msgstr "Die markierten Dateien verschl??sseln und verifizieren." #: src/gpgex.cc:422 msgid "Encrypt the marked files." -msgstr "Die markierten Dateien verschl?sseln." +msgstr "Die markierten Dateien verschl??sseln." #: src/gpgex.cc:426 msgid "Sign the marked files." @@ -100,11 +100,11 @@ #: src/gpgex.cc:434 msgid "Create checksums." -msgstr "F?r die markierten Dateien Pr?fsummen erstellen." +msgstr "F??r die markierten Dateien Pr??fsummen erstellen." #: src/gpgex.cc:438 msgid "Verify checksums." -msgstr "Die Pr?fsummen der markierten Dateien verifizieren." +msgstr "Die Pr??fsummen der markierten Dateien verifizieren." #: src/gpgex.cc:442 #, fuzzy From cvs at cvs.gnupg.org Mon Oct 8 18:49:00 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 08 Oct 2007 18:49:00 +0200 Subject: [svn] GpgEX - r31 - in trunk: . doc Message-ID: Author: marcus Date: 2007-10-08 18:48:52 +0200 (Mon, 08 Oct 2007) New Revision: 31 Modified: trunk/ChangeLog trunk/doc/gpgex.texi Log: 2007-10-08 Marcus Brinkmann * doc/gpgex.texi (Certificate management): New section Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-08 16:42:03 UTC (rev 30) +++ trunk/ChangeLog 2007-10-08 16:48:52 UTC (rev 31) @@ -1,5 +1,7 @@ 2007-10-08 Marcus Brinkmann + * doc/gpgex.texi (Certificate management): New section + * po/de.po: Convert to UTF-8. * autogen.sh: Add --add-missing to automake invocation. Modified: trunk/doc/gpgex.texi =================================================================== --- trunk/doc/gpgex.texi 2007-10-08 16:42:03 UTC (rev 30) +++ trunk/doc/gpgex.texi 2007-10-08 16:48:52 UTC (rev 31) @@ -123,6 +123,7 @@ * Specifying input files:: Specifying the input files to operate on. * Encrypt and sign files:: Encrypting and signing files. * Decrypt and verify files:: Decrypting and verifying files. +* Certificate management:: Managing certificates. * Checksum files:: Create and verify checksums for files. * Miscellaneous commands:: Support functions. @end menu @@ -213,6 +214,29 @@ @end deffn + at node Certificate management + at section Managing certificates. + +First, the input files need to be specified by one or more + at code{INPUT} commands. Afterwards, the actual operation is requested: + + at deffn Command IMPORT --nohup +Request that the certificates contained in the files specified by + at code{INPUT} are imported into the local certificate databases. + +For directories, the server may offer multiple options to the user +(for example ignore or process recursively). + +The option @code{--nohup} is mandatory. It is currently unspecified +what should happen if @code{--nohup} is not present. Because + at code{--nohup} is present, the server always returns @code{OK} +promptly, and completes the operation asynchronously. + at end deffn + +FIXME: It may be nice to support an @code{EXPORT} command as well, +which is enabled by the context menu of the background of a directory. + + @node Checksum files @section Create and verify checksums for files. From cvs at cvs.gnupg.org Mon Oct 8 20:03:48 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 08 Oct 2007 20:03:48 +0200 Subject: [svn] assuan - r275 - in trunk: . src Message-ID: Author: wk Date: 2007-10-08 20:03:38 +0200 (Mon, 08 Oct 2007) New Revision: 275 Modified: trunk/NEWS trunk/src/ChangeLog trunk/src/assuan-defs.h trunk/src/assuan-io-pth.c trunk/src/assuan-io.c trunk/src/assuan-util.c trunk/src/assuan.h Log: Add assuan_set_io_hooks. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/NEWS 2007-10-08 18:03:38 UTC (rev 275) @@ -1,10 +1,12 @@ Noteworthy changes in version 1.0.4 ------------------------------------------------ - * New socket wrapper fucntions to support Unix domain sockets under + * New socket wrapper functions to support Unix domain sockets under Windows. + * New hook feature to enhance the internal I/O functions. + Noteworthy changes in version 1.0.3 (2007-08-24) ------------------------------------------------ Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/ChangeLog 2007-10-08 18:03:38 UTC (rev 275) @@ -1,3 +1,16 @@ +2007-10-08 Werner Koch + + * assuan-util.c (assuan_set_io_hooks): New. + * assuan.h (struct assuan_io_hooks): New. + (assuan_set_io_hooks, _assuan_io_hooks): Add prefix macros. + * assuan-defs.h (_assuan_io_hooks): New. + * assuan-io.c (do_io_read): Take all code from _assuan_io_read. + (_assuan_io_read, _assuan_simple_read): Add hook feature. + (do_io_write): Take all code from _assuan_io_write. + (_assuan_io_write, _assuan_simple_write): Add hook feature. + * assuan-io-pth.c (_assuan_simple_read, _assuan_simple_write) + (_assuan_io_read, _assuan_io_write): Add hook feature. + 2007-10-05 Marcus Brinkmann * assuan.h (_assuan_error_is_eagain): Add prefix macro. Modified: trunk/src/assuan-defs.h =================================================================== --- trunk/src/assuan-defs.h 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/assuan-defs.h 2007-10-08 18:03:38 UTC (rev 275) @@ -75,6 +75,10 @@ }; +/* The global variable with the optional hook fucntions. */ +extern struct assuan_io_hooks _assuan_io_hooks; + + /* The context we use with most functions. */ struct assuan_context_s { Modified: trunk/src/assuan-io-pth.c =================================================================== --- trunk/src/assuan-io-pth.c 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/assuan-io-pth.c 2007-10-08 18:03:38 UTC (rev 275) @@ -1,5 +1,5 @@ /* assuan-io-pth.c - Pth version of assua-io.c. - * Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -56,24 +56,47 @@ { /* Fixme: For W32 we should better not cast the HANDLE type to int. However, this requires changes in w32pth too. */ + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd, + buffer, size, &retval) == 1) + return retval; + return _assuan_io_read (ctx->inbound.fd, buffer, size); } ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) { + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd, + buffer, size, &retval) == 1) + return retval; return _assuan_io_write (ctx->outbound.fd, buffer, size); } ssize_t _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) { + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; return pth_read ((int)fd, buffer, size); } ssize_t _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) { + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; return pth_write ((int)fd, buffer, size); } Modified: trunk/src/assuan-io.c =================================================================== --- trunk/src/assuan-io.c 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/assuan-io.c 2007-10-08 18:03:38 UTC (rev 275) @@ -1,5 +1,5 @@ /* assuan-io.c - Wraps the read and write functions. - * Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. + * Copyright (C) 2002, 2004, 2006, 2007 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -46,8 +46,8 @@ #endif -ssize_t -_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) +static ssize_t +do_io_read (assuan_fd_t fd, void *buffer, size_t size) { #ifdef HAVE_W32_SYSTEM /* Due to the peculiarities of the W32 API we can't use read for a @@ -92,14 +92,34 @@ ssize_t +_assuan_io_read (assuan_fd_t fd, void *buffer, size_t size) +{ + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; + + return do_io_read (fd, buffer, size); +} + +ssize_t _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size) { - return _assuan_io_read (ctx->inbound.fd, buffer, size); + ssize_t retval; + + if (_assuan_io_hooks.read_hook + && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd, + buffer, size, &retval) == 1) + return retval; + + return do_io_read (ctx->inbound.fd, buffer, size); } -ssize_t -_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) + +static ssize_t +do_io_write (assuan_fd_t fd, const void *buffer, size_t size) { #ifdef HAVE_W32_SYSTEM /* Due to the peculiarities of the W32 API we can't use write for a @@ -132,11 +152,28 @@ #endif /*!HAVE_W32_SYSTEM*/ } +ssize_t +_assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size) +{ + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1) + return retval; + return do_io_write (fd, buffer, size); +} ssize_t _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size) { - return _assuan_io_write (ctx->outbound.fd, buffer, size); + ssize_t retval; + + if (_assuan_io_hooks.write_hook + && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd, + buffer, size, &retval) == 1) + return retval; + + return do_io_write (ctx->outbound.fd, buffer, size); } Modified: trunk/src/assuan-util.c =================================================================== --- trunk/src/assuan-util.c 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/assuan-util.c 2007-10-08 18:03:38 UTC (rev 275) @@ -30,6 +30,10 @@ static void *(*realloc_func)(void *p, size_t n) = realloc; static void (*free_func)(void*) = free; +struct assuan_io_hooks _assuan_io_hooks; + + + void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), void *(*new_realloc_func)(void *p, size_t n), @@ -40,6 +44,20 @@ free_func = new_free_func; } + +void +assuan_set_io_hooks (assuan_io_hooks_t io_hooks) +{ + _assuan_io_hooks.read_hook = NULL; + _assuan_io_hooks.write_hook = NULL; + if (io_hooks) + { + _assuan_io_hooks.read_hook = io_hooks->read_hook; + _assuan_io_hooks.write_hook = io_hooks->write_hook; + } +} + + void * _assuan_malloc (size_t n) { @@ -168,4 +186,3 @@ return 0; } - Modified: trunk/src/assuan.h =================================================================== --- trunk/src/assuan.h 2007-10-05 16:55:51 UTC (rev 274) +++ trunk/src/assuan.h 2007-10-08 18:03:38 UTC (rev 275) @@ -121,6 +121,7 @@ #define assuan_sendfd _ASSUAN_PREFIX(assuan_sendfd) #define assuan_receivefd _ASSUAN_PREFIX(assuan_receivefd) #define assuan_set_malloc_hooks _ASSUAN_PREFIX(assuan_set_malloc_hooks) +#define assuan_set_io_hooks _ASSUAN_PREFIX(assuan_set_io_hooks) #define assuan_set_log_stream _ASSUAN_PREFIX(assuan_set_log_stream) #define assuan_set_error _ASSUAN_PREFIX(assuan_set_error) #define assuan_set_pointer _ASSUAN_PREFIX(assuan_set_pointer) @@ -162,6 +163,7 @@ #define _assuan_simple_write _ASSUAN_PREFIX(_assuan_simple_write) #define _assuan_io_read _ASSUAN_PREFIX(_assuan_io_read) #define _assuan_io_write _ASSUAN_PREFIX(_assuan_io_write) +#define _assuan_io_hooks _ASSUAN_PREFIX(_assuan_io_hooks) #define _assuan_new_context _ASSUAN_PREFIX(_assuan_new_context) #define _assuan_release_context _ASSUAN_PREFIX(_assuan_release_context) #define _assuan_malloc _ASSUAN_PREFIX(_assuan_malloc) @@ -420,6 +422,18 @@ #endif +/* Definition of hook functions used to conditionally replace the + default I/O functions. */ +struct assuan_io_hooks +{ + int (*read_hook)(assuan_context_t, assuan_fd_t, void *, size_t, ssize_t *); + int (*write_hook)(assuan_context_t, assuan_fd_t fd, + const void *, size_t, ssize_t *); +}; +typedef struct assuan_io_hooks *assuan_io_hooks_t; + + + /*-- assuan-handler.c --*/ int assuan_register_command (assuan_context_t ctx, const char *cmd_string, @@ -560,6 +574,7 @@ void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), void *(*new_realloc_func)(void *p, size_t n), void (*new_free_func)(void*) ); +void assuan_set_io_hooks (assuan_io_hooks_t io_hooks); void assuan_set_log_stream (assuan_context_t ctx, FILE *fp); int assuan_set_error (assuan_context_t ctx, int err, const char *text); void assuan_set_pointer (assuan_context_t ctx, void *pointer); From cvs at cvs.gnupg.org Tue Oct 9 23:23:59 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 09 Oct 2007 23:23:59 +0200 Subject: [svn] gpgme - r1274 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-09 23:23:50 +0200 (Tue, 09 Oct 2007) New Revision: 1274 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp Log: 2007-10-09 Marcus Brinkmann * kdpipeiodevice.cpp: New version from Frank Osterfeld and Marc Mutz. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-10-05 00:20:43 UTC (rev 1273) +++ trunk/gpgme/ChangeLog 2007-10-09 21:23:50 UTC (rev 1274) @@ -1,3 +1,8 @@ +2007-10-09 Marcus Brinkmann + + * kdpipeiodevice.cpp: New version from Frank Osterfeld and Marc + Mutz. + 2007-10-05 Marcus Brinkmann * kdpipeiodevice.cpp, w32-qt-io.cpp: New versions from Frank Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-10-05 00:20:43 UTC (rev 1273) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-10-09 21:23:50 UTC (rev 1274) @@ -95,6 +95,7 @@ Qt::HANDLE handle; public: QMutex mutex; + QWaitCondition waitForCancelCondition; QWaitCondition bufferNotFullCondition; QWaitCondition bufferNotEmptyCondition; QWaitCondition hasStarted; @@ -126,8 +127,8 @@ error( false ), eofShortCut( false ), errorCode( 0 ), - rptr( 0 ), wptr( 0 ), - consumerBlocksOnUs( false ) + consumerBlocksOnUs( false ), + rptr( 0 ), wptr( 0 ) { } @@ -207,8 +208,6 @@ bool startReaderThread(); bool startWriterThread(); void stopThreads(); - bool triedToStartReader; - bool triedToStartWriter; public Q_SLOTS: void emitReadyRead(); @@ -218,6 +217,8 @@ Qt::HANDLE handle; Reader * reader; Writer * writer; + bool triedToStartReader; + bool triedToStartWriter; }; KDPipeIODevice::Private::Private( KDPipeIODevice * qq ) @@ -521,9 +522,9 @@ if ( bytesAvailable() > 0 ) maxSize = std::min( maxSize, bytesAvailable() ); // don't block } - qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)" ); + qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)", this ); LOCKED( r ); - qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)" ); + qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)", this ); r->readyReadSentCondition.wakeAll(); if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0? @@ -626,6 +627,7 @@ // tell thread to cancel: r->cancel = true; // and wake it, so it can terminate: + r->waitForCancelCondition.wakeAll(); r->bufferNotFullCondition.wakeAll(); r->readyReadSentCondition.wakeAll(); } @@ -653,7 +655,7 @@ qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer ); waitAndDelete( d->writer ); qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader ); - { + if ( d->reader ) { LOCKED( d->reader ); d->reader->readyReadSentCondition.wakeAll(); } @@ -682,15 +684,20 @@ while ( true ) { if ( !cancel && ( eof || error ) ) { + //notify the client until the buffer is empty and then once + //again so he receives eof/error. After that, wait for him + //to cancel + const bool wasEmpty = bufferEmpty(); qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error ); notifyReadyRead(); - cancel = true; + if ( !cancel && wasEmpty ) + waitForCancelCondition.wait( &mutex ); } else if ( !cancel && !bufferFull() && !bufferEmpty() ) { qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this ); notifyReadyRead(); } - while ( !error && !cancel && bufferFull() ) { + while ( !cancel && !error && bufferFull() ) { notifyReadyRead(); if ( bufferFull() ) { qDebug( "%p: Reader::run: buffer is full, going to sleep", this ); @@ -836,8 +843,7 @@ goto leave; } #endif - qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, -buffer ); + qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%u): %s:", this, fd, numBytesInBuffer, buffer ); totalWritten += numWritten; mutex.lock(); } while ( totalWritten < numBytesInBuffer ); From cvs at cvs.gnupg.org Wed Oct 10 15:23:52 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 10 Oct 2007 15:23:52 +0200 Subject: [svn] GpgOL - r188 - in trunk: . doc m4 po src Message-ID: Author: wk Date: 2007-10-10 15:23:41 +0200 (Wed, 10 Oct 2007) New Revision: 188 Added: trunk/m4/libassuan.m4 Modified: trunk/ChangeLog trunk/autogen.sh trunk/doc/gpgol.texi trunk/po/de.po trunk/po/sv.po trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/common.c trunk/src/common.h trunk/src/engine-assuan.c trunk/src/engine-assuan.h trunk/src/engine-gpgme.c trunk/src/engine.c trunk/src/ext-commands.cpp trunk/src/main.c trunk/src/util.h Log: First encryption using the new Assuan based engine and GPA succeeded. The asyncronous I/O framework is basically working now. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/ChangeLog 2007-10-10 13:23:41 UTC (rev 188) @@ -1,3 +1,14 @@ +2007-10-05 Werner Koch + + * doc/ New. + * doc/Makefile.am: New. + * doc/gpgol.texi: New. + * doc/gpl.texi: New. + +2007-09-25 Werner Koch + + * configure.ac: Check for libassuan. + 2007-09-17 Werner Koch * autogen.sh (FORCE): Add --force option. Modified: trunk/autogen.sh =================================================================== --- trunk/autogen.sh 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/autogen.sh 2007-10-10 13:23:41 UTC (rev 188) @@ -91,7 +91,8 @@ ./configure --enable-maintainer-mode --prefix=${w32root} \ --host=i586-mingw32msvc --build=${build} \ --with-gpg-error-prefix=${w32root} \ - --with-gpgme-prefix=${w32root} + --with-gpgme-prefix=${w32root} \ + --with-libassuan-prefix=${w32root} rc=$? exit $rc Modified: trunk/doc/gpgol.texi =================================================================== --- trunk/doc/gpgol.texi 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/doc/gpgol.texi 2007-10-10 13:23:41 UTC (rev 188) @@ -122,7 +122,7 @@ Assuan manual for details. @menu -* ENCRYPT:: Encrypting a message. +* ENCRYPT:: Encrypt a message. * SIGN:: Sign a message. * DECRYPT:: Decrypt a message. * VERIFY:: Verify a message. @@ -132,7 +132,7 @@ @node ENCRYPT - at section Encrypting a Message + at section Encrypt a Message Before encryption can be done the recipients must be set using the command: @@ -248,11 +248,13 @@ @noindent The signing operation is then initiated by: - at deffn Command SIGN [- at w{}-detached] + at deffn Command SIGN - at w{}-protocol=@var{name} [- at w{}-detached] Sign the data set with the @code{INPUT} command and write it to the sink -set by OUTPUT. With option @code{--detached} given, a detached +set by OUTPUT. @var{name} is the signing protocol used for the +message. For a description of the allowed protocols see the + at code{ENCRYPT} command. With option @code{--detached} given, a detached signature is created; this is actually the usual way the command is -used. +used. @end deffn @noindent @@ -443,7 +445,44 @@ @bye + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at c + at c E D I T O R ' S A T T I C + at c + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +What about the message class mangling? + +* On receiving a new message GpgOL checks the MAPI message class + property of the message and if this is an S/MIME message class + ("IPM.Note.SMIME"), it is changed to a GpgOL specific one + ("IPM.Note.GpgOL"). This change is required so that OL does not not + apply its own S/MIME handler to the message but leaves it unchanged in + the message store. + +* For ease of implementarion the same thing applies to PGP messgaes, + although OL would not touch these messages. + +* When reading a message GpgOL quickly checks the message class and if + it is "IPM.Note.GpgOL" it will hook itself into the code path and + decrypt/verify the message. + +* Messages already in the message store before GpgOL was installed are + handled diffwerently: Here an Outlook specific event is used to change + the message class when browsing the messages folder. This code path + is not fully ready as it requires the installation of an ECF(ile) + which has to be done manually as of now. + +* If GpgOL is deinstalled, the existing S/MIME messages can't be + decrypted or verified by Outlook's internal S/MIME support. + Multipart/signed messages are still readable, though. We plan to add + a little tool for changing the GpgOL message classes back to + "IPM.Note.SMIME" which in turn allows using internal S/MIME support + again. + + + + @c Local Variables: @c coding: latin-1 @c End: Added: trunk/m4/libassuan.m4 =================================================================== --- trunk/m4/libassuan.m4 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/m4/libassuan.m4 2007-10-10 13:23:41 UTC (rev 188) @@ -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 ($libassuan_version)]) + 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/de.po =================================================================== --- trunk/po/de.po 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/po/de.po 2007-10-10 13:23:41 UTC (rev 188) @@ -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-11 20:30+0200\n" +"POT-Creation-Date: 2007-09-25 12:20+0200\n" "PO-Revision-Date: 2007-04-13 12:55+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" @@ -23,62 +23,79 @@ msgid "Select GPG Key Manager" msgstr "Das Schl?sselverwaltungsprogramm festlegen" -#: src/engine-gpgme.c:1099 +#: src/engine-gpgme.c:356 src/gpgmsg.cpp:1812 +msgid "" +"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 "" +"Der voreingestellte zus?tzliche Schl?ssel zum Verschl?sseln ist nicht\n" +"vorhanden oder nicht eindeutig. Bitte beheben Sie dies in den\n" +"Optionseinstellungen.\n" +"\n" +"Die Nachricht wird deswegen nicht f?r diesen Schl?ssel verschl?sselt!" + +#: src/engine-gpgme.c:360 src/gpgmsg.cpp:1816 +msgid "Encryption" +msgstr "Verschl?sselung" + +#: src/engine-gpgme.c:766 msgid "Fingerprint: " msgstr "Fingerabdruck: " -#: src/engine-gpgme.c:1156 +#: src/engine-gpgme.c:823 msgid "This signature is valid\n" msgstr "Diese Unterschrift ist korrekt\n" -#: src/engine-gpgme.c:1158 +#: src/engine-gpgme.c:825 msgid "signature state is \"green\"\n" msgstr "Status der Unterschrift ist \"gr?n\"\n" -#: src/engine-gpgme.c:1160 +#: src/engine-gpgme.c:827 msgid "signature state is \"red\"\n" msgstr "Status der Unterschrift ist \"rot\"\n" -#: src/engine-gpgme.c:1164 +#: src/engine-gpgme.c:831 msgid "Warning: One of the keys has been revoked\n" msgstr "Warnung: Einer der Schl?ssel wurde widerrufen\n" -#: src/engine-gpgme.c:1174 +#: src/engine-gpgme.c:841 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:1180 +#: src/engine-gpgme.c:847 msgid "Warning: At least one certification key has expired\n" msgstr "" "Warnung: Mindestens einer der Zertifizierungsschl?ssel ist abgelaufen\n" -#: src/engine-gpgme.c:1186 +#: src/engine-gpgme.c:853 msgid "Warning: The signature expired at: " msgstr "Die Unterschrift verfiel am: " -#: src/engine-gpgme.c:1192 +#: src/engine-gpgme.c:859 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:1196 +#: src/engine-gpgme.c:863 msgid "The CRL is not available\n" msgstr "Die CRL ist nicht verf?gbar\n" -#: src/engine-gpgme.c:1202 +#: src/engine-gpgme.c:869 msgid "Available CRL is too old\n" msgstr "Die vorhandene CRL ist zu alt\n" -#: src/engine-gpgme.c:1207 +#: src/engine-gpgme.c:874 msgid "A policy requirement was not met\n" msgstr "Eine Richtlinie wurde nicht erf?llt\n" -#: src/engine-gpgme.c:1213 +#: src/engine-gpgme.c:880 msgid "A system error occured" msgstr "Ein Systemfehler ist aufgetreten" -#: src/engine-gpgme.c:1250 +#: src/engine-gpgme.c:917 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -86,12 +103,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:1257 +#: src/engine-gpgme.c:924 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:1261 +#: src/engine-gpgme.c:928 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -99,43 +116,43 @@ "WARNING: Es ist nicht sicher, da? der Schl?ssel der Person geh?rt, die oben " "angezeigt ist\n" -#: src/engine-gpgme.c:1294 +#: src/engine-gpgme.c:961 msgid "Verification started at: " msgstr "?berpr?fung begann am: " -#: src/engine-gpgme.c:1299 +#: src/engine-gpgme.c:966 msgid "Verification result for: " msgstr "Pr?fungsresultat f?r: " -#: src/engine-gpgme.c:1300 +#: src/engine-gpgme.c:967 msgid "[unnamed part]" msgstr "[Unbenannter Teil]" -#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348 +#: src/engine-gpgme.c:985 src/engine-gpgme.c:1015 msgid "Good signature from: " msgstr "Korrekte Unterschrift von: " -#: src/engine-gpgme.c:1325 +#: src/engine-gpgme.c:992 msgid " aka: " msgstr " alias: " -#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351 +#: src/engine-gpgme.c:996 src/engine-gpgme.c:1018 msgid " created: " msgstr " erzeugt: " -#: src/engine-gpgme.c:1338 +#: src/engine-gpgme.c:1005 msgid "*BAD* signature claimed to be from: " msgstr "*FALSCHE* Unterschrift, vorgeblich von: " -#: src/engine-gpgme.c:1361 +#: src/engine-gpgme.c:1028 msgid "Error checking signature" msgstr "Fehler beim Pr?fen der Unterschrift" -#: src/engine-gpgme.c:1377 +#: src/engine-gpgme.c:1044 msgid "*** Begin Notation (signature by: " msgstr "*** Anfang Notation (Unterschrift von: " -#: src/engine-gpgme.c:1397 +#: src/engine-gpgme.c:1064 msgid "*** End Notation ***\n" msgstr "*** Ende Notation ***\n" @@ -246,23 +263,6 @@ msgid "Signing Failure" msgstr "Unterschrifterstellungsfehler" -#: src/gpgmsg.cpp:1812 -msgid "" -"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 "" -"Der voreingestellte zus?tzliche Schl?ssel zum Verschl?sseln ist nicht\n" -"vorhanden oder nicht eindeutig. Bitte beheben Sie dies in den\n" -"Optionseinstellungen.\n" -"\n" -"Die Nachricht wird deswegen nicht f?r diesen Schl?ssel verschl?sselt!" - -#: src/gpgmsg.cpp:1816 -msgid "Encryption" -msgstr "Verschl?sselung" - #: src/gpgmsg.cpp:1859 msgid "Encryption Failure" msgstr "Verschl?sselungsfehler" @@ -287,7 +287,7 @@ msgid "The default key may not contain any spaces." msgstr "Der Standardschl?ssel darf keine Leerzeichen enthalten." -#: src/olflange.cpp:475 +#: src/olflange.cpp:485 msgid "" "This version of Outlook is too old!\n" "\n" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/po/sv.po 2007-10-10 13:23:41 UTC (rev 188) @@ -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-11 20:30+0200\n" +"POT-Creation-Date: 2007-09-25 12:20+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -23,59 +23,75 @@ msgid "Select GPG Key Manager" msgstr "V?lj GPG-nyckelhanterare" -#: src/engine-gpgme.c:1099 +#: src/engine-gpgme.c:356 src/gpgmsg.cpp:1812 +msgid "" +"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" +"\n" +"Det h?r meddelandet kommer inte att krypteras med den h?r nyckeln!" + +#: src/engine-gpgme.c:360 src/gpgmsg.cpp:1816 +msgid "Encryption" +msgstr "Kryptering" + +#: src/engine-gpgme.c:766 msgid "Fingerprint: " msgstr "Fingeravtryck: " -#: src/engine-gpgme.c:1156 +#: src/engine-gpgme.c:823 msgid "This signature is valid\n" msgstr "Den h?r signaturen ?r giltig\n" -#: src/engine-gpgme.c:1158 +#: src/engine-gpgme.c:825 msgid "signature state is \"green\"\n" msgstr "signaturens tillst?nd ?r \"gr?n\"\n" -#: src/engine-gpgme.c:1160 +#: src/engine-gpgme.c:827 msgid "signature state is \"red\"\n" msgstr "signaturens tillst?nd ?r \"r?d\"\n" -#: src/engine-gpgme.c:1164 +#: src/engine-gpgme.c:831 msgid "Warning: One of the keys has been revoked\n" msgstr "Varning: En av nycklarna har sp?rrats\n" -#: src/engine-gpgme.c:1174 +#: src/engine-gpgme.c:841 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:1180 +#: src/engine-gpgme.c:847 msgid "Warning: At least one certification key has expired\n" msgstr "Varning: ?tminstone en certifieringsnyckel har g?tt ut\n" -#: src/engine-gpgme.c:1186 +#: src/engine-gpgme.c:853 msgid "Warning: The signature expired at: " msgstr "Varning: Signaturen gick ut den: " -#: src/engine-gpgme.c:1192 +#: src/engine-gpgme.c:859 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:1196 +#: src/engine-gpgme.c:863 msgid "The CRL is not available\n" msgstr "Sp?rrlistan ?r inte tillg?nglig\n" -#: src/engine-gpgme.c:1202 +#: src/engine-gpgme.c:869 msgid "Available CRL is too old\n" msgstr "Tillg?nglig sp?rrlista ?r f?r gammal\n" -#: src/engine-gpgme.c:1207 +#: src/engine-gpgme.c:874 msgid "A policy requirement was not met\n" msgstr "Ett policykrav matchades inte\n" -#: src/engine-gpgme.c:1213 +#: src/engine-gpgme.c:880 msgid "A system error occured" msgstr "Ett systemfel intr?ffade" -#: src/engine-gpgme.c:1250 +#: src/engine-gpgme.c:917 msgid "" "WARNING: We have NO indication whether the key belongs to the person named " "as shown above\n" @@ -83,11 +99,11 @@ "VARNING: Vi har INGA indikationer p? huruvida nyckeln tillh?r personen vars " "namn visas ovanf?r\n" -#: src/engine-gpgme.c:1257 +#: src/engine-gpgme.c:924 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:1261 +#: src/engine-gpgme.c:928 msgid "" "WARNING: It is NOT certain that the key belongs to the person named as shown " "above\n" @@ -95,43 +111,43 @@ "VARNING: Det ?r INTE s?kert att nyckeln tillh?r den person vars namn visas " "ovanf?r\n" -#: src/engine-gpgme.c:1294 +#: src/engine-gpgme.c:961 msgid "Verification started at: " msgstr "Validering startad: " -#: src/engine-gpgme.c:1299 +#: src/engine-gpgme.c:966 msgid "Verification result for: " msgstr "Valideringsresultat f?r: " -#: src/engine-gpgme.c:1300 +#: src/engine-gpgme.c:967 msgid "[unnamed part]" msgstr "[ej namngiven del]" -#: src/engine-gpgme.c:1318 src/engine-gpgme.c:1348 +#: src/engine-gpgme.c:985 src/engine-gpgme.c:1015 msgid "Good signature from: " msgstr "Korrekt signatur fr?n: " -#: src/engine-gpgme.c:1325 +#: src/engine-gpgme.c:992 msgid " aka: " msgstr "?ven k?nd som:" -#: src/engine-gpgme.c:1329 src/engine-gpgme.c:1351 +#: src/engine-gpgme.c:996 src/engine-gpgme.c:1018 msgid " created: " msgstr " skapad: " -#: src/engine-gpgme.c:1338 +#: src/engine-gpgme.c:1005 msgid "*BAD* signature claimed to be from: " msgstr "*FELAKTIG* signatur h?vdades komma fr?n: " -#: src/engine-gpgme.c:1361 +#: src/engine-gpgme.c:1028 msgid "Error checking signature" msgstr "Fel vid kontroll av signatur" -#: src/engine-gpgme.c:1377 +#: src/engine-gpgme.c:1044 msgid "*** Begin Notation (signature by: " msgstr "*** Notation start (signatur av: " -#: src/engine-gpgme.c:1397 +#: src/engine-gpgme.c:1064 msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" @@ -241,22 +257,6 @@ msgid "Signing Failure" msgstr "Signering misslyckades" -#: src/gpgmsg.cpp:1812 -msgid "" -"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" -"\n" -"Det h?r meddelandet kommer inte att krypteras med den h?r nyckeln!" - -#: src/gpgmsg.cpp:1816 -msgid "Encryption" -msgstr "Kryptering" - #: src/gpgmsg.cpp:1859 msgid "Encryption Failure" msgstr "Kryptering misslyckades" @@ -281,7 +281,7 @@ msgid "The default key may not contain any spaces." msgstr "Standardnyckeln f?r inte inneh?lla n?gra blanksteg." -#: src/olflange.cpp:475 +#: src/olflange.cpp:485 msgid "" "This version of Outlook is too old!\n" "\n" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/ChangeLog 2007-10-10 13:23:41 UTC (rev 188) @@ -1,3 +1,22 @@ +2007-10-08 Werner Koch + + * main.c (do_log): Remove trailing LF from w32 error message and + also print the numeric error code. + +2007-09-25 Werner Koch + + * Makefile.am (gpgol_LDADD): Link against libassuan. + + * util.h (DIM, DIMof): New. + + * engine.c (filter_gpgme_read_cb): Implement nonblock feature. + (filter_gpgme_write_cb): Ditto. + +2007-09-24 Werner Koch + + * common.c (standard_homedir, default_homedir): New. + (w32_shgetfolderpath): Make static. + 2007-09-21 Werner Koch * mimeparser.c (build_mimeinfo): New. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/Makefile.am 2007-10-10 13:23:41 UTC (rev 188) @@ -66,22 +66,26 @@ # versions of GPGME and gpg-error, because we want to link to them # statically, and not dynamically (otherwise Outlook would not find # them). -gpgol_DEPENDENCIES = libmapi32.a libgpgme.a libgpg-error.a +gpgol_DEPENDENCIES = libmapi32.a libgpg-error.a libgpgme.a libassuan.a libmapi32.a: mapi32.def $(DLLTOOL) --output-lib $@ --def $< +libgpg-error.a: + ln -s $(shell $(GPG_ERROR_CONFIG) --prefix)/lib/libgpg-error.a + libgpgme.a: ln -s $(shell $(GPGME_CONFIG) --prefix)/lib/libgpgme.a -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 libmapi32.a libgpgme.a libgpg-error.a + rm -f libmapi32.a libgpg-error.a libgpgme.a libassuan.a gpgol_LDADD = $(srcdir)/gpgol.def \ - -L . -lgpgme -lgpg-error -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \ + -L . -lgpgme -lassuan -lgpg-error \ + -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \ -lole32 -loleaut32 -lws2_32 -ladvapi32 resource.o: resource.rc versioninfo.rc gpgol-rsrcs.rc olflange-rsrcs.rc Modified: trunk/src/common.c =================================================================== --- trunk/src/common.c 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/common.c 2007-10-10 13:23:41 UTC (rev 188) @@ -1,4 +1,4 @@ -/* common.c - Common routines used bu GpgOL +/* common.c - Common routines used by GpgOL * Copyright (C) 2005, 2007 g10 Code GmbH * * This file is part of GpgOL. @@ -21,7 +21,18 @@ #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 +#include #include "common.h" @@ -194,7 +205,7 @@ /* This is a helper function to load a Windows function from either of one DLLs. */ -HRESULT +static HRESULT w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) { static int initialized; @@ -447,8 +458,79 @@ } +/* Get the standard home directory. In general this function should + not be used as it does not consider a registry value or the + GNUPGHOME environment variable. Please use default_homedir(). */ +static const 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 = xstrdup ("C:\\gnupg"); + } + return dir; +} + + +/* Retrieve the default home directory. */ +const char * +default_homedir (void) +{ + static char *dir; + + if (!dir) + { + dir = getenv ("GNUPGHOME"); + if (!dir || !*dir) + { + char *tmp; + + tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", + "HomeDir"); + if (tmp && !*tmp) + { + free (tmp); + tmp = NULL; + } + if (tmp) + dir = tmp; + else + dir = xstrdup (standard_homedir ()); + } + else + dir = xstrdup (dir); + } + + return dir; +} + + /* Do in-place decoding of quoted-printable data of LENGTH in BUFFER. Returns the new length of the buffer. */ size_t Modified: trunk/src/common.h =================================================================== --- trunk/src/common.h 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/common.h 2007-10-10 13:23:41 UTC (rev 188) @@ -145,7 +145,7 @@ char *get_save_filename (HWND root, const char *srcname); char *utf8_to_wincp (const char *string); -HRESULT w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e); +const char *default_homedir (void); size_t qp_decode (char *buffer, size_t length); void b64_init (b64_state_t *state); Modified: trunk/src/engine-assuan.c =================================================================== --- trunk/src/engine-assuan.c 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/engine-assuan.c 2007-10-10 13:23:41 UTC (rev 188) @@ -30,6 +30,7 @@ #define WIN32_LEAN_AND_MEAN #include +#include #include "common.h" #include "engine.h" #include "engine-assuan.h" @@ -40,32 +41,347 @@ } while (0) -/* 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. */ +/* This is the buffer object used for the asynchronous reading of the + status channel. */ +struct status_buffer_s +{ + int eof; + int linelen; /* Used length of LINE. */ + char line[ASSUAN_LINELENGTH]; +}; +typedef struct status_buffer_s *status_buffer_t; + + +/* We operate in an asynchronous mode and thus need to run code for + final cleanup. Thus all functions need to implement a closure + function and setup an closure_data_t object. */ 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); + void (*closure)(closure_data_t); + gpg_error_t final_err; /* Final error code. */ engine_filter_t filter; - struct passphrase_cb_s pw_cb; /* Passphrase callback info. */ + assuan_context_t assctx; + ULONG cmdid; + assuan_fd_t status_read_fd; + struct gpgme_data_cbs status_cbs; + gpgme_data_t status_data; + status_buffer_t status_buffer; /* Allocated on demand. */ + int status_ready; + gpg_error_t last_err; }; -static int init_done = 0; +/* The object used by our I/O worker thread. */ +struct work_item_s; +typedef struct work_item_s *work_item_t; +struct work_item_s +{ + work_item_t next; + int used; /* If not set this object may be reused. */ + int waiting; /* Helper for async_worker_thread. */ + const char *name; /* Description used for debugging. */ + ULONG cmdid; /* Used to group work items of one command. */ + closure_data_t cld;/* NULL or the closure. */ + int wait_on_success; /* This work item needs to be ready before + invoking a closure for this command. */ + gpgme_data_t data; /* The data object we write to or read from. */ + int writing; /* If true we are going to write to HD. */ + HANDLE hd; /* The handle we read from or write to. */ + int io_pending; /* I/O is still pending. The value is the number + of bytes to be written or the size of the + buffer given to ReadFile. */ + int got_ready; /* Operation finished. */ + int delayed_ready; /* Ready but delayed to to a missing prerequesite. */ + int got_error; /* An error as been encountered. */ + int aborting; /* Set to true after a CancelIO has been issued. */ + void (*finalize)(work_item_t); /* Function called immediately before + the item is removed from the + queue. */ + OVERLAPPED ov; /* The overlapped info structure. */ + char buffer[128]; /* The buffer used by ReadFile or WriteFile. */ +}; -static DWORD WINAPI pipe_worker_thread (void *dummy); +/* The queue of all outstandig I/O operations. Protected by the + work_queue_lock. */ +static work_item_t work_queue; +/* The big lock used to protect the work queue. */ +static CRITICAL_SECTION work_queue_lock; + +/* An auto-reset event which will be signaled to get the + async_worker_thread out of its WFMO and to inspect the work + queue. */ +static HANDLE work_queue_event; + + +/*-- prototypes --*/ +static DWORD WINAPI async_worker_thread (void *dummy); + + + + +/* Return the next command id. Command Ids are used to group + resources of one command. */ +static ULONG +create_command_id (void) +{ + static ULONG command_id; + ULONG cmdid; + + while (!(cmdid = InterlockedIncrement (&command_id))) + ; + return cmdid; +} + + +/* Duplicate HANDLE into the server's process and close HANDLE. Note + that HANDLE is closed even if the function fails. Returns the + duplicated handle on success or INVALID_HANDLE_VALUE on error. */ +static HANDLE +dup_to_server (HANDLE handle, pid_t serverpid) +{ + HANDLE prochandle, newhandle; + + prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, serverpid); + if (!prochandle) + { + log_error_w32 (-1, "%s:%s: OpenProcess(%lu) failed", + SRCNAME, __func__, (unsigned long)serverpid); + CloseHandle (handle); + return INVALID_HANDLE_VALUE; + } + + if (!DuplicateHandle (GetCurrentProcess(), handle, + prochandle, &newhandle, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + log_error_w32 (-1, "%s:%s: DuplicateHandle to pid %lu failed", + SRCNAME, __func__, (unsigned long)serverpid); + CloseHandle (prochandle); + CloseHandle (handle); + return INVALID_HANDLE_VALUE; + } + CloseHandle (prochandle); + CloseHandle (handle); + return newhandle; +} + + +/* Create pipe with one end being inheritable and prepared for + overlapped I/O. + + FILEDES[0] := read handle. + FILEDES[1] := write handle. + + SERVERPID is the PID of the server. FOR_WRITE is seen out of our + perspective; if it is set, the read handle is created in the server + process and the write handle is overlapped. If it is not set the + write handle is created in the server process and the read handle + is overlapped. +*/ +static gpg_error_t +create_io_pipe (HANDLE filedes[2], pid_t serverpid, int for_write) +{ + static ULONG pipenumber; + ULONG pipeno; + char pipename[100]; + HANDLE r, w; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + + /* CreatePipe is in reality implemented using a Named Pipe. We do + it the same but use a name which is in our name space. We allow + only one instance, use the standard timeout of 120 seconds and + buffers of 4k. */ + pipeno = InterlockedIncrement (&pipenumber); + snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\GpgOL_anon.%08lx.%08lx", + (unsigned long)GetCurrentProcessId(), pipeno); + sec_attr.bInheritHandle = /*for_write? TRUE :*/FALSE; + r = CreateNamedPipe (pipename, (PIPE_ACCESS_INBOUND + | (for_write? 0:FILE_FLAG_OVERLAPPED)), + PIPE_TYPE_BYTE | PIPE_WAIT, + 1, 4096, 4096, 120000, &sec_attr); + if (r == INVALID_HANDLE_VALUE) + { + log_error_w32 (-1, "%s:%s: CreateNamedPipe failed for `%s'", + SRCNAME, __func__, pipename); + return gpg_error (GPG_ERR_GENERAL); + } + if (for_write) + { + r = dup_to_server (r, serverpid); + if (r == INVALID_HANDLE_VALUE) + { + log_error_w32 (-1, "%s:%s: dup_for_server(r) failed for `%s'", + SRCNAME, __func__, pipename); + return gpg_error (GPG_ERR_GENERAL); + } + } + + /* Now open the other side of the named pipe. Because we have not + called ConnectNamedPipe another process should not be able to + open the pipe in the meantime. This is an educated guess by + looking at REACTOS and WINE - they implement an anonymous pipe + this way. */ + sec_attr.bInheritHandle = /*for_write?*/ FALSE /*: TRUE*/; + w = CreateFile (pipename, GENERIC_WRITE, 0, &sec_attr, + OPEN_EXISTING, (FILE_ATTRIBUTE_NORMAL + | (for_write? FILE_FLAG_OVERLAPPED:0)), + NULL); + if (w == INVALID_HANDLE_VALUE) + { + log_error_w32 (-1, "%s:%s: CreateFile failed for `%s'", + SRCNAME, __func__, pipename); + CloseHandle (r); + return gpg_error (GPG_ERR_GENERAL); + } + if (!for_write) + { + w = dup_to_server (w, serverpid); + if (w == INVALID_HANDLE_VALUE) + { + log_error_w32 (-1, "%s:%s: dup_for_server(w) failed for `%s'", + SRCNAME, __func__, pipename); + CloseHandle (r); + return gpg_error (GPG_ERR_GENERAL); + } + } + + filedes[0] = r; + filedes[1] = w; + log_debug ("%s:%s: new pipe created: r=%p%s w=%p%s", SRCNAME, __func__, + r, for_write? " (server)":"", + w, !for_write?" (server)":""); + return 0; +} + + +/* Return the socket name of the UI Server. */ +static const char * +get_socket_name (void) +{ + static char *name; + + if (!name) + { + const char *dir = default_homedir (); + name = xmalloc (strlen (dir) + 11 + 1); + strcpy (stpcpy (name, dir), "\\S.uiserver"); + } + + return name; +} + + + +static gpg_error_t +send_one_option (assuan_context_t ctx, const char *name, const char *value) +{ + gpg_error_t err; + char buffer[1024]; + + if (!value || !*value) + err = 0; /* Avoid sending empty strings. */ + else + { + snprintf (buffer, sizeof buffer, "OPTION %s=%s", name, value); + err = assuan_transact (ctx, buffer, NULL, NULL, NULL, NULL, NULL, NULL); + } + + return err; +} + + +static int +getinfo_pid_cb (void *opaque, const void *buffer, size_t length) +{ + pid_t *pid = opaque; + char pidbuf[50]; + + /* There is only the pid in the server's response. */ + if (length >= sizeof pidbuf) + length = sizeof pidbuf -1; + if (length) + { + strncpy (pidbuf, buffer, length); + pidbuf[length] = 0; + *pid = (pid_t)strtoul (pidbuf, NULL, 10); + } + return 0; +} + + +/* Send options to the UI server and return the server's PID. */ +static gpg_error_t +send_options (assuan_context_t ctx, void *hwnd, pid_t *r_pid) +{ + gpg_error_t err = 0; + char numbuf[50]; + + *r_pid = (pid_t)(-1); + if (hwnd) + { + snprintf (numbuf, sizeof numbuf, "%lx", (unsigned long)hwnd); + err = send_one_option (ctx, "window-id", numbuf); + } + if (!err) + { + err = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, r_pid, + NULL, NULL, NULL, NULL); + if (!err && *r_pid == (pid_t)(-1)) + { + log_debug ("%s:%s: server did not return a PID", SRCNAME, __func__); + err = gpg_error (GPG_ERR_ASSUAN_SERVER_FAULT); + } + } + + return err; +} + + +/* Connect to the UI server and setup the connection. */ +static gpg_error_t +connect_uiserver (assuan_context_t *r_ctx, pid_t *r_pid, ULONG *r_cmdid, + void *hwnd) +{ + gpg_error_t err; + assuan_context_t ctx; + + *r_ctx = NULL; + *r_pid = (pid_t)(-1); + *r_cmdid = 0; + err = assuan_socket_connect (&ctx, get_socket_name (), -1); + if (err) + { + log_error ("%s:%s: error connecting `%s': %s\n", SRCNAME, __func__, + get_socket_name (), gpg_strerror (err)); + } + else if ((err = send_options (ctx, hwnd, r_pid))) + { + assuan_disconnect (ctx); + } + else + { + *r_cmdid = create_command_id (); + *r_ctx = ctx; + } + return err; +} + + + + + static void cleanup (void) { - /* Fixme: We should stop the thread. */ + /* Fixme: We should stop the worker thread. */ } @@ -81,23 +397,40 @@ int op_assuan_init (void) { + static int init_done; gpgme_error_t err; + assuan_context_t ctx; + pid_t pid; + ULONG cmdid; if (init_done) return 0; - - /* FIXME: Connect to the server and return failure if it is not - possible. */ - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); - + + /* Run a test connection to see whether the UI server is available. */ + err = connect_uiserver (&ctx, &pid, &cmdid, NULL); + if (!err) + { + err = assuan_transact (ctx, "NOP", NULL, NULL, NULL, NULL, NULL, NULL); + assuan_disconnect (ctx); + } + if (err) + return err; + /* Fire up the pipe worker thread. */ { HANDLE th; DWORD tid; - th = CreateThread (NULL, 128*1024, pipe_worker_thread, NULL, 0, &tid); + InitializeCriticalSection (&work_queue_lock); + work_queue_event = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!work_queue_event) + { + log_error_w32 (-1, "%s:%s: CreateEvent failed", SRCNAME, __func__); + return gpg_error (GPG_ERR_GENERAL); + } + th = CreateThread (NULL, 256*1024, async_worker_thread, NULL, 0, &tid); if (th == INVALID_HANDLE_VALUE) - log_error ("failed to start the piper worker thread\n"); + log_error ("failed to launch the async_worker_thread"); else CloseHandle (th); } @@ -107,87 +440,809 @@ } + +/* Helper for async_worker_thread. Returns true if the item's handle + needs to be put on the wait list. This is called with the worker + mutex hold. */ +static int +worker_start_read (work_item_t item) +{ + int nwritten; + DWORD nbytes; + int retval = 0; + + /* Read from the handle and write to the callback. The gpgme + callback is expected to never block. */ + if (ReadFile (item->hd, item->buffer, sizeof item->buffer, + &nbytes, &item->ov) ) + { + /* (With overlapped, EOF is not indicated by NBYTES==0.) */ + if (!nbytes) + log_error ("%s:%s: [%s:%p] short read (0 bytes)", + SRCNAME, __func__, item->name, item->hd); + else + { + nwritten = gpgme_data_write (item->data, item->buffer, nbytes); + if (nwritten < 0) + { + log_error ("%s:%s: [%s:%p] writing to callback failed: %s", + SRCNAME, __func__, item->name, item->hd, + strerror (errno)); + item->got_error = 1; + } + else if (nwritten < nbytes) + { + log_error ("%s:%s: [%s:%p] short write to callback (%d of %lu)", + SRCNAME, __func__, item->name, item->hd, + nwritten, nbytes); + item->got_error = 1; + } + else + log_debug ("%s:%s: [%s:%p] wrote %d bytes to callback", + SRCNAME, __func__, item->name, item->hd, nwritten); + } + retval = 1; + } + else + { + int syserr = GetLastError (); + + if (syserr == ERROR_IO_PENDING) + { + log_debug ("%s:%s: [%s:%p] io(read) pending", + SRCNAME, __func__, item->name, item->hd); + item->io_pending = sizeof item->buffer; + retval = 1; + } + else if (syserr == ERROR_HANDLE_EOF || syserr == ERROR_BROKEN_PIPE) + { + log_debug ("%s:%s: [%s:%p] EOF%s seen", + SRCNAME, __func__, item->name, item->hd, + syserr == ERROR_BROKEN_PIPE? " (broken pipe)":""); + item->got_ready = 1; + } + else + { + log_error_w32 (syserr, "%s:%s: [%s:%p] read error", + SRCNAME, __func__, item->name, item->hd); + item->got_error = 1; + } + } + + return retval; +} + +/* Result checking helper for async_worker_thread. This is called with + the worker mutex hold. */ +static void +worker_check_read (work_item_t item, DWORD nbytes) +{ + int nwritten; + + if (!nbytes) + log_error ("%s:%s: [%s:%p] short read (0 bytes)", + SRCNAME, __func__, item->name, item->hd); + else + { + assert (nbytes > 0); + nwritten = gpgme_data_write (item->data, item->buffer, nbytes); + if (nwritten < 0) + { + log_error ("%s:%s: [%s:%p] error writing to callback: %s", + SRCNAME, __func__, item->name, item->hd,strerror (errno)); + item->got_error = 1; + } + else if (nwritten < nbytes) + { + log_error ("%s:%s: [%s:%p] short write to callback (%d of %lu)", + SRCNAME, __func__, item->name, item->hd, nwritten,nbytes); + item->got_error = 1; + } + else + log_debug ("%s:%s: [%s:%p] wrote %d bytes to callback", + SRCNAME, __func__, item->name, item->hd, nwritten); + } +} + + + +/* Helper for async_worker_thread. Returns true if the item's handle + needs to be put on the wait list. This is called with the worker + mutex hold. */ +static int +worker_start_write (work_item_t item) +{ + int nread; + DWORD nbytes; + int retval = 0; + + /* Read from the callback and the write to the handle. The gpgme + callback is expected to never block. */ + nread = gpgme_data_read (item->data, item->buffer, sizeof item->buffer); + if (nread < 0) + { + if (errno == EAGAIN) + { + log_debug ("%s:%s: [%s:%p] ignoring EAGAIN from callback", + SRCNAME, __func__, item->name, item->hd); + Sleep (0); + retval = 1; + } + else + { + log_error ("%s:%s: [%s:%p] error reading from callback: %s", + SRCNAME, __func__, item->name, item->hd,strerror (errno)); + item->got_error = 1; + } + } + else if (!nread) + { + log_debug ("%s:%s: [%s:%p] EOF received from callback", + SRCNAME, __func__, item->name, item->hd); + item->got_ready = 1; + retval = 1; + } + else + { + if (WriteFile (item->hd, item->buffer, nread, &nbytes, &item->ov)) + { + if (nbytes < nread) + { + log_error ("%s:%s: [%s:%p] short write (%lu of %d)", + SRCNAME, __func__, item->name,item->hd,nbytes, nread); + item->got_error = 1; + } + else + log_debug ("%s:%s: [%s:%p] wrote %lu bytes", + SRCNAME, __func__, item->name, item->hd, nbytes); + retval = 1; + } + else + { + int syserr = GetLastError (); + + if (syserr == ERROR_IO_PENDING) + { + log_debug ("%s:%s: [%s:%p] io(write) pending (%d bytes)", + SRCNAME, __func__, item->name, item->hd, nread); + item->io_pending = nread; + retval = 1; + } + else + { + log_error_w32 (syserr, "%s:%s: [%s:%p] write error", + SRCNAME, __func__, item->name, item->hd); + item->got_error = 1; + } + } + } + + return retval; +} + + +/* Result checking helper for async_worker_thread. This is called with + the worker mutex hold. */ +static void +worker_check_write (work_item_t item, DWORD nbytes) +{ + if (nbytes < item->io_pending) + { + log_error ("%s:%s: [%s:%p] short write (%lu of %d)", + SRCNAME,__func__, item->name, item->hd, nbytes, + item->io_pending); + item->got_error = 1; + } + else + log_debug ("%s:%s: [%s:%p] write finished (%lu bytes)", + SRCNAME, __func__, item->name, item->hd, nbytes); +} + + + /* The worker thread which feeds the pipes. */ static DWORD WINAPI -pipe_worker_thread (void *dummy) +async_worker_thread (void *dummy) { - gpgme_ctx_t ctx; - gpg_error_t err; - void *a_voidptr; - closure_data_t closure_data; + work_item_t item; + int n; + DWORD nbytes; + HANDLE hdarray[MAXIMUM_WAIT_OBJECTS]; + int count, addit, any_ready, hdarraylen; (void)dummy; for (;;) { - Sleep (1000); + /* Process our queue and fire up async I/O requests. */ + log_debug ("%s:%s: processing work queue", SRCNAME, __func__); + EnterCriticalSection (&work_queue_lock); + hdarraylen = 0; + hdarray[hdarraylen++] = work_queue_event; + count = 0; + any_ready = 0; + for (item = work_queue; item; item = item->next) + { + item->waiting = 0; + if (!item->used) + continue; + assert (item->hd != INVALID_HANDLE_VALUE); + count++; + if (item->got_error) + { + if (!item->delayed_ready) + any_ready = 1; + continue; + } + assert (item->data); + if (hdarraylen == DIM (hdarray)) + { + log_debug ("%s:%s: [%s:%p] wait array full - ignored for now", + SRCNAME, __func__, item->name, item->hd); + continue; + } + + if (item->io_pending) + addit = 1; + else if (item->writing) + addit = worker_start_write (item); + else + addit = worker_start_read (item); + + if (addit) + { + hdarray[hdarraylen++] = item->hd; + item->waiting = 1; /* Just for the tarce output. */ + } + if (!item->delayed_ready && (item->got_error || item->got_ready)) + any_ready = 1; + } + LeaveCriticalSection (&work_queue_lock); + + if (any_ready) + log_debug ("%s:%s: %d items in queue; skipping wait", + SRCNAME, __func__, count); + else + { + log_debug ("%s:%s: %d items in queue; waiting for %d items:", + SRCNAME, __func__, count, hdarraylen-1); + for (item = work_queue; item; item = item->next) + { + if (item->waiting) + log_debug ("%s:%s: [%s:%p]", + SRCNAME, __func__, item->name, item->hd); + } + n = WaitForMultipleObjects (hdarraylen, hdarray, FALSE, INFINITE); + if (n == WAIT_FAILED) + { + log_error_w32 (-1, "%s:%s: WFMO failed", SRCNAME, __func__); + Sleep (1000); + } + else if (n >= 0 && n < hdarraylen) + { + log_debug ("%s:%s: WFMO succeeded (res=%d)",SRCNAME,__func__, n); + } + else + { + log_error ("%s:%s: WFMO returned: %d", SRCNAME, __func__, n); + Sleep (1000); + } + } + + /* Handle completion status. */ + EnterCriticalSection (&work_queue_lock); + log_debug ("%s:%s: checking completion states", SRCNAME, __func__); + for (item = work_queue; item; item = item->next) + { + if (!item->io_pending) + ; + else if (GetOverlappedResult (item->hd, &item->ov, &nbytes, FALSE)) + { + if (item->writing) + worker_check_write (item, nbytes); + else + worker_check_read (item, nbytes); + item->io_pending = 0; + } + else + { + int syserr = GetLastError (); + if (syserr == ERROR_IO_INCOMPLETE) + ; + else if (!item->writing && syserr == ERROR_HANDLE_EOF) + { + /* Got EOF. */ + log_debug ("%s:%s: [%s:%p] EOF received", + SRCNAME, __func__, item->name, item->hd); + item->io_pending = 0; + item->got_ready = 1; + } + else + { + log_error_w32 (syserr, + "%s:%s: [%s:%p] GetOverlappedResult failed", + SRCNAME, __func__, item->name, item->hd); + item->got_error = 1; + if (!item->aborting) + { + item->aborting = 1; + if (!CancelIo (item->hd)) + log_error_w32 (-1, "%s:%s: [%s:%p] CancelIo failed", + SRCNAME,__func__, item->name, item->hd); + } + else + item->got_ready = 1; + } + } + } + LeaveCriticalSection (&work_queue_lock); + + Sleep (0); + + EnterCriticalSection (&work_queue_lock); + log_debug ("%s:%s: cleaning up work queue", SRCNAME, __func__); + for (item = work_queue; item; item = item->next) + { + if (item->used && (item->got_ready || item->got_error)) + { + if (item->cld) + { + if (!item->cld->final_err && item->got_error) + item->cld->final_err = gpg_error (GPG_ERR_EIO); + + if (!item->cld->final_err) + { + /* Check whether there are other work items in + this group we need to wait for before + invoking the closure. */ + work_item_t itm2; + + for (itm2=work_queue; itm2; itm2 = itm2->next) + if (itm2->used && itm2 != item + && itm2->cmdid == item->cmdid + && itm2->wait_on_success + && !(itm2->got_ready || itm2->got_error)) + break; + if (itm2) + { + log_debug ("%s:%s: [%s:%p] delaying closure due to " + "[%s/%p]", SRCNAME, __func__, + item->name, item->hd, + itm2->name, itm2->hd); + item->delayed_ready = 1; + break; + } + } + item->delayed_ready = 0; + log_debug ("%s:%s: [%s:%p] invoking closure", + SRCNAME,__func__, item->name, item->hd); + + item->cld->closure (item->cld); + xfree (item->cld); + item->cld = NULL; + } + + item->got_ready = 0; + item->finalize (item); + item->used = 0; + } + } + + LeaveCriticalSection (&work_queue_lock); } } +void +engine_assuan_cancel (void *cancel_data) +{ + /* FIXME */ +} +/* Standard finalize handler. Called right before the item is removed + from the queue. Called while the work_queue_lock is hold. */ +static void +finalize_handler (work_item_t item) +{ + log_debug ("%s:%s: [%s:%p] closing handle", + SRCNAME, __func__, item->name, item->hd); + CloseHandle (item->hd); + item->hd = INVALID_HANDLE_VALUE; +} +/* A finalize handler which does not close the handle. */ +static void +noclose_finalize_handler (work_item_t item) +{ + log_debug ("%s:%s: [%s:%p] called", SRCNAME, __func__, item->name, item->hd); + item->hd = INVALID_HANDLE_VALUE; +} -/* Not that this closure is called in the context of the + +/* Add a data callback and a handle to the work queue. This should + only be called once per handle. Caller gives up ownership of + CLD. */ +static void +enqueue_callback (const char *name, assuan_context_t ctx, + gpgme_data_t data, HANDLE hd, + int for_write, void (*fin_handler)(work_item_t), + ULONG cmdid, closure_data_t cld, int wait_on_success) +{ + work_item_t item; + int created = 0; + + EnterCriticalSection (&work_queue_lock); + for (item = work_queue; item; item = item->next) + if (!item->used) + break; + if (!item) + { + item = xmalloc (sizeof *item); + item->next = work_queue; + work_queue = item; + created = 1; + } + item->used = 1; + item->name = name; + item->cmdid = cmdid; + item->cld = cld; + item->wait_on_success = wait_on_success; + item->data = data; + item->writing = for_write; + item->hd = hd; + item->io_pending = 0; + item->got_ready = 0; + item->delayed_ready = 0; + item->got_error = 0; + item->aborting = 0; + item->finalize = fin_handler; + memset (&item->ov, 0, sizeof item->ov); + log_debug ("%s:%s: [%s:%p] created%s", + SRCNAME, __func__, item->name, item->hd, created?"":" (reusing)"); + LeaveCriticalSection (&work_queue_lock); +} + + +/* Remove all items from the work queue belonging to the command with + the id CMDID. */ +static int +destroy_command (ULONG cmdid) +{ + work_item_t item; + + EnterCriticalSection (&work_queue_lock); + for (item = work_queue; item; item = item->next) + if (item->used && item->cmdid == cmdid && !item->wait_on_success) + { + log_debug ("%s:%s: [%s:%p] cmdid=%lu registered for destroy", + SRCNAME, __func__, item->name, item->hd, item->cmdid); + /* First send an I/O cancel in case the the last + GetOverlappedResult returned only a partial result. This + works because we are always running within the + async_worker_thread. */ +/* if (!CancelIo (item->hd)) */ +/* log_error_w32 (-1, "%s:%s: [%s:%p] CancelIo failed", */ +/* SRCNAME, __func__, item->name, item->hd); */ + item->got_ready = 1; + } + LeaveCriticalSection (&work_queue_lock); +} + + +/* Process a status line. */ +static int +status_handler (closure_data_t cld, const char *line) +{ + gpg_error_t err; + int retval = 0; + + log_debug ("%s:%s: cld %p, line `%s'", SRCNAME, __func__, cld, line); + + if (*line == '#' || !*line) + ; + else if (line[0] == 'D' && line[1] == ' ') + { + line += 2; + } + else if (line[0] == 'S' && (!line[1] || line[1] == ' ')) + { + for (line += 1; *line == ' '; line++) + ; + } + else if (line[0] == 'O' && line[1] == 'K' && (!line[2] || line[2] == ' ')) + { + for (line += 2; *line == ' '; line++) + ; + cld->final_err = 0; + retval = 1; + } + else if (!strncmp (line, "ERR", 3) && (!line[3] || line[3] == ' ')) + { + for (line += 3; *line == ' '; line++) + ; + err = strtoul (line, NULL, 10); + if (!err) + err = gpg_error (GPG_ERR_ASS_INV_RESPONSE); + cld->final_err = err; + retval = 1; + } + else if (!strncmp (line, "INQUIRE", 7) && (!line[7] || line[7] == ' ')) + { + for (line += 7; *line == ' '; line++) + ; + /* We have no inquire handler thus get out of it immediately. */ + err = assuan_write_line (cld->assctx, "END"); + if (err) + cld->last_err = err; + } + else if (!strncmp (line, "END", 3) && (!line[3] || line[3] == ' ')) + { + for (line += 3; *line == ' '; line++) + ; + } + else + retval = -1; /* Invalid response. */ + + return retval; +} + + +/* This write callback is used by GPGME to push data to our status + line handler. 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 +status_in_cb (void *opaque, const void *buffer, size_t size) +{ + size_t orig_size = size; + closure_data_t cld = opaque; + status_buffer_t sb; + size_t nleft, nbytes; + char *p; + + assert (cld); + if (!size) + return 0; + + if (!(sb=cld->status_buffer)) + { + cld->status_buffer = sb = xmalloc (sizeof *cld->status_buffer); + sb->eof = 0; + sb->linelen = 0; + } + + do + { + assert (sb->linelen < ASSUAN_LINELENGTH); + nleft = ASSUAN_LINELENGTH - sb->linelen; + nbytes = size < nleft? size : nleft; + memcpy (sb->line+sb->linelen, buffer, nbytes); + sb->linelen += nbytes; + size -= nbytes; + p = memchr (sb->line, '\n', sb->linelen); + if (p && !cld->status_ready) + { + *p = 0; + if (p > sb->line && p[-1] == '\r') + p[-1] = 0; + switch (status_handler (cld, sb->line)) + { + case 0: + break; + case 1: /* Ready. */ + cld->status_ready = 1; + destroy_command (cld->cmdid); + break; + default: + log_error ("%s:%s: invalid line from server", SRCNAME, __func__); + errno = EINVAL; + return -1; + } + sb->linelen -= (p+1 - sb->line); + memmove (sb->line, p+1, sb->linelen); + } + else if (sb->linelen >= ASSUAN_LINELENGTH) + { + log_error ("%s:%s: line from server too long", SRCNAME, __func__); + errno = ERANGE; + return -1; + } + } + while (size); + + return orig_size; +} + + + +/* Start an asynchronous command. Caller gives up owenership of + CLD. */ +static gpg_error_t +start_command (assuan_context_t ctx, closure_data_t cld, + ULONG cmdid, const char *line) +{ + gpg_error_t err; + assuan_fd_t fds[5]; + int nfds; + + /* Get the fd used by assuan for status channel reads. This is the + first fd returned by assuan_get_active_fds for read fds. */ + nfds = assuan_get_active_fds (ctx, 0, fds, DIM (fds)); + if (nfds < 1) + return gpg_error (GPG_ERR_GENERAL); /* Ooops. */ + + cld->cmdid = cmdid; + cld->status_cbs.write = status_in_cb; + cld->assctx = ctx; + /* Fixme: We might want to have reference counting for CLD to cope + with thye problem that the gpgme data object uses CLD which might + get invalidated at any time. */ + err = gpgme_data_new_from_cbs (&cld->status_data, &cld->status_cbs, cld); + if (err) + { + xfree (cld); + return err; + } + + enqueue_callback ("status", ctx, cld->status_data, fds[0], 0, + noclose_finalize_handler, cmdid, cld, 0); + cld = NULL; /* Now belongs to the status work item. */ + + /* Process the work queue. */ + if (!SetEvent (work_queue_event)) + log_error_w32 (-1, "%s:%s: SetEvent failed", SRCNAME, __func__); + /* Send the command. */ + return assuan_write_line (ctx, line); +} + + + + +/* Note that this closure is called in the context of the waiter_thread. */ static void -encrypt_closure (closure_data_t cld, gpg_error_t err) +encrypt_closure (closure_data_t cld) { - engine_private_finished (cld->filter, err); + engine_private_finished (cld->filter, cld->final_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. */ + recpients given in the NULL terminated array RECIPIENTS. This + function terminates with success and then expects the caller to + wait for the result of the encryption using engine_wait. FILTER is + used for asynchronous commnication with the engine module. HWND is + the window handle of the current window and used to maintain the + correct relationship between a popups and the active window. If + this function returns success, the data objects may only be + destroyed after an engine_wait or engine_cancel. */ int op_assuan_encrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, - void *notify_data, /* FIXME: Add hwnd */ + engine_filter_t filter, void *hwnd, char **recipients) { gpg_error_t err; closure_data_t cld; + assuan_context_t ctx; + char line[1024]; + HANDLE inpipe[2], outpipe[2]; + ULONG cmdid; + pid_t pid; + int i; + char *p; + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); + if (err) + return err; + + if ((err = create_io_pipe (inpipe, pid, 1))) + return err; + if ((err = create_io_pipe (outpipe, pid, 0))) + { + CloseHandle (inpipe[0]); + CloseHandle (outpipe[0]); + return err; + } + cld = xcalloc (1, sizeof *cld); cld->closure = encrypt_closure; - cld->filter = notify_data; + cld->filter = filter; + err = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + for (i=0; recipients && recipients[i]; i++) + { + snprintf (line, sizeof line, "RECIPIENT %s", recipients[i]); + for (p=line; *p; p++) + if (*p == '\n' || *p =='\r' ) + *p = ' '; + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + } - /* FIXME: We should not hardcode always trust. */ -/* if (sign_key) */ -/* { */ -/* 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); */ -/* } */ -/* else */ -/* err = gpgme_op_encrypt_start (ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, */ -/* indata, outdata); */ + /* Note: We don't use real descriptor passing but a hack: We + duplicate the handle into the server process and the server then + uses this handle. Eventually we should put this code into + assuan_sendfd. */ + snprintf (line, sizeof line, "INPUT FD=%ld", (unsigned long int)inpipe[0]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + snprintf (line, sizeof line, "OUTPUT FD=%ld", (unsigned long int)outpipe[1]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; - err = -1; + enqueue_callback (" input", ctx, indata, inpipe[1], 1, finalize_handler, + cmdid, NULL, 0); + enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, + cmdid, NULL, 1 /* Wait on success */); + err = start_command (ctx, cld, cmdid, + (protocol == PROTOCOL_OPENPGP + ? "ENCRYPT --protocol=OpenPGP" + : protocol == PROTOCOL_SMIME + ? "ENCRYPT --protocol=CMS" + : "ENCRYPT --protocol=unknown-protocol")); + cld = NULL; /* Now owned by start_command. */ + if (err) + goto leave; + leave: if (err) { + /* Fixme: Cancel stuff in the work_queue. */ + if (inpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[0]); + if (inpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (inpipe[1]); + if (outpipe[0] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[0]); + if (outpipe[1] != INVALID_HANDLE_VALUE) + CloseHandle (outpipe[1]); xfree (cld); + assuan_disconnect (ctx); } + else + engine_private_set_cancel (filter, ctx); return err; } + +int +op_assuan_sign (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + engine_filter_t filter, void *hwnd) +{ + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +} + + +int +op_assuan_decrypt (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + engine_filter_t filter, void *hwnd, + int with_verify) +{ + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +} + + + +int +op_assuan_verify (gpgme_protocol_t protocol, + gpgme_data_t data, const char *signature, + engine_filter_t filter, void *hwnd) +{ + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +} + + Modified: trunk/src/engine-assuan.h =================================================================== --- trunk/src/engine-assuan.h 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/engine-assuan.h 2007-10-10 13:23:41 UTC (rev 188) @@ -31,20 +31,30 @@ #include /* We need it for gpgme_data_t. */ +#include "engine.h" - int op_assuan_init (void); void op_assuan_deinit (void); +void engine_assuan_cancel (void *cancel_data); int op_assuan_encrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, - void *notify_data, /* FIXME: Add hwnd */ + engine_filter_t notify_data, void *hwnd, char **recipients); +int op_assuan_sign (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + engine_filter_t filter, void *hwnd); +int op_assuan_decrypt (protocol_t protocol, + gpgme_data_t indata, gpgme_data_t outdata, + engine_filter_t filter, void *hwnd, + int with_verify); +int op_assuan_verify (gpgme_protocol_t protocol, + gpgme_data_t data, const char *signature, + engine_filter_t filter, void *hwnd); - #ifdef __cplusplus } #endif Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/engine-gpgme.c 2007-10-10 13:23:41 UTC (rev 188) @@ -410,14 +410,12 @@ /* 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_private_finished() is called with - FILTER 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. */ + recpients given in the NULL terminated array RECIPIENTS. This + function terminates with success and then expects the caller to + wait for the result of the encryption using engine_wait. FILTER is + used for asynchronous commnication with the engine module. HWND is + the window handle of the current window and used to maintain the + correct relationship between a popups and the active window. */ int op_gpgme_encrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, Modified: trunk/src/engine.c =================================================================== --- trunk/src/engine.c 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/engine.c 2007-10-10 13:23:41 UTC (rev 188) @@ -43,9 +43,12 @@ SRCNAME, __func__, __LINE__); \ } while (0) -static int debug_filter = 0; +static int debug_filter = 1; +/* This variable indicates whether the assuan engine is used. */ +static int use_assuan; + /* Definition of the key object. */ struct engine_keyinfo_s { @@ -60,9 +63,12 @@ accessed by one thread. */ struct engine_filter_s { + int use_assuan; /* The same as the global USE_ASSUAN. */ + struct { CRITICAL_SECTION lock; /* The lock for the this object. */ HANDLE condvar; /* Manual reset event signaled if LENGTH > 0. */ + int nonblock; /* Put gpgme data cb in non blocking mode. */ size_t length; /* Number of bytes in BUFFER waiting to be send down the pipe. */ char buffer[FILTER_BUFFER_SIZE]; @@ -77,6 +83,7 @@ struct { CRITICAL_SECTION lock; /* The lock for the this object. */ HANDLE condvar; /* Manual reset event signaled if LENGTH == 0. */ + int nonblock; /* Put gpgme data cb in non blocking mode. */ size_t length; /* Number of bytes in BUFFER waiting to be send back to the caller. */ char buffer[FILTER_BUFFER_SIZE]; @@ -155,6 +162,14 @@ if (!filter->in.ready_event) log_error_w32 (-1, "%s:%s: CreateEvent failed", SRCNAME, __func__); + /* If we are using the assuan engine we need to make the gpgme read + callback non blocking. */ + if (use_assuan) + { + filter->use_assuan = 1; + filter->in.nonblock = 1; + } + return filter; } @@ -208,6 +223,13 @@ return 0; /* Return EOF. */ } release_in_lock (filter, __func__); + if (filter->in.nonblock) + { + errno = EAGAIN; + if (debug_filter) + log_debug ("%s:%s: leave; result=EAGAIN\n", SRCNAME, __func__); + return -1; + } if (debug_filter) log_debug ("%s:%s: waiting for in.condvar\n", SRCNAME, __func__); WaitForSingleObject (filter->in.condvar, 500); @@ -257,6 +279,13 @@ while (filter->out.length) { release_out_lock (filter, __func__); + if (filter->out.nonblock) + { + errno = EAGAIN; + if (debug_filter) + log_debug ("%s:%s: leave; result=EAGAIN\n", SRCNAME, __func__); + return -1; + } if (debug_filter) log_debug ("%s:%s: waiting for out.condvar\n", SRCNAME, __func__); WaitForSingleObject (filter->out.condvar, 500); @@ -274,7 +303,7 @@ release_out_lock (filter, __func__); if (debug_filter) - log_debug ("%s:%s: write; result=%d\n", SRCNAME, __func__, (int)nbytes); + log_debug ("%s:%s: leave; result=%d\n", SRCNAME, __func__, (int)nbytes); return nbytes; } @@ -331,14 +360,17 @@ err = op_assuan_init (); if (err) { -/* MessageBox (NULL, */ -/* _("The user interface server is not available or does " */ -/* "not work. Using an internal user interface.\n\n" */ -/* "This is limited to the OpenPGP protocol and " */ -/* "thus S/MIME protected message are not readable."), */ -/* _("GpgOL"), MB_ICONWARNING|MB_OK); */ + use_assuan = 0; + MessageBox (NULL, + _("The user interface server is not available or does " + "not work. Using an internal user interface.\n\n" + "This is limited to the OpenPGP protocol and " + "thus S/MIME protected message are not readable."), + _("GpgOL"), MB_ICONWARNING|MB_OK); err = op_gpgme_init (); } + else + use_assuan = 1; return err; } @@ -605,7 +637,10 @@ { log_debug ("%s:%s: filter %p: sending cancel command to backend", SRCNAME, __func__, filter); - engine_gpgme_cancel (cancel_data); + if (filter->use_assuan) + engine_assuan_cancel (cancel_data); + else + engine_gpgme_cancel (cancel_data); if (WaitForSingleObject (filter->in.ready_event, INFINITE) != WAIT_OBJECT_0) log_error_w32 (-1, "%s:%s: WFSO failed", SRCNAME, __func__); @@ -632,8 +667,12 @@ { gpg_error_t err; - err = op_gpgme_encrypt (protocol, filter->indata, filter->outdata, - filter, NULL, recipients); + if (filter->use_assuan) + err = op_assuan_encrypt (protocol, filter->indata, filter->outdata, + filter, NULL, recipients); + else + err = op_gpgme_encrypt (protocol, filter->indata, filter->outdata, + filter, NULL, recipients); return err; } @@ -649,8 +688,12 @@ { gpg_error_t err; - err = op_gpgme_sign (protocol, filter->indata, filter->outdata, - filter, NULL); + if (filter->use_assuan) + err = op_assuan_sign (protocol, filter->indata, filter->outdata, + filter, NULL); + else + err = op_gpgme_sign (protocol, filter->indata, filter->outdata, + filter, NULL); return err; } @@ -667,8 +710,12 @@ { gpg_error_t err; - err = op_gpgme_decrypt (protocol, filter->indata, filter->outdata, - filter, NULL, with_verify); + if (filter->use_assuan) + err = op_assuan_decrypt (protocol, filter->indata, filter->outdata, + filter, NULL, with_verify); + else + err = op_gpgme_decrypt (protocol, filter->indata, filter->outdata, + filter, NULL, with_verify); return err; } @@ -693,7 +740,10 @@ return gpg_error (GPG_ERR_NOT_SUPPORTED); } - err = op_gpgme_verify (protocol, filter->indata, signature, filter, NULL); + if (filter->use_assuan) + err = op_assuan_verify (protocol, filter->indata, signature, filter, NULL); + else + err = op_gpgme_verify (protocol, filter->indata, signature, filter, NULL); return err; } Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/ext-commands.cpp 2007-10-10 13:23:41 UTC (rev 188) @@ -430,6 +430,9 @@ pDisp = find_outlook_property (pEECB, "Close", &dispid); if (pDisp) { + /* Note that there is a report on the Net from 2005 by Amit + Joshi where he claims that in Outlook XP olDiscard does + not work but is treated like olSave. */ dispparams.rgvarg = &aVariant; dispparams.rgvarg[0].vt = VT_INT; dispparams.rgvarg[0].intVal = 1; /* olDiscard */ Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/main.c 2007-10-10 13:23:41 UTC (rev 188) @@ -31,6 +31,7 @@ #include "msgcache.h" #include "mymapi.h" + /* Registry key for this software. */ #define REGKEY "Software\\GNU\\GnuPG" @@ -197,15 +198,6 @@ } -/* Create a new boundary for use with MIME. */ -void -create_boundary (char *buffer, size_t buflen) -{ - - -} - - /* Acquire the mutex for logging. Returns 0 on success. */ static int lock_log (void) @@ -255,7 +247,11 @@ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tmpbuf, sizeof (tmpbuf)-1, NULL); fputs (": ", logfp); - fputs (tmpbuf, logfp); + if (*tmpbuf && tmpbuf[strlen (tmpbuf)-1] == '\n') + tmpbuf[strlen (tmpbuf)-1] = 0; + if (*tmpbuf && tmpbuf[strlen (tmpbuf)-1] == '\r') + tmpbuf[strlen (tmpbuf)-1] = 0; + fprintf (logfp, "%s (%d)", tmpbuf, w32err); } if (buf) { Modified: trunk/src/util.h =================================================================== --- trunk/src/util.h 2007-10-08 10:19:07 UTC (rev 187) +++ trunk/src/util.h 2007-10-10 13:23:41 UTC (rev 188) @@ -94,6 +94,9 @@ void read_options (void); int write_options (void); +/*-- Convenience macros. -- */ +#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIMof(type,member) DIM(((type *)0)->member) /*-- Macros to replace ctype ones to avoid locale problems. --*/ #define spacep(p) (*(p) == ' ' || *(p) == '\t') From cvs at cvs.gnupg.org Wed Oct 10 19:17:00 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Wed, 10 Oct 2007 19:17:00 +0200 Subject: [svn] GpgOL - r189 - trunk/src Message-ID: Author: wk Date: 2007-10-10 19:16:51 +0200 (Wed, 10 Oct 2007) New Revision: 189 Modified: trunk/src/ChangeLog trunk/src/common.h trunk/src/engine-assuan.c trunk/src/ext-commands.cpp trunk/src/ext-commands.h trunk/src/main.c trunk/src/message-events.cpp trunk/src/message.cpp trunk/src/message.h trunk/src/olflange-dlgs.cpp trunk/src/olflange-ids.h trunk/src/olflange-rsrcs.rc trunk/src/olflange.cpp trunk/src/olflange.h Log: Added missing commands for engine-assuan.c. Add option to select S/MIME. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/ChangeLog 2007-10-10 17:16:51 UTC (rev 189) @@ -1,3 +1,8 @@ +2007-10-10 Werner Koch + + * main.c (read_options): Remove saveDecryptedAttachment. Add + smimeDefault. + 2007-10-08 Werner Koch * main.c (do_log): Remove trailing LF from w32 error message and Modified: trunk/src/common.h =================================================================== --- trunk/src/common.h 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/common.h 2007-10-10 17:16:51 UTC (rev 189) @@ -103,9 +103,9 @@ struct { int passwd_ttl; /* Time in seconds the passphrase is stored. */ + int smime_default; /* Use S/MIME by default. */ int encrypt_default; /* Encrypt by default. */ int sign_default; /* Sign by default. */ - int save_decrypted_attach; /* Save decrypted attachments. */ int auto_sign_attach; /* Sign all outgoing attachments. */ int enc_format; /* Encryption format for attachments. */ char *default_key; /* The key we want to always encrypt to. */ Modified: trunk/src/engine-assuan.c =================================================================== --- trunk/src/engine-assuan.c 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/engine-assuan.c 2007-10-10 17:16:51 UTC (rev 189) @@ -69,6 +69,7 @@ gpgme_data_t status_data; status_buffer_t status_buffer; /* Allocated on demand. */ int status_ready; + gpgme_data_t sigdata; /* Used by verify_closure. */ gpg_error_t last_err; }; @@ -138,6 +139,20 @@ } +static void +close_pipe (HANDLE apipe[2]) +{ + int i; + + for (i=0; i < 2; i++) + if (apipe[i] != INVALID_HANDLE_VALUE) + { + CloseHandle (apipe[i]); + apipe[i] = INVALID_HANDLE_VALUE; + } +} + + /* Duplicate HANDLE into the server's process and close HANDLE. Note that HANDLE is closed even if the function fails. Returns the duplicated handle on success or INVALID_HANDLE_VALUE on error. */ @@ -1099,10 +1114,21 @@ } +static const char * +get_protocol_name (protocol_t protocol) +{ + switch (protocol) + { + case PROTOCOL_OPENPGP: return "OpenPGP"; break; + case PROTOCOL_SMIME: return "CMS"; break; + default: return NULL; + } +} + /* Note that this closure is called in the context of the - waiter_thread. */ + async_worker_thread. */ static void encrypt_closure (closure_data_t cld) { @@ -1134,7 +1160,11 @@ pid_t pid; int i; char *p; + const char *protocol_name; + if (!(protocol_name = get_protocol_name (protocol))) + return gpg_error(GPG_ERR_INV_VALUE); + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); if (err) return err; @@ -1143,8 +1173,7 @@ return err; if ((err = create_io_pipe (outpipe, pid, 0))) { - CloseHandle (inpipe[0]); - CloseHandle (outpipe[0]); + close_pipe (inpipe); return err; } @@ -1183,12 +1212,8 @@ cmdid, NULL, 0); enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, cmdid, NULL, 1 /* Wait on success */); - err = start_command (ctx, cld, cmdid, - (protocol == PROTOCOL_OPENPGP - ? "ENCRYPT --protocol=OpenPGP" - : protocol == PROTOCOL_SMIME - ? "ENCRYPT --protocol=CMS" - : "ENCRYPT --protocol=unknown-protocol")); + snprintf (line, sizeof line, "ENCRYPT --protocol=%s", protocol_name); + err = start_command (ctx, cld, cmdid, line); cld = NULL; /* Now owned by start_command. */ if (err) goto leave; @@ -1198,14 +1223,8 @@ if (err) { /* Fixme: Cancel stuff in the work_queue. */ - if (inpipe[0] != INVALID_HANDLE_VALUE) - CloseHandle (inpipe[0]); - if (inpipe[1] != INVALID_HANDLE_VALUE) - CloseHandle (inpipe[1]); - if (outpipe[0] != INVALID_HANDLE_VALUE) - CloseHandle (outpipe[0]); - if (outpipe[1] != INVALID_HANDLE_VALUE) - CloseHandle (outpipe[1]); + close_pipe (inpipe); + close_pipe (outpipe); xfree (cld); assuan_disconnect (ctx); } @@ -1216,33 +1235,278 @@ +/* Note that this closure is called in the context of the + async_worker_thread. */ +static void +sign_closure (closure_data_t cld) +{ + engine_private_finished (cld->filter, cld->final_err); +} + + +/* Created a detached signature for INDATA and write it to OUTDATA. + On termination of the signing command engine_private_finished() is + called with FILTER as the first argument. */ int op_assuan_sign (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpg_error_t err; + closure_data_t cld; + assuan_context_t ctx; + char line[1024]; + HANDLE inpipe[2], outpipe[2]; + ULONG cmdid; + pid_t pid; + const char *protocol_name; + + + if (!(protocol_name = get_protocol_name (protocol))) + return gpg_error(GPG_ERR_INV_VALUE); + + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); + if (err) + return err; + + if ((err = create_io_pipe (inpipe, pid, 1))) + return err; + if ((err = create_io_pipe (outpipe, pid, 0))) + { + close_pipe (inpipe); + return err; + } + + cld = xcalloc (1, sizeof *cld); + cld->closure = sign_closure; + cld->filter = filter; + + err = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + snprintf (line, sizeof line, "INPUT FD=%ld", (unsigned long int)inpipe[0]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + snprintf (line, sizeof line, "OUTPUT FD=%ld", (unsigned long int)outpipe[1]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + /* FIXME: Implement the optinonal SENDER command. */ + + enqueue_callback (" input", ctx, indata, inpipe[1], 1, finalize_handler, + cmdid, NULL, 0); + enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, + cmdid, NULL, 1 /* Wait on success */); + + snprintf (line, sizeof line, "SIGN --protocol=%s --detached", + protocol_name); + err = start_command (ctx, cld, cmdid, line); + cld = NULL; /* Now owned by start_command. */ + if (err) + goto leave; + + + leave: + if (err) + { + /* Fixme: Cancel stuff in the work_queue. */ + close_pipe (inpipe); + close_pipe (outpipe); + xfree (cld); + assuan_disconnect (ctx); + } + else + engine_private_set_cancel (filter, ctx); + return err; } + +/* Note that this closure is called in the context of the + async_worker_thread. */ +static void +decrypt_closure (closure_data_t cld) +{ + engine_private_finished (cld->filter, cld->final_err); +} + + +/* Decrypt data from INDATA to OUTDATE. If WITH_VERIFY is set, the + signature of a PGP/MIME combined message is also verified the same + way as with op_assuan_verify. */ int op_assuan_decrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd, int with_verify) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpg_error_t err; + closure_data_t cld; + assuan_context_t ctx; + char line[1024]; + HANDLE inpipe[2], outpipe[2]; + ULONG cmdid; + pid_t pid; + const char *protocol_name; + + if (!(protocol_name = get_protocol_name (protocol))) + return gpg_error(GPG_ERR_INV_VALUE); + + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); + if (err) + return err; + + if ((err = create_io_pipe (inpipe, pid, 1))) + return err; + if ((err = create_io_pipe (outpipe, pid, 0))) + { + close_pipe (inpipe); + return err; + } + + cld = xcalloc (1, sizeof *cld); + cld->closure = decrypt_closure; + cld->filter = filter; + + err = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + snprintf (line, sizeof line, "INPUT FD=%ld", (unsigned long int)inpipe[0]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + snprintf (line, sizeof line, "OUTPUT FD=%ld", (unsigned long int)outpipe[1]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + enqueue_callback (" input", ctx, indata, inpipe[1], 1, finalize_handler, + cmdid, NULL, 0); + enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, + cmdid, NULL, 1 /* Wait on success */); + + snprintf (line, sizeof line, "DECRYPT --protocol=%s%s", + protocol_name, with_verify? "":" --no-verify"); + err = start_command (ctx, cld, cmdid, line); + cld = NULL; /* Now owned by start_command. */ + if (err) + goto leave; + + + leave: + if (err) + { + /* Fixme: Cancel stuff in the work_queue. */ + close_pipe (inpipe); + close_pipe (outpipe); + xfree (cld); + assuan_disconnect (ctx); + } + else + engine_private_set_cancel (filter, ctx); + return err; } +/* Note that this closure is called in the context of the + async_worker_thread. */ +static void +verify_closure (closure_data_t cld) +{ + gpgme_data_release (cld->sigdata); + cld->sigdata = NULL; + engine_private_finished (cld->filter, cld->final_err); +} + + +/* Verify a detached message where the data is in the gpgme object + MSGDATA and the signature given as the string SIGNATURE. */ int op_assuan_verify (gpgme_protocol_t protocol, - gpgme_data_t data, const char *signature, - engine_filter_t filter, void *hwnd) + gpgme_data_t msgdata, const char *signature, + engine_filter_t filter, void *hwnd) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); + gpg_error_t err; + closure_data_t cld = NULL; + assuan_context_t ctx; + char line[1024]; + HANDLE msgpipe[2], sigpipe[2]; + ULONG cmdid; + pid_t pid; + gpgme_data_t sigdata = NULL; + const char *protocol_name; + + msgpipe[0] = INVALID_HANDLE_VALUE; + msgpipe[1] = INVALID_HANDLE_VALUE; + sigpipe[0] = INVALID_HANDLE_VALUE; + sigpipe[1] = INVALID_HANDLE_VALUE; + + if (!(protocol_name = get_protocol_name (protocol))) + return gpg_error(GPG_ERR_INV_VALUE); + + err = gpgme_data_new_from_mem (&sigdata, signature, strlen (signature), 0); + if (err) + goto leave; + + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); + if (err) + goto leave; + + if ((err = create_io_pipe (msgpipe, pid, 1))) + goto leave; + if ((err = create_io_pipe (sigpipe, pid, 1))) + goto leave; + + cld = xcalloc (1, sizeof *cld); + cld->closure = verify_closure; + cld->filter = filter; + cld->sigdata = sigdata; + + err = assuan_transact (ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + snprintf (line, sizeof line, "MESSAGE FD=%ld",(unsigned long int)msgpipe[0]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + snprintf (line, sizeof line, "INPUT FD=%ld", (unsigned long int)sigpipe[0]); + err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + enqueue_callback (" msg", ctx, msgdata, msgpipe[1], 1, finalize_handler, + cmdid, NULL, 0); + enqueue_callback (" sig", ctx, sigdata, sigpipe[1], 1, finalize_handler, + cmdid, NULL, 0); + + snprintf (line, sizeof line, "VERIFY --protocol=%s", protocol_name); + err = start_command (ctx, cld, cmdid, line); + cld = NULL; /* Now owned by start_command. */ + sigdata = NULL; /* Ditto. */ + if (err) + goto leave; + + + leave: + if (err) + { + /* Fixme: Cancel stuff in the work_queue. */ + close_pipe (msgpipe); + close_pipe (sigpipe); + gpgme_data_release (sigdata); + xfree (cld); + assuan_disconnect (ctx); + } + else + engine_private_set_cancel (filter, ctx); + return err; } Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/ext-commands.cpp 2007-10-10 17:16:51 UTC (rev 189) @@ -78,6 +78,7 @@ m_pExchExt = pParentInterface; m_lRef = 0; m_lContext = 0; + m_nCmdSelectSmime = 0; m_nCmdEncrypt = 0; m_nCmdDecrypt = 0; m_nCmdSign = 0; @@ -88,8 +89,10 @@ m_nCmdDebug2 = 0; m_nToolbarButtonID1 = 0; m_nToolbarButtonID2 = 0; + m_nToolbarButtonID3 = 0; m_nToolbarBitmap1 = 0; m_nToolbarBitmap2 = 0; + m_nToolbarBitmap3 = 0; m_hWnd = NULL; } @@ -345,6 +348,7 @@ if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) { toolbar_add_menu (pEECB, pnCommandIDBase, "", NULL, + _("use S/MIME protocol"), &m_nCmdSelectSmime, _("&encrypt message with GnuPG"), &m_nCmdEncrypt, _("&sign message with GnuPG"), &m_nCmdSign, NULL ); @@ -367,8 +371,16 @@ tbab.nID = IDB_SIGN; m_nToolbarBitmap2 = SendMessage (hwnd_toolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab); + + m_nToolbarButtonID3 = pTBEArray[tb_idx].itbbBase; + pTBEArray[tb_idx].itbbBase++; + + tbab.nID = IDB_SELECT_SMIME; + m_nToolbarBitmap3 = SendMessage (hwnd_toolbar, TB_ADDBITMAP, + 1, (LPARAM)&tbab); } + m_pExchExt->m_gpgSelectSmime = opt.smime_default; m_pExchExt->m_gpgEncrypt = opt.encrypt_default; m_pExchExt->m_gpgSign = opt.sign_default; if (force_encrypt) @@ -509,6 +521,11 @@ ul_release (message); ul_release (mdb); } + else if (nCommandID == m_nCmdSelectSmime + && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + { + m_pExchExt->m_gpgSelectSmime = !m_pExchExt->m_gpgSelectSmime; + } else if (nCommandID == m_nCmdEncrypt && m_lContext == EECONTEXT_SENDNOTEMESSAGE) { @@ -588,6 +605,13 @@ _("Check the signature now and display the result"), "GpgOL", MB_OK); } + else if (nCommandID == m_nCmdSelectSmime + && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + { + MessageBox (m_hWnd, + _("Select this option to select the S/MIME protocol."), + "GpgOL", MB_OK); + } else if (nCommandID == m_nCmdEncrypt && m_lContext == EECONTEXT_SENDNOTEMESSAGE) { @@ -656,6 +680,16 @@ _("Check the signature now and display the result"), nCharCnt); } + else if (nCommandID == m_nCmdSelectSmime + && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + { + if (lFlags == EECQHT_STATUS) + lstrcpyn (pszText, ".", nCharCnt); + if (lFlags == EECQHT_TOOLTIP) + lstrcpyn (pszText, + _("Use S/MIME for sign/encrypt"), + nCharCnt); + } else if (nCommandID == m_nCmdEncrypt && m_lContext == EECONTEXT_SENDNOTEMESSAGE) { @@ -749,6 +783,20 @@ lstrcpyn (description, _("Sign message with GPG"), description_size); } + else if (buttonid == m_nToolbarButtonID3 + && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + { + pTBB->iBitmap = m_nToolbarBitmap3; + pTBB->idCommand = m_nCmdSelectSmime; + pTBB->fsState = TBSTATE_ENABLED; + if (m_pExchExt->m_gpgSelectSmime) + pTBB->fsState |= TBSTATE_CHECKED; + pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK; + pTBB->dwData = 0; + pTBB->iString = -1; + lstrcpyn (description, _("Use the S/MIME protocol"), + description_size); + } else if (buttonid == m_nToolbarButtonID1 && m_lContext == EECONTEXT_VIEWER) { Modified: trunk/src/ext-commands.h =================================================================== --- trunk/src/ext-commands.h 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/ext-commands.h 2007-10-10 17:16:51 UTC (rev 189) @@ -37,6 +37,7 @@ ULONG m_lRef; ULONG m_lContext; + UINT m_nCmdSelectSmime; UINT m_nCmdEncrypt; UINT m_nCmdDecrypt; UINT m_nCmdSign; @@ -48,8 +49,10 @@ UINT m_nToolbarButtonID1; UINT m_nToolbarButtonID2; + UINT m_nToolbarButtonID3; UINT m_nToolbarBitmap1; UINT m_nToolbarBitmap2; + UINT m_nToolbarBitmap3; HWND m_hWnd; Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/main.c 2007-10-10 17:16:51 UTC (rev 189) @@ -483,8 +483,8 @@ opt.auto_sign_attach = val == NULL || *val != '1' ? 0 : 1; xfree (val); val = NULL; - load_extension_value ("saveDecryptedAttachments", &val); - opt.save_decrypted_attach = val == NULL || *val != '1'? 0 : 1; + load_extension_value ("smimeDefault", &val); + opt.smime_default = val == NULL || *val != '1'? 0 : 1; xfree (val); val = NULL; load_extension_value ("encryptDefault", &val); @@ -566,9 +566,9 @@ int value; char *s_val; } table[] = { + {"smimeDefault", 0, opt.smime_default}, {"encryptDefault", 0, opt.encrypt_default}, {"signDefault", 0, opt.sign_default}, - {"saveDecryptedAttachments", 0, opt.save_decrypted_attach}, {"autoSignAttachments", 0, opt.auto_sign_attach}, {"previewDecrypt", 0, opt.preview_decrypt}, {"storePasswdTime", 1, opt.passwd_ttl}, Modified: trunk/src/message-events.cpp =================================================================== --- trunk/src/message-events.cpp 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/message-events.cpp 2007-10-10 17:16:51 UTC (rev 189) @@ -272,12 +272,16 @@ HRESULT hr = eecb->GetObject (&pMDB, (LPMAPIPROP *)&msg); if (SUCCEEDED (hr)) { + protocol_t proto = (m_pExchExt->m_gpgSelectSmime + ? PROTOCOL_SMIME + : PROTOCOL_OPENPGP); + if (m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) - rc = message_sign_encrypt (msg, hWnd); + rc = message_sign_encrypt (msg, proto, hWnd); else if (m_pExchExt->m_gpgEncrypt && !m_pExchExt->m_gpgSign) - rc = message_encrypt (msg, hWnd); + rc = message_encrypt (msg, proto, hWnd); else if (!m_pExchExt->m_gpgEncrypt && m_pExchExt->m_gpgSign) - rc = message_sign (msg, hWnd); + rc = message_sign (msg, proto, hWnd); else rc = 0; Modified: trunk/src/message.cpp =================================================================== --- trunk/src/message.cpp 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/message.cpp 2007-10-10 17:16:51 UTC (rev 189) @@ -741,7 +741,7 @@ static int -sign_encrypt (LPMESSAGE message, HWND hwnd, int signflag) +sign_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd, int signflag) { gpg_error_t err; char **recipients; @@ -757,9 +757,9 @@ else { if (signflag) - err = mime_sign_encrypt (message, PROTOCOL_OPENPGP, recipients); + err = mime_sign_encrypt (message, protocol, recipients); else - err = mime_encrypt (message, PROTOCOL_OPENPGP, recipients); + err = mime_encrypt (message, protocol, recipients); if (err) { char buf[200]; @@ -776,11 +776,11 @@ /* Sign the MESSAGE. */ int -message_sign (LPMESSAGE message, HWND hwnd) +message_sign (LPMESSAGE message, protocol_t protocol, HWND hwnd) { gpg_error_t err; - err = mime_sign (message, PROTOCOL_OPENPGP); + err = mime_sign (message, protocol); if (err) { char buf[200]; @@ -796,17 +796,17 @@ /* Encrypt the MESSAGE. */ int -message_encrypt (LPMESSAGE message, HWND hwnd) +message_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd) { - return sign_encrypt (message, hwnd, 0); + return sign_encrypt (message, protocol, hwnd, 0); } /* Sign+Encrypt the MESSAGE. */ int -message_sign_encrypt (LPMESSAGE message, HWND hwnd) +message_sign_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd) { - return sign_encrypt (message, hwnd, 1); + return sign_encrypt (message, protocol, hwnd, 1); } Modified: trunk/src/message.h =================================================================== --- trunk/src/message.h 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/message.h 2007-10-10 17:16:51 UTC (rev 189) @@ -31,9 +31,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); +int message_sign (LPMESSAGE message, protocol_t protocol, HWND hwnd); +int message_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd); +int message_sign_encrypt (LPMESSAGE message, protocol_t protocol, HWND hwnd); #endif /*MESSAGE_H*/ Modified: trunk/src/olflange-dlgs.cpp =================================================================== --- trunk/src/olflange-dlgs.cpp 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/olflange-dlgs.cpp 2007-10-10 17:16:51 UTC (rev 189) @@ -117,7 +117,7 @@ case IDC_ENCRYPT_WITH_STANDARD_KEY: case IDC_PREFER_HTML: case IDC_SIGN_DEFAULT: - case IDC_SAVE_DECRYPTED: + case IDC_SMIME_DEFAULT: case IDC_PREVIEW_DECRYPT: case IDC_SIGN_ATTACHMENTS: SendMessage (GetParent (hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L); @@ -159,8 +159,8 @@ !!opt.sign_default, 0L); SendDlgItemMessage (hDlg, IDC_ENCRYPT_WITH_STANDARD_KEY, BM_SETCHECK, opt.enable_default_key, 0L); - SendDlgItemMessage (hDlg, IDC_SAVE_DECRYPTED, BM_SETCHECK, - !!opt.save_decrypted_attach, 0L); + SendDlgItemMessage (hDlg, IDC_SMIME_DEFAULT, BM_SETCHECK, + !!opt.smime_default, 0L); SendDlgItemMessage (hDlg, IDC_SIGN_ATTACHMENTS, BM_SETCHECK, !!opt.auto_sign_attach, 0L); SendDlgItemMessage (hDlg, IDC_PREVIEW_DECRYPT, BM_SETCHECK, @@ -198,8 +198,8 @@ (hDlg, IDC_ENCRYPT_DEFAULT, BM_GETCHECK, 0, 0L); opt.sign_default = !!SendDlgItemMessage (hDlg, IDC_SIGN_DEFAULT, BM_GETCHECK, 0, 0L); - opt.save_decrypted_attach = !!SendDlgItemMessage - (hDlg, IDC_SAVE_DECRYPTED, BM_GETCHECK, 0, 0L); + opt.smime_default = !!SendDlgItemMessage + (hDlg, IDC_SMIME_DEFAULT, BM_GETCHECK, 0, 0L); opt.auto_sign_attach = !!SendDlgItemMessage (hDlg, IDC_SIGN_ATTACHMENTS, BM_GETCHECK, 0, 0L); opt.preview_decrypt = !!SendDlgItemMessage Modified: trunk/src/olflange-ids.h =================================================================== --- trunk/src/olflange-ids.h 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/olflange-ids.h 2007-10-10 17:16:51 UTC (rev 189) @@ -16,7 +16,7 @@ #define IDB_ADD_KEYS 4003 #define IDC_ENCRYPT_WITH_STANDARD_KEY 4003 #define IDB_KEY_MANAGER 4004 -#define IDC_SAVE_DECRYPTED 4004 +#define IDC_SMIME_DEFAULT 4004 #define IDC_GPG_OPTIONS 4006 #define IDC_BITMAP 4007 #define IDB_BANNER 4009 @@ -27,5 +27,6 @@ #define IDD_GPG_OPTIONS_DE 4012 #define IDC_PREVIEW_DECRYPT 4013 #define IDC_PREFER_HTML 4014 +#define IDB_SELECT_SMIME 4015 #endif /*OLFLANGE_IDS_H*/ Modified: trunk/src/olflange-rsrcs.rc =================================================================== --- trunk/src/olflange-rsrcs.rc 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/olflange-rsrcs.rc 2007-10-10 17:16:51 UTC (rev 189) @@ -63,8 +63,8 @@ CONTROL "Neue Nachrichten per Voreinstellung signieren", IDC_SIGN_DEFAULT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 24,30,162,10 - CONTROL "Entschl?sselte Attachments automatisch speichern", - IDC_SAVE_DECRYPTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + CONTROL "S/MIME per Voreinstellung verwenden", + IDC_SMIME_DEFAULT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 24,42,175,10 CONTROL "Automatisch Attachments signieren",IDC_SIGN_ATTACHMENTS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,54,126,10 @@ -141,8 +141,8 @@ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,19,121,10 CONTROL "&Sign new messages by default",IDC_SIGN_DEFAULT,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,24,30,111,10 - CONTROL "Save decrypted message &automatically", - IDC_SAVE_DECRYPTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + CONTROL "Use S/MIME by default", + IDC_SMIME_DEFAULT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, 24,42,139,10 CONTROL "Automatically sign attachments",IDC_SIGN_ATTACHMENTS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,54,113,10 Modified: trunk/src/olflange.cpp =================================================================== --- trunk/src/olflange.cpp 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/olflange.cpp 2007-10-10 17:16:51 UTC (rev 189) @@ -290,6 +290,7 @@ m_lRef = 1; m_lContext = 0; m_hWndExchange = 0; + m_gpgSelectSmime = FALSE; m_gpgEncrypt = FALSE; m_gpgSign = FALSE; msgtype = MSGTYPE_UNKNOWN; Modified: trunk/src/olflange.h =================================================================== --- trunk/src/olflange.h 2007-10-10 13:23:41 UTC (rev 188) +++ trunk/src/olflange.h 2007-10-10 17:16:51 UTC (rev 189) @@ -41,6 +41,7 @@ HWND m_hWndExchange; /* Handle of the exchange window. */ /* Parameters for sending mails. */ + BOOL m_gpgSelectSmime; BOOL m_gpgEncrypt; BOOL m_gpgSign; From cvs at cvs.gnupg.org Thu Oct 11 15:04:09 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 11 Oct 2007 15:04:09 +0200 Subject: [svn] gpgme - r1275 - trunk/gpgme Message-ID: Author: marcus Date: 2007-10-11 15:03:59 +0200 (Thu, 11 Oct 2007) New Revision: 1275 Modified: trunk/gpgme/ChangeLog trunk/gpgme/kdpipeiodevice.cpp Log: 2007-10-11 Marcus Brinkmann * kdpipeiodevice.cpp: New version from Frank Osterfeld. Modified: trunk/gpgme/ChangeLog =================================================================== --- trunk/gpgme/ChangeLog 2007-10-09 21:23:50 UTC (rev 1274) +++ trunk/gpgme/ChangeLog 2007-10-11 13:03:59 UTC (rev 1275) @@ -1,3 +1,7 @@ +2007-10-11 Marcus Brinkmann + + * kdpipeiodevice.cpp: New version from Frank Osterfeld. + 2007-10-09 Marcus Brinkmann * kdpipeiodevice.cpp: New version from Frank Osterfeld and Marc Modified: trunk/gpgme/kdpipeiodevice.cpp =================================================================== --- trunk/gpgme/kdpipeiodevice.cpp 2007-10-09 21:23:50 UTC (rev 1274) +++ trunk/gpgme/kdpipeiodevice.cpp 2007-10-11 13:03:59 UTC (rev 1275) @@ -728,7 +728,12 @@ DWORD numRead; const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 ); mutex.lock(); - if ( !ok ) { + if ( ok ) { + if ( numRead == 0 ) { + qDebug( "%p: Reader::run: got eof (numRead==0)", this ); + eof = true; + } + } else { // !ok errorCode = static_cast( GetLastError() ); if ( errorCode == ERROR_BROKEN_PIPE ) { assert( numRead == 0 ); @@ -758,7 +763,7 @@ } #endif qDebug( "%p: Reader::run: read %ld bytes", this, static_cast(numRead) ); - qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, fd, buffer ); + qDebug( "%p: Reader::run(fd=%d): %s", this, fd, buffer ); if ( numRead > 0 ) { qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr ); From cvs at cvs.gnupg.org Thu Oct 11 19:35:40 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 11 Oct 2007 19:35:40 +0200 Subject: [svn] GnuPG - r4590 - trunk/tools Message-ID: Author: wk Date: 2007-10-11 19:35:31 +0200 (Thu, 11 Oct 2007) New Revision: 4590 Modified: trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c Log: * gpg-connect-agent.c (get_var): Expand environment variables. Suggested by Marc Mutz. (set_var): Return the value. (assign_variable): Add arg syslet. (main): New command /slet. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-02 21:46:29 UTC (rev 4589) +++ trunk/tools/ChangeLog 2007-10-11 17:35:31 UTC (rev 4590) @@ -1,3 +1,11 @@ +2007-10-11 Werner Koch + + * gpg-connect-agent.c (get_var): Expand environment variables. + Suggested by Marc Mutz. + (set_var): Return the value. + (assign_variable): Add arg syslet. + (main): New command /slet. + 2007-10-02 Werner Koch * no-libgcrypt.c (gcry_malloc_secure): New. Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-02 21:46:29 UTC (rev 4589) +++ trunk/tools/gpg-connect-agent.c 2007-10-11 17:35:31 UTC (rev 4590) @@ -166,7 +166,7 @@ } -static void +static const char * set_var (const char *name, const char *value) { variable_t var; @@ -184,6 +184,7 @@ } xfree (var->value); var->value = value? xstrdup (value) : NULL; + return var->value; } @@ -196,16 +197,22 @@ set_var (name, numbuf); } + /* Return the value of a variable. That value is valid until a - variable of the name is changed. Return NULL if not found. */ + variable of the name is changed. Return NULL if not found. Note + that envvars are copied to our variable list at the first access + and not at oprogram start. */ static const char * get_var (const char *name) { variable_t var; + const char *s; for (var = variable_table; var; var = var->next) if (!strcmp (var->name, name)) break; + if (!var && (s = getenv (name))) + return set_var (name, s); if (!var || !var->value) return NULL; return var->value; @@ -282,7 +289,7 @@ static void -assign_variable (char *line) +assign_variable (char *line, int syslet) { char *name, *p, *tmp; @@ -297,6 +304,20 @@ if (!*p) set_var (name, NULL); /* Remove variable. */ + else if (syslet) + { + tmp = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmp) + p = tmp; + if (!strcmp (p, "homedir")) + set_var (name, opt.homedir); + else + { + log_error ("undefined tag `%s'\n", p); + log_info ("valid tags are: homedir\n"); + } + xfree (tmp); + } else { tmp = opt.enable_varsubst? substitute_line (p) : NULL; @@ -601,7 +622,7 @@ static int -getinfo_pin_cb (void *opaque, const void *buffer, size_t length) +getinfo_pid_cb (void *opaque, const void *buffer, size_t length) { membuf_t *mb = opaque; put_membuf (mb, buffer, length); @@ -617,7 +638,7 @@ char *buffer; init_membuf (&mb, 100); - rc = assuan_transact (ctx, "GETINFO pid", getinfo_pin_cb, &mb, + rc = assuan_transact (ctx, "GETINFO pid", getinfo_pid_cb, &mb, NULL, NULL, NULL, NULL); put_membuf (&mb, "", 1); buffer = get_membuf (&mb, NULL); @@ -816,8 +837,12 @@ p++; if (!strcmp (cmd, "let")) { - assign_variable (p); + assign_variable (p, 0); } + else if (!strcmp (cmd, "slet")) + { + assign_variable (p, 1); + } else if (!strcmp (cmd, "showvar")) { show_variables (); @@ -929,6 +954,7 @@ "Available commands:\n" "/echo ARGS Echo ARGS.\n" "/let NAME VALUE Set variable NAME to VALUE.\n" +"/slet NAME TAG Set variable NAME to the value described by TAG.\n" "/showvar Show all variables.\n" "/definqfile NAME FILE\n" " Use content of FILE for inquiries with NAME.\n" From cvs at cvs.gnupg.org Thu Oct 11 20:18:33 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 11 Oct 2007 20:18:33 +0200 Subject: [svn] GnuPG - r4591 - trunk/tools Message-ID: Author: wk Date: 2007-10-11 20:18:24 +0200 (Thu, 11 Oct 2007) New Revision: 4591 Modified: trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c Log: Add more sytem variables: cwd, foodir and serverpid. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-11 17:35:31 UTC (rev 4590) +++ trunk/tools/ChangeLog 2007-10-11 18:18:24 UTC (rev 4591) @@ -5,6 +5,8 @@ (set_var): Return the value. (assign_variable): Add arg syslet. (main): New command /slet. + (gnu_getcwd): New. + (assign_variable): Add tag cwd, and *dir. 2007-10-02 Werner Koch Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-11 17:35:31 UTC (rev 4590) +++ trunk/tools/gpg-connect-agent.c 2007-10-11 18:18:24 UTC (rev 4591) @@ -165,6 +165,26 @@ return p; } + +static char * +gnu_getcwd (void) +{ + char *buffer; + size_t size = 100; + + for (;;) + { + buffer = xmalloc (size+1); + if (getcwd (buffer, size) == buffer) + return buffer; + xfree (buffer); + if (errno != ERANGE) + return NULL; + size *= 2; + } +} + + static const char * set_var (const char *name, const char *value) @@ -291,7 +311,7 @@ static void assign_variable (char *line, int syslet) { - char *name, *p, *tmp; + char *name, *p, *tmp, *free_me; /* Get the name. */ name = line; @@ -306,17 +326,38 @@ set_var (name, NULL); /* Remove variable. */ else if (syslet) { - tmp = opt.enable_varsubst? substitute_line (p) : NULL; - if (tmp) - p = tmp; - if (!strcmp (p, "homedir")) + free_me = opt.enable_varsubst? substitute_line (p) : NULL; + if (free_me) + p = free_me; + if (!strcmp (p, "cwd")) + { + tmp = gnu_getcwd (); + if (!tmp) + log_error ("getcwd failed: %s\n", strerror (errno)); + set_var (name, tmp); + xfree (tmp); + } + else if (!strcmp (p, "homedir")) set_var (name, opt.homedir); + else if (!strcmp (p, "sysconfdir")) + set_var (name, gnupg_sysconfdir ()); + else if (!strcmp (p, "bindir")) + set_var (name, gnupg_bindir ()); + else if (!strcmp (p, "libdir")) + set_var (name, gnupg_libdir ()); + else if (!strcmp (p, "libexecdir")) + set_var (name, gnupg_libexecdir ()); + else if (!strcmp (p, "datadir")) + set_var (name, gnupg_datadir ()); + else if (!strcmp (p, "serverpid")) + set_int_var (name, (int)server_pid); else { log_error ("undefined tag `%s'\n", p); - log_info ("valid tags are: homedir\n"); + log_info ("valid tags are: cwd, {home,bin,lib,libexec,data}dir, " + "serverpid\n"); } - xfree (tmp); + xfree (free_me); } else { From cvs at cvs.gnupg.org Thu Oct 11 21:05:00 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Thu, 11 Oct 2007 21:05:00 +0200 Subject: [svn] GpgOL - r191 - tags Message-ID: Author: wk Date: 2007-10-11 21:04:51 +0200 (Thu, 11 Oct 2007) New Revision: 191 Added: tags/gpgol-0.10.0/ Log: From cvs at cvs.gnupg.org Fri Oct 12 18:05:22 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 12 Oct 2007 18:05:22 +0200 Subject: [svn] GnuPG - r4592 - trunk/tools Message-ID: Author: wk Date: 2007-10-12 18:05:14 +0200 (Fri, 12 Oct 2007) New Revision: 4592 Modified: trunk/tools/ChangeLog trunk/tools/gpg-connect-agent.c Log: Allow ${foo} syntax for variables. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-11 18:18:24 UTC (rev 4591) +++ trunk/tools/ChangeLog 2007-10-12 16:05:14 UTC (rev 4592) @@ -1,3 +1,7 @@ +2007-10-12 Werner Koch + + * gpg-connect-agent.c (substitute_line): Allow ${foo} syntax. + 2007-10-11 Werner Koch * gpg-connect-agent.c (get_var): Expand environment variables. Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-11 18:18:24 UTC (rev 4591) +++ trunk/tools/gpg-connect-agent.c 2007-10-12 16:05:14 UTC (rev 4592) @@ -228,6 +228,8 @@ variable_t var; const char *s; + if (!*name) + return ""; for (var = variable_table; var; var = var->next) if (!strcmp (var->name, name)) break; @@ -264,10 +266,25 @@ line = p + 1; continue; } - for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++) - ; - if (*pend) + if (p[1] == '{') { + for (pend=p+2; *pend && *pend != '}' ; pend++) + ; + if (!*pend) + return result; /* Unclosed - don't substitute. */ + } + else + { + for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++) + ; + } + if (p[1] == '{' && *pend == '}') + { + *pend++ = 0; + value = get_var (p+2); + } + else if (*pend) + { int save = *pend; *pend = 0; value = get_var (p+1); From cvs at cvs.gnupg.org Fri Oct 12 20:11:51 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 12 Oct 2007 20:11:51 +0200 Subject: [svn] GpgOL - r192 - trunk/src Message-ID: Author: wk Date: 2007-10-12 20:11:41 +0200 (Fri, 12 Oct 2007) New Revision: 192 Modified: trunk/src/ChangeLog trunk/src/config-dialog.c trunk/src/engine-gpgme.c trunk/src/gpgol-ids.h trunk/src/gpgol-rsrcs.rc trunk/src/olflange-dlgs.cpp trunk/src/olflange-ids.h trunk/src/olflange-rsrcs.rc trunk/src/passphrase-dialog.c trunk/src/recipient-dialog.c trunk/src/verify-dialog.c Log: Cleaned up dialogs to use gettext. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/ChangeLog 2007-10-12 18:11:41 UTC (rev 192) @@ -1,3 +1,23 @@ +2007-10-12 Werner Koch + + * verify-dialog.c (verify_dialog_box): Do not distinguish + languages. + (verify_dlg_set_labels): New. + (verify_dlg_proc): Call it. + + * passphrase-dialog.c (passphrase_callback_box): Do not + distinguish languages. + (decrypt_key_dlg_set_labels): New. + (decrypt_key_dlg_proc): Call it. + (decrypt_key_ext_dlg_set_labels): New. + (decrypt_key_ext_dlg_proc): Call it. + + * recipient-dialog.c (recipient_dialog_box): Do not distinguish + languages. + (recipient_dialog_box2): Ditto. + (recipient_dlg_set_labels): New. + (recipient_dlg_proc): Call it. + 2007-10-11 Werner Koch * ext-commands.cpp (toolbar_add_menu): USe "@" to indicate a Modified: trunk/src/config-dialog.c =================================================================== --- trunk/src/config-dialog.c 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/config-dialog.c 2007-10-12 18:11:41 UTC (rev 192) @@ -267,7 +267,7 @@ config_dlg_set_labels (HWND dlg) { static struct { int itemid; const char *label; } labels[] = { - { IDC_T_OPT_KEYMAN_PATH, N_("Path to key-manager binary")}, + { IDC_T_OPT_KEYMAN_PATH, N_("Path to certificate manager binary")}, { IDC_T_DEBUG_LOGFILE, N_("Debug output (for analysing problems)")}, { 0, NULL} }; Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/engine-gpgme.c 2007-10-12 18:11:41 UTC (rev 192) @@ -351,8 +351,8 @@ if (!defkey) { MessageBox (hwnd, - _("The configured default encryption key is not " - "available or does not unambigiously specify a key. " + _("The configured default encryption certificate is not " + "available or does not unambigiously specify one. " "Please fix this in the option dialog.\n\n" "This message won't be be encrypted to this key!"), _("Encryption"), MB_ICONWARNING|MB_OK); @@ -826,7 +826,7 @@ if ((sum & GPGME_SIGSUM_KEY_REVOKED)) { - at_puts (a, _("Warning: One of the keys has been revoked\n")); + at_puts (a, _("Warning: One of the certificates has been revoked\n")); severe = 1; } @@ -836,13 +836,13 @@ if (t) { - at_puts (a, _("Warning: The key used to create the " + at_puts (a, _("Warning: The certificate 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 " + at_puts (a, _("Warning: At least one certification certificate " "has expired\n")); } @@ -854,7 +854,7 @@ } if ((sum & GPGME_SIGSUM_KEY_MISSING)) - at_puts (a, _("Can't verify due to a missing key or certificate\n")); + at_puts (a, _("Can't verify due to a missing certificate\n")); if ((sum & GPGME_SIGSUM_CRL_MISSING)) { @@ -913,17 +913,17 @@ { case GPGME_VALIDITY_UNKNOWN: txt = _("WARNING: We have NO indication whether " - "the key belongs to the person named " + "this certificate 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 " + txt = _("WARNING: The certificate 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 " + txt = _("WARNING: It is NOT certain that the certificate " "belongs to the person named as shown above\n"); break; case GPGME_VALIDITY_FULL: Modified: trunk/src/gpgol-ids.h =================================================================== --- trunk/src/gpgol-ids.h 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/gpgol-ids.h 2007-10-12 18:11:41 UTC (rev 192) @@ -6,19 +6,9 @@ #ifndef GPGOL_IDS_H #define GPGOL_IDS_H -#define IDD_ENC 101 #define IDD_MAIN 102 #define IDD_SYMENC 103 -#define IDD_DEC 104 #define IDD_SIG 105 -#define IDD_VRY 107 -#define IDD_DEC_EXT 108 -#define IDD_VRY_DE 111 -#define IDD_DEC_DE 113 -#define IDD_DEC_EXT_DE 114 -#define IDD_ENC_DE 115 -#define IDC_ENC_RSET1 1000 -#define IDC_ENC_RSET2 1001 #define IDC_MAIN_ENC 1002 #define IDC_ENC_OPTARMOR 1003 #define IDC_ENC_OPTSYM 1004 @@ -27,8 +17,6 @@ #define IDC_SYMENC_HASH 1007 #define IDC_SYMENC_PASS 1008 #define IDC_SYMENC_PASSCHK 1009 -#define IDC_DEC_KEYLIST 1010 -#define IDC_DEC_PASS 1011 #define IDC_SYMENC_HIDE 1012 #define IDC_MAIN_DEC 1014 #define IDC_MAIN_SIG 1016 @@ -38,29 +26,12 @@ #define IDC_SIG_PASS 1020 #define IDC_MAIN_VRY 1021 #define IDC_SIG_HIDE 1022 -#define IDC_DEC_HIDE 1023 #define IDC_MAIN_SIGNENC 1024 #define IDC_OPT_GPGPRG 1025 #define IDC_OPT_SELPRG 1026 #define IDC_OPT_HOMEDIR 1027 #define IDC_OPT_SELHOMEDIR 1028 -#define IDC_VRY_TIME 1029 -#define IDC_VRY_KEYID 1030 -#define IDC_VRY_STATUS 1031 -#define IDC_VRY_ISSUER 1032 -#define IDC_VRY_AKALIST 1033 -#define IDC_VRY_PKALGO 1034 -#define IDC_ENC_NOTFOUND 1035 -#define IDC_ENC_INFO 1036 -#define IDC_DEC_HINT 1039 -#define IDC_VRY_HINT 1040 -#define IDC_DEC_PASSINF 1041 -#define IDC_DECEXT_RSET 1042 -#define IDC_DECEXT_KEYLIST 1043 -#define IDC_DECEXT_HIDE 1044 -#define IDC_DECEXT_PASS 1045 -#define IDC_DECEXT_HINT 1046 -#define IDC_DECEXT_PASSINF 1047 + #endif /*GPGOL_IDS_H*/ Modified: trunk/src/gpgol-rsrcs.rc =================================================================== --- trunk/src/gpgol-rsrcs.rc 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/gpgol-rsrcs.rc 2007-10-12 18:11:41 UTC (rev 192) @@ -38,136 +38,95 @@ // Dialog // -IDD_ENC_DE DIALOG DISCARDABLE 0, 0, 332, 215 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auswahl des Empf?ngerschl?ssels" -FONT 8, "MS Sans Serif" -BEGIN - CONTROL "List1",IDC_ENC_RSET1,"SysListView32",LVS_REPORT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,4,314,92 - LTEXT "Ausgew?hlte Empf?nger:",IDC_STATIC, - 8,98,130,8 - CONTROL "List2",IDC_ENC_RSET2,"SysListView32",LVS_REPORT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,110,313,49 - LTEXT "Empf?nger die NICHT gefunden wurden:",IDC_ENC_INFO, - 8,161,128,8 - LISTBOX IDC_ENC_NOTFOUND,8,170,313,22,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "&OK",IDOK,221,196,50,14 - PUSHBUTTON "&Abbrechen",IDCANCEL,273,196,50,14 -END +//IDD_ENC_DE DIALOG DISCARDABLE 0, 0, 332, 215 +//STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +//CAPTION "Auswahl des Empf?ngerschl?ssels" +//FONT 8, "MS Sans Serif" +//BEGIN +// CONTROL "List1",IDC_ENC_RSET1,"SysListView32",LVS_REPORT | +// LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,4,314,92 +// LTEXT "Ausgew?hlte Empf?nger:",IDC_STATIC, +// 8,98,130,8 +// CONTROL "List2",IDC_ENC_RSET2,"SysListView32",LVS_REPORT | +// LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,110,313,49 +// LTEXT "Empf?nger die NICHT gefunden wurden:",IDC_ENC_INFO, +// 8,161,128,8 +// LISTBOX IDC_ENC_NOTFOUND,8,170,313,22,LBS_SORT | +// LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +// DEFPUSHBUTTON "&OK",IDOK,221,196,50,14 +// PUSHBUTTON "&Abbrechen",IDCANCEL,273,196,50,14 +//END +// -IDD_DEC_EXT_DE DIALOG DISCARDABLE 0, 0, 207, 143 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auswahl des geheimen Schl?ssels" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Verschl?sselt mit folgenden Public-Keys:",IDC_STATIC,7, - 4,127,8 - LISTBOX IDC_DECEXT_RSET,7,16,193,25,LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_DECEXT_KEYLIST,7,54,191,14,CBS_DROPDOWN | CBS_SORT | - WS_DISABLED | WS_VSCROLL | WS_TABSTOP - LTEXT "",IDC_DECEXT_HINT,7,73,193,8 - LTEXT "Passphrase um geheimen Schl?ssel zu entsperren", - IDC_DECEXT_PASSINF,7,85,158,8 - EDITTEXT IDC_DECEXT_PASS,7,96,192,12,ES_PASSWORD | ES_AUTOHSCROLL - CONTROL "&Eingabe ausblenden",IDC_DECEXT_HIDE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,122,108,81,10 - DEFPUSHBUTTON "OK",IDOK,98,125,50,14 - PUSHBUTTON "&Abbrechen",IDCANCEL,149,125,50,14 -END +/* IDD_DEC_DE DIALOG DISCARDABLE 0, 0, 225, 101 */ +/* STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU */ +/* CAPTION "Auswahl des geheimen Schl?ssels" */ +/* FONT 8, "MS Sans Serif" */ +/* BEGIN */ +/* COMBOBOX IDC_DEC_KEYLIST,9,7,209,58,CBS_DROPDOWNLIST | WS_VSCROLL | */ +/* WS_TABSTOP */ +/* LTEXT "",IDC_DEC_HINT,9,25,201,10 */ +/* LTEXT "Passphrase eingeben f?r den geheimen Schl?ssel", */ +/* "Enter passphrase for your secret key" */ +/* IDC_DEC_PASSINF,9,37,158,8 */ +/* EDITTEXT IDC_DEC_PASS,9,51,207,12,ES_PASSWORD | ES_AUTOHSCROLL */ +/* CONTROL "&Eingabe ausblenden",IDC_DEC_HIDE,"Button", */ +/* BS_AUTOCHECKBOX | WS_TABSTOP,138,64,81,10 */ +/* DEFPUSHBUTTON "&OK",IDOK,115,83,50,14 */ +/* PUSHBUTTON "&Cancel",IDCANCEL,167,83,50,14 */ +/* END */ -IDD_VRY_DE DIALOG DISCARDABLE 0, 0, 253, 116 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION -CAPTION "Pr?fungsresultat" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Signatur erstellt",IDC_STATIC,3,6,49,8 - EDITTEXT IDC_VRY_TIME,55,4,76,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "mit",IDC_STATIC,132,6,10,8 - EDITTEXT IDC_VRY_PKALGO,152,4,20,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "key ID",IDC_STATIC,174,7,22,8 - EDITTEXT IDC_VRY_KEYID,196,4,51,12,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_VRY_STATUS,3,29,92,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "von",IDC_STATIC,98,31,13,8 - EDITTEXT IDC_VRY_ISSUER,117,29,131,13,ES_AUTOHSCROLL | - ES_READONLY - LTEXT "auch bekannt als",IDC_STATIC,3,47,56,8 - LISTBOX IDC_VRY_AKALIST,3,56,245,25,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - LTEXT "",IDC_VRY_HINT,3,83,245,10 - DEFPUSHBUTTON "&OK",IDOK,198,96,50,14 -END -IDD_DEC_DE DIALOG DISCARDABLE 0, 0, 225, 101 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auswahl des geheimen Schl?ssels" -FONT 8, "MS Sans Serif" -BEGIN - COMBOBOX IDC_DEC_KEYLIST,9,7,209,58,CBS_DROPDOWNLIST | WS_VSCROLL | - WS_TABSTOP - LTEXT "",IDC_DEC_HINT,9,25,201,10 - LTEXT "Passphrase eingeben f?r den geheimen Schl?ssel", - IDC_DEC_PASSINF,9,37,158,8 - EDITTEXT IDC_DEC_PASS,9,51,207,12,ES_PASSWORD | ES_AUTOHSCROLL - CONTROL "&Eingabe ausblenden",IDC_DEC_HIDE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,138,64,81,10 - DEFPUSHBUTTON "&OK",IDOK,115,83,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,167,83,50,14 -END +/* IDD_DEC_EXT_DE DIALOG DISCARDABLE 0, 0, 207, 143 */ +/* STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU */ +/* CAPTION "Auswahl des geheimen Schl?ssels" */ +/* FONT 8, "MS Sans Serif" */ +/* BEGIN */ +/* LTEXT "Verschl?sselt mit folgenden Public-Keys:",IDC_STATIC,7, */ +/* "Encrypted with the following public-keys:" */ +/* 4,127,8 */ +/* LISTBOX IDC_DECEXT_RSET,7,16,193,25,LBS_NOINTEGRALHEIGHT | */ +/* WS_VSCROLL | WS_TABSTOP */ +/* COMBOBOX IDC_DECEXT_KEYLIST,7,54,191,14,CBS_DROPDOWN | CBS_SORT | */ +/* WS_DISABLED | WS_VSCROLL | WS_TABSTOP */ +/* LTEXT "",IDC_DECEXT_HINT,7,73,193,8 */ +/* LTEXT "Passphrase um geheimen Schl?ssel zu entsperren", */ +/* "Enter passphrase for your secret key" */ +/* IDC_DECEXT_PASSINF,7,85,158,8 */ +/* EDITTEXT IDC_DECEXT_PASS,7,96,192,12,ES_PASSWORD | ES_AUTOHSCROLL */ +/* CONTROL "&Eingabe ausblenden",IDC_DECEXT_HIDE,"Button", */ +/* "&Hide Typing" */ +/* BS_AUTOCHECKBOX | WS_TABSTOP,122,108,81,10 */ +/* DEFPUSHBUTTON "OK",IDOK,98,125,50,14 */ +/* PUSHBUTTON "&Abbrechen",IDCANCEL,149,125,50,14 */ +/* END */ -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// +/* IDD_VRY_DE DIALOG DISCARDABLE 0, 0, 253, 116 */ +/* STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION */ +/* CAPTION "Pr?fungsresultat" */ +/* FONT 8, "MS Sans Serif" */ +/* BEGIN */ +/* LTEXT "Signatur erstellt",IDC_STATIC,3,6,49,8 */ +/* EDITTEXT IDC_VRY_TIME,55,4,76,12,ES_AUTOHSCROLL | ES_READONLY */ +/* LTEXT "mit",IDC_STATIC,132,6,10,8 */ +/* EDITTEXT IDC_VRY_PKALGO,152,4,20,12,ES_AUTOHSCROLL | ES_READONLY */ -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_ENC_DE, DIALOG - BEGIN - LEFTMARGIN, 4 - RIGHTMARGIN, 326 - TOPMARGIN, 3 - BOTTOMMARGIN, 211 - END +/* LTEXT "key ID",IDC_STATIC,174,7,22,8 */ +/* EDITTEXT IDC_VRY_KEYID,196,4,51,12,ES_AUTOHSCROLL | ES_READONLY */ +/* EDITTEXT IDC_VRY_STATUS,3,29,92,12,ES_AUTOHSCROLL | ES_READONLY */ - IDD_DEC_EXT_DE, DIALOG - BEGIN - LEFTMARGIN, 1 - RIGHTMARGIN, 202 - TOPMARGIN, 3 - BOTTOMMARGIN, 139 - END +/* LTEXT "von",IDC_STATIC,98,31,13,8 */ +/* EDITTEXT IDC_VRY_ISSUER,117,29,131,13,ES_AUTOHSCROLL | */ +/* ES_READONLY */ +/* LTEXT "auch bekannt als",IDC_STATIC,3,47,56,8 */ +/* LISTBOX IDC_VRY_AKALIST,3,56,245,25,LBS_SORT | */ +/* LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP */ +/* LTEXT "",IDC_VRY_HINT,3,83,245,10 */ +/* DEFPUSHBUTTON "&OK",IDOK,198,96,50,14 */ +/* END */ - IDD_OPT_DE, DIALOG - BEGIN - LEFTMARGIN, 2 - RIGHTMARGIN, 162 - TOPMARGIN, 4 - BOTTOMMARGIN, 115 - END - IDD_VRY_DE, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 248 - TOPMARGIN, 4 - BOTTOMMARGIN, 110 - END - - IDD_DEC_DE, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 218 - TOPMARGIN, 3 - BOTTOMMARGIN, 97 - END -END -#endif // APSTUDIO_INVOKED - #endif // Deutsch (Deutschland) resources ///////////////////////////////////////////////////////////////////////////// @@ -186,147 +145,37 @@ // Dialog // -IDD_DEC DIALOG DISCARDABLE 0, 0, 225, 87 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Secret Key Dialog" -FONT 8, "MS Sans Serif" -BEGIN - COMBOBOX IDC_DEC_KEYLIST,9,7,209,58,CBS_DROPDOWNLIST | WS_VSCROLL | - WS_TABSTOP - LTEXT "",IDC_DEC_HINT,9,25,201,10 - LTEXT "Enter passphrase for your secret key",IDC_DEC_PASSINF,9, - 37,116,8 - CONTROL "&Hide Typing",IDC_DEC_HIDE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,162,37,54,10 - EDITTEXT IDC_DEC_PASS,9,51,207,12,ES_PASSWORD | ES_AUTOHSCROLL - DEFPUSHBUTTON "&OK",IDOK,115,69,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,167,69,50,14 -END +/* IDD_VRY DIALOG DISCARDABLE 0, 0, 253, 116 */ +/* STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION */ +/* CAPTION "Verification Result" */ +/* FONT 8, "MS Sans Serif" */ +/* BEGIN */ +/* LTEXT "Signature made",IDC_STATIC,3,6,50,8 */ +/* EDITTEXT IDC_VRY_TIME,55,4,76,12,ES_AUTOHSCROLL | ES_READONLY */ +/* LTEXT "using",IDC_STATIC,132,6,18,8 */ +/* EDITTEXT IDC_VRY_PKALGO,152,4,20,12,ES_AUTOHSCROLL | ES_READONLY */ +/* LTEXT "key ID",IDC_STATIC,174,7,22,8 */ +/* EDITTEXT IDC_VRY_KEYID,196,4,51,12,ES_AUTOHSCROLL | ES_READONLY */ +/* EDITTEXT IDC_VRY_STATUS,3,29,92,12,ES_AUTOHSCROLL | ES_READONLY */ +/* LTEXT "from",IDC_STATIC,98,31,14,8 */ +/* EDITTEXT IDC_VRY_ISSUER,117,29,131,13,ES_AUTOHSCROLL | */ +/* ES_READONLY */ +/* LTEXT "also known as",IDC_STATIC,3,47,46,8 */ +/* LISTBOX IDC_VRY_AKALIST,3,56,245,25,LBS_SORT | */ +/* LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP */ +/* LTEXT "",IDC_VRY_HINT,3,83,245,10 */ +/* DEFPUSHBUTTON "&OK",IDOK,198,96,50,14 */ +/* END */ -IDD_VRY DIALOG DISCARDABLE 0, 0, 253, 116 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION -CAPTION "Verification Result" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Signature made",IDC_STATIC,3,6,50,8 - EDITTEXT IDC_VRY_TIME,55,4,76,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "using",IDC_STATIC,132,6,18,8 - EDITTEXT IDC_VRY_PKALGO,152,4,20,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "key ID",IDC_STATIC,174,7,22,8 - EDITTEXT IDC_VRY_KEYID,196,4,51,12,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_VRY_STATUS,3,29,92,12,ES_AUTOHSCROLL | ES_READONLY - LTEXT "from",IDC_STATIC,98,31,14,8 - EDITTEXT IDC_VRY_ISSUER,117,29,131,13,ES_AUTOHSCROLL | - ES_READONLY - LTEXT "also known as",IDC_STATIC,3,47,46,8 - LISTBOX IDC_VRY_AKALIST,3,56,245,25,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - LTEXT "",IDC_VRY_HINT,3,83,245,10 - DEFPUSHBUTTON "&OK",IDOK,198,96,50,14 -END - -IDD_ENC DIALOG DISCARDABLE 0, 0, 332, 215 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Recipient Dialog" -FONT 8, "MS Sans Serif" -BEGIN - CONTROL "List1",IDC_ENC_RSET1,"SysListView32",LVS_REPORT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,4,314,92 - CONTROL "List2",IDC_ENC_RSET2,"SysListView32",LVS_REPORT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,98,313,49 - LTEXT "Recipient which were NOT found",IDC_ENC_INFO,8,149,106, - 8 - LISTBOX IDC_ENC_NOTFOUND,8,158,313,22,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "&OK",IDOK,221,196,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,273,196,50,14 -END - -IDD_DEC_EXT DIALOG DISCARDABLE 0, 0, 205, 134 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Secret Key Dialog" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Encrypted with the following public-keys:",IDC_STATIC,7, - 4,128,8 - LISTBOX IDC_DECEXT_RSET,7,16,193,25,LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_DECEXT_KEYLIST,8,54,191,14,CBS_DROPDOWN | CBS_SORT | - WS_DISABLED | WS_VSCROLL | WS_TABSTOP - LTEXT "",IDC_DECEXT_HINT,7,73,193,8 - LTEXT "Enter passphrase for your secret key", - IDC_DECEXT_PASSINF,7,83,116,8 - CONTROL "&Hide Typing",IDC_DECEXT_HIDE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,144,82,54,10 - EDITTEXT IDC_DECEXT_PASS,7,95,192,12,ES_PASSWORD | ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,98,116,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,150,116,50,14 -END - - ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_DEC, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 218 - TOPMARGIN, 3 - BOTTOMMARGIN, 83 - END - IDD_OPT, DIALOG - BEGIN - LEFTMARGIN, 2 - RIGHTMARGIN, 162 - TOPMARGIN, 4 - BOTTOMMARGIN, 115 - END - - IDD_VRY, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 248 - TOPMARGIN, 4 - BOTTOMMARGIN, 110 - END - - IDD_ENC, DIALOG - BEGIN - LEFTMARGIN, 4 - RIGHTMARGIN, 326 - TOPMARGIN, 3 - BOTTOMMARGIN, 211 - END - - IDD_DEC_EXT, DIALOG - BEGIN - LEFTMARGIN, 1 - RIGHTMARGIN, 200 - TOPMARGIN, 3 - BOTTOMMARGIN, 130 - END -END -#endif // APSTUDIO_INVOKED - #endif // Englisch (USA) resources ///////////////////////////////////////////////////////////////////////////// -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - Modified: trunk/src/olflange-dlgs.cpp =================================================================== --- trunk/src/olflange-dlgs.cpp 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/olflange-dlgs.cpp 2007-10-12 18:11:41 UTC (rev 192) @@ -47,7 +47,7 @@ { IDC_SMIME_DEFAULT, N_("Use S/MIME by default")}, { IDC_ENABLE_SMIME, N_("Enable the S/MIME support")}, { IDC_ENCRYPT_WITH_STANDARD_KEY, - N_("Also encrypt message with the &default key")}, + N_("Also encrypt message with the default certificate")}, { IDC_PREVIEW_DECRYPT, N_("Also decrypt in preview window")}, { IDC_PREFER_HTML, N_("Show HTML view if possible")}, @@ -219,7 +219,7 @@ { if (opt.enable_default_key) { - MessageBox (hDlg,_("The default key may not" + MessageBox (hDlg,_("The default certificate may not" " contain any spaces."), "GpgOL", MB_ICONERROR|MB_OK); bMsgResult = PSNRET_INVALID_NOCHANGEPAGE; Modified: trunk/src/olflange-ids.h =================================================================== --- trunk/src/olflange-ids.h 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/olflange-ids.h 2007-10-12 18:11:41 UTC (rev 192) @@ -43,6 +43,45 @@ #define IDC_T_DEBUG_LOGFILE 4113 #define IDC_DEBUG_LOGFILE 4114 +/* Ids for the recipient selection dialog. */ +#define IDD_ENC 4201 +#define IDC_ENC_RSET1 4210 +#define IDC_ENC_RSET2_T 4211 +#define IDC_ENC_RSET2 4212 +#define IDC_ENC_NOTFOUND_T 4213 +#define IDC_ENC_NOTFOUND 4214 +/* Ids for the two decryption dialogs. */ +#define IDD_DEC 4301 +#define IDD_DECEXT 4302 +#define IDC_DEC_KEYLIST 4310 +#define IDC_DEC_HINT 4311 +#define IDC_DEC_PASSINF 4312 +#define IDC_DEC_PASS 4313 +#define IDC_DEC_HIDE 4314 +#define IDC_DECEXT_RSET_T 4320 +#define IDC_DECEXT_RSET 4321 +#define IDC_DECEXT_KEYLIST 4322 +#define IDC_DECEXT_HINT 4323 +#define IDC_DECEXT_PASSINF 4324 +#define IDC_DECEXT_PASS 4325 +#define IDC_DECEXT_HIDE 4326 +/* Ids for the verification dialog. */ +#define IDD_VRY 4401 +#define IDC_VRY_TIME_T 4410 +#define IDC_VRY_TIME 4411 +#define IDC_VRY_PKALGO_T 4412 +#define IDC_VRY_PKALGO 4413 +#define IDC_VRY_KEYID_T 4414 +#define IDC_VRY_KEYID 4415 +#define IDC_VRY_STATUS 4416 +#define IDC_VRY_ISSUER_T 4417 +#define IDC_VRY_ISSUER 4418 +#define IDC_VRY_AKALIST_T 4419 +#define IDC_VRY_AKALIST 4420 +#define IDC_VRY_HINT 4421 + + + #endif /*OLFLANGE_IDS_H*/ Modified: trunk/src/olflange-rsrcs.rc =================================================================== --- trunk/src/olflange-rsrcs.rc 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/olflange-rsrcs.rc 2007-10-12 18:11:41 UTC (rev 192) @@ -124,6 +124,161 @@ END +/* + The dialog to select recipient keys + */ +IDD_ENC DIALOG DISCARDABLE 0, 0, 332, 215 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "GpgOL - Select Recipients" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "List1", IDC_ENC_RSET1, + "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP, + 8, 4, 314, 92 + LTEXT "Ausgew??hlte Empf??nger:", IDC_ENC_RSET2_T, + 8, 98, 130, 8 + CONTROL "List2", IDC_ENC_RSET2, + "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP, + 8, 110, 313, 49 + LTEXT "Recipient which were NOT found", IDC_ENC_NOTFOUND_T, + 8, 161, 128, 8 + + LISTBOX IDC_ENC_NOTFOUND, + 8, 170, 313, 22, LBS_SORT | LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + DEFPUSHBUTTON "&OK", IDOK, + 221, 196, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 273, 196, 50, 14 +END + + +/* + The decryption dialog used to select the secret key. +*/ +IDD_DEC DIALOG DISCARDABLE 0, 0, 225, 101 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Secret Key Selection" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_DEC_KEYLIST, + 9, 7, 209, 58, CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + + LTEXT "", IDC_DEC_HINT, + 9, 25, 201, 10 + + LTEXT "enter-passphrase", IDC_DEC_PASSINF, + 9, 37, 158, 8 + + EDITTEXT IDC_DEC_PASS, + 9, 51, 207, 12, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "&Hide Typing", IDC_DEC_HIDE, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 138, 64, 81, 10 + + DEFPUSHBUTTON "&OK", IDOK, + 115, 83, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 167, 83, 50, 14 +END + + +/* + The extended decryption dialog used to select the secret key. +*/ +IDD_DECEXT DIALOG DISCARDABLE 0, 0, 207, 134 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "GpgOL - Secret Key Selection" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "encrypted-to",IDC_DECEXT_RSET_T, + 7, 4, 128, 8 + + LISTBOX IDC_DECEXT_RSET, + 7, 16, 193, 25, LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_DECEXT_KEYLIST, + 8, 54, 191, 14, CBS_DROPDOWN | CBS_SORT | + WS_DISABLED | WS_VSCROLL | WS_TABSTOP + + LTEXT "", IDC_DECEXT_HINT, + 7, 73, 193, 8 + + LTEXT "enter-passphrase", IDC_DECEXT_PASSINF, + 7, 85, 158, 8 + + EDITTEXT IDC_DECEXT_PASS, + 7, 96, 192, 12, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "hide-typing", IDC_DECEXT_HIDE, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 122, 108, 81, 10 + + DEFPUSHBUTTON "OK", IDOK, + 98, 125, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 149, 125, 50, 14 +END + + +/* + The dialog to display verification results. +*/ +IDD_VRY DIALOG DISCARDABLE 0, 0, 253, 116 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "GpgOL - Signature Verification Result" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "made-at", IDC_VRY_TIME_T, + 3, 6, 50, 8 + + EDITTEXT IDC_VRY_TIME, + 55, 4, 76, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "using", IDC_VRY_PKALGO_T, + 132, 6, 18, 8 + + EDITTEXT IDC_VRY_PKALGO, + 152, 4, 20, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "key-id", IDC_VRY_KEYID_T, + 174, 7, 50, 8 + + EDITTEXT IDC_VRY_KEYID, + 196, 4, 51, 12, ES_AUTOHSCROLL | ES_READONLY + + EDITTEXT IDC_VRY_STATUS, + 3, 29, 92, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "from", IDC_VRY_ISSUER_T, + 98, 31, 14, 8 + + EDITTEXT IDC_VRY_ISSUER, + 117, 29, 131, 13, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "aka", IDC_VRY_AKALIST_T, + 3, 47, 56, 8 + + LISTBOX IDC_VRY_AKALIST, + 3, 56, 245, 25, LBS_SORT | LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + LTEXT "", IDC_VRY_HINT, + 3, 83, 245, 10 + + DEFPUSHBUTTON "&OK", IDOK, + 198, 96, 50, 14 +END + Modified: trunk/src/passphrase-dialog.c =================================================================== --- trunk/src/passphrase-dialog.c 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/passphrase-dialog.c 2007-10-12 18:11:41 UTC (rev 192) @@ -1,6 +1,6 @@ /* passphrase-dialog.c * Copyright (C) 2004 Timo Schulz - * Copyright (C) 2005, 2006 g10 Code GmbH + * Copyright (C) 2005, 2006, 2007 g10 Code GmbH * * This file is part of GpgOL. * @@ -29,6 +29,7 @@ #include "common.h" #include "gpgol-ids.h" +#include "olflange-ids.h" #include "passcache.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ @@ -80,7 +81,7 @@ key_hint[i] = 0; } else - key_hint = xstrdup (_("No key hint given.")); + key_hint = xstrdup (_("No certificate hint given.")); SendDlgItemMessage (dlg, ctrlid, CB_ADDSTRING, 0, (LPARAM)(const char *)key_hint); SendDlgItemMessage (dlg, ctrlid, CB_SETCURSEL, 0, 0); @@ -301,6 +302,26 @@ } +/* To avoid writing a dialog template for each language we use gettext + for the labels and hope that there is enough space in the dialog to + fit teh longest translation. */ +static void +decrypt_key_dlg_set_labels (HWND dlg) +{ + static struct { int itemid; const char *label; } labels[] = { + { IDC_DEC_PASSINF, N_("Enter passphrase to unlock the secret key")}, + { IDC_DEC_HIDE, N_("Hide typing")}, + { IDCANCEL, N_("&Cancel")}, + { 0, NULL} + }; + int i; + + for (i=0; labels[i].itemid; i++) + SetDlgItemText (dlg, labels[i].itemid, _(labels[i].label)); +} + + + static BOOL CALLBACK decrypt_key_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -327,19 +348,21 @@ (dec && dec->last_was_bad)? _("Invalid passphrase; please try again..."):""); - if (dec && !context->use_as_cb) { - context->keyarray = load_secbox (dlg, IDC_DEC_KEYLIST, &n); - /* if only one secret key is availble, it makes no sense to - ask the user to select one. */ - if (n == 1) - { - dec->signer = context->keyarray[0]; - gpgme_key_ref (context->keyarray[0]); - EndDialog (dlg, TRUE); - return FALSE; - } - } + if (dec && !context->use_as_cb) + { + context->keyarray = load_secbox (dlg, IDC_DEC_KEYLIST, &n); + /* If only one secret key is available, it makes no sense to + ask the user to select one. */ + if (n == 1) + { + dec->signer = context->keyarray[0]; + gpgme_key_ref (context->keyarray[0]); + EndDialog (dlg, TRUE); + return FALSE; + } + } + decrypt_key_dlg_set_labels (dlg); CheckDlgButton (dlg, IDC_DEC_HIDE, BST_CHECKED); center_window (dlg, NULL); if (dec && dec->hide_pwd) @@ -429,6 +452,25 @@ } +/* To avoid writing a dialog template for each language we use gettext + for the labels and hope that there is enough space in the dialog to + fit teh longest translation. */ +static void +decrypt_key_ext_dlg_set_labels (HWND dlg) +{ + static struct { int itemid; const char *label; } labels[] = { + { IDC_DECEXT_RSET_T, N_("Encrypted to the following certificates:")}, + { IDC_DECEXT_PASSINF, N_("Enter passphrase to unlock the secret key")}, + { IDC_DECEXT_HIDE, N_("Hide typing")}, + { IDCANCEL, N_("&Cancel")}, + { 0, NULL} + }; + int i; + + for (i=0; labels[i].itemid; i++) + SetDlgItemText (dlg, labels[i].itemid, _(labels[i].label)); +} + static BOOL CALLBACK decrypt_key_ext_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -457,6 +499,7 @@ if (dec) load_recipbox (dlg, IDC_DECEXT_RSET, dec->ctx); + decrypt_key_ext_dlg_set_labels (dlg); CheckDlgButton (dlg, IDC_DECEXT_HIDE, BST_CHECKED); center_window (dlg, NULL); SetFocus (GetDlgItem (dlg, IDC_DECEXT_PASS)); @@ -537,10 +580,7 @@ context.dec = &dec; context.no_encrypt_warning = encrypting; - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_DEC_DE; - else - resid = IDD_DEC; + resid = IDD_DEC; DialogBoxParam (glob_hinst, (LPCTSTR)resid, GetDesktopWindow (), decrypt_key_dlg_proc, (LPARAM)&context); @@ -700,20 +740,14 @@ dec->last_was_bad = prev_was_bad; if (!dec->decrypt_cmd) { - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_DEC_DE; - else - resid = IDD_DEC; + resid = IDD_DEC; rc = DialogBoxParam (glob_hinst, (LPCSTR)resid, GetDesktopWindow (), decrypt_key_dlg_proc, (LPARAM)&context); } else { - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_DEC_EXT_DE; - else - resid = IDD_DEC_EXT; + resid = IDD_DECEXT; rc = DialogBoxParam (glob_hinst, (LPCTSTR)resid, GetDesktopWindow (), decrypt_key_ext_dlg_proc, (LPARAM)&context); Modified: trunk/src/recipient-dialog.c =================================================================== --- trunk/src/recipient-dialog.c 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/recipient-dialog.c 2007-10-12 18:11:41 UTC (rev 192) @@ -1,6 +1,6 @@ /* recipient-dialog.c * Copyright (C) 2004 Timo Schulz - * Copyright (C) 2005, 2006 g10 Code GmbH + * Copyright (C) 2005, 2006, 2007 g10 Code GmbH * * This file is part of GpgOL. * @@ -34,6 +34,7 @@ #include "common.h" #include "gpgol-ids.h" +#include "olflange-ids.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ @@ -372,7 +373,25 @@ } } +/* To avoid writing a dialog template for each language we use gettext + for the labels and hope that there is enough space in the dialog to + fit teh longest translation. */ +static void +recipient_dlg_set_labels (HWND dlg) +{ + static struct { int itemid; const char *label; } labels[] = { + { IDC_ENC_RSET2_T, N_("Selected recipients:")}, + { IDC_ENC_NOTFOUND_T, N_("Recipient which were NOT found")}, + { IDCANCEL, N_("&Cancel")}, + { 0, NULL} + }; + int i; + for (i=0; labels[i].itemid; i++) + SetDlgItemText (dlg, labels[i].itemid, _(labels[i].label)); +} + + BOOL CALLBACK recipient_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -387,6 +406,7 @@ case WM_INITDIALOG: rset_cb = (struct recipient_cb_s *)lparam; assert (rset_cb != NULL); + recipient_dlg_set_labels (dlg); initialize_rsetbox (GetDlgItem (dlg, IDC_ENC_RSET1)); rset_cb->keyarray = load_rsetbox (GetDlgItem (dlg, IDC_ENC_RSET1), &rset_cb->keyarray_count); @@ -396,8 +416,8 @@ initialize_keybox (dlg, rset_cb); else { - /* No unknown keys and thus we need unwanted dialog windows. */ - ShowWindow (GetDlgItem (dlg, IDC_ENC_INFO), SW_HIDE); + /* No unknown keys; thus we do not need the unwanted key box. */ + ShowWindow (GetDlgItem (dlg, IDC_ENC_NOTFOUND_T), SW_HIDE); ShowWindow (GetDlgItem (dlg, IDC_ENC_NOTFOUND), SW_HIDE); } @@ -420,8 +440,9 @@ hrset = GetDlgItem (dlg, IDC_ENC_RSET2); if (ListView_GetItemCount (hrset) == 0) { - MessageBox (dlg, _("Please select at least one recipient key."), - _("Recipient Dialog"), MB_ICONINFORMATION|MB_OK); + MessageBox (dlg, + _("Please select at least one recipient certificate."), + _("Recipient Dialog"), MB_ICONINFORMATION|MB_OK); return TRUE; } @@ -501,10 +522,7 @@ *ret_rset = NULL; memset (&cb, 0, sizeof (cb)); - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_ENC_DE; - else - resid = IDD_ENC; + resid = IDD_ENC; DialogBoxParam (glob_hinst, (LPCTSTR)resid, GetDesktopWindow(), recipient_dlg_proc, (LPARAM)&cb); if (cb.opts & OPT_FLAG_CANCEL) @@ -539,10 +557,7 @@ cb.fnd_keys = fnd; cb.unknown_keys = unknown; - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_ENC_DE; - else - resid = IDD_ENC; + resid = IDD_ENC; DialogBoxParam (glob_hinst, (LPCTSTR)resid, GetDesktopWindow (), recipient_dlg_proc, (LPARAM)&cb); Modified: trunk/src/verify-dialog.c =================================================================== --- trunk/src/verify-dialog.c 2007-10-11 19:04:51 UTC (rev 191) +++ trunk/src/verify-dialog.c 2007-10-12 18:11:41 UTC (rev 192) @@ -125,14 +125,14 @@ else if (!stat || (stat & GPGME_SIGSUM_GREEN)) s = _("Good signature"); else if (stat & GPGME_SIGSUM_KEY_REVOKED) - s = _("Good signature from revoked key"); + s = _("Good signature from revoked certificate"); else if (stat & GPGME_SIGSUM_KEY_EXPIRED) - s = _("Good signature from expired key"); + s = _("Good signature from expired certificate"); else if (stat & GPGME_SIGSUM_SIG_EXPIRED) s = _("Good expired signature"); else if (stat & GPGME_SIGSUM_KEY_MISSING) { - s = _("Could not check signature: missing key"); + s = _("Could not check signature: missing certificate"); no_key = 1; } else @@ -183,14 +183,14 @@ switch (valid) { case GPGME_VALIDITY_NEVER: - s = _("Signature issued by a key we do NOT trust."); + s = _("Signature issued by a certificate we do NOT trust."); break; default: if (no_key) s = ""; else - s = _("Signature issued by a non-valid key."); + s = _("Signature issued by a non-valid certificate."); break; } SetDlgItemText (dlg, IDC_VRY_HINT, s); @@ -198,53 +198,79 @@ } + +/* To avoid writing a dialog template for each language we use gettext + for the labels and hope that there is enough space in the dialog to + fit teh longest translation. */ +static void +verify_dlg_set_labels (HWND dlg) +{ + static struct { int itemid; const char *label; } labels[] = { + { IDC_VRY_TIME_T, N_("Signature made")}, + { IDC_VRY_PKALGO_T, N_("using")}, + { IDC_VRY_KEYID_T, N_("cert-ID")}, + { IDC_VRY_ISSUER_T, N_("from")}, + { IDC_VRY_AKALIST_T,N_("also known as")}, + { 0, NULL} + }; + int i; + + for (i=0; labels[i].itemid; i++) + SetDlgItemText (dlg, labels[i].itemid, _(labels[i].label)); +} + + + static BOOL CALLBACK verify_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam) { - static struct dialog_context *ctx; + static struct dialog_context *ctx; - switch (msg) { + switch (msg) + { case WM_INITDIALOG: - - ctx = (struct dialog_context *)lparam; - load_sigbox (dlg, ctx->res, ctx->protocol); - center_window (dlg, NULL); - SetForegroundWindow (dlg); - if (ctx->filename) - { - const char *s; - - switch (ctx->protocol) - { - case GPGME_PROTOCOL_OpenPGP: - s = _("OpenPGP Verification Result"); - break; - case GPGME_PROTOCOL_CMS: - s = _("S/MIME Verification Result"); - break; + ctx = (struct dialog_context *)lparam; + load_sigbox (dlg, ctx->res, ctx->protocol); + verify_dlg_set_labels (dlg); + center_window (dlg, NULL); + SetForegroundWindow (dlg); + if (ctx->filename) + { + const char *s; + + switch (ctx->protocol) + { + case GPGME_PROTOCOL_OpenPGP: + s = _("OpenPGP Verification Result"); + break; + case GPGME_PROTOCOL_CMS: + s = _("S/MIME Verification Result"); + break; default: s = "?"; break; - } - - char *tmp = xmalloc (strlen (ctx->filename) - + strlen (s) + 100); - strcpy (stpcpy (stpcpy (stpcpy (tmp, s), - " ("), ctx->filename), ")"); - SetWindowText (dlg, tmp); - xfree (tmp); + } + + char *tmp = xmalloc (strlen (ctx->filename) + + strlen (s) + 100); + strcpy (stpcpy (stpcpy (stpcpy (tmp, s), + " ("), ctx->filename), ")"); + SetWindowText (dlg, tmp); + xfree (tmp); } - break; - + break; + case WM_COMMAND: - switch (LOWORD(wparam)) { - case IDOK: - EndDialog (dlg, TRUE); - break; - } - break; + switch (LOWORD(wparam)) + { + case IDOK: + EndDialog (dlg, TRUE); + break; + } + break; } - return FALSE; + + return FALSE; } @@ -263,10 +289,7 @@ ctx.protocol = protocol; ctx.filename = filename; - if (!strncmp (gettext_localename (), "de", 2)) - resid = IDD_VRY_DE; - else - resid = IDD_VRY; + resid = IDD_VRY; DialogBoxParam (glob_hinst, (LPCTSTR)resid, GetDesktopWindow (), verify_dlg_proc, (LPARAM)&ctx); return res->signatures->summary == GPGME_SIGSUM_GREEN? 0 : -1; From cvs at cvs.gnupg.org Fri Oct 12 21:22:45 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 12 Oct 2007 21:22:45 +0200 Subject: [svn] GpgOL - r193 - in trunk: . po src Message-ID: Author: wk Date: 2007-10-12 21:22:35 +0200 (Fri, 12 Oct 2007) New Revision: 193 Added: trunk/src/dialogs.h trunk/src/dialogs.rc Removed: trunk/src/gpgol-rsrcs.rc trunk/src/olflange-ids.h trunk/src/olflange-rsrcs.rc Modified: trunk/ChangeLog trunk/NEWS trunk/configure.ac trunk/po/POTFILES.in trunk/po/de.po trunk/po/sv.po trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/common.c trunk/src/config-dialog.c trunk/src/engine-gpgme.c trunk/src/ext-commands.cpp trunk/src/message-events.cpp trunk/src/ol-ext-callback.cpp trunk/src/olflange-dlgs.cpp trunk/src/olflange.cpp trunk/src/passphrase-dialog.c trunk/src/property-sheets.cpp trunk/src/recipient-dialog.c trunk/src/resource.rc trunk/src/verify-dialog.c Log: Revamped the i18n support. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/ChangeLog 2007-10-12 19:22:35 UTC (rev 193) @@ -1,3 +1,7 @@ +2007-10-12 Werner Koch + + * po/POTFILES.in: Add more files. + 2007-10-11 Werner Koch Released 0.10.0 development version. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/NEWS 2007-10-12 19:22:35 UTC (rev 193) @@ -1,8 +1,12 @@ -Noteworthy changes for version 0.10.0 (2007-10-11) +Noteworthy changes for version 0.10.1 ================================================== UNDER HEAVY DEVELOPMENT - DO NOT USE FOR PRODUCTION! + +Noteworthy changes for version 0.10.0 (2007-10-11) +================================================== + * Basically a complete rewrite. A lot of things are still missing but if might be useful to see the direction the development takes. Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/configure.ac 2007-10-12 19:22:35 UTC (rev 193) @@ -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.10.0]) -m4_define([my_issvn], [no]) +m4_define([my_version], [0.10.1]) +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: trunk/po/POTFILES.in =================================================================== --- trunk/po/POTFILES.in 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/po/POTFILES.in 2007-10-12 19:22:35 UTC (rev 193) @@ -1,9 +1,17 @@ +src/attached-file-events.cpp src/common.c src/config-dialog.c src/display.cpp +src/engine.c src/engine-gpgme.c +src/engine-assuan.c +src/ext-commands.cpp src/main.c +src/mapihelp.cpp +src/message-events.cpp +src/message.cpp +src/mimeparser.c src/msgcache.c src/olflange-dlgs.cpp src/olflange.cpp @@ -11,7 +19,5 @@ src/passphrase-dialog.c src/recipient-dialog.c src/rfc822parse.c -src/vasprintf.c src/verify-dialog.c src/w32-gettext.c - Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/po/de.po 2007-10-12 19:22:35 UTC (rev 193) @@ -1,27 +1,52 @@ -# de.po - German translation for GPGol -# Copyright (C) 2005 g10 Code GmbH -# This file is distributed under the same license as the GPGol package. -# Werner Koch , 2005. +# de.po - German translation for GpgOL +# Copyright (C) 2005, 2007 g10 Code GmbH +# This file is distributed under the same license as the GpgOL package. +# Werner Koch , 2005, 2007. # msgid "" msgstr "" -"Project-Id-Version: GPGol 0.9.4\n" +"Project-Id-Version: GpgOL 0.10.0\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-10-11 20:39+0200\n" -"PO-Revision-Date: 2007-10-11 18:26+0200\n" +"POT-Creation-Date: 2007-10-12 21:12+0200\n" +"PO-Revision-Date: 2007-10-12 21:12+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +#: src/attached-file-events.cpp:58 +msgid "Error creating file for attachment." +msgstr "Fehler bei der Erstellung der Datei f?r das Attachment." + +#: src/attached-file-events.cpp:71 +msgid "Error reading attachment." +msgstr "Fehler beim Lesen des Attachments." + +#: src/attached-file-events.cpp:82 src/attached-file-events.cpp:95 +msgid "Error writing attachment." +msgstr "Fehler beim Schreiben des Attachments." + +#: src/attached-file-events.cpp:216 +msgid "" +"Sorry, we are not able to decrypt this attachment.\n" +"\n" +"Please use the decrypt/verify button to decrypt the\n" +"entire message again. Then open this attachment." +msgstr "" +"Es ist leider nicht mehr m?glich, diese Attachment zu ?ffnen.\n" +"\n" +"Bitten benutzen Sie den \"Entschl?sseln/Verifizieren\" Men?punkt\n" +"um die gesamte Nachricht nochmal zu entschl?sseln. Danach k?nnen\n" +"Sie das Attachment wieder ?ffenen." + #: src/common.c:145 -msgid "GPG - Save decrypted attachment" -msgstr "GPG - Sichern der entschl?sselten Anlage" +msgid "GpgOL - Save decrypted attachment" +msgstr "GpgOL - Sichern der entschl?sselten Anlage" #: src/config-dialog.c:270 -msgid "Path to key-manager binary" -msgstr "Dateiname der Schl?sselverwaltung" +msgid "Path to certificate manager binary" +msgstr "Dateiname der Zertifikatsverwaltung" #: src/config-dialog.c:271 msgid "Debug output (for analysing problems)" @@ -31,18 +56,36 @@ msgid "Select GPG Key Manager" msgstr "Das Schl?sselverwaltungsprogramm festlegen" +#: src/engine.c:363 +msgid "" +"The user interface server is not available or does not work. Using an " +"internal user interface.\n" +"\n" +"This is limited to the OpenPGP protocol and thus S/MIME protected message " +"are not readable." +msgstr "" +"Der Dienst f?r GpgOLs Benutzerschnittstelle ist nicht verf?gbar oder " +"arbeitet nicht. Eine interne Benutzerschnittstelle wird verwendet.\n" +"\n" +"Diese ist allerdings sehr vereinfacht und kann z.B. keine S/MIME " +"verschl?sselten Nachrichten entschl?sseln." + +#: src/engine.c:367 +msgid "GpgOL" +msgstr "GpgOL" + #: src/engine-gpgme.c:354 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 certificate is not available or does not " +"unambigiously specify one. Please fix this in the option dialog.\n" "\n" -"This message won't be be encrypted to this key!" +"This message won't be be encrypted to this certificate!" msgstr "" -"Der voreingestellte zus?tzliche Schl?ssel zum Verschl?sseln ist nicht\n" +"Das voreingestellte zus?tzliche Zertifikat zum Verschl?sseln ist nicht\n" "vorhanden oder nicht eindeutig. Bitte beheben Sie dies in den\n" "Optionseinstellungen.\n" "\n" -"Die Nachricht wird deswegen nicht f?r diesen Schl?ssel verschl?sselt!" +"Die Nachricht wird deswegen nicht f?r dieses Zertifikat verschl?sselt!" #: src/engine-gpgme.c:358 msgid "Encryption" @@ -65,27 +108,27 @@ msgstr "Status der Unterschrift ist \"rot\"\n" #: src/engine-gpgme.c:829 -msgid "Warning: One of the keys has been revoked\n" -msgstr "Warnung: Einer der Schl?ssel wurde widerrufen\n" +msgid "Warning: One of the certificates has been revoked\n" +msgstr "Warnung: Eines der Zertifikate wurde widerrufen\n" #: src/engine-gpgme.c:839 -msgid "Warning: The key used to create the signature expired at: " +msgid "Warning: The certificate used to create the signature expired at: " msgstr "" -"Warnung: Der Schl?ssel mit der diese Unterschrift erzeugt wurde verfiel am: " +"Warnung: Das Zertifikat mit der diese Unterschrift erzeugt wurde verfiel am: " #: src/engine-gpgme.c:845 -msgid "Warning: At least one certification key has expired\n" +msgid "Warning: At least one certification certificate has expired\n" msgstr "" -"Warnung: Mindestens einer der Zertifizierungsschl?ssel ist abgelaufen\n" +"Warnung: Mindestens eines der Zertifizierungs-Zertifikate ist abgelaufen\n" #: src/engine-gpgme.c:851 msgid "Warning: The signature expired at: " msgstr "Die Unterschrift verfiel am: " #: src/engine-gpgme.c:857 -msgid "Can't verify due to a missing key or certificate\n" +msgid "Can't verify due to a missing certificate\n" msgstr "" -"Aufrund eines fehlenden Schl?ssels ist eine ?berpr?fung nicht m?glich\n" +"Aufrund eines fehlenden Zertifikats ist eine ?berpr?fung nicht m?glich\n" #: src/engine-gpgme.c:861 msgid "The CRL is not available\n" @@ -105,23 +148,24 @@ #: src/engine-gpgme.c:915 msgid "" -"WARNING: We have NO indication whether the key belongs to the person named " -"as shown above\n" +"WARNING: We have NO indication whether this certificate belongs to the " +"person named as shown above\n" msgstr "" -"WARNUNG: Es gibt keinen Hinweis darauf, ob der Schl?ssel wirklich der Person " -"geh?rt, die oben angezeigt ist\n" +"WARNUNG: Es gibt keinen Hinweis darauf, ob dieses Zertifikat wirklich der " +"Person geh?rt, die oben angezeigt ist\n" #: src/engine-gpgme.c:922 -msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" +msgid "" +"WARNING: The certificate 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" +"WARNUNG: Das Zertifikat geh?rt NICHT der Person die oben angezeigt ist\n" #: src/engine-gpgme.c:926 msgid "" -"WARNING: It is NOT certain that the key belongs to the person named as shown " -"above\n" +"WARNING: It is NOT certain that the certificate belongs to the person named " +"as shown above\n" msgstr "" -"WARNING: Es ist nicht sicher, da? der Schl?ssel der Person geh?rt, die oben " +"WARNING: Es ist nicht sicher, da? das Zertifikat der Person geh?rt, die oben " "angezeigt ist\n" #: src/engine-gpgme.c:959 @@ -164,6 +208,176 @@ msgid "*** End Notation ***\n" msgstr "*** Ende Notation ***\n" +#: src/ext-commands.cpp:325 +msgid "&Decrypt and verify message" +msgstr "Entschl?sseln/Pr?fen der Nachricht" + +#: src/ext-commands.cpp:326 +msgid "&Verify signature" +msgstr "&Unterschrift pr?fen" + +#: src/ext-commands.cpp:327 +msgid "&Display crypto information" +msgstr "~Krypto Informationen anzeigen" + +#: src/ext-commands.cpp:353 +msgid "use S/MIME protocol" +msgstr "S/MIME verwenden" + +#: src/ext-commands.cpp:354 +msgid "&encrypt message with GnuPG" +msgstr "Nachricht mit GnuPG verschl?sseln" + +#: src/ext-commands.cpp:355 +msgid "&sign message with GnuPG" +msgstr "Nachricht mit GnuPG unterschreiben" + +#: src/ext-commands.cpp:397 +msgid "GnuPG Certificate &Manager" +msgstr "GnuPG Zertifikats&verwaltung" + +#: src/ext-commands.cpp:548 +msgid "Could not start certificate manager" +msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden" + +#: src/ext-commands.cpp:595 +msgid "Select this option to decrypt and verify the message." +msgstr "" +"W?hlen Sie diese Option um die Nachricht zu entschl?sseln bzw. zu " +"verifizieren." + +#: src/ext-commands.cpp:602 +msgid "Select this option to show information on the crypto status" +msgstr "" +"W?hlen Sie diese Option um Informationen ?ber den Krypto-Status der " +"Nachricht anzuzeigen." + +#: src/ext-commands.cpp:610 src/ext-commands.cpp:686 +msgid "Check the signature now and display the result" +msgstr "Die digitale Unterschrift jetzt pr?fen und das Resultat anzeigen" + +#: src/ext-commands.cpp:617 +msgid "Select this option to select the S/MIME protocol." +msgstr "W?hlen Sie diese Option zum das S/MIME Protokoll auszuw?hlen." + +#: src/ext-commands.cpp:624 +msgid "Select this option to encrypt the message." +msgstr "W?hlen Sie diese Option zum Verschl?sseln der Nachricht." + +#: src/ext-commands.cpp:631 +msgid "Select this option to sign the message." +msgstr "W?hlen Sie diese Option zum Unterschreiben der Nachricht." + +#: src/ext-commands.cpp:638 +msgid "Select this option to open the certificate manager" +msgstr "W?hlen Sie diese Option zum die Zertifikatsverwaltung zu ?ffenen." + +#: src/ext-commands.cpp:667 src/ext-commands.cpp:761 +msgid "Decrypt message and verify signature" +msgstr "Nachricht entschl?sseln und Unterschrift pr?fen" + +#: src/ext-commands.cpp:676 +msgid "Show S/MIME status info" +msgstr "S/MIME Status Informationen anzeigen" + +#: src/ext-commands.cpp:696 +msgid "Use S/MIME for sign/encrypt" +msgstr "S/MIME zum signieren/verschl?sseln verwenden" + +#: src/ext-commands.cpp:706 src/ext-commands.cpp:775 +msgid "Encrypt message with GPG" +msgstr "Nachricht mit GnuPG unterschreiben" + +#: src/ext-commands.cpp:716 src/ext-commands.cpp:789 +msgid "Sign message with GPG" +msgstr "Nachricht mit GnuPG unterschreiben" + +#: src/ext-commands.cpp:726 +msgid "Open the GpgOL certificate manager" +msgstr "Zertifikatsverwaltung von GpgOL ?ffnen" + +#: src/ext-commands.cpp:803 +msgid "Use the S/MIME protocol" +msgstr "S/MIME Unterst?tzung einschalten" + +#: src/ext-commands.cpp:815 +msgid "Open the certificate manager" +msgstr "Die Zertifikatsverwaltung ?ffnen" + +#: src/mapihelp.cpp:1183 +msgid "" +"[The content of this message is not visible because it has been decrypted by " +"another Outlook session. Use the \"decrypt/verify\" command to make it " +"visible]" +msgstr "" +"[Der Inhalt dieser Nachricht ist nicht sichtbar, da sie in einer anderen " +"Outlook Sitzung entschl?sselt wurde. Verwenden Sie den Men?punkt " +"\"entschl?sseln/verifizieren\" um den Inhalt wieder sichtbar zu machen.]" + +#: src/mapihelp.cpp:1678 +msgid "" +"[The content of this message is not visible due to an processing error in " +"GpgOL.]" +msgstr "" +"[Aufgrund eines Verarbeitungsfehlers in GpgOL ist der Inhalt dieser " +"Nachricht nicht sichtbar.]" + +#: src/message-events.cpp:214 +msgid "" +"Sorry, we can only encrypt plain text messages and\n" +"no RTF messages. Please make sure that only the text\n" +"format has been selected." +msgstr "" +"Leider ist es nur m?glich reine Textnachrichten aber keine\n" +"Nachrichten im RTF Format zu verschl?sseln. Bitte stellen \n" +"Sie sicher, da? lediglich das Text Format ausgew?hlt wurde.\n" +"(In der Men?leiste: \"Format\" => \"Nur Text\")" + +#: src/message.cpp:130 +msgid "[Crypto operation failed - can't show the body of the message]" +msgstr "" +"[Krypto-Operation ist fehlgeschlagen - Der Text der Nachricht kann nicht " +"angezeigt werden.]" + +#: src/message.cpp:159 +#, c-format +msgid "" +"Message class: %s\n" +"Sig Status : %s\n" +"Structure of the message:\n" +"%s" +msgstr "" +"Nachrichtenklasse: %s\n" +"Signatur-Status: %s\n" +"Struktur der Nachricht:\n" +"%s" + +#: src/message.cpp:167 +msgid "GpgOL - Message Information" +msgstr "GpgOL - Informationen zu der Nachricht" + +#: src/message.cpp:750 +msgid "No recipients to encrypt to are given" +msgstr "Empf?nger zum Verschl?sseln wurde nicht angegeben" + +#: src/message.cpp:766 +#, c-format +msgid "Encryption failed (%s)" +msgstr "Verschl?sselungsfehler (%s)" + +#: src/message.cpp:787 +#, c-format +msgid "Signing failed (%s)" +msgstr "Unterschrifterstellungsfehler (%s)" + +#: src/mimeparser.c:929 +msgid "Error writing to stream" +msgstr "Dateischreibfehler" + +#: src/mimeparser.c:930 +msgid "I/O-Error" +msgstr "Ein-/Ausgabefehler" + #: src/olflange-dlgs.cpp:45 msgid "&Encrypt new messages by default" msgstr "Neue Nachrichten per Voreinstellung verschl?sseln" @@ -181,8 +395,8 @@ msgstr "S/MIME Unterst?tzung einschalten" #: src/olflange-dlgs.cpp:50 -msgid "Also encrypt message with the &default key" -msgstr "Nachricht ebenfalls mit voreingestellten Schl?ssel verschl?sseln" +msgid "Also encrypt message with the default certificate" +msgstr "Nachricht ebenfalls an das voreingestellte Zertifikat verschl?sseln" #: src/olflange-dlgs.cpp:51 msgid "Also decrypt in preview window" @@ -209,8 +423,9 @@ msgstr "&Erweitert..." #: src/olflange-dlgs.cpp:222 -msgid "The default key may not contain any spaces." -msgstr "Der Standardschl?ssel darf keine Leerzeichen enthalten." +msgid "The default certificate may not contain any spaces." +msgstr "" +"Der Bezeichner f?r das Standardzertifikat darf keine Leerzeichen enthalten." #: src/olflange-dlgs.cpp:244 msgid "" @@ -261,7 +476,7 @@ msgid "This is GpgOL version %s" msgstr "Dies ist GpgOL Version %s" -#: src/olflange.cpp:484 +#: src/olflange.cpp:483 msgid "" "This version of Outlook is too old!\n" "\n" @@ -278,43 +493,68 @@ "\n" "Bitte updaten Sie auf SP2 bevor Sie versuchen eine Nachricht zu versenden." -#: src/passphrase-dialog.c:83 -msgid "No key hint given." -msgstr "Kein Hinweis auf den Schl?ssel" +#: src/passphrase-dialog.c:85 +msgid "No certificate hint given." +msgstr "Kein Hinweis auf das Zertifikat" -#: src/passphrase-dialog.c:328 src/passphrase-dialog.c:456 +#: src/passphrase-dialog.c:313 src/passphrase-dialog.c:464 +msgid "Enter passphrase to unlock the secret key" +msgstr "Passphrase um geheimen Schl?ssel zu entsperren" + +#: src/passphrase-dialog.c:314 src/passphrase-dialog.c:465 +msgid "Hide typing" +msgstr "&Eingabe ausblenden" + +#: src/passphrase-dialog.c:315 src/passphrase-dialog.c:466 +#: src/recipient-dialog.c:385 +msgid "&Cancel" +msgstr "&Abbrechen" + +#: src/passphrase-dialog.c:350 src/passphrase-dialog.c:499 msgid "Invalid passphrase; please try again..." msgstr "Ung?ltige Passphrase; bitte nochmal versuchen..." -#: src/passphrase-dialog.c:355 +#: src/passphrase-dialog.c:379 msgid "Select Signing Key" msgstr "Signaturschl?ssel ausw?hlen" -#: src/recipient-dialog.c:87 +#: src/passphrase-dialog.c:463 +msgid "Encrypted to the following certificates:" +msgstr "Verschl?sselt f?r diese Zertifikate:" + +#: src/recipient-dialog.c:88 msgid "Name" msgstr "Name" -#: src/recipient-dialog.c:92 +#: src/recipient-dialog.c:93 msgid "E-Mail" msgstr "E-Mail" -#: src/recipient-dialog.c:97 +#: src/recipient-dialog.c:98 msgid "Key-Info" msgstr "Key-Info" -#: src/recipient-dialog.c:102 +#: src/recipient-dialog.c:103 msgid "Key ID" msgstr "Key-ID" -#: src/recipient-dialog.c:107 +#: src/recipient-dialog.c:108 msgid "Validity" msgstr "G?ltigkeit" -#: src/recipient-dialog.c:423 -msgid "Please select at least one recipient key." -msgstr "Bitte w?hlen Sie mindestens einen Empf?ngerschl?ssel." +#: src/recipient-dialog.c:383 +msgid "Selected recipients:" +msgstr "Ausgew?hlte Empf?nger:" -#: src/recipient-dialog.c:424 +#: src/recipient-dialog.c:384 +msgid "Recipient which were NOT found" +msgstr "Empf?nger die NICHT gefunden wurden:" + +#: src/recipient-dialog.c:444 +msgid "Please select at least one recipient certificate." +msgstr "Bitte w?hlen Sie mindestens ein Empf?ngerzertifikat." + +#: src/recipient-dialog.c:445 msgid "Recipient Dialog" msgstr "Auswahl des Empf?ngerschl?ssels" @@ -327,20 +567,20 @@ msgstr "Korrekte Unterschrift" #: src/verify-dialog.c:128 -msgid "Good signature from revoked key" -msgstr "Korrekte Unterschrift; aber Schl?ssel wurde widerrufen" +msgid "Good signature from revoked certificate" +msgstr "Korrekte Unterschrift; aber Zertifikat wurde widerrufen" #: src/verify-dialog.c:130 -msgid "Good signature from expired key" -msgstr "Korrekte Unterschrift; allerdings ist der Schl?ssel abgelaufen" +msgid "Good signature from expired certificate" +msgstr "Korrekte Unterschrift; allerdings ist das Zertifikat abgelaufen" #: src/verify-dialog.c:132 msgid "Good expired signature" msgstr "Korrekte aber abgelaufene Unterschrift" #: src/verify-dialog.c:135 -msgid "Could not check signature: missing key" -msgstr "Unterschrift konnte nicht gepr?ft werden: Schl?ssel fehlt" +msgid "Could not check signature: missing certificate" +msgstr "Unterschrift konnte nicht gepr?ft werden: Zertifikat fehlt" #: src/verify-dialog.c:139 msgid "Verification error" @@ -360,21 +600,44 @@ msgstr "Unterschrift abgelaufen am %s" #: src/verify-dialog.c:186 -msgid "Signature issued by a key we do NOT trust." -msgstr "Die Unterschrift stammt von einem Schl?ssel dem wir NICHT vertrauen." +msgid "Signature issued by a certificate we do NOT trust." +msgstr "Die Unterschrift stammt von einem Zertifikat dem wir NICHT vertrauen." #: src/verify-dialog.c:193 -msgid "Signature issued by a non-valid key." -msgstr "Die Unterschrift stammt von einem ung?ltigen Schl?ssel." +msgid "Signature issued by a non-valid certificate." +msgstr "Die Unterschrift stammt von einem ung?ltigen Zertifikat." -#: src/verify-dialog.c:220 +#: src/verify-dialog.c:209 +msgid "Signature made" +msgstr "Signatur erstellt" + +#: src/verify-dialog.c:210 +msgid "using" +msgstr "mit" + +#: src/verify-dialog.c:211 +msgid "cert-ID" +msgstr "Key-Id" + +#: src/verify-dialog.c:212 +msgid "from" +msgstr "von" + +#: src/verify-dialog.c:213 +msgid "also known as" +msgstr "auch bekannt als" + +#: src/verify-dialog.c:244 msgid "OpenPGP Verification Result" msgstr "OpenPGP Pr?fungsresultat" -#: src/verify-dialog.c:223 +#: src/verify-dialog.c:247 msgid "S/MIME Verification Result" msgstr "S/MIME Pr?fungsresultat" +#~ msgid "Debug-1 (open_inspector)" +#~ msgstr "Debug-1 (Inspektor Fenster ?ffnen)" + #~ msgid "No valid OpenPGP data found." #~ msgstr "Keine g?ltigen OpenPGP Daten gefunden" @@ -459,12 +722,6 @@ #~ msgid "Attachment Decryption" #~ msgstr "Entschl?sselung eines Anhangs" -#~ msgid "Signing Failure" -#~ msgstr "Unterschrifterstellungsfehler" - -#~ msgid "Encryption Failure" -#~ msgstr "Verschl?sselungsfehler" - #~ msgid "Attachment Encryption Failure" #~ msgstr "Verschl?sselungsfehler eines Anhangs" @@ -477,19 +734,6 @@ #~ msgid "Attachment Signing Failure" #~ msgstr "Unterschrifterstellungsfehler eines Anhangs" -#~ msgid "" -#~ "Error creating file\n" -#~ "Please select another one" -#~ msgstr "" -#~ "Fehler bei der Erstellung der Datei.\n" -#~ "Bitte w?hlen Sie eine anderen Namen." - -#~ msgid "I/O-Error" -#~ msgstr "Ein-/Ausgabefehler" - -#~ msgid "Error writing file" -#~ msgstr "Dateischreibfehler" - #~ msgid "[PGP/MIME message]" #~ msgstr "[PGP/MIME Nachricht]" @@ -502,49 +746,18 @@ #~ msgid "[PGP/MIME signature]" #~ msgstr "[PGP/MIME Signatur]" -#~ msgid "" -#~ "Sorry, we can only encrypt plain text messages and\n" -#~ "no RTF messages. Please make sure that only the text\n" -#~ "format has been selected." -#~ msgstr "" -#~ "Leider ist es nur m?glich reine Textnachrichten aber keine\n" -#~ "Nachrichten im RTF Format zu verschl?sseln. Bitte stellen \n" -#~ "Sie sicher, da? lediglich das Text Format ausgew?hlt wurde.\n" -#~ "(In der Men?leiste: \"Format\" => \"Nur Text\")" - -#~ msgid "&Decrypt and verify message" -#~ msgstr "Entschl?sseln/Pr?fen der Nachricht" - #~ msgid "GPG &encrypt message" #~ msgstr "Mit GPG &verschl?sseln" #~ msgid "GPG &sign message" #~ msgstr "Mit GPG unter&schreiben" -#~ msgid "GPG Key &Manager" -#~ msgstr "GPG Schl?ssel&verwaltung" - -#~ msgid "Could not start Key-Manager" -#~ msgstr "Dei Schl?sselverwaltung konnte nicht aufgerufen werden" - #~ msgid "Decrypt and verify the message." #~ msgstr "Entschl?sseln und Pr?fen der Nachricht." -#~ msgid "Select this option to encrypt the message." -#~ msgstr "W?hlen Sie diese Option zum Verschl?sseln der Nachricht." - -#~ msgid "Select this option to sign the message." -#~ msgstr "W?hlen Sie diese Option zum Unterschreiben der Nachricht." - #~ msgid "Open GPG Key Manager" #~ msgstr "Die GPG Schl?sselverwaltung ?ffnen" -#~ msgid "Decrypt message and verify signature" -#~ msgstr "Nachricht entschl?sseln und Unterschrift pr?fen" - -#~ msgid "Sign message with GPG" -#~ msgstr "Nachricht mit GPG unterschreiben" - #~ msgid "" #~ "If you cancel this dialog, the message will be sent in cleartext!\n" #~ "\n" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/po/sv.po 2007-10-12 19:22:35 UTC (rev 193) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-10-11 20:39+0200\n" +"POT-Creation-Date: 2007-10-12 21:12+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -15,12 +15,37 @@ "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +#: src/attached-file-events.cpp:58 +#, fuzzy +msgid "Error creating file for attachment." +msgstr "" +"Fel vid skapande av fil\n" +"V?lj en annan" + +#: src/attached-file-events.cpp:71 +msgid "Error reading attachment." +msgstr "" + +#: src/attached-file-events.cpp:82 src/attached-file-events.cpp:95 +#, fuzzy +msgid "Error writing attachment." +msgstr "Fel vid skrivning av fil" + +#: src/attached-file-events.cpp:216 +msgid "" +"Sorry, we are not able to decrypt this attachment.\n" +"\n" +"Please use the decrypt/verify button to decrypt the\n" +"entire message again. Then open this attachment." +msgstr "" + #: src/common.c:145 -msgid "GPG - Save decrypted attachment" +#, fuzzy +msgid "GpgOL - Save decrypted attachment" msgstr "GPG - Spara dekrypterad bilaga" #: src/config-dialog.c:270 -msgid "Path to key-manager binary" +msgid "Path to certificate manager binary" msgstr "" #: src/config-dialog.c:271 @@ -31,12 +56,26 @@ msgid "Select GPG Key Manager" msgstr "V?lj GPG-nyckelhanterare" +#: src/engine.c:363 +msgid "" +"The user interface server is not available or does not work. Using an " +"internal user interface.\n" +"\n" +"This is limited to the OpenPGP protocol and thus S/MIME protected message " +"are not readable." +msgstr "" + +#: src/engine.c:367 +msgid "GpgOL" +msgstr "" + #: src/engine-gpgme.c:354 +#, fuzzy 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 certificate is not available or does not " +"unambigiously specify one. Please fix this in the option dialog.\n" "\n" -"This message won't be be encrypted to this key!" +"This message won't be be encrypted to this certificate!" msgstr "" "Den konfigurerade standardkrypteringsnyckeln ?r inte tillg?nglig eller anger " "inte uttryckligen en nyckel. R?tta till det h?r i inst?llningarna.\n" @@ -64,15 +103,18 @@ msgstr "signaturens tillst?nd ?r \"r?d\"\n" #: src/engine-gpgme.c:829 -msgid "Warning: One of the keys has been revoked\n" +#, fuzzy +msgid "Warning: One of the certificates has been revoked\n" msgstr "Varning: En av nycklarna har sp?rrats\n" #: src/engine-gpgme.c:839 -msgid "Warning: The key used to create the signature expired at: " +#, fuzzy +msgid "Warning: The certificate 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:845 -msgid "Warning: At least one certification key has expired\n" +#, fuzzy +msgid "Warning: At least one certification certificate has expired\n" msgstr "Varning: ?tminstone en certifieringsnyckel har g?tt ut\n" #: src/engine-gpgme.c:851 @@ -80,7 +122,8 @@ msgstr "Varning: Signaturen gick ut den: " #: src/engine-gpgme.c:857 -msgid "Can't verify due to a missing key or certificate\n" +#, fuzzy +msgid "Can't verify due to a missing certificate\n" msgstr "Kan inte validera p? grund av en saknad nyckel eller certifikat\n" #: src/engine-gpgme.c:861 @@ -100,21 +143,25 @@ msgstr "Ett systemfel intr?ffade" #: src/engine-gpgme.c:915 +#, fuzzy msgid "" -"WARNING: We have NO indication whether the key belongs to the person named " -"as shown above\n" +"WARNING: We have NO indication whether this certificate 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:922 -msgid "WARNING: The key does NOT BELONG to the person named as shown above\n" +#, fuzzy +msgid "" +"WARNING: The certificate 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:926 +#, fuzzy msgid "" -"WARNING: It is NOT certain that the key belongs to the person named as shown " -"above\n" +"WARNING: It is NOT certain that the certificate 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" @@ -159,6 +206,172 @@ msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" +#: src/ext-commands.cpp:325 +msgid "&Decrypt and verify message" +msgstr "&Dekryptera och validera meddelandet" + +#: src/ext-commands.cpp:326 +#, fuzzy +msgid "&Verify signature" +msgstr "FELAKTIG signatur!" + +#: src/ext-commands.cpp:327 +msgid "&Display crypto information" +msgstr "" + +#: src/ext-commands.cpp:353 +msgid "use S/MIME protocol" +msgstr "" + +#: src/ext-commands.cpp:354 +#, fuzzy +msgid "&encrypt message with GnuPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:355 +#, fuzzy +msgid "&sign message with GnuPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:397 +#, fuzzy +msgid "GnuPG Certificate &Manager" +msgstr "GPG-nyckel&hanterare" + +#: src/ext-commands.cpp:548 +#, fuzzy +msgid "Could not start certificate manager" +msgstr "Kunde inte starta nyckelhanteraren" + +#: src/ext-commands.cpp:595 +#, fuzzy +msgid "Select this option to decrypt and verify the message." +msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." + +#: src/ext-commands.cpp:602 +#, fuzzy +msgid "Select this option to show information on the crypto status" +msgstr "V?lj det h?r alternativet f?r att signera meddelandet." + +#: src/ext-commands.cpp:610 src/ext-commands.cpp:686 +msgid "Check the signature now and display the result" +msgstr "" + +#: src/ext-commands.cpp:617 +#, fuzzy +msgid "Select this option to select the S/MIME protocol." +msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." + +#: src/ext-commands.cpp:624 +msgid "Select this option to encrypt the message." +msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." + +#: src/ext-commands.cpp:631 +msgid "Select this option to sign the message." +msgstr "V?lj det h?r alternativet f?r att signera meddelandet." + +#: src/ext-commands.cpp:638 +#, fuzzy +msgid "Select this option to open the certificate manager" +msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." + +#: src/ext-commands.cpp:667 src/ext-commands.cpp:761 +msgid "Decrypt message and verify signature" +msgstr "Dekryptera meddelandet och validera signaturen" + +#: src/ext-commands.cpp:676 +msgid "Show S/MIME status info" +msgstr "" + +#: src/ext-commands.cpp:696 +msgid "Use S/MIME for sign/encrypt" +msgstr "" + +#: src/ext-commands.cpp:706 src/ext-commands.cpp:775 +#, fuzzy +msgid "Encrypt message with GPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:716 src/ext-commands.cpp:789 +msgid "Sign message with GPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:726 +msgid "Open the GpgOL certificate manager" +msgstr "" + +#: src/ext-commands.cpp:803 +msgid "Use the S/MIME protocol" +msgstr "" + +#: src/ext-commands.cpp:815 +msgid "Open the certificate manager" +msgstr "" + +#: src/mapihelp.cpp:1183 +msgid "" +"[The content of this message is not visible because it has been decrypted by " +"another Outlook session. Use the \"decrypt/verify\" command to make it " +"visible]" +msgstr "" + +#: src/mapihelp.cpp:1678 +msgid "" +"[The content of this message is not visible due to an processing error in " +"GpgOL.]" +msgstr "" + +# A bit unclear in the original text +#: src/message-events.cpp:214 +msgid "" +"Sorry, we can only encrypt plain text messages and\n" +"no RTF messages. Please make sure that only the text\n" +"format has been selected." +msgstr "" +"Tyv?rr, vi kan endast kryptera vanliga textmeddelanden\n" +"och inte RTF-meddelanden. Se till att endast textformatet\n" +"har valts i inst?llningarna." + +#: src/message.cpp:130 +msgid "[Crypto operation failed - can't show the body of the message]" +msgstr "" + +#: src/message.cpp:159 +#, c-format +msgid "" +"Message class: %s\n" +"Sig Status : %s\n" +"Structure of the message:\n" +"%s" +msgstr "" + +#: src/message.cpp:167 +msgid "GpgOL - Message Information" +msgstr "" + +#: src/message.cpp:750 +msgid "No recipients to encrypt to are given" +msgstr "" + +#: src/message.cpp:766 +#, fuzzy, c-format +msgid "Encryption failed (%s)" +msgstr "Kryptering misslyckades" + +#: src/message.cpp:787 +#, fuzzy, c-format +msgid "Signing failed (%s)" +msgstr "Signering misslyckades" + +#: src/mimeparser.c:929 +#, fuzzy +msgid "Error writing to stream" +msgstr "Fel vid skrivning av fil" + +#: src/mimeparser.c:930 +msgid "I/O-Error" +msgstr "In-/Ut-fel" + #: src/olflange-dlgs.cpp:45 #, fuzzy msgid "&Encrypt new messages by default" @@ -178,7 +391,7 @@ #: src/olflange-dlgs.cpp:50 #, fuzzy -msgid "Also encrypt message with the &default key" +msgid "Also encrypt message with the default certificate" msgstr "Kryptera meddelandet med GPG" #: src/olflange-dlgs.cpp:51 @@ -206,7 +419,8 @@ msgstr "" #: src/olflange-dlgs.cpp:222 -msgid "The default key may not contain any spaces." +#, fuzzy +msgid "The default certificate may not contain any spaces." msgstr "Standardnyckeln f?r inte inneh?lla n?gra blanksteg." #: src/olflange-dlgs.cpp:244 @@ -229,7 +443,7 @@ msgid "This is GpgOL version %s" msgstr "" -#: src/olflange.cpp:484 +#: src/olflange.cpp:483 msgid "" "This version of Outlook is too old!\n" "\n" @@ -245,43 +459,70 @@ "\n" "Uppdatera ?tminstone till SP2 innan du f?rs?ker skicka ett meddelande" -#: src/passphrase-dialog.c:83 -msgid "No key hint given." +#: src/passphrase-dialog.c:85 +#, fuzzy +msgid "No certificate hint given." msgstr "Inget nyckeltips angivet." -#: src/passphrase-dialog.c:328 src/passphrase-dialog.c:456 +#: src/passphrase-dialog.c:313 src/passphrase-dialog.c:464 +msgid "Enter passphrase to unlock the secret key" +msgstr "" + +#: src/passphrase-dialog.c:314 src/passphrase-dialog.c:465 +msgid "Hide typing" +msgstr "" + +#: src/passphrase-dialog.c:315 src/passphrase-dialog.c:466 +#: src/recipient-dialog.c:385 +msgid "&Cancel" +msgstr "" + +#: src/passphrase-dialog.c:350 src/passphrase-dialog.c:499 msgid "Invalid passphrase; please try again..." msgstr "Ogiltig l?senfras; f?rs?k igen..." -#: src/passphrase-dialog.c:355 +#: src/passphrase-dialog.c:379 msgid "Select Signing Key" msgstr "V?lj signeringsnyckel" -#: src/recipient-dialog.c:87 +#: src/passphrase-dialog.c:463 +msgid "Encrypted to the following certificates:" +msgstr "" + +#: src/recipient-dialog.c:88 msgid "Name" msgstr "Namn" -#: src/recipient-dialog.c:92 +#: src/recipient-dialog.c:93 msgid "E-Mail" msgstr "E-post" -#: src/recipient-dialog.c:97 +#: src/recipient-dialog.c:98 msgid "Key-Info" msgstr "Nyckelinfo" -#: src/recipient-dialog.c:102 +#: src/recipient-dialog.c:103 msgid "Key ID" msgstr "Nyckel-id" -#: src/recipient-dialog.c:107 +#: src/recipient-dialog.c:108 msgid "Validity" msgstr "Giltighet" -#: src/recipient-dialog.c:423 -msgid "Please select at least one recipient key." +#: src/recipient-dialog.c:383 +msgid "Selected recipients:" +msgstr "" + +#: src/recipient-dialog.c:384 +msgid "Recipient which were NOT found" +msgstr "" + +#: src/recipient-dialog.c:444 +#, fuzzy +msgid "Please select at least one recipient certificate." msgstr "V?lj ?tminstone en mottagarnyckel." -#: src/recipient-dialog.c:424 +#: src/recipient-dialog.c:445 msgid "Recipient Dialog" msgstr "Mottagardialog" @@ -294,11 +535,13 @@ msgstr "Korrekt signatur" #: src/verify-dialog.c:128 -msgid "Good signature from revoked key" +#, fuzzy +msgid "Good signature from revoked certificate" msgstr "Korrekt signatur fr?n sp?rrad nyckel" #: src/verify-dialog.c:130 -msgid "Good signature from expired key" +#, fuzzy +msgid "Good signature from expired certificate" msgstr "Korrekt signatur fr?n utg?ngen nyckel" #: src/verify-dialog.c:132 @@ -306,7 +549,8 @@ msgstr "Korrekt utg?ngen signatur" #: src/verify-dialog.c:135 -msgid "Could not check signature: missing key" +#, fuzzy +msgid "Could not check signature: missing certificate" msgstr "Kunde inte kontrollera signaturen: saknar nyckel" #: src/verify-dialog.c:139 @@ -327,19 +571,41 @@ msgstr "Signaturen gick ut den %s" #: src/verify-dialog.c:186 -msgid "Signature issued by a key we do NOT trust." +#, fuzzy +msgid "Signature issued by a certificate we do NOT trust." msgstr "Signaturen utf?rdad av en nyckel som vi INTE litar p?." #: src/verify-dialog.c:193 -msgid "Signature issued by a non-valid key." +#, fuzzy +msgid "Signature issued by a non-valid certificate." msgstr "Signaturen utf?rdad av en icke-giltig nyckel." -#: src/verify-dialog.c:220 +#: src/verify-dialog.c:209 +msgid "Signature made" +msgstr "" + +#: src/verify-dialog.c:210 +msgid "using" +msgstr "" + +#: src/verify-dialog.c:211 +msgid "cert-ID" +msgstr "" + +#: src/verify-dialog.c:212 +msgid "from" +msgstr "" + +#: src/verify-dialog.c:213 +msgid "also known as" +msgstr "" + +#: src/verify-dialog.c:244 #, fuzzy msgid "OpenPGP Verification Result" msgstr "Resultat fr?n validering" -#: src/verify-dialog.c:223 +#: src/verify-dialog.c:247 #, fuzzy msgid "S/MIME Verification Result" msgstr "Resultat fr?n validering" @@ -429,12 +695,6 @@ #~ msgid "Attachment Decryption" #~ msgstr "Dekryptering av bilaga" -#~ msgid "Signing Failure" -#~ msgstr "Signering misslyckades" - -#~ msgid "Encryption Failure" -#~ msgstr "Kryptering misslyckades" - #~ msgid "Attachment Encryption Failure" #~ msgstr "Kryptering av bilaga misslyckades" @@ -447,19 +707,6 @@ #~ msgid "Attachment Signing Failure" #~ msgstr "Signering av bilaga misslyckades" -#~ msgid "" -#~ "Error creating file\n" -#~ "Please select another one" -#~ msgstr "" -#~ "Fel vid skapande av fil\n" -#~ "V?lj en annan" - -#~ msgid "I/O-Error" -#~ msgstr "In-/Ut-fel" - -#~ msgid "Error writing file" -#~ msgstr "Fel vid skrivning av fil" - #~ msgid "[PGP/MIME message]" #~ msgstr "[PGP/MIME-meddelande]" @@ -472,45 +719,14 @@ #~ msgid "[PGP/MIME signature]" #~ msgstr "[PGP/MIME-signatur]" -# A bit unclear in the original text -#~ msgid "" -#~ "Sorry, we can only encrypt plain text messages and\n" -#~ "no RTF messages. Please make sure that only the text\n" -#~ "format has been selected." -#~ msgstr "" -#~ "Tyv?rr, vi kan endast kryptera vanliga textmeddelanden\n" -#~ "och inte RTF-meddelanden. Se till att endast textformatet\n" -#~ "har valts i inst?llningarna." - -#~ msgid "&Decrypt and verify message" -#~ msgstr "&Dekryptera och validera meddelandet" - #~ msgid "GPG &encrypt message" #~ msgstr "GPG-&kryptera meddelandet" #~ msgid "GPG &sign message" #~ msgstr "GPG-&signera meddelandet" -#~ msgid "GPG Key &Manager" -#~ msgstr "GPG-nyckel&hanterare" - -#~ msgid "Could not start Key-Manager" -#~ msgstr "Kunde inte starta nyckelhanteraren" - #~ msgid "Decrypt and verify the message." #~ msgstr "Dekryptera och validera meddelandet." -#~ msgid "Select this option to encrypt the message." -#~ msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." - -#~ msgid "Select this option to sign the message." -#~ msgstr "V?lj det h?r alternativet f?r att signera meddelandet." - #~ msgid "Open GPG Key Manager" #~ msgstr "?ppna GPG-nyckelhanteraren" - -#~ msgid "Decrypt message and verify signature" -#~ msgstr "Dekryptera meddelandet och validera signaturen" - -#~ msgid "Sign message with GPG" -#~ msgstr "Signera meddelandet med GPG" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/ChangeLog 2007-10-12 19:22:35 UTC (rev 193) @@ -1,5 +1,10 @@ 2007-10-12 Werner Koch + * gpgol-rsrcs.rc: Remove. + * dialogs.rc: Renamed from olflange-rsrcs.rc. + * dialogs.h: Rename for olflange-ids.h. Changed all includers. + * Makefile.am: Adjust accordingly. + * verify-dialog.c (verify_dialog_box): Do not distinguish languages. (verify_dlg_set_labels): New. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/Makefile.am 2007-10-12 19:22:35 UTC (rev 193) @@ -12,9 +12,9 @@ ## Process this file with automake to produce Makefile.in bin_PROGRAMS = gpgol -EXTRA_DIST = versioninfo.rc.in gpgol-rsrcs.rc olflange-rsrcs.rc \ - logo.bmp decrypt.bmp encrypt.bmp sign.bmp key_mana.bmp \ - mapi32.def +EXTRA_DIST = versioninfo.rc.in mapi32.def \ + logo.bmp decrypt.bmp encrypt.bmp sign.bmp key_mana.bmp + EXEEXT = .dll AM_CFLAGS = $(GPGME_CFLAGS) $(LIBASSUAN_CFLAGS) -shared @@ -27,7 +27,7 @@ olflange.cpp olflange.h \ olflange-def.h \ olflange-dlgs.cpp \ - olflange-ids.h \ + dialogs.rc dialogs.h \ myexchext.h \ display.cpp display.h \ message.cpp message.h \ @@ -88,7 +88,7 @@ -lmapi32 -lshell32 -lgdi32 -lcomdlg32 \ -lole32 -loleaut32 -lws2_32 -ladvapi32 -resource.o: resource.rc versioninfo.rc gpgol-rsrcs.rc olflange-rsrcs.rc +resource.o: resource.rc versioninfo.rc dialogs.rc .rc.o: $(WINDRES) -I $(srcdir) -I . `test -f '$<' || echo '$(srcdir)/'`$< $@ Modified: trunk/src/common.c =================================================================== --- trunk/src/common.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/common.c 2007-10-12 19:22:35 UTC (rev 193) @@ -142,7 +142,7 @@ ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.Flags |= OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; - ofn.lpstrTitle = _("GPG - Save decrypted attachment"); + ofn.lpstrTitle = _("GpgOL - Save decrypted attachment"); ofn.lpstrFilter = filter; if (GetSaveFileName (&ofn)) Modified: trunk/src/config-dialog.c =================================================================== --- trunk/src/config-dialog.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/config-dialog.c 2007-10-12 19:22:35 UTC (rev 193) @@ -29,7 +29,7 @@ #include "common.h" #include "gpgol-ids.h" -#include "olflange-ids.h" +#include "dialogs.h" /* Registry path to GnuPG */ #define REGPATH "Software\\GNU\\GnuPG" Copied: trunk/src/dialogs.h (from rev 192, trunk/src/olflange-ids.h) =================================================================== --- trunk/src/olflange-ids.h 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/dialogs.h 2007-10-12 19:22:35 UTC (rev 193) @@ -0,0 +1,93 @@ +/* dialogs.h + + Resouces IDs for the dialogs. + */ + +#ifndef DIALOGS_H +#define DIALOGS_H + + +/* Ids used for bitmaps. */ +#define IDB_DECRYPT 3001 +#define IDB_ENCRYPT 3002 +#define IDB_SIGN 3003 +#define IDB_ADD_KEYS 3004 +#define IDB_KEY_MANAGER 3005 +#define IDB_BANNER 3006 +#define IDB_BANNER_HI 3007 +#define IDB_SELECT_SMIME 3008 + + +/* Ids used for the main config dialog. */ +#define IDD_GPG_OPTIONS 4001 +#define IDC_TIME_PHRASES 4010 +#define IDC_ENCRYPT_DEFAULT 4011 +#define IDC_SIGN_DEFAULT 4012 +#define IDC_ENCRYPT_WITH_STANDARD_KEY 4013 +#define IDC_SMIME_DEFAULT 4014 +#define IDC_GPG_OPTIONS 4015 +#define IDC_BITMAP 4016 +#define IDC_VERSION_INFO 4017 +#define IDC_ENCRYPT_TO 4018 +#define IDC_ENABLE_SMIME 4019 +#define IDC_PREVIEW_DECRYPT 4020 +#define IDC_PREFER_HTML 4021 +#define IDC_G_OPTIONS 4022 +#define IDC_G_PASSPHRASE 4023 +#define IDC_T_PASSPHRASE_TTL 4024 +#define IDC_T_PASSPHRASE_MIN 4025 + + +/* Ids for the extended options dialog. */ +#define IDD_EXT_OPTIONS 4101 +#define IDC_T_OPT_KEYMAN_PATH 4110 +#define IDC_OPT_KEYMAN_PATH 4111 +#define IDC_OPT_SEL_KEYMAN_PATH 4112 +#define IDC_T_DEBUG_LOGFILE 4113 +#define IDC_DEBUG_LOGFILE 4114 + + +/* Ids for the recipient selection dialog. */ +#define IDD_ENC 4201 +#define IDC_ENC_RSET1 4210 +#define IDC_ENC_RSET2_T 4211 +#define IDC_ENC_RSET2 4212 +#define IDC_ENC_NOTFOUND_T 4213 +#define IDC_ENC_NOTFOUND 4214 + + +/* Ids for the two decryption dialogs. */ +#define IDD_DEC 4301 +#define IDD_DECEXT 4302 +#define IDC_DEC_KEYLIST 4310 +#define IDC_DEC_HINT 4311 +#define IDC_DEC_PASSINF 4312 +#define IDC_DEC_PASS 4313 +#define IDC_DEC_HIDE 4314 +#define IDC_DECEXT_RSET_T 4320 +#define IDC_DECEXT_RSET 4321 +#define IDC_DECEXT_KEYLIST 4322 +#define IDC_DECEXT_HINT 4323 +#define IDC_DECEXT_PASSINF 4324 +#define IDC_DECEXT_PASS 4325 +#define IDC_DECEXT_HIDE 4326 + + +/* Ids for the verification dialog. */ +#define IDD_VRY 4401 +#define IDC_VRY_TIME_T 4410 +#define IDC_VRY_TIME 4411 +#define IDC_VRY_PKALGO_T 4412 +#define IDC_VRY_PKALGO 4413 +#define IDC_VRY_KEYID_T 4414 +#define IDC_VRY_KEYID 4415 +#define IDC_VRY_STATUS 4416 +#define IDC_VRY_ISSUER_T 4417 +#define IDC_VRY_ISSUER 4418 +#define IDC_VRY_AKALIST_T 4419 +#define IDC_VRY_AKALIST 4420 +#define IDC_VRY_HINT 4421 + + + +#endif /*DIALOGS_H*/ Copied: trunk/src/dialogs.rc (from rev 192, trunk/src/olflange-rsrcs.rc) =================================================================== --- trunk/src/olflange-rsrcs.rc 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/dialogs.rc 2007-10-12 19:22:35 UTC (rev 193) @@ -0,0 +1,284 @@ +/* dialogs.rc - GpgOL dialog resources. -*- c -*- + * Copyright (C) 2004, 2005, 2006, 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 this program; if not, see . + */ + + +#include "dialogs.h" + +#include "afxres.h" + + +IDB_DECRYPT BITMAP DISCARDABLE "decrypt.bmp" +IDB_ENCRYPT BITMAP DISCARDABLE "encrypt.bmp" +IDB_SIGN BITMAP DISCARDABLE "sign.bmp" +IDB_KEY_MANAGER BITMAP DISCARDABLE "key_mana.bmp" +IDB_BANNER BITMAP DISCARDABLE "logo.bmp" + + +IDD_GPG_OPTIONS DIALOG DISCARDABLE 0, 0, 266, 274 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "GpgOL" +FONT 8, "MS Sans Serif" +BEGIN + /* Options box. */ + GROUPBOX "options", IDC_G_OPTIONS, + 9, 9, 242, 112 + + CONTROL "encrypt-by-default", IDC_ENCRYPT_DEFAULT, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 19, 215, 10 + + CONTROL "sign-by-default", IDC_SIGN_DEFAULT, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 30, 215, 10 + + CONTROL "smime-by-default", IDC_SMIME_DEFAULT, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 42, 215, 10 + + CONTROL "enable-smime", IDC_ENABLE_SMIME, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 54, 215, 10 + + CONTROL "encrypt-to", IDC_ENCRYPT_WITH_STANDARD_KEY, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 67, 215, 10 + + EDITTEXT IDC_ENCRYPT_TO, + 36, 79, 133, 12, ES_AUTOHSCROLL + + CONTROL "preview-decrypt", IDC_PREVIEW_DECRYPT, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 95, 215, 10 + + CONTROL "prefer-html", IDC_PREFER_HTML, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 24, 107, 215, 10 + + /* Passphrase option box. */ + GROUPBOX "Passphrase", IDC_G_PASSPHRASE, + 9, 124, 242, 31 + + LTEXT "passphrase-ttl", IDC_T_PASSPHRASE_TTL, + 24, 136, 80, 8 + + EDITTEXT IDC_TIME_PHRASES, + 107, 135, 39, 14, ES_AUTOHSCROLL + + LTEXT "minutes", IDC_T_PASSPHRASE_MIN, + 151, 137, 50, 8 + + /* Stuff below the group boxes. */ + PUSHBUTTON "advanced", IDC_GPG_OPTIONS, + 202, 166, 50, 14 + + LTEXT "GpgOL by g10 Code GmbH", IDC_STATIC, + 8, 185, 100, 8 + LTEXT "Version x ", IDC_VERSION_INFO, + 150, 185, 109, 9 + + CONTROL IDB_BANNER, IDC_BITMAP, + "Static", SS_BITMAP | SS_REALSIZEIMAGE, + 8, 200, 150, 64 +END + + + +IDD_EXT_OPTIONS DIALOG DISCARDABLE 0, 0, 167, 119 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "GpgOL - Extended Options" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "keyman", IDC_T_OPT_KEYMAN_PATH, + 2,20, 122,8 + + EDITTEXT IDC_OPT_KEYMAN_PATH, + 2, 34, 144, 12, ES_AUTOHSCROLL + + PUSHBUTTON "...", IDC_OPT_SEL_KEYMAN_PATH, + 148, 34, 11, 14 + + LTEXT "debug-logfile", IDC_T_DEBUG_LOGFILE, + 2, 50, 122,8 + + EDITTEXT IDC_DEBUG_LOGFILE, + 2, 60, 144, 12, ES_AUTOHSCROLL + + DEFPUSHBUTTON "&OK", IDOK, + 112, 101, 50, 14 +END + + +/* + The dialog to select recipient keys + */ +IDD_ENC DIALOG DISCARDABLE 0, 0, 332, 215 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "GpgOL - Select Recipients" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "List1", IDC_ENC_RSET1, + "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP, + 8, 4, 314, 92 + + LTEXT "Ausgew?hlte Empf?nger:", IDC_ENC_RSET2_T, + 8, 98, 130, 8 + + CONTROL "List2", IDC_ENC_RSET2, + "SysListView32", LVS_REPORT | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP, + 8, 110, 313, 49 + + LTEXT "Recipient which were NOT found", IDC_ENC_NOTFOUND_T, + 8, 161, 128, 8 + + LISTBOX IDC_ENC_NOTFOUND, + 8, 170, 313, 22, LBS_SORT | LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + DEFPUSHBUTTON "&OK", IDOK, + 221, 196, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 273, 196, 50, 14 +END + + +/* + The decryption dialog used to select the secret key. +*/ +IDD_DEC DIALOG DISCARDABLE 0, 0, 225, 101 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Secret Key Selection" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_DEC_KEYLIST, + 9, 7, 209, 58, CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + + LTEXT "", IDC_DEC_HINT, + 9, 25, 201, 10 + + LTEXT "enter-passphrase", IDC_DEC_PASSINF, + 9, 37, 158, 8 + + EDITTEXT IDC_DEC_PASS, + 9, 51, 207, 12, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "&Hide Typing", IDC_DEC_HIDE, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 138, 64, 81, 10 + + DEFPUSHBUTTON "&OK", IDOK, + 115, 83, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 167, 83, 50, 14 +END + + +/* + The extended decryption dialog used to select the secret key. +*/ +IDD_DECEXT DIALOG DISCARDABLE 0, 0, 207, 134 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "GpgOL - Secret Key Selection" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "encrypted-to",IDC_DECEXT_RSET_T, + 7, 4, 128, 8 + + LISTBOX IDC_DECEXT_RSET, + 7, 16, 193, 25, LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_DECEXT_KEYLIST, + 8, 54, 191, 14, CBS_DROPDOWN | CBS_SORT | + WS_DISABLED | WS_VSCROLL | WS_TABSTOP + + LTEXT "", IDC_DECEXT_HINT, + 7, 73, 193, 8 + + LTEXT "enter-passphrase", IDC_DECEXT_PASSINF, + 7, 85, 158, 8 + + EDITTEXT IDC_DECEXT_PASS, + 7, 96, 192, 12, ES_PASSWORD | ES_AUTOHSCROLL + + CONTROL "hide-typing", IDC_DECEXT_HIDE, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP, + 122, 108, 81, 10 + + DEFPUSHBUTTON "OK", IDOK, + 98, 125, 50, 14 + + PUSHBUTTON "&Cancel-btn", IDCANCEL, + 149, 125, 50, 14 +END + + +/* + The dialog to display verification results. +*/ +IDD_VRY DIALOG DISCARDABLE 0, 0, 253, 116 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "GpgOL - Signature Verification Result" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "made-at", IDC_VRY_TIME_T, + 3, 6, 50, 8 + + EDITTEXT IDC_VRY_TIME, + 55, 4, 76, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "using", IDC_VRY_PKALGO_T, + 132, 6, 18, 8 + + EDITTEXT IDC_VRY_PKALGO, + 152, 4, 20, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "key-id", IDC_VRY_KEYID_T, + 174, 7, 50, 8 + + EDITTEXT IDC_VRY_KEYID, + 196, 4, 51, 12, ES_AUTOHSCROLL | ES_READONLY + + EDITTEXT IDC_VRY_STATUS, + 3, 29, 92, 12, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "from", IDC_VRY_ISSUER_T, + 98, 31, 14, 8 + + EDITTEXT IDC_VRY_ISSUER, + 117, 29, 131, 13, ES_AUTOHSCROLL | ES_READONLY + + LTEXT "aka", IDC_VRY_AKALIST_T, + 3, 47, 56, 8 + + LISTBOX IDC_VRY_AKALIST, + 3, 56, 245, 25, LBS_SORT | LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + + LTEXT "", IDC_VRY_HINT, + 3, 83, 245, 10 + + DEFPUSHBUTTON "&OK", IDOK, + 198, 96, 50, 14 +END + Modified: trunk/src/engine-gpgme.c =================================================================== --- trunk/src/engine-gpgme.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/engine-gpgme.c 2007-10-12 19:22:35 UTC (rev 193) @@ -351,11 +351,11 @@ if (!defkey) { MessageBox (hwnd, - _("The configured default encryption certificate is not " - "available or does not unambigiously specify one. " - "Please fix this in the option dialog.\n\n" - "This message won't be be encrypted to this key!"), - _("Encryption"), MB_ICONWARNING|MB_OK); + _("The configured default encryption certificate is not " + "available or does not unambigiously specify one. " + "Please fix this in the option dialog.\n\n" + "This message won't be be encrypted to this certificate!"), + _("Encryption"), MB_ICONWARNING|MB_OK); } else { Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/ext-commands.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -31,7 +31,7 @@ #include "msgcache.h" #include "mapihelp.h" -#include "olflange-ids.h" +#include "dialogs.h" /* For IDB_foo. */ #include "olflange-def.h" #include "olflange.h" #include "ol-ext-callback.h" @@ -326,8 +326,8 @@ _("&Verify signature"), &m_nCmdCheckSig, _("&Display crypto information"), &m_nCmdShowInfo, "@", NULL, - _("Debug-1 (open_inspector)"), &m_nCmdDebug1, - _("Debug-2 (n/a)"), &m_nCmdDebug2, + "Debug-1 (open_inspector)", &m_nCmdDebug1, + "Debug-2 (n/a)", &m_nCmdDebug2, NULL); hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx); @@ -394,7 +394,7 @@ toolbar_add_menu (pEECB, pnCommandIDBase, "@", NULL, - _("GnuPG Key &Manager"), &m_nCmdKeyManager, + _("GnuPG Certificate &Manager"), &m_nCmdKeyManager, NULL); hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx); @@ -545,7 +545,7 @@ && m_lContext == EECONTEXT_VIEWER) { if (start_key_manager ()) - MessageBox (NULL, _("Could not start Key-Manager"), + MessageBox (NULL, _("Could not start certificate manager"), "GpgOL", MB_ICONERROR|MB_OK); } else if (nCommandID == m_nCmdDebug1 @@ -634,7 +634,8 @@ else if (nCommandID == m_nCmdKeyManager && m_lContext == EECONTEXT_VIEWER) { - MessageBox (m_hWnd, _("Select this option to open GpgOL Key Manager"), + MessageBox (m_hWnd, + _("Select this option to open the certificate manager"), "GpgOL", MB_OK); } else @@ -722,7 +723,7 @@ lstrcpyn (pszText, ".", nCharCnt); if (lFlags == EECQHT_TOOLTIP) lstrcpyn (pszText, - _("Open the GpgOL Key Manager"), + _("Open the GpgOL certificate manager"), nCharCnt); } else @@ -811,7 +812,7 @@ pTBB->fsStyle = TBSTYLE_BUTTON; pTBB->dwData = 0; pTBB->iString = -1; - lstrcpyn (description, _("Open GPG Key Manager"), + lstrcpyn (description, _("Open the certificate manager"), description_size); } else Deleted: trunk/src/gpgol-rsrcs.rc Modified: trunk/src/message-events.cpp =================================================================== --- trunk/src/message-events.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/message-events.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -30,7 +30,6 @@ #include "msgcache.h" #include "mapihelp.h" -#include "olflange-ids.h" #include "olflange-def.h" #include "olflange.h" #include "ol-ext-callback.h" Modified: trunk/src/ol-ext-callback.cpp =================================================================== --- trunk/src/ol-ext-callback.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/ol-ext-callback.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -31,7 +31,6 @@ #include "msgcache.h" #include "mapihelp.h" -#include "olflange-ids.h" #include "olflange-def.h" #include "olflange.h" #include "ol-ext-callback.h" Modified: trunk/src/olflange-dlgs.cpp =================================================================== --- trunk/src/olflange-dlgs.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/olflange-dlgs.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -32,7 +32,7 @@ #include "display.h" #include "ol-ext-callback.h" #include "olflange-def.h" -#include "olflange-ids.h" +#include "dialogs.h" /* To avoid writing a dialog template for each language we use gettext Deleted: trunk/src/olflange-ids.h Deleted: trunk/src/olflange-rsrcs.rc Modified: trunk/src/olflange.cpp =================================================================== --- trunk/src/olflange.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/olflange.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -39,7 +39,6 @@ #include "engine.h" #include "mapihelp.h" -#include "olflange-ids.h" #include "olflange-def.h" #include "olflange.h" #include "ext-commands.h" Modified: trunk/src/passphrase-dialog.c =================================================================== --- trunk/src/passphrase-dialog.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/passphrase-dialog.c 2007-10-12 19:22:35 UTC (rev 193) @@ -29,9 +29,10 @@ #include "common.h" #include "gpgol-ids.h" -#include "olflange-ids.h" #include "passcache.h" +#include "dialogs.h" + #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ SRCNAME, __func__, __LINE__); \ } while (0) Modified: trunk/src/property-sheets.cpp =================================================================== --- trunk/src/property-sheets.cpp 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/property-sheets.cpp 2007-10-12 19:22:35 UTC (rev 193) @@ -32,9 +32,9 @@ #include "engine.h" #include "mapihelp.h" -#include "olflange-ids.h" #include "olflange-def.h" #include "olflange.h" +#include "dialogs.h" #include "property-sheets.h" Modified: trunk/src/recipient-dialog.c =================================================================== --- trunk/src/recipient-dialog.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/recipient-dialog.c 2007-10-12 19:22:35 UTC (rev 193) @@ -34,7 +34,7 @@ #include "common.h" #include "gpgol-ids.h" -#include "olflange-ids.h" +#include "dialogs.h" #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \ Modified: trunk/src/resource.rc =================================================================== --- trunk/src/resource.rc 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/resource.rc 2007-10-12 19:22:35 UTC (rev 193) @@ -1,8 +1,7 @@ /* Simple wrapper to create one resource file from several RC files. */ -#include "gpgol-rsrcs.rc" -#include "olflange-rsrcs.rc" +#include "dialogs.rc" #include "versioninfo.rc" Modified: trunk/src/verify-dialog.c =================================================================== --- trunk/src/verify-dialog.c 2007-10-12 18:11:41 UTC (rev 192) +++ trunk/src/verify-dialog.c 2007-10-12 19:22:35 UTC (rev 193) @@ -24,8 +24,8 @@ #include "common.h" #include "gpgol-ids.h" +#include "dialogs.h" - struct dialog_context { gpgme_verify_result_t res; From cvs at cvs.gnupg.org Mon Oct 15 21:41:44 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Mon, 15 Oct 2007 21:41:44 +0200 Subject: [svn] GpgEX - r32 - trunk/src Message-ID: Author: marcus Date: 2007-10-15 21:41:35 +0200 (Mon, 15 Oct 2007) New Revision: 32 Added: trunk/src/debug.h trunk/src/exechelp.c trunk/src/exechelp.h Modified: trunk/src/ChangeLog trunk/src/Makefile.am trunk/src/client.cc trunk/src/main.cc trunk/src/main.h trunk/src/registry.c trunk/src/registry.h Log: 2007-10-15 Marcus Brinkmann (client_t::call_assuan): Call uiserver_connect. * registry.c: Include assert.h. Check return value of malloc. * exechelp.h, exechelp.c: New files. * Makefile.am (gpgex_SOURCES): Add exechelp.h and exechelp.c. * main.h (REGKEY): Move to ... * registry.h (REGKEY): ... here. * main.cc (_gpgme_debug): Put into extern C. * main.h: Move debug stuff into ... * debug.h: ... this new file. * client.cc (default_uiserver_name, uiserver_connect): New functions. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/ChangeLog 2007-10-15 19:41:35 UTC (rev 32) @@ -1,3 +1,16 @@ +2007-10-15 Marcus Brinkmann + + (client_t::call_assuan): Call uiserver_connect. + * registry.c: Include assert.h. Check return value of malloc. + * exechelp.h, exechelp.c: New files. + * Makefile.am (gpgex_SOURCES): Add exechelp.h and exechelp.c. + * main.h (REGKEY): Move to ... + * registry.h (REGKEY): ... here. + * main.cc (_gpgme_debug): Put into extern C. + * main.h: Move debug stuff into ... + * debug.h: ... this new file. + * client.cc (default_uiserver_name, uiserver_connect): New functions. + 2007-10-05 Marcus Brinkmann * main.cc (DllMain): Call WSACleanup. Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/Makefile.am 2007-10-15 19:41:35 UTC (rev 32) @@ -28,13 +28,14 @@ gpgex.def \ icons.rc \ registry.h registry.c \ + exechelp.h exechelp.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 \ client.h client.cc \ - main.h main.cc \ + main.h debug.h main.cc \ $(ICONS) libgpg-error.a: Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/client.cc 2007-10-15 19:41:35 UTC (rev 32) @@ -33,13 +33,54 @@ #include +#include "main.h" #include "registry.h" -#include "main.h" +#include "exechelp.h" #include "client.h" static const char * +default_uiserver_name (void) +{ + static string name; + + if (name.size () == 0) + { + char *dir = NULL; + + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + "Install Directory"); + if (dir) + { + char *uiserver = NULL; + int uiserver_malloced = 1; + + uiserver = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + "UI Server"); + if (!uiserver) + { + uiserver = "bin\\kleopatra.exe"; + uiserver_malloced = 0; + } + + /* FIXME: Very dirty work-around to make kleopatra find its + DLLs. */ + if (strcmp (uiserver, "bin\\kleopatra.exe")) + chdir (dir); + + try { name = ((string) dir) + "\\" + uiserver; } catch (...) {} + + if (uiserver_malloced) + free (uiserver); + free ((void *) dir); + } + } + + return name.c_str (); +} + +static const char * default_socket_name (void) { static string name; @@ -48,7 +89,6 @@ { char *dir = NULL; - /* FIXME: Wrong directory. */ dir = default_homedir (); if (dir) { @@ -126,27 +166,63 @@ } +static int +uiserver_connect (assuan_context_t *ctx) +{ + int rc; + const char *socket_name = NULL; + + TRACE_BEG (DEBUG_ASSUAN, "client_t::uiserver_connect", ctx); + + socket_name = default_socket_name (); + if (! socket_name || ! *socket_name) + { + (void) TRACE_LOG ("invalid socket name"); + return TRACE_GPGERR (gpg_error (GPG_ERR_INV_ARG)); + } + + (void) TRACE_LOG1 ("socket name: %s", socket_name); + rc = assuan_socket_connect (ctx, socket_name, -1); + if (rc) + { + const char *argv[3]; + int count; + + (void) TRACE_LOG ("UI server not running, starting it"); + + argv[0] = "--uiserver-socket"; + argv[1] = socket_name; + argv[2] = NULL; + + rc = gpgex_spawn_detached (default_uiserver_name (), argv); + if (rc) + return TRACE_GPGERR (rc); + + /* Give it a bit of time to start up and try a couple of + times. */ + for (count = 0; count < 10; count++) + { + Sleep (1000); + rc = assuan_socket_connect (ctx, socket_name, -1); + if (!rc) + break; + } + } + return TRACE_GPGERR (rc); +} + + 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); + rc = uiserver_connect (&ctx); if (rc) goto leave; Added: trunk/src/debug.h =================================================================== --- trunk/src/debug.h 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/debug.h 2007-10-15 19:41:35 UTC (rev 32) @@ -0,0 +1,201 @@ +/* debug.h - trace 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 DEBUG_H +#define DEBUG_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + + +#define DEBUG_INIT 1 +#define DEBUG_CONTEXT_MENU 2 +#define DEBUG_ASSUAN 4 + +#define STRINGIFY(v) #v + +/* Log the formatted string FORMAT in categories FLAGS. */ +void _gpgex_debug (unsigned int flags, const char *format, ...); + +#define _TRACE(lvl, name, tag) \ + int _gpgex_trace_level = lvl; \ + const char *const _gpgex_trace_func = name; \ + const char *const _gpgex_trace_tagname = STRINGIFY (tag); \ + void *_gpgex_trace_tag = (void *) tag + +#define TRACE_BEG(lvl, name, tag) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag) +#define TRACE_BEG0(lvl, name, tag, fmt) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag) +#define TRACE_BEG1(lvl, name, tag, fmt, arg1) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1) +#define TRACE_BEG2(lvl, name, tag, fmt, arg1, arg2) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2) +#define TRACE_BEG3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3) +#define TRACE_BEG4(lvl, name, tag, fmt, arg1, arg2, arg3, arg4) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4) +#define TRACE_BEG5(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5) +#define TRACE_BEG12(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12) +#define TRACE_BEG13(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ + arg13) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12, arg13) +#define TRACE_BEG22(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ + arg13, arg14, arg15, arg16, arg17, arg18, arg19, \ + arg20, arg21, arg22) \ + _TRACE (lvl, name, tag); \ + _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ + arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, \ + arg15, arg16, arg17, arg18, arg19, arg20, arg21, \ + arg22) + +#define TRACE(lvl, name, tag) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call\n", \ + name, STRINGIFY (tag), (void *) tag), 0) +#define TRACE0(lvl, name, tag, fmt) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag), 0) +#define TRACE1(lvl, name, tag, fmt, arg1) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1), 0) +#define TRACE2(lvl, name, tag, fmt, arg1, arg2) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2), 0) +#define TRACE3(lvl, name, tag, fmt, arg1, arg2, arg3) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + name, STRINGIFY (tag), (void *) tag, arg1, arg2, \ + arg3), 0) +#define TRACE6(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ + 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", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, \ + SUCCEEDED (err) ? "leave" : "error", \ + err), (err)) + +#define TRACE_SUC() \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_SUC0(fmt) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_SUC1(fmt, arg1) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1), 0) +#define TRACE_SUC2(fmt, arg1, arg2) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2), 0) +#define TRACE_SUC5(fmt, arg1, arg2, arg3, arg4, arg5) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5), 0) + +#define TRACE_LOG(fmt) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag), 0) +#define TRACE_LOG1(fmt, arg1) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1), 0) +#define TRACE_LOG2(fmt, arg1, arg2) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2), 0) +#define TRACE_LOG3(fmt, arg1, arg2, arg3) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3), 0) +#define TRACE_LOG4(fmt, arg1, arg2, arg3, arg4) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4), 0) +#define TRACE_LOG6(fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ + (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ + _gpgex_trace_func, _gpgex_trace_tagname, \ + _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, \ + arg6), 0) + +#ifdef __cplusplus +#if 0 +{ +#endif +} +#endif + +#endif Added: trunk/src/exechelp.c =================================================================== --- trunk/src/exechelp.c 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/exechelp.c 2007-10-15 19:41:35 UTC (rev 32) @@ -0,0 +1,203 @@ +/* exechelp.c - fork and exec helpers + * Copyright (C) 2004, 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 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 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 + */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include + +#include + +#include "debug.h" +#include "exechelp.h" + +/* Define to 1 do enable debugging. */ +#define DEBUG_W32_SPAWN 0 + + +/* Replacement function. */ + +#define stpcpy my_sptcpy + +static char * +stpcpy (char *d, const char *s) +{ + do + *d++ = *s; + while (*s++ != '\0'); + + return d - 1; +} + + +/* Helper function to build_w32_commandline. */ +static char * +build_w32_commandline_copy (char *buffer, const char *string) +{ + char *p = buffer; + const char *s; + + if (!*string) /* Empty string. */ + p = stpcpy (p, "\"\""); + else if (strpbrk (string, " \t\n\v\f\"")) + { + /* Need to do some kind of quoting. */ + p = stpcpy (p, "\""); + for (s=string; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (p, string); + + return p; +} + +/* Build a command line for use with W32's CreateProcess. On success + CMDLINE gets the address of a newly allocated string. */ +static gpg_error_t +build_w32_commandline (const char *pgmname, const char * const *argv, + char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = 0; + s = pgmname; + n += strlen (s) + 1 + 2; /* (1 space, 2 quotes) */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = malloc (n); + if (!buf) + return gpg_error_from_syserror (); + + p = build_w32_commandline_copy (p, pgmname); + for (i = 0; argv[i]; i++) + { + *p++ = ' '; + p = build_w32_commandline_copy (p, argv[i]); + } + + *cmdline = buf; + return 0; +} + + +/* Fork and exec the PGMNAME with /dev/null as stdin, stdout and + stderr. The arguments for the process are expected in the NULL + terminated array ARGV. The program name itself should not be + included there. Returns 0 on success or an error code. */ +gpg_error_t +gpgex_spawn_detached (const char *pgmname, const char *const argv[]) +{ + gpg_error_t err; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int cr_flags; + char *cmdline; + int i; + + TRACE_BEG1 (DEBUG_ASSUAN, "gpgex_spawn_detached", pgmname, + "pgmname=%s", pgmname); + i = 0; + while (argv[i]) + { + TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); + i++; + } + + /* Build the command line. */ + err = build_w32_commandline (pgmname, argv, &cmdline); + if (err) + return err; + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Start the process. Note that we can't run the PREEXEC function + because this would change our own environment. */ + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN ? SW_SHOW : SW_MINIMIZE; + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_NEW_PROCESS_GROUP + | DETACHED_PROCESS); + + (void) TRACE_LOG2 ("CreateProcess, path=`%s' cmdline=`%s'\n", + pgmname, cmdline); + if (!CreateProcess (pgmname, /* pgmname; Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + (void) TRACE_LOG1 ("CreateProcess failed: %i\n", GetLastError ()); + free (cmdline); + return gpg_error (GPG_ERR_GENERAL); + } + free (cmdline); + + /* Process has been created suspended; resume it now. */ + CloseHandle (pi.hThread); + CloseHandle (pi.hProcess); + + return 0; +} Added: trunk/src/exechelp.h =================================================================== --- trunk/src/exechelp.h 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/exechelp.h 2007-10-15 19:41:35 UTC (rev 32) @@ -0,0 +1,46 @@ +/* exechelp.h - fork and exec helpers + * Copyright (C) 2004, 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 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 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 + */ + +#ifndef GPGEX_EXECHELP_H +#define GPGEX_EXECHELP_H + +#include + +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + +/* Fork and exec the PGMNAME with /dev/null as stdin, stdout and + stderr. The arguments for the process are expected in the NULL + terminated array ARGV. The program name itself should not be + included there. Returns 0 on success or an error code. */ +gpg_error_t gpgex_spawn_detached (const char *pgmname, + const char *const argv[]); +#ifdef __cplusplus +#if 0 +{ +#endif +} +#endif + +#endif /* GPGEX_EXECHELP_H */ Modified: trunk/src/main.cc =================================================================== --- trunk/src/main.cc 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/main.cc 2007-10-15 19:41:35 UTC (rev 32) @@ -160,7 +160,15 @@ } +#ifdef __cplusplus +extern "C" { +#if 0 +} +#endif +#endif + /* Log the formatted string FORMAT at debug level LEVEL or higher. */ +extern void _gpgex_debug (unsigned int flags, const char *format, ...) { @@ -184,6 +192,13 @@ errno = saved_errno; } +#ifdef __cplusplus +#if 0 +{ +#endif +} +#endif + /* Entry point called by DLL loader. */ STDAPI Modified: trunk/src/main.h =================================================================== --- trunk/src/main.h 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/main.h 2007-10-15 19:41:35 UTC (rev 32) @@ -23,18 +23,15 @@ #include -#include +#include "debug.h" + #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 { @@ -67,169 +64,9 @@ }; -#define DEBUG_INIT 1 -#define DEBUG_CONTEXT_MENU 2 -#define DEBUG_ASSUAN 4 - -#define STRINGIFY(v) #v - #define GUID_FMT "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" #define GUID_ARG(x) (x).Data1, (x).Data2, (x).Data3, (x).Data4[0], \ (x).Data4[1], (x).Data4[2], (x).Data4[3], (x).Data4[4], \ (x).Data4[5], (x).Data4[6], (x).Data4[7] -/* Log the formatted string FORMAT in categories FLAGS. */ -void _gpgex_debug (unsigned int flags, const char *format, ...); - -#define _TRACE(lvl, name, tag) \ - int _gpgex_trace_level = lvl; \ - const char *const _gpgex_trace_func = name; \ - const char *const _gpgex_trace_tagname = STRINGIFY (tag); \ - void *_gpgex_trace_tag = (void *) tag - -#define TRACE_BEG(lvl, name, tag) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag) -#define TRACE_BEG0(lvl, name, tag, fmt) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag) -#define TRACE_BEG1(lvl, name, tag, fmt, arg1) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1) -#define TRACE_BEG2(lvl, name, tag, fmt, arg1, arg2) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2) -#define TRACE_BEG3(lvl, name, tag, fmt, arg1, arg2, arg3) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3) -#define TRACE_BEG4(lvl, name, tag, fmt, arg1, arg2, arg3, arg4) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4) -#define TRACE_BEG5(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5) -#define TRACE_BEG12(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ - arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ - arg7, arg8, arg9, arg10, arg11, arg12) -#define TRACE_BEG13(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ - arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ - arg13) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ - arg7, arg8, arg9, arg10, arg11, arg12, arg13) -#define TRACE_BEG22(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, \ - arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, \ - arg13, arg14, arg15, arg16, arg17, arg18, arg19, \ - arg20, arg21, arg22) \ - _TRACE (lvl, name, tag); \ - _gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): enter: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, arg6, \ - arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, \ - arg15, arg16, arg17, arg18, arg19, arg20, arg21, \ - arg22) - -#define TRACE(lvl, name, tag) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call\n", \ - name, STRINGIFY (tag), (void *) tag), 0) -#define TRACE0(lvl, name, tag, fmt) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ - name, STRINGIFY (tag), (void *) tag), 0) -#define TRACE1(lvl, name, tag, fmt, arg1) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ - name, STRINGIFY (tag), (void *) tag, arg1), 0) -#define TRACE2(lvl, name, tag, fmt, arg1, arg2) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ - name, STRINGIFY (tag), (void *) tag, arg1, arg2), 0) -#define TRACE3(lvl, name, tag, fmt, arg1, arg2, arg3) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ - name, STRINGIFY (tag), (void *) tag, arg1, arg2, \ - arg3), 0) -#define TRACE6(lvl, name, tag, fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ - (_gpgex_debug (lvl, "%s (%s=0x%x): call: " fmt "\n", \ - 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", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, \ - SUCCEEDED (err) ? "leave" : "error", \ - err), (err)) - -#define TRACE_SUC() \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag), 0) -#define TRACE_SUC0(fmt) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag), 0) -#define TRACE_SUC1(fmt, arg1) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1), 0) -#define TRACE_SUC2(fmt, arg1, arg2) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2), 0) -#define TRACE_SUC5(fmt, arg1, arg2, arg3, arg4, arg5) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): leave: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5), 0) - -#define TRACE_LOG(fmt) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag), 0) -#define TRACE_LOG1(fmt, arg1) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1), 0) -#define TRACE_LOG2(fmt, arg1, arg2) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2), 0) -#define TRACE_LOG3(fmt, arg1, arg2, arg3) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3), 0) -#define TRACE_LOG4(fmt, arg1, arg2, arg3, arg4) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4), 0) -#define TRACE_LOG6(fmt, arg1, arg2, arg3, arg4, arg5, arg6) \ - (_gpgex_debug (_gpgex_trace_level, "%s (%s=0x%x): check: " fmt "\n", \ - _gpgex_trace_func, _gpgex_trace_tagname, \ - _gpgex_trace_tag, arg1, arg2, arg3, arg4, arg5, \ - arg6), 0) - #endif Modified: trunk/src/registry.c =================================================================== --- trunk/src/registry.c 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/registry.c 2007-10-15 19:41:35 UTC (rev 32) @@ -23,6 +23,7 @@ #endif #include +#include #include #include @@ -215,6 +216,9 @@ { char *tmp = malloc (strlen (path) + 6 + 1); + /* FIXME. */ + assert (tmp); + strcpy (tmp, path); strcat (tmp, "\\gnupg"); Modified: trunk/src/registry.h =================================================================== --- trunk/src/registry.h 2007-10-08 16:48:52 UTC (rev 31) +++ trunk/src/registry.h 2007-10-15 19:41:35 UTC (rev 32) @@ -43,6 +43,9 @@ /* Retrieve the default home directory. */ char *default_homedir (void); +/* Registry key for this software. */ +#define REGKEY "Software\\GNU\\GnuPG" + #ifdef __cplusplus #if 0 { From cvs at cvs.gnupg.org Tue Oct 16 12:55:30 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 16 Oct 2007 12:55:30 +0200 Subject: [svn] GpgEX - r33 - trunk/src Message-ID: Author: marcus Date: 2007-10-16 12:55:22 +0200 (Tue, 16 Oct 2007) New Revision: 33 Modified: trunk/src/ChangeLog trunk/src/client.cc Log: 2007-10-16 Marcus Brinkmann * client.cc (default_uiserver_name): Get UI Server from HKCU. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-15 19:41:35 UTC (rev 32) +++ trunk/src/ChangeLog 2007-10-16 10:55:22 UTC (rev 33) @@ -1,3 +1,7 @@ +2007-10-16 Marcus Brinkmann + + * client.cc (default_uiserver_name): Get UI Server from HKCU. + 2007-10-15 Marcus Brinkmann (client_t::call_assuan): Call uiserver_connect. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-15 19:41:35 UTC (rev 32) +++ trunk/src/client.cc 2007-10-16 10:55:22 UTC (rev 33) @@ -56,7 +56,7 @@ char *uiserver = NULL; int uiserver_malloced = 1; - uiserver = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + uiserver = read_w32_registry_string ("HKEY_CURRENT_USER", REGKEY, "UI Server"); if (!uiserver) { From cvs at cvs.gnupg.org Tue Oct 16 13:11:09 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 16 Oct 2007 13:11:09 +0200 Subject: [svn] GpgEX - r34 - in trunk: . src Message-ID: Author: marcus Date: 2007-10-16 13:11:00 +0200 (Tue, 16 Oct 2007) New Revision: 34 Modified: trunk/README trunk/src/ChangeLog trunk/src/client.cc Log: 2007-10-16 Marcus Brinkmann * client.cc (default_uiserver_name): Fall back to HKLM for UI Server. Modified: trunk/README =================================================================== --- trunk/README 2007-10-16 10:55:22 UTC (rev 33) +++ trunk/README 2007-10-16 11:11:00 UTC (rev 34) @@ -4,6 +4,38 @@ This package contains GpgEX, the GNU Privacy Guard extensions for the Windows Explorer shell. + +Registry Settings +================= + +The following registry entries are read by GpgEX and affect its +operation: + +HKLM\Software\GNU\GnuPG:Install Directory + The installation directory of Gpg4Win. This is used to compose the + path to the UI server executable. Also known as INSTDIR below. Set + by the installer at installation time. + +HKCU\Software\GNU\GnuPG:UI Server +HKLM\Software\GNU\GnuPG:UI Server + The path to the executable binary of the UI server, relative to + INSTDIR. Absolute paths are currently not supported. + +HKCU\Software\GNU\GnuPG:HomeDir +HKLM\Software\GNU\GnuPG:HomeDir + The GnuPG home directory. Defaults to APPDATA\gnupg. + +HKLM\Software\GNU\GnuPG:GpgEX Debug File + See below. + +The following registry entries are set by GpgEX at installation time +to register it as a shell extension: + +HKCR\CLSID\CCD955E4-5C16-4A33-AFDA-A8947A94946B +HKCR\*\ShellEx\ContextMenuHandlers\GpgEX +HKCR\Directory\ShellEx\ContextMenuHandlers\GpgEX + + Debugging ========= Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-16 10:55:22 UTC (rev 33) +++ trunk/src/ChangeLog 2007-10-16 11:11:00 UTC (rev 34) @@ -1,5 +1,7 @@ 2007-10-16 Marcus Brinkmann + * client.cc (default_uiserver_name): Fall back to HKLM for UI Server. + * client.cc (default_uiserver_name): Get UI Server from HKCU. 2007-10-15 Marcus Brinkmann Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-16 10:55:22 UTC (rev 33) +++ trunk/src/client.cc 2007-10-16 11:11:00 UTC (rev 34) @@ -56,8 +56,7 @@ char *uiserver = NULL; int uiserver_malloced = 1; - uiserver = read_w32_registry_string ("HKEY_CURRENT_USER", REGKEY, - "UI Server"); + uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server"); if (!uiserver) { uiserver = "bin\\kleopatra.exe"; From cvs at cvs.gnupg.org Tue Oct 16 17:16:39 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 16 Oct 2007 17:16:39 +0200 Subject: [svn] dirmngr - r272 - in trunk: . doc/examples Message-ID: Author: marcus Date: 2007-10-16 17:16:30 +0200 (Tue, 16 Oct 2007) New Revision: 272 Modified: trunk/ChangeLog trunk/doc/examples/Makefile.am Log: 2007-10-16 Marcus Brinkmann * doc/examples/Makefile.am (dist_doc_example_DATA): Rename to ... (nobase_dist_doc_example_DATA): ... this, to preserve subdirectories. Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-10-08 10:25:48 UTC (rev 271) +++ trunk/ChangeLog 2007-10-16 15:16:30 UTC (rev 272) @@ -1,3 +1,8 @@ +2007-10-16 Marcus Brinkmann + + * doc/examples/Makefile.am (dist_doc_example_DATA): Rename to ... + (nobase_dist_doc_example_DATA): ... this, to preserve subdirectories. + 2007-10-08 Werner Koch * configure.ac: Require libassuan 1.0.4. Modified: trunk/doc/examples/Makefile.am =================================================================== --- trunk/doc/examples/Makefile.am 2007-10-08 10:25:48 UTC (rev 271) +++ trunk/doc/examples/Makefile.am 2007-10-16 15:16:30 UTC (rev 272) @@ -1,13 +1,13 @@ doc_exampledir = $(docdir)/examples -dist_doc_example_DATA = README dirmngr.conf bnetza-10r-ocsp.signer +nobase_dist_doc_example_DATA = README dirmngr.conf bnetza-10r-ocsp.signer -dist_doc_example_DATA += \ +nobase_dist_doc_example_DATA += \ trusted-certs/README \ trusted-certs/bnetza-10r-ca.crt -dist_doc_example_DATA += \ +nobase_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 \ From cvs at cvs.gnupg.org Wed Oct 17 00:50:54 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Wed, 17 Oct 2007 00:50:54 +0200 Subject: [svn] GpgEX - r35 - trunk/src Message-ID: Author: marcus Date: 2007-10-17 00:50:46 +0200 (Wed, 17 Oct 2007) New Revision: 35 Modified: trunk/src/ChangeLog trunk/src/client.cc Log: 2007-10-17 Marcus Brinkmann * client.cc (default_uiserver_name): Fix check for dirty hack. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-16 11:11:00 UTC (rev 34) +++ trunk/src/ChangeLog 2007-10-16 22:50:46 UTC (rev 35) @@ -1,3 +1,7 @@ +2007-10-17 Marcus Brinkmann + + * client.cc (default_uiserver_name): Fix check for dirty hack. + 2007-10-16 Marcus Brinkmann * client.cc (default_uiserver_name): Fall back to HKLM for UI Server. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-16 11:11:00 UTC (rev 34) +++ trunk/src/client.cc 2007-10-16 22:50:46 UTC (rev 35) @@ -65,7 +65,7 @@ /* FIXME: Very dirty work-around to make kleopatra find its DLLs. */ - if (strcmp (uiserver, "bin\\kleopatra.exe")) + if (!strcmp (uiserver, "bin\\kleopatra.exe")) chdir (dir); try { name = ((string) dir) + "\\" + uiserver; } catch (...) {} From cvs at cvs.gnupg.org Wed Oct 17 18:11:18 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Wed, 17 Oct 2007 18:11:18 +0200 Subject: [svn] GnuPG - r4594 - branches/STABLE-BRANCH-1-4 Message-ID: Author: dshaw Date: 2007-10-17 18:11:09 +0200 (Wed, 17 Oct 2007) New Revision: 4594 Modified: branches/STABLE-BRANCH-1-4/ChangeLog branches/STABLE-BRANCH-1-4/configure.ac Log: * configure.ac: Change various help messages to use AC_HELP_STRING. Modified: branches/STABLE-BRANCH-1-4/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/ChangeLog 2007-10-15 14:50:07 UTC (rev 4593) +++ branches/STABLE-BRANCH-1-4/ChangeLog 2007-10-17 16:11:09 UTC (rev 4594) @@ -1,3 +1,8 @@ +2007-10-17 David Shaw + + * configure.ac: Change various help messages to use + AC_HELP_STRING. + 2007-07-18 David Shaw * configure.ac: It seems that AM_GNU_GETTEXT doesn't like being Modified: branches/STABLE-BRANCH-1-4/configure.ac =================================================================== --- branches/STABLE-BRANCH-1-4/configure.ac 2007-10-15 14:50:07 UTC (rev 4593) +++ branches/STABLE-BRANCH-1-4/configure.ac 2007-10-17 16:11:09 UTC (rev 4594) @@ -53,8 +53,9 @@ dnl AC_MSG_CHECKING([which random module to use]) AC_ARG_ENABLE(static-rnd, - [ --enable-static-rnd=[egd|unix|linux|auto] ], -[use_static_rnd=$enableval], [use_static_rnd=default] ) + AC_HELP_STRING([[--enable-static-rnd=[egd|unix|linux|auto]]], + [specify a random number source]), + [use_static_rnd=$enableval], [use_static_rnd=default]) if test "$use_static_rnd" = no; then use_static_rnd=default @@ -74,7 +75,7 @@ esac AC_ARG_WITH(egd-socket, - [ --with-egd-socket=NAME use NAME for the EGD socket], + AC_HELP_STRING([--with-egd-socket=NAME],[use NAME for the EGD socket]), egd_socket_name="$withval", egd_socket_name="" ) AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name", [Define if you don't want the default EGD socket name. @@ -86,8 +87,8 @@ AC_MSG_CHECKING([whether use of /dev/random is requested]) AC_ARG_ENABLE(dev-random, -[ --disable-dev-random disable the use of dev random], - try_dev_random=$enableval, try_dev_random=yes) + AC_HELP_STRING([--disable-dev-random],[disable the use of dev random]), + try_dev_random=$enableval, try_dev_random=yes) AC_MSG_RESULT($try_dev_random) @@ -97,7 +98,7 @@ AC_MSG_CHECKING([whether assembler modules are requested]) AC_ARG_ENABLE(asm, -[ --disable-asm do not use assembler modules], + AC_HELP_STRING([--disable-asm],[do not use assembler modules]), try_asm_modules=$enableval, try_asm_modules=yes) AC_MSG_RESULT($try_asm_modules) @@ -305,7 +306,7 @@ if test "$use_exec" = yes ; then AC_MSG_CHECKING([whether to enable photo ID viewing]) AC_ARG_ENABLE(photo-viewers, - [ --disable-photo-viewers disable photo ID viewers], + AC_HELP_STRING([--disable-photo-viewers],[disable photo ID viewers]), [if test "$enableval" = no ; then AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing]) fi],enableval=yes) @@ -315,7 +316,8 @@ if test "$gnupg_cv_enable_photo_viewers" = yes ; then AC_MSG_CHECKING([whether to use a fixed photo ID viewer]) AC_ARG_WITH(photo-viewer, - [ --with-photo-viewer=FIXED_VIEWER set a fixed photo ID viewer], + AC_HELP_STRING([--with-photo-viewer=FIXED_VIEWER], + [set a fixed photo ID viewer]), [if test "$withval" = yes ; then withval=no elif test "$withval" != no ; then @@ -327,7 +329,8 @@ AC_MSG_CHECKING([whether to enable external keyserver helpers]) AC_ARG_ENABLE(keyserver-helpers, - [ --disable-keyserver-helpers disable all external keyserver support], + AC_HELP_STRING([--disable-keyserver-helpers], + [disable all external keyserver support]), [if test "$enableval" = no ; then AC_DEFINE(DISABLE_KEYSERVER_HELPERS,1, [define to disable keyserver helpers]) @@ -383,7 +386,7 @@ AC_MSG_CHECKING([whether the included zlib is requested]) AC_ARG_WITH(included-zlib, - [ --with-included-zlib use the zlib code included here], + AC_HELP_STRING([--with-included-zlib],[use the zlib code included here]), [g10_force_zlib="$withval"], [g10_force_zlib=no] ) AC_MSG_RESULT($g10_force_zlib) @@ -417,7 +420,8 @@ dnl AC_MSG_CHECKING([whether use of capabilities is requested]) AC_ARG_WITH(capabilities, - [ --with-capabilities use linux capabilities [default=no]], + AC_HELP_STRING([--with-capabilities], + [use linux capabilities [default=no]]), [use_capabilities="$withval"],[use_capabilities=no]) AC_MSG_RESULT($use_capabilities) @@ -765,7 +769,9 @@ dnl postfix, etc. Basically, anything that can handle "sendmail -t". if test "$try_mailto" = yes ; then - AC_ARG_WITH(mailprog,[ --with-mailprog=NAME use "NAME -t" for mail transport],,with_mailprog=yes) + AC_ARG_WITH(mailprog, + AC_HELP_STRING([--with-mailprog=NAME], + [use "NAME -t" for mail transport]),,with_mailprog=yes) if test "$with_mailprog" = yes ; then AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib) @@ -1196,7 +1202,8 @@ if test "$use_regex" = yes ; then AC_MSG_CHECKING([whether the included regex lib is requested]) AC_ARG_WITH(included-regex, - [ --with-included-regex use the included GNU regex library], + AC_HELP_STRING([--with-included-regex], + [use the included GNU regex library]), [gnupg_cv_included_regex="$withval"],[gnupg_cv_included_regex=no]) AC_MSG_RESULT($gnupg_cv_included_regex) @@ -1240,7 +1247,7 @@ _ldflags="${LDFLAGS}" AC_ARG_WITH(zlib, - [ --with-zlib=DIR use libz in DIR],[ + AC_HELP_STRING([--with-zlib=DIR],[use libz in DIR]),[ if test -d "$withval"; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" From cvs at cvs.gnupg.org Wed Oct 17 18:37:20 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Wed, 17 Oct 2007 18:37:20 +0200 Subject: [svn] GnuPG - r4595 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2007-10-17 18:37:09 +0200 (Wed, 17 Oct 2007) New Revision: 4595 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/gpg.c branches/STABLE-BRANCH-1-4/g10/keyedit.c branches/STABLE-BRANCH-1-4/g10/misc.c branches/STABLE-BRANCH-1-4/g10/options.h Log: * options.h, gpg.c (main), misc.c (compliance_option_string): Add --rfc4880, and make --openpgp an alias to it. --rfc2440 now stands alone. For now, use the old 2440 defaults for 4880. * keyedit.c (keyedit_menu): Use compliance_option_string() instead of printing the compliance modes here. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-17 16:11:09 UTC (rev 4594) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-17 16:37:09 UTC (rev 4595) @@ -1,3 +1,12 @@ +2007-10-17 David Shaw + + * options.h, gpg.c (main), misc.c (compliance_option_string): Add + --rfc4880, and make --openpgp an alias to it. --rfc2440 now + stands alone. For now, use the old 2440 defaults for 4880. + + * keyedit.c (keyedit_menu): Use compliance_option_string() instead + of printing the compliance modes here. + 2007-09-02 David Shaw * import.c (collapse_uids): Significant speedup for de-duping user Modified: branches/STABLE-BRANCH-1-4/g10/gpg.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-17 16:11:09 UTC (rev 4594) +++ branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-17 16:37:09 UTC (rev 4595) @@ -204,6 +204,7 @@ oGnuPG, oRFC1991, oRFC2440, + oRFC4880, oOpenPGP, oPGP2, oPGP6, @@ -532,6 +533,7 @@ { oGnuPG, "no-pgp8", 0, "@"}, { oRFC1991, "rfc1991", 0, "@"}, { oRFC2440, "rfc2440", 0, "@" }, + { oRFC4880, "rfc4880", 0, "@" }, { oOpenPGP, "openpgp", 0, N_("use strict OpenPGP behavior")}, { oPGP2, "pgp2", 0, N_("generate PGP 2.x compatible messages")}, { oPGP6, "pgp6", 0, "@"}, @@ -2255,11 +2257,32 @@ opt.escape_from = 1; break; case oOpenPGP: + case oRFC4880: + /* Note these are the same defaults as CO_RFC2440. Update + this. */ + opt.compliance = CO_RFC4880; + opt.rfc2440_text=1; + opt.allow_non_selfsigned_uid = 1; + opt.allow_freeform_uid = 1; + opt.pgp2_workarounds = 0; + opt.escape_from = 0; + opt.force_v3_sigs = 0; + opt.compress_keys = 0; /* not mandated, but we do it */ + opt.compress_sigs = 0; /* ditto. */ + opt.not_dash_escaped = 0; + opt.def_cipher_algo = 0; + opt.def_digest_algo = 0; + opt.cert_digest_algo = 0; + opt.compress_algo = -1; + opt.s2k_mode = 3; /* iterated+salted */ + opt.s2k_digest_algo = DIGEST_ALGO_SHA1; + opt.s2k_cipher_algo = CIPHER_ALGO_3DES; + break; case oRFC2440: /* TODO: When 2440bis becomes a RFC, set new values for oOpenPGP. */ + opt.compliance = CO_RFC2440; opt.rfc2440_text=1; - opt.compliance = CO_RFC2440; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; Modified: branches/STABLE-BRANCH-1-4/g10/keyedit.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/keyedit.c 2007-10-17 16:11:09 UTC (rev 4594) +++ branches/STABLE-BRANCH-1-4/g10/keyedit.c 2007-10-17 16:37:09 UTC (rev 4595) @@ -1,6 +1,6 @@ /* keyedit.c - keyedit stuff - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1790,7 +1790,7 @@ { tty_printf( _("This command is not allowed while in %s mode.\n"), - RFC2440?"OpenPGP":PGP2?"PGP2":"RFC-1991"); + compliance_option_string()); break; } photo=1; Modified: branches/STABLE-BRANCH-1-4/g10/misc.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/misc.c 2007-10-17 16:11:09 UTC (rev 4594) +++ branches/STABLE-BRANCH-1-4/g10/misc.c 2007-10-17 16:37:09 UTC (rev 4595) @@ -801,8 +801,12 @@ { switch(opt.compliance) { + case CO_RFC4880: + return "--openpgp"; case CO_RFC2440: - return "--openpgp"; + return "--rfc2440"; + case CO_RFC1991: + return "--rfc1991"; case CO_PGP2: return "--pgp2"; case CO_PGP6: Modified: branches/STABLE-BRANCH-1-4/g10/options.h =================================================================== --- branches/STABLE-BRANCH-1-4/g10/options.h 2007-10-17 16:11:09 UTC (rev 4594) +++ branches/STABLE-BRANCH-1-4/g10/options.h 2007-10-17 16:37:09 UTC (rev 4595) @@ -1,6 +1,6 @@ /* options.h - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -105,7 +105,8 @@ int force_ownertrust; enum { - CO_GNUPG=0, CO_RFC2440, CO_RFC1991, CO_PGP2, CO_PGP6, CO_PGP7, CO_PGP8 + CO_GNUPG, CO_RFC4880, CO_RFC2440, CO_RFC1991, CO_PGP2, + CO_PGP6, CO_PGP7, CO_PGP8 } compliance; enum { @@ -272,14 +273,15 @@ #define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) #define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE) - #define GNUPG (opt.compliance==CO_GNUPG) #define RFC1991 (opt.compliance==CO_RFC1991 || opt.compliance==CO_PGP2) #define RFC2440 (opt.compliance==CO_RFC2440) +#define RFC4880 (opt.compliance==CO_RFC4880) #define PGP2 (opt.compliance==CO_PGP2) #define PGP6 (opt.compliance==CO_PGP6) #define PGP7 (opt.compliance==CO_PGP7) #define PGP8 (opt.compliance==CO_PGP8) +#define PGPX (PGP2 || PGP6 || PGP7 || PGP8) /* Various option flags. Note that there should be no common string names between the IMPORT_ and EXPORT_ flags as they can be mixed in From cvs at cvs.gnupg.org Thu Oct 18 16:42:00 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Thu, 18 Oct 2007 16:42:00 +0200 Subject: [svn] assuan - r276 - in trunk: doc src Message-ID: Author: marcus Date: 2007-10-18 16:41:51 +0200 (Thu, 18 Oct 2007) New Revision: 276 Modified: trunk/doc/ChangeLog trunk/doc/assuan.texi trunk/src/ChangeLog trunk/src/assuan-handler.c Log: doc/ 2007-10-18 Marcus Brinkmann * assuan.texi (Client requests): Document HELP. src/ 2007-10-18 Marcus Brinkmann * assuan-handler.c (std_handler_help): New function. (std_cmd_table): Add new command HELP. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-10-08 18:03:38 UTC (rev 275) +++ trunk/doc/ChangeLog 2007-10-18 14:41:51 UTC (rev 276) @@ -1,3 +1,7 @@ +2007-10-18 Marcus Brinkmann + + * assuan.texi (Client requests): Document HELP. + 2007-09-07 Moritz Schulte * assuan.texi (Client code): mention assuan_send_data() instead of Modified: trunk/doc/assuan.texi =================================================================== --- trunk/doc/assuan.texi 2007-10-08 18:03:38 UTC (rev 275) +++ trunk/doc/assuan.texi 2007-10-18 14:41:51 UTC (rev 276) @@ -339,7 +339,8 @@ to indicate a partial end of data. @item HELP -Reserved for future extensions. +Lists all commands that the server understands as comment lines on the +status channel. @item QUIT Reserved for future extensions. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-08 18:03:38 UTC (rev 275) +++ trunk/src/ChangeLog 2007-10-18 14:41:51 UTC (rev 276) @@ -1,3 +1,8 @@ +2007-10-18 Marcus Brinkmann + + * assuan-handler.c (std_handler_help): New function. + (std_cmd_table): Add new command HELP. + 2007-10-08 Werner Koch * assuan-util.c (assuan_set_io_hooks): New. Modified: trunk/src/assuan-handler.c =================================================================== --- trunk/src/assuan-handler.c 2007-10-08 18:03:38 UTC (rev 275) +++ trunk/src/assuan-handler.c 2007-10-18 14:41:51 UTC (rev 276) @@ -139,6 +139,23 @@ } static int +std_handler_help (assuan_context_t ctx, char *line) +{ + int i; + char buf[ASSUAN_LINELENGTH]; + + for (i = 0; i < ctx->cmdtbl_used; i++) + { + snprintf (buf, sizeof (buf), "# %s", ctx->cmdtbl[i].name); + buf[ASSUAN_LINELENGTH - 1] = '\0'; + assuan_write_line (ctx, buf); + } + + return PROCESS_DONE (ctx, 0); +} + + +static int std_handler_end (assuan_context_t ctx, char *line) { return PROCESS_DONE (ctx, set_error (ctx, Not_Implemented, NULL)); @@ -232,6 +249,7 @@ { "AUTH", std_handler_auth, 1 }, { "RESET", std_handler_reset, 1 }, { "END", std_handler_end, 1 }, + { "HELP", std_handler_help, 1 }, { "INPUT", std_handler_input }, { "OUTPUT", std_handler_output }, From cvs at cvs.gnupg.org Fri Oct 19 10:49:16 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 19 Oct 2007 10:49:16 +0200 Subject: [svn] GnuPG - r4596 - trunk/tools Message-ID: Author: wk Date: 2007-10-19 10:49:07 +0200 (Fri, 19 Oct 2007) New Revision: 4596 Modified: trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Fixed bug 842 (segv in gpgconf) Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-17 16:37:09 UTC (rev 4595) +++ trunk/tools/ChangeLog 2007-10-19 08:49:07 UTC (rev 4596) @@ -1,3 +1,8 @@ +2007-10-19 Werner Koch + + * gpgconf-comp.c (retrieve_options_from_file): Don't call fclose + with NULL. Fixes bug 842. + 2007-10-12 Werner Koch * gpg-connect-agent.c (substitute_line): Allow ${foo} syntax. Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-10-17 16:37:09 UTC (rev 4595) +++ trunk/tools/gpgconf-comp.c 2007-10-19 08:49:07 UTC (rev 4596) @@ -1880,7 +1880,7 @@ list_option->active = 1; list_option->value = list; - if (fclose (list_file) && ferror (list_file)) + if (list_file && fclose (list_file) && ferror (list_file)) gc_error (1, errno, "error closing %s", list_pathname); xfree (line); } From cvs at cvs.gnupg.org Fri Oct 19 16:51:49 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 19 Oct 2007 16:51:49 +0200 Subject: [svn] GnuPG - r4597 - in trunk: . common doc tools Message-ID: Author: wk Date: 2007-10-19 16:51:39 +0200 (Fri, 19 Oct 2007) New Revision: 4597 Modified: trunk/NEWS trunk/common/xreadline.c trunk/doc/ChangeLog trunk/doc/tools.texi trunk/tools/ChangeLog trunk/tools/Makefile.am trunk/tools/gpg-connect-agent.c trunk/tools/no-libgcrypt.c Log: Enhanced gpg-conect-agent scripting. Typo fixes in comments. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/NEWS 2007-10-19 14:51:39 UTC (rev 4597) @@ -5,7 +5,11 @@ taken into account. This required a change of our the socket emulation code; thus old GnuPG modules can't be used anymore. + * Fixed a crash in gpgconf. + * Enhanced gpg-connect-agent with a small scripting language. + + Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ Modified: trunk/common/xreadline.c =================================================================== --- trunk/common/xreadline.c 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/common/xreadline.c 2007-10-19 14:51:39 UTC (rev 4597) @@ -33,7 +33,7 @@ maximum allowed allocation. Returns the length of the line. EOF is indicated by a line of - length zero. A truncated line is indicated my setting the value at + length zero. A truncated line is indicated by setting the value at MAX_LENGTH to 0. If the returned value is less then 0 not enough memory was enable and ERRNO is set accordingly. Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/doc/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) @@ -1,3 +1,7 @@ +2007-10-19 Werner Koch + + * tools.texi (Controlling gpg-connect-agent): Updated. + 2007-08-29 Werner Koch * tools.texi (Checking programs): New. Modified: trunk/doc/tools.texi =================================================================== --- trunk/doc/tools.texi 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/doc/tools.texi 2007-10-19 14:51:39 UTC (rev 4597) @@ -1045,6 +1045,16 @@ connects to the assuan server in extended mode to allow descriptor passing. This option makes it use the old mode. + at item --run @var{file} + at opindex run +Run the commands from @var{file} at startup and then continue with the +regular input method. + + at item -s + at itemx --subst + at opindex subst +Run the command @code{/subst} at startup. + @item --hex @opindex hex Print data lines in a hex format and the ASCII representation of @@ -1065,20 +1075,85 @@ commands to control its operation. These control commands all start with a slash (@code{/}). - @table @code @item /echo @var{args} Just print @var{args}. + at item /let @var{name} @var{value} +Set the variable @var{name} to @var{value}. Variables are only +substituted on the input if the @command{/subst} has been used. +Variables are referenced by prefixing the name with a dollr sign and +optionally include the name in curly braces. The rules for a valid name +are idnetically to those of the standard bourne shell. This is not yet +enforced but may be in the future. When used with curly braces no +leading or trailing white space is allowed. + +If a variable is not found, it is searched in the environment and if +found copied to the table of variables. + +Variable functions are available: The name of the function must be +followed by at least one space and the at least one argument. The +following functions are available: + + at table @code + at item get +Return a value described by the argument. Available arguments are: + + at table @code + at item cwd +The current working directory. + at item homedir +The gnupg homedir. + at item sysconfdir +GnuPG's system configuration directory. + at item bindir +GnuPG's binary directory. + at item libdir +GnuPG's library directory. + at item libexecdir +GnuPG's library directory for executable files. + at item datadir +GnuPG's data directory. + at item serverpid +The PID of the current server. Command @command{/serverpid} must +have been given to return a useful value. + at end table + + at item unescape @var{args} +Remove C-style escapes from @var{args}. Note that @code{\0} and + at code{\x00} terminate the returned string implictly. The string to be +converted are the entire arguments right behind the delimiting space of +the function name. + + at item unpercent @var{args} + at itemx unpercent+ @var{args} +Remove percent style ecaping from @var{args}. Note that @code{%00} +terminates the string implicitly. The string to be converted are the +entire arguments right behind the delimiting space of the function +name. @code{unpercent+} also maps plus signs to a spaces. + + at item percent @var{args} + at item percent+ @var{args} +Escape the @var{args} using percent style ecaping. Tabs, formfeeds, +linefeeds, carriage returns and colons are escaped. @code{percent+} also +maps spaces to plus signs. + + at end table + + + at item /definq @var{name} @var{var} +Use content of the variable @var{var} for inquiries with @var{name}. + at var{name} may be an asterisk (@code{*}) to match any inquiry. + + @item /definqfile @var{name} @var{file} - Use content of @var{file} for inquiries with @var{name}. - at var{name} may be an asterisk (@code{*} to match any inquiry. + at var{name} may be an asterisk (@code{*}) to match any inquiry. @item /definqprog @var{name} @var{prog} Run @var{prog} for inquiries matching @var{name} and pass the -entire line to it as command line arguments +entire line to it as command line arguments. @item /showdef Print all definitions @@ -1095,6 +1170,21 @@ @item /recvfd Not yet implemented. + at item /open @var{var} @var{file} [@var{mode}] +Open @var{file} and assign the file descriptor to @var{var}. Warning: +This command is experimental and might change in future versions. + + at item /close @var{fd} +Close the file descriptor @var{fd}. Warning: This command is +experimental and might change in future versions. + + at item /showopen +Show a listy of open files. + + at item /serverpid +Send the Assuan command @command{GETINFO pid} to the server and store +the returned PID for internal purposes. + @item /hex @itemx /nohex Same as the command line option @option{--hex}. @@ -1103,6 +1193,17 @@ @itemx /nodecode Same as the command line option @option{--decode}. + at item /subst + at itemx /nosubst +Enable and disable variable substitution. It defaults to disabled +unless the command line option @option{--subst} has been used. + + at item /run @var{file} +Run commands from @var{file}. + + at item /bye +Terminate the connection and the program + @item /help Print a list of available control commands. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/tools/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) @@ -1,5 +1,18 @@ 2007-10-19 Werner Koch + * gpg-connect-agent.c (get_var_ext): New. + (substitute_line): Use it. + (assign_variable): Implement /slet in terms of get_var_ext. + (main): New option -s/--subst. + (add_definq): Add arg IS_VAR. Change all callers. + (main): Add command /definq. + (handle_inquire): Implement new command. + (substitute_line_copy): New. + (unescape_string, unpercent_string): New. + * no-libgcrypt.c (gcry_set_outofcore_handler) + (gcry_set_fatalerror_handler, gcry_set_log_handler): New. + * Makefile.am (gpg_connect_agent_LDADD): Link to libreadline. + * gpgconf-comp.c (retrieve_options_from_file): Don't call fclose with NULL. Fixes bug 842. Modified: trunk/tools/Makefile.am =================================================================== --- trunk/tools/Makefile.am 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/tools/Makefile.am 2007-10-19 14:51:39 UTC (rev 4597) @@ -80,7 +80,9 @@ gpg_connect_agent_SOURCES = gpg-connect-agent.c no-libgcrypt.c # FIXME: remove PTH_LIBS (why do we need them at all?) gpg_connect_agent_LDADD = $(common_libs) $(LIBASSUAN_LIBS) $(PTH_LIBS) \ - $(GPG_ERROR_LIBS) $(LIBINTL) $(NETLIBS) $(LIBICONV) + $(GPG_ERROR_LIBS) \ + ../common/libgpgrl.a $(LIBREADLINE) \ + $(LIBINTL) $(NETLIBS) $(LIBICONV) gpgkey2ssh_SOURCES = gpgkey2ssh.c gpgkey2ssh_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) @@ -99,5 +101,5 @@ # Make sure that all libs are build before we use them. This is # important for things like make -j2. -$(PROGRAMS): $(common_libs) $(pwquery_libs) +$(PROGRAMS): $(common_libs) $(pwquery_libs) ../common/libgpgrl.a Modified: trunk/tools/gpg-connect-agent.c =================================================================== --- trunk/tools/gpg-connect-agent.c 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/tools/gpg-connect-agent.c 2007-10-19 14:51:39 UTC (rev 4597) @@ -25,13 +25,18 @@ #include #include #include +#include #include "i18n.h" #include "../common/util.h" #include "../common/asshelp.h" #include "../common/sysutils.h" #include "../common/membuf.h" +#include "../common/ttyio.h" +#define CONTROL_D ('D' - 'A' + 1) +#define octdigitp(p) (*(p) >= '0' && *(p) <= '7') + /* Constants to identify the commands and options. */ enum cmd_and_opt_values { @@ -41,6 +46,7 @@ oRawSocket = 'S', oExec = 'E', oRun = 'r', + oSubst = 's', oNoVerbose = 500, oHomedir, @@ -65,6 +71,7 @@ { oNoExtConnect, "no-ext-connect", 0, N_("do not use extended connect mode")}, { oRun, "run", 2, N_("|FILE|run commands from FILE on startup")}, + { oSubst, "subst", 0, N_("run /subst on startup")}, /* hidden options */ { oNoVerbose, "no-verbose", 0, "@"}, { oHomedir, "homedir", 2, "@" }, @@ -94,7 +101,8 @@ { struct definq_s *next; char *name; /* Name of inquiry or NULL for any name. */ - int is_prog; /* True if this is a program to run. */ + int is_var; /* True if FILE is a variable name. */ + int is_prog; /* True if FILE is a program to run. */ char file[1]; /* Name of file or program. */ }; typedef struct definq_s *definq_t; @@ -129,6 +137,7 @@ /*-- local prototypes --*/ +static char *substitute_line_copy (const char *buffer); static int read_and_print_response (assuan_context_t ctx, int *r_goterr); static assuan_context_t start_agent (void); @@ -185,6 +194,145 @@ } +/* Unescale STRING and returned the malloced result. The surrounding + quotes must already be removed from STRING. */ +static char * +unescape_string (const char *string) +{ + const unsigned char *s; + int esc; + size_t n; + char *buffer; + unsigned char *d; + + n = 0; + for (s = (const unsigned char*)string, esc=0; *s; s++) + { + if (esc) + { + switch (*s) + { + case 'b': + case 't': + case 'v': + case 'n': + case 'f': + case 'r': + case '"': + case '\'': + case '\\': n++; break; + case 'x': + if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2)) + n++; + break; + + default: + if (s[1] && s[2] + && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) + n++; + break; + } + esc = 0; + } + else if (*s == '\\') + esc = 1; + else + n++; + } + + buffer = xmalloc (n+1); + d = (unsigned char*)buffer; + for (s = (const unsigned char*)string, esc=0; *s; s++) + { + if (esc) + { + switch (*s) + { + case 'b': *d++ = '\b'; break; + case 't': *d++ = '\t'; break; + case 'v': *d++ = '\v'; break; + case 'n': *d++ = '\n'; break; + case 'f': *d++ = '\f'; break; + case 'r': *d++ = '\r'; break; + case '"': *d++ = '\"'; break; + case '\'': *d++ = '\''; break; + case '\\': *d++ = '\\'; break; + case 'x': + if (s[1] && s[2] && hexdigitp (s+1) && hexdigitp (s+2)) + { + s++; + *d++ = xtoi_2 (s); + s++; + } + break; + + default: + if (s[1] && s[2] + && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2)) + { + *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2); + s += 2; + } + break; + } + esc = 0; + } + else if (*s == '\\') + esc = 1; + else + *d++ = *s; + } + *d = 0; + return buffer; +} + + +/* Do the percent unescaping and return a newly malloced string. + If WITH_PLUS is set '+' characters will be changed to space. */ +static char * +unpercent_string (const char *string, int with_plus) +{ + const unsigned char *s; + unsigned char *buffer, *p; + size_t n; + + n = 0; + for (s=(const unsigned char *)string; *s; s++) + { + if (*s == '%' && s[1] && s[2]) + { + s++; + n++; + s++; + } + else if (with_plus && *s == '+') + n++; + else + n++; + } + + buffer = xmalloc (n+1); + p = buffer; + for (s=(const unsigned char *)string; *s; s++) + { + if (*s == '%' && s[1] && s[2]) + { + s++; + *p++ = xtoi_2 (s); + s++; + } + else if (with_plus && *s == '+') + *p++ = ' '; + else + *p++ = *s; + } + *p = 0; + return (char*)buffer; +} + + + + static const char * set_var (const char *name, const char *value) @@ -241,7 +389,146 @@ } +/* Extended version of get_var. This returns a malloced string and + understand the fucntion syntax: "func args". + Defined functions are + + get - Return a value described by the next argument: + cwd - The current working directory. + homedir - The gnupg homedir. + sysconfdir - GnuPG's system configuration directory. + bindir - GnuPG's binary directory. + libdir - GnuPG's library directory. + libexecdir - GnuPG's library directory for executable files. + datadir - GnuPG's data directory. + serverpid - The PID of the current server. + + unescape ARGS + Remove C-style escapes from string. Note that "\0" and + "\x00" terminate the string implictly. Use "\x7d" to + represent the closing brace. The args start right after + the first space after the function name. + + unpercent ARGS + unpercent+ ARGS + Remove percent style ecaping from string. NOte that "%00 + terminates the string implicitly. Use "%7d" to represetn + the closing brace. The args start right after the first + space after the function name. "unpercent+" also maps '+' + to space. + + percent ARGS + percent+ ARGS + Escape the args using the percent style. Tabs, formfeeds, + linefeeds and carriage returns are also escaped. + "percent+" also maps spaces to plus characters. + + Example: get_var_ext ("get sysconfdir") -> "/etc/gnupg" + + */ +static char * +get_var_ext (const char *name) +{ + static int recursion_count; + const char *s; + char *result; + char *p; + char *free_me = NULL; + + if (recursion_count > 50) + { + log_error ("variables nested too deeply\n"); + return NULL; + } + + recursion_count++; + free_me = opt.enable_varsubst? substitute_line_copy (name) : NULL; + if (free_me) + name = free_me; + for (s=name; *s && !spacep (s); s++) + ; + if (!*s) + { + s = get_var (name); + result = s? xstrdup (s): NULL; + } + else if ( (s - name) == 3 && !strncmp (name, "get", 3)) + { + while ( spacep (s) ) + s++; + if (!strcmp (s, "cwd")) + { + result = gnu_getcwd (); + if (!result) + log_error ("getcwd failed: %s\n", strerror (errno)); + } + else if (!strcmp (s, "homedir")) + result = make_filename (opt.homedir, NULL); + else if (!strcmp (s, "sysconfdir")) + result = xstrdup (gnupg_sysconfdir ()); + else if (!strcmp (s, "bindir")) + result = xstrdup (gnupg_bindir ()); + else if (!strcmp (s, "libdir")) + result = xstrdup (gnupg_libdir ()); + else if (!strcmp (s, "libexecdir")) + result = xstrdup (gnupg_libexecdir ()); + else if (!strcmp (s, "datadir")) + result = xstrdup (gnupg_datadir ()); + else if (!strcmp (s, "serverpid")) + { + char numbuf[30]; + snprintf (numbuf, sizeof numbuf, "%d", (int)server_pid); + result = xstrdup (numbuf); + } + else + { + log_error ("invalid argument `%s' for variable function `get'\n", s); + log_info ("valid are: cwd, " + "{home,bin,lib,libexec,data}dir, serverpid\n"); + result = NULL; + } + } + else if ( (s - name) == 8 && !strncmp (name, "unescape", 8)) + { + s++; + result = unescape_string (s); + } + else if ( (s - name) == 9 && !strncmp (name, "unpercent", 9)) + { + s++; + result = unpercent_string (s, 0); + } + else if ( (s - name) == 10 && !strncmp (name, "unpercent+", 10)) + { + s++; + result = unpercent_string (s, 1); + } + else if ( (s - name) == 7 && !strncmp (name, "percent", 7)) + { + s++; + result = percent_escape (s, "\t\r\n\f\v"); + } + else if ( (s - name) == 8 && !strncmp (name, "percent+", 8)) + { + s++; + result = percent_escape (s, "\t\r\n\f\v"); + for (p=result; *p; p++) + if (*p == ' ') + *p = '+'; + } + else + { + log_error ("unknown variable function `%.*s'\n", (int)(s-name), name); + result = NULL; + } + + xfree (free_me); + recursion_count--; + return result; +} + + /* Substitute variables in LINE and return a new allocated buffer if required. The function might modify LINE if the expanded version fits into it. */ @@ -253,6 +540,7 @@ const char *value; size_t valuelen, n; char *result = NULL; + char *freeme = NULL; while (*line) { @@ -268,8 +556,18 @@ } if (p[1] == '{') { - for (pend=p+2; *pend && *pend != '}' ; pend++) - ; + int count = 0; + + for (pend=p+2; *pend; pend++) + { + if (*pend == '{') + count++; + else if (*pend == '}') + { + if (--count < 0) + break; + } + } if (!*pend) return result; /* Unclosed - don't substitute. */ } @@ -281,7 +579,8 @@ if (p[1] == '{' && *pend == '}') { *pend++ = 0; - value = get_var (p+2); + freeme = get_var_ext (p+2); + value = freeme; } else if (*pend) { @@ -319,16 +618,32 @@ free (result); result = dst; } + xfree (freeme); + freeme = NULL; } return result; } +/* Same as substitute_line but do not modify BUFFER. */ +static char * +substitute_line_copy (const char *buffer) +{ + char *result, *p; + + p = xstrdup (buffer?buffer:""); + result = substitute_line (p); + if (!result) + result = p; + else + xfree (p); + return result; +} static void assign_variable (char *line, int syslet) { - char *name, *p, *tmp, *free_me; + char *name, *p, *tmp, *free_me, *buffer; /* Get the name. */ name = line; @@ -343,42 +658,20 @@ set_var (name, NULL); /* Remove variable. */ else if (syslet) { - free_me = opt.enable_varsubst? substitute_line (p) : NULL; + free_me = opt.enable_varsubst? substitute_line_copy (p) : NULL; if (free_me) p = free_me; - if (!strcmp (p, "cwd")) - { - tmp = gnu_getcwd (); - if (!tmp) - log_error ("getcwd failed: %s\n", strerror (errno)); - set_var (name, tmp); - xfree (tmp); - } - else if (!strcmp (p, "homedir")) - set_var (name, opt.homedir); - else if (!strcmp (p, "sysconfdir")) - set_var (name, gnupg_sysconfdir ()); - else if (!strcmp (p, "bindir")) - set_var (name, gnupg_bindir ()); - else if (!strcmp (p, "libdir")) - set_var (name, gnupg_libdir ()); - else if (!strcmp (p, "libexecdir")) - set_var (name, gnupg_libexecdir ()); - else if (!strcmp (p, "datadir")) - set_var (name, gnupg_datadir ()); - else if (!strcmp (p, "serverpid")) - set_int_var (name, (int)server_pid); - else - { - log_error ("undefined tag `%s'\n", p); - log_info ("valid tags are: cwd, {home,bin,lib,libexec,data}dir, " - "serverpid\n"); - } + buffer = xmalloc (4 + strlen (p) + 1); + strcpy (stpcpy (buffer, "get "), p); + tmp = get_var_ext (buffer); + xfree (buffer); + set_var (name, tmp); + xfree (tmp); xfree (free_me); } else { - tmp = opt.enable_varsubst? substitute_line (p) : NULL; + tmp = opt.enable_varsubst? substitute_line_copy (p) : NULL; if (tmp) { set_var (name, tmp); @@ -405,7 +698,7 @@ change the content of LINE. We assume that leading white spaces are already removed. */ static void -add_definq (char *line, int is_prog) +add_definq (char *line, int is_var, int is_prog) { definq_t d; char *name, *p; @@ -421,6 +714,7 @@ d = xmalloc (sizeof *d + strlen (p) ); strcpy (d->file, p); + d->is_var = is_var; d->is_prog = is_prog; if ( !strcmp (name, "*")) d->name = NULL; @@ -441,10 +735,12 @@ for (d=definq_list; d; d = d->next) if (d->name) - printf ("%-20s %c %s\n", d->name, d->is_prog? 'p':'f', d->file); + printf ("%-20s %c %s\n", + d->name, d->is_var? 'v' : d->is_prog? 'p':'f', d->file); for (d=definq_list; d; d = d->next) if (!d->name) - printf ("%-20s %c %s\n", "*", d->is_prog? 'p':'f', d->file); + printf ("%-20s %c %s\n", "*", + d->is_var? 'v': d->is_prog? 'p':'f', d->file); } @@ -727,7 +1023,10 @@ int cmderr; const char *opt_run = NULL; FILE *script_fp = NULL; + int use_tty, last_was_tty; + + gnupg_rl_initialize (); set_strusage (my_strusage); log_set_prefix ("gpg-connect-agent", 1); @@ -759,6 +1058,7 @@ case oExec: opt.exec = 1; break; case oNoExtConnect: opt.connect_flags &= ~(1); break; case oRun: opt_run = pargs.r.ret_str; break; + case oSubst: opt.enable_varsubst = 1; break; default: pargs.err = 2; break; } @@ -767,6 +1067,8 @@ if (log_get_errorcount (0)) exit (2); + use_tty = (isatty ( fileno (stdin)) && isatty (fileno (stdout))); + if (opt.exec) { if (!argc) @@ -841,13 +1143,35 @@ line = NULL; linesize = 0; + last_was_tty = 0; for (;;) { int n; size_t maxlength; maxlength = 2048; - n = read_line (script_fp? script_fp:stdin, &line, &linesize, &maxlength); + if (use_tty && !script_fp) + { + last_was_tty = 1; + line = tty_get ("> "); + n = strlen (line); + if (n==1 && *line == CONTROL_D) + n = 0; + if (n >= maxlength) + maxlength = 0; + } + else + { + if (last_was_tty) + { + xfree (line); + line = NULL; + linesize = 0; + last_was_tty = 0; + } + n = read_line (script_fp? script_fp:stdin, + &line, &linesize, &maxlength); + } if (n < 0) { log_error (_("error reading input: %s\n"), strerror (errno)); @@ -899,19 +1223,45 @@ } else if (!strcmp (cmd, "slet")) { + /* Deprecated - never used in a released version. */ assign_variable (p, 1); } else if (!strcmp (cmd, "showvar")) { show_variables (); } + else if (!strcmp (cmd, "definq")) + { + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + add_definq (tmpline, 1, 0); + xfree (tmpline); + } + else + add_definq (p, 1, 0); + } else if (!strcmp (cmd, "definqfile")) { - add_definq (p, 0); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + add_definq (tmpline, 0, 0); + xfree (tmpline); + } + else + add_definq (p, 0, 0); } else if (!strcmp (cmd, "definqprog")) { - add_definq (p, 1); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + add_definq (tmpline, 0, 1); + xfree (tmpline); + } + else + add_definq (p, 0, 1); } else if (!strcmp (cmd, "showdef")) { @@ -934,21 +1284,49 @@ } else if (!strcmp (cmd, "sendfd")) { - do_sendfd (ctx, p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + do_sendfd (ctx, tmpline); + xfree (tmpline); + } + else + do_sendfd (ctx, p); continue; } else if (!strcmp (cmd, "recvfd")) { - do_recvfd (ctx, p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + do_recvfd (ctx, tmpline); + xfree (tmpline); + } + else + do_recvfd (ctx, p); continue; } else if (!strcmp (cmd, "open")) { - do_open (p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + do_open (tmpline); + xfree (tmpline); + } + else + do_open (p); } else if (!strcmp (cmd, "close")) { - do_close (p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + do_close (tmpline); + xfree (tmpline); + } + else + do_close (p); } else if (!strcmp (cmd, "showopen")) { @@ -1012,19 +1390,15 @@ "Available commands:\n" "/echo ARGS Echo ARGS.\n" "/let NAME VALUE Set variable NAME to VALUE.\n" -"/slet NAME TAG Set variable NAME to the value described by TAG.\n" "/showvar Show all variables.\n" -"/definqfile NAME FILE\n" -" Use content of FILE for inquiries with NAME.\n" -" NAME may be \"*\" to match any inquiry.\n" -"/definqprog NAME PGM\n" -" Run PGM for inquiries matching NAME and pass the\n" -" entire line to it as arguments.\n" +"/definq NAME VAR Use content of VAR for inquiries with NAME.\n" +"/definqfile NAME FILE Use content of FILE for inquiries with NAME.\n" +"/definqprog NAME PGM Run PGM for inquiries with NAME.\n" "/showdef Print all definitions.\n" "/cleardef Delete all definitions.\n" "/sendfd FILE MODE Open FILE and pass descriptor to server.\n" "/recvfd Receive FD from server and print.\n" -"/open VAR FILE MODE Open FILE and assign the descrptor to VAR.\n" +"/open VAR FILE MODE Open FILE and assign the file descriptor to VAR.\n" "/close FD Close file with descriptor FD.\n" "/showopen Show descriptors of all open files.\n" "/serverpid Retrieve the pid of the server.\n" @@ -1094,7 +1468,7 @@ { const char *name; definq_t d; - FILE *fp; + FILE *fp = NULL; char buffer[1024]; int rc, n; @@ -1126,43 +1500,58 @@ return 0; } - if (d->is_prog) + if (d->is_var) { - fp = popen (d->file, "r"); - if (!fp) - log_error ("error executing `%s': %s\n", d->file, strerror (errno)); - else if (opt.verbose) - log_error ("handling inquiry `%s' by running `%s'\n", name, d->file); + char *tmpvalue = get_var_ext (d->file); + rc = assuan_send_data (ctx, tmpvalue, strlen (tmpvalue)); + xfree (tmpvalue); + if (rc) + log_error ("sending data back failed: %s\n", gpg_strerror (rc) ); } else { - fp = fopen (d->file, "rb"); + if (d->is_prog) + { + fp = popen (d->file, "r"); + if (!fp) + log_error ("error executing `%s': %s\n", + d->file, strerror (errno)); + else if (opt.verbose) + log_error ("handling inquiry `%s' by running `%s'\n", + name, d->file); + } + else + { + fp = fopen (d->file, "rb"); + if (!fp) + log_error ("error opening `%s': %s\n", d->file, strerror (errno)); + else if (opt.verbose) + log_error ("handling inquiry `%s' by returning content of `%s'\n", + name, d->file); + } if (!fp) - log_error ("error opening `%s': %s\n", d->file, strerror (errno)); - else if (opt.verbose) - log_error ("handling inquiry `%s' by returning content of `%s'\n", - name, d->file); - } - if (!fp) - return 0; + return 0; - while ( (n = fread (buffer, 1, sizeof buffer, fp)) ) - { - rc = assuan_send_data (ctx, buffer, n); - if (rc) + while ( (n = fread (buffer, 1, sizeof buffer, fp)) ) { - log_error ("sending data back failed: %s\n", gpg_strerror (rc) ); - break; + rc = assuan_send_data (ctx, buffer, n); + if (rc) + { + log_error ("sending data back failed: %s\n", gpg_strerror (rc) ); + break; + } } + if (ferror (fp)) + log_error ("error reading from `%s': %s\n", d->file, strerror (errno)); } - if (ferror (fp)) - log_error ("error reading from `%s': %s\n", d->file, strerror (errno)); rc = assuan_send_data (ctx, NULL, 0); if (rc) log_error ("sending data back failed: %s\n", gpg_strerror (rc) ); - if (d->is_prog) + if (d->is_var) + ; + else if (d->is_prog) { if (pclose (fp)) log_error ("error running `%s': %s\n", d->file, strerror (errno)); Modified: trunk/tools/no-libgcrypt.c =================================================================== --- trunk/tools/no-libgcrypt.c 2007-10-19 08:49:07 UTC (rev 4596) +++ trunk/tools/no-libgcrypt.c 2007-10-19 14:51:39 UTC (rev 4597) @@ -117,3 +117,24 @@ { return 0; } + +void +gcry_set_outofcore_handler (gcry_handler_no_mem_t h, void *opaque) +{ + (void)h; + (void)opaque; +} + +void +gcry_set_fatalerror_handler (gcry_handler_error_t fnc, void *opaque) +{ + (void)fnc; + (void)opaque; +} + +void +gcry_set_log_handler (gcry_handler_log_t f, void *opaque) +{ + (void)f; + (void)opaque; +} From cvs at cvs.gnupg.org Fri Oct 19 17:58:49 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Fri, 19 Oct 2007 17:58:49 +0200 Subject: [svn] GnuPG - r4598 - in trunk: agent common g10 sm tools Message-ID: Author: wk Date: 2007-10-19 17:58:38 +0200 (Fri, 19 Oct 2007) New Revision: 4598 Modified: trunk/agent/ChangeLog trunk/agent/protect-tool.c trunk/common/ChangeLog trunk/common/i18n.c trunk/common/i18n.h trunk/g10/ChangeLog trunk/g10/passphrase.c trunk/sm/ChangeLog trunk/sm/certdump.c trunk/sm/qualified.c trunk/tools/ChangeLog trunk/tools/symcryptrun.c Log: Factored utf8 switching code out to i18n.c. Modified: trunk/agent/ChangeLog =================================================================== --- trunk/agent/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/agent/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) @@ -1,3 +1,7 @@ +2007-10-19 Werner Koch + + * protect-tool.c (get_passphrase): Use new utf8 switch fucntions. + 2007-10-15 Daiki Ueno (wk) * command-ssh.c (reenter_compare_cb): New function; imported from Modified: trunk/agent/protect-tool.c =================================================================== --- trunk/agent/protect-tool.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/agent/protect-tool.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -1171,38 +1171,16 @@ char *pw; int err; const char *desc; -#ifdef ENABLE_NLS - char *orig_codeset = NULL; -#endif + char *orig_codeset; int error_msgno; - if (opt_passphrase) return xstrdup (opt_passphrase); error_msgno = promptno / 100; promptno %= 100; -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset && !strcmp (orig_codeset, "UTF-8")) - orig_codeset = NULL; - if (orig_codeset) - { - /* We only switch when we are able to restore the codeset later. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif + orig_codeset = i18n_switchto_utf8 (); if (promptno == 1 && opt_prompt) desc = opt_prompt; @@ -1226,13 +1204,7 @@ _("Passphrase:"), desc, opt_check, &err); err = map_spwq_error (err); -#ifdef ENABLE_NLS - if (orig_codeset) - { - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); - xfree (orig_codeset); - } -#endif + i18n_switchback (orig_codeset); if (!pw) { Modified: trunk/common/ChangeLog =================================================================== --- trunk/common/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/common/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) @@ -1,3 +1,7 @@ +2007-10-19 Werner Koch + + * i18n.c (i18n_switchto_utf8, i18n_switchback): New. + 2007-10-01 Werner Koch * sysutils.h (FD2INT, INT2FD): New. Modified: trunk/common/i18n.c =================================================================== --- trunk/common/i18n.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/common/i18n.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -18,9 +18,17 @@ */ #include +#ifdef HAVE_LOCALE_H +#include +#endif +#ifdef HAVE_LANGINFO_CODESET +#include +#endif +#include "util.h" #include "i18n.h" + void i18n_init (void) { @@ -35,3 +43,59 @@ #endif } + +/* The Assuan agent protocol requires us to transmit utf-8 strings + thus we need a fucntion to temporary switch gettext from native to + utf8. */ +char * +i18n_switchto_utf8 (void) +{ +#ifdef ENABLE_NLS + char *orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); +#ifdef HAVE_LANGINFO_CODESET + if (!orig_codeset) + orig_codeset = nl_langinfo (CODESET); +#endif + if (orig_codeset) + { /* We only switch when we are able to restore the codeset later. + Note that bind_textdomain_codeset does only return on memory + errors but not if a codeset is not available. Thus we don't + bother printing a diagnostic here. */ + orig_codeset = xstrdup (orig_codeset); + if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) + { + xfree (orig_codeset); + orig_codeset = NULL; + } + } + return orig_codeset; +#else + return NULL; +#endif +} + +/* Switch back to the saved codeset. */ +void +i18n_switchback (char *saved_codeset) +{ +#ifdef ENABLE_NLS + if (saved_codeset) + { + bind_textdomain_codeset (PACKAGE_GT, saved_codeset); + xfree (saved_codeset); + } +#else + (void)saved_codeset; +#endif +} + + +/* Gettext variant which temporary switches to utf-8 for string. */ +const char * +i18n_utf8 (const char *string) +{ + char *saved = i18n_switchto_utf8 (); + const char *result = _(string); + i18n_switchback (saved); + return result; +} Modified: trunk/common/i18n.h =================================================================== --- trunk/common/i18n.h 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/common/i18n.h 2007-10-19 15:58:38 UTC (rev 4598) @@ -39,6 +39,9 @@ #endif /*!USE_SIMPLE_GETTEXT*/ void i18n_init (void); +char *i18n_switchto_utf8 (void); +void i18n_switchback (char *saved_codeset); +const char *i18n_utf8 (const char *string); #endif /*GNUPG_COMMON_I18N_H*/ Modified: trunk/g10/ChangeLog =================================================================== --- trunk/g10/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/g10/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) @@ -1,3 +1,7 @@ +2007-10-19 Werner Koch + + * passphrase.c (passphrase_get): Use new utf8 switching fucntions. + 2007-09-14 Werner Koch * gpg.c (build_lib_list): New. Modified: trunk/g10/passphrase.c =================================================================== --- trunk/g10/passphrase.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/g10/passphrase.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -257,9 +257,7 @@ PKT_public_key *pk = xmalloc_clear( sizeof *pk ); byte fpr[MAX_FINGERPRINT_LEN]; int have_fpr = 0; -#ifdef ENABLE_NLS - char *orig_codeset = NULL; -#endif + char *orig_codeset; char *my_prompt; char hexfprbuf[20*2+1]; const char *my_cacheid; @@ -279,23 +277,7 @@ pk = NULL; /* oops: no key for some reason */ } -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset) - { /* We only switch when we are able to restore the codeset later. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif + orig_codeset = i18n_switchto_utf8 (); if (custom_description) atext = native_to_utf8 (custom_description); @@ -371,6 +353,9 @@ xfree (my_prompt); xfree (atext); atext = NULL; + i18n_switchback (orig_codeset); + + if (!rc) ; else if ( gpg_err_code (rc) == GPG_ERR_CANCELED ) @@ -392,14 +377,7 @@ if (canceled) *canceled = 1; } - -#ifdef ENABLE_NLS - if (orig_codeset) - { - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); - xfree (orig_codeset); - } -#endif + if (pk) free_public_key( pk ); if (rc) Modified: trunk/sm/ChangeLog =================================================================== --- trunk/sm/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/sm/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) @@ -1,3 +1,9 @@ +2007-10-19 Werner Koch + + * qualified.c (gpgsm_qualified_consent): Use i18N-swicth functions. + (gpgsm_not_qualified_warning): Ditto. + * certdump.c (gpgsm_format_keydesc): Ditto. + 2007-09-14 Werner Koch * gpgsm.c (build_lib_list): New. Modified: trunk/sm/certdump.c =================================================================== --- trunk/sm/certdump.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/sm/certdump.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -891,9 +891,7 @@ char created[20]; char *sn; ksba_sexp_t sexp; -#ifdef ENABLE_NLS - char *orig_codeset = NULL; -#endif + char *orig_codeset; name = ksba_cert_get_subject (cert, 0); subject = name? gpgsm_format_name2 (name, 0) : NULL; @@ -909,29 +907,8 @@ else *created = 0; + orig_codeset = i18n_switchto_utf8 (); -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset) - { /* We only switch when we are able to restore the codeset later. - Note that bind_textdomain_codeset does only return on memory - errors but not if a codeset is not available. Thus we don't - bother printing a diagnostic here. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif - - rc = asprintf (&name, _("Please enter the passphrase to unlock the" " secret key for:\n" @@ -942,13 +919,7 @@ gpgsm_get_short_fingerprint (cert), created); -#ifdef ENABLE_NLS - if (orig_codeset) - { - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); - xfree (orig_codeset); - } -#endif + i18n_switchback (orig_codeset); if (rc < 0) { Modified: trunk/sm/qualified.c =================================================================== --- trunk/sm/qualified.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/sm/qualified.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -24,12 +24,6 @@ #include #include #include -#ifdef HAVE_LOCALE_H -#include -#endif -#ifdef HAVE_LANGINFO_CODESET -#include -#endif #include "gpgsm.h" #include "i18n.h" @@ -200,26 +194,7 @@ subject = gpgsm_format_name2 (name, 0); ksba_free (name); name = NULL; -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset) - { /* We only switch when we are able to restore the codeset later. - Note that bind_textdomain_codeset does only return on memory - errors but not if a codeset is not available. Thus we don't - bother printing a diagnostic here. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif + orig_codeset = i18n_switchto_utf8 (); if (asprintf (&name, _("You are about to create a signature using your " @@ -239,10 +214,7 @@ else err = 0; -#ifdef ENABLE_NLS - if (orig_codeset) - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); -#endif + i18n_switchback (orig_codeset); xfree (orig_codeset); xfree (subject); @@ -288,9 +260,7 @@ gpg_error_t err; char *name, *subject, *buffer, *p; const char *s; -#ifdef ENABLE_NLS - char *orig_codeset = NULL; -#endif + char *orig_codeset; if (!opt.qualsig_approval) return 0; @@ -301,28 +271,8 @@ subject = gpgsm_format_name2 (name, 0); ksba_free (name); name = NULL; + orig_codeset = i18n_switchto_utf8 (); -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset) - { /* We only switch when we are able to restore the codeset later. - Note that bind_textdomain_codeset does only return on memory - errors but not if a codeset is not available. Thus we don't - bother printing a diagnostic here. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif - if (asprintf (&name, _("You are about to create a signature using your " "certificate:\n" @@ -334,13 +284,7 @@ else err = 0; -#ifdef ENABLE_NLS - if (orig_codeset) - { - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); - xfree (orig_codeset); - } -#endif + i18n_switchback (orig_codeset); xfree (subject); if (err) Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/tools/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) @@ -1,5 +1,7 @@ 2007-10-19 Werner Koch + * symcryptrun.c (confucius_get_pass): Use utf8 switching functions. + * gpg-connect-agent.c (get_var_ext): New. (substitute_line): Use it. (assign_variable): Implement /slet in terms of get_var_ext. Modified: trunk/tools/symcryptrun.c =================================================================== --- trunk/tools/symcryptrun.c 2007-10-19 14:51:39 UTC (rev 4597) +++ trunk/tools/symcryptrun.c 2007-10-19 15:58:38 UTC (rev 4598) @@ -424,47 +424,18 @@ { int err; char *pw; -#ifdef ENABLE_NLS - char *orig_codeset = NULL; -#endif + char *orig_codeset; if (canceled) *canceled = 0; -#ifdef ENABLE_NLS - /* The Assuan agent protocol requires us to transmit utf-8 strings */ - orig_codeset = bind_textdomain_codeset (PACKAGE_GT, NULL); -#ifdef HAVE_LANGINFO_CODESET - if (!orig_codeset) - orig_codeset = nl_langinfo (CODESET); -#endif - if (orig_codeset && !strcmp (orig_codeset, "UTF-8")) - orig_codeset = NULL; - if (orig_codeset) - { - /* We only switch when we are able to restore the codeset later. */ - orig_codeset = xstrdup (orig_codeset); - if (!bind_textdomain_codeset (PACKAGE_GT, "utf-8")) - { - xfree (orig_codeset); - orig_codeset = NULL; - } - } -#endif - + orig_codeset = i18n_switchto_utf8 (); pw = simple_pwquery (cacheid, again ? _("does not match - try again"):NULL, _("Passphrase:"), NULL, 0, &err); err = map_spwq_error (err); + i18n_switchback (orig_codeset); -#ifdef ENABLE_NLS - if (orig_codeset) - { - bind_textdomain_codeset (PACKAGE_GT, orig_codeset); - xfree (orig_codeset); - } -#endif - if (!pw) { if (err) From cvs at cvs.gnupg.org Sun Oct 21 18:07:23 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Sun, 21 Oct 2007 18:07:23 +0200 Subject: [svn] GnuPG - r4599 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2007-10-21 18:07:13 +0200 (Sun, 21 Oct 2007) New Revision: 4599 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/armor.c branches/STABLE-BRANCH-1-4/g10/misc.c Log: * misc.c (compliance_option_string, compliance_failure): Minor cleanup. * armor.c (is_armor_header): Comment about 4880. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-19 15:58:38 UTC (rev 4598) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-21 16:07:13 UTC (rev 4599) @@ -1,3 +1,10 @@ +2007-10-21 David Shaw + + * misc.c (compliance_option_string, compliance_failure): Minor + cleanup. + + * armor.c (is_armor_header): Comment about 4880. + 2007-10-17 David Shaw * options.h, gpg.c (main), misc.c (compliance_option_string): Add Modified: branches/STABLE-BRANCH-1-4/g10/armor.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/armor.c 2007-10-19 15:58:38 UTC (rev 4598) +++ branches/STABLE-BRANCH-1-4/g10/armor.c 2007-10-21 16:07:13 UTC (rev 4599) @@ -356,7 +356,8 @@ --rfc2440 is set since 2440 reads "The header lines, therefore, MUST start at the beginning of a line, and MUST NOT have text following them on the same line." It is unclear whether "text" - refers to all text or just non-whitespace text. */ + refers to all text or just non-whitespace text. 4880 clarified + this was only non-whitespace text. */ if(RFC2440) { Modified: branches/STABLE-BRANCH-1-4/g10/misc.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/misc.c 2007-10-19 15:58:38 UTC (rev 4598) +++ branches/STABLE-BRANCH-1-4/g10/misc.c 2007-10-21 16:07:13 UTC (rev 4599) @@ -799,51 +799,64 @@ const char * compliance_option_string(void) { + char *ver="???"; + switch(opt.compliance) { - case CO_RFC4880: - return "--openpgp"; - case CO_RFC2440: - return "--rfc2440"; - case CO_RFC1991: - return "--rfc1991"; - case CO_PGP2: - return "--pgp2"; - case CO_PGP6: - return "--pgp6"; - case CO_PGP7: - return "--pgp7"; - case CO_PGP8: - return "--pgp8"; - default: - return "???"; + case CO_GNUPG: return "--gnupg"; + case CO_RFC4880: return "--openpgp"; + case CO_RFC2440: return "--rfc2440"; + case CO_RFC1991: return "--rfc1991"; + case CO_PGP2: return "--pgp2"; + case CO_PGP6: return "--pgp6"; + case CO_PGP7: return "--pgp7"; + case CO_PGP8: return "--pgp8"; } + + return ver; } -static const char * -compliance_string(void) +void +compliance_failure(void) { + char *ver="???"; + switch(opt.compliance) { + case CO_GNUPG: + ver="GnuPG"; + break; + + case CO_RFC4880: + ver="OpenPGP"; + break; + case CO_RFC2440: - return "OpenPGP"; + ver="OpenPGP (older)"; + break; + + case CO_RFC1991: + ver="old PGP"; + break; + case CO_PGP2: - return "PGP 2.x"; + ver="PGP 2.x"; + break; + case CO_PGP6: - return "PGP 6.x"; + ver="PGP 6.x"; + break; + case CO_PGP7: - return "PGP 7.x"; + ver="PGP 7.x"; + break; + case CO_PGP8: - return "PGP 8.x"; - default: - return "???"; + ver="PGP 8.x"; + break; } -} -void -compliance_failure(void) -{ - log_info(_("this message may not be usable by %s\n"),compliance_string()); + log_info(_("this message may not be usable by %s\n"),ver); opt.compliance=CO_GNUPG; } From cvs at cvs.gnupg.org Mon Oct 22 17:31:20 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 22 Oct 2007 17:31:20 +0200 Subject: [svn] GpgOL - r194 - in trunk: . doc po src Message-ID: Author: wk Date: 2007-10-22 17:31:09 +0200 (Mon, 22 Oct 2007) New Revision: 194 Modified: trunk/NEWS trunk/configure.ac trunk/doc/gpgol.texi trunk/po/de.po trunk/po/sv.po trunk/src/ChangeLog trunk/src/common.c trunk/src/common.h trunk/src/decrypt.bmp trunk/src/dialogs.h trunk/src/encrypt.bmp trunk/src/engine-assuan.c trunk/src/engine-assuan.h trunk/src/engine.c trunk/src/engine.h trunk/src/ext-commands.cpp trunk/src/ext-commands.h trunk/src/key_mana.bmp trunk/src/logo.bmp trunk/src/main.c trunk/src/mimemaker.c trunk/src/myexchext.h trunk/src/olflange-dlgs.cpp trunk/src/sign.bmp Log: Code cleanups. Auto start the server. Prepared a release. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/NEWS 2007-10-22 15:31:09 UTC (rev 194) @@ -1,9 +1,21 @@ -Noteworthy changes for version 0.10.1 +Noteworthy changes for version 0.10.1 (2007-10-22) ================================================== UNDER HEAVY DEVELOPMENT - DO NOT USE FOR PRODUCTION! + - Signed and encrypt has not yet been implemented + - Under OL2007 some menu entries are missing. + * Auto start the server. + + * Code cleanups. + + * Made all dialogs language neutral. + + * The manual has some notes about the Registry usage and new MAPI + properties. + + Noteworthy changes for version 0.10.0 (2007-10-11) ================================================== Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/configure.ac 2007-10-22 15:31:09 UTC (rev 194) @@ -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.10.1]) -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: trunk/doc/gpgol.texi =================================================================== --- trunk/doc/gpgol.texi 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/doc/gpgol.texi 2007-10-22 15:31:09 UTC (rev 194) @@ -9,7 +9,15 @@ * gpgol: (gpgol). An Outlook Plugin for GnuPG. @end direntry + at macro clnt + @sc{c:} @c + at end macro + at macro srvr + @sc{s:} @c + at end macro + + @c Unify some of the indices. @syncodeindex tp fn @syncodeindex pg fn @@ -79,6 +87,8 @@ @menu * Introduction:: How to use this manual. * Assuan Protocol:: Description of the UI server protocol. +* MAPI Properties:: MAPI Properties used by GpgOL. +* Registry Settings:: How GpgOL uses the Registry. Appendices @@ -208,7 +218,61 @@ @end deffn +To support automagically selection of the protocol depending on the +selected keys, the server may implement the follwoing extra command: + at deffn Command PREP_ENCRYPT [- at w{}-protocol=@var{name}] + +This commands considers all recipients set so far and decides whether it +is able to take input and start the actual decryption. This is kind of +a dry-run @command{ENCRYPT} without requiring or using the input and +output file descriptors. The server shall cache the result of any user +selection to avoid asking this again when the actual @command{ENCRYPT} +command is send. The @option{--protocol} option is optional; if it is +not given, the server should allow the user to select the protocol to be +used based on the recipients given or by any other means. + +If this command is given again before a successful @command{ENCRYPT} +command, the second one takes effect. + +Before sending the OK response the server shall tell the client the +protocol to be used (either the one given by the argument or the one +selected by the user) by means of a status line: + at end deffn + + at deffn {Status line} PROTOCOL @var{name} +Advise the client to use the protocol @var{name} for the + at command{ENCRYPT} command. The valid protocol names are listed under +the description of the @command{ENCRYPT} command. The server shall emit +exactly one PROTOCOL status line. + at end deffn + + at noindent +Here is an example of a complete encryption sequence; client lines are +indicated by a @sc{c:}, server responses by @sc{c:}: + + at smallexample + at group + @clnt RESET + @srvr OK + @clnt RECIPIENT foo@@example.net + @srvr OK + @clnt RECIPIENT bar@@example.com + @srvr OK + @clnt PREP_ENCRYPT + @srvr S PROTOCOL OpenPGP + @srvr OK + @clnt INPUT FD=17 + @srvr OK + @clnt OUTPUT FD=18 + @srvr OK + @clnt ENCRYPT + @srvr OK + at end group + at end smallexample + + + @node SIGN @section Sign a Message @@ -433,6 +497,146 @@ @end deffn + at noindent +GpgOL features a button to invoke the certificate manager. To do this +it uses the Assuan command: + + at deffn Command START_KEYMANAGER +The server shall pop up the main window of the key manager (aka +certificate manager). The client expects that the key manger is brought +into the foregound and that this command immediatley returns (does not +wait until the key manager has been fully brought up). + at end deffn + + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at c + at c M A P I P r o p e r t i e s + at c + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at node MAPI Properties + at chapter MAPI Properties used by GpgOL + +GpgOL uses a some custom MAPI properties in the named properties range. +Thus their actual numbers are determined at runtime and only the names +should be used. The GUID assigned to these properties is + at code{31805ab8-3e92-11dc-879c-00061b031004}. + + at table @code + + at item GpgOL Attach Type +This is a property of type LONG and used to further describe the +attachments created by GpgOL. These values are used: + + @table @asis + @item ATTACHTYPE_MOSS = 1 + The attachment contains the original MOSS message. That is either an + S/MIME or a PGP/MIME message in its original RFC-2822 format (but only + with the relevant MIME parts of the main header). + + @item ATTACHTYPE_FROMMOSS = 2 + The attachment has been created from the original MOSS attachment. It + will automagically be recreated as needed. If the atatchment has + been created from an encrypted message, it is saved re-encrypted under + a non-permanent session key. This session key is valid as long as the + current Outlook porcess exists. + + @item ATTACHTYPE_MOSSTEMPL = 3 + The attachment has been created in the course of sending a message. + @end table + + at item GpgOL Sig Status +This is a property of type STRING8 and used to cache the result of the +last signature verification. It is used with the actual message and +consists of a single character, a space and a human readable string +(utf-8 encoded). The first character is used as a machine processable +flag indicating the status. These values are defined: + + @table @code + @item # + The message is not of interest to us. GpgOL may flag any message with + this signature status to avoid extra processing for messages already + known not to need any processing by GpgOL. + + @item @@ + The message has been created and signed or encrypted by GpgOL. + + @item ? + The signature status has not been checked. This is for example used + if the public key to be used for the verification could not be found. + + @item ! + The signature verified okay and is deemed to be fully valid. + + @item ~ + The signature was not fully verified. This often means that the full + result information of the signature verification needs to be + considered to decide the actual validity. Used for example if the + signing key has expired + + @item - + The signature is bad. Either this means the message has been tampered + with or an intermediate message relay has accidently changed + the message (e.g. due to recoding). + + @end table + + at item GpgOL Protect IV +This binary property is used to store the initialization vector of an +re-encrypted attachment. The existence of this property indicates that +the attachment has been encrypted under the non-permanent session key. + + at item GpgOL MIME Info +This property is of type STRING8 and used to store the MIME structure of +the orginal message. The content are lines of colon delimited fields. +The specification has not yet been finished. + + at end table + + + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at c + at c R e g i s t r y S e t t i n g s + at c + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at node Registry Settings + at chapter How GpgOL uses the Registry + +This is a list of registry entries GpgOL knows about. + + at table @code + + at item HKLM\Software\Gnu\GnuPG:Install Directory +This is used by GnuPG to describe the directory where GnupG has been +installed. GpgOL requires this to get the location of the localedir +which is used to show translated strings (@file{gpgol.mo}). It is +further used to check whether GnuPG has been installed at all. + + at item HKCU\Software\Gnu\GnuPG:UI Server +If the UI server could not be connected, GpgOL tries to start the one +given in this entry. It is assumed that the UI server is stored in the + at code{Install Directory} (as described above). This Registry entry +gives the actual command name relative to this directory. If the key +does not exist, is is first searched below @code{HKLM} and then it +defaults to @code{bin/kleopatra.exe} (FIXME: The final name will be just + at code{kleopatra.exe}). + +In case the UI server requires the socket name as an argument, the +placeholder @code{$s} may be used to indicate this. Due to this feature +it is required that all verbatim dollar are too be doubled. If the +actual program name contains spaces the program name nees to be enclosed +in quotes. + + + at end table + + + + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + at c + at c A P P E N D I X + at c + at c xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + @include gpl.texi @c Modified: trunk/po/de.po =================================================================== --- trunk/po/de.po 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/po/de.po 2007-10-22 15:31:09 UTC (rev 194) @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: GpgOL 0.10.0\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-10-12 21:12+0200\n" -"PO-Revision-Date: 2007-10-12 21:12+0200\n" +"POT-Creation-Date: 2007-10-22 17:20+0200\n" +"PO-Revision-Date: 2007-10-22 17:21+0200\n" "Last-Translator: Werner Koch \n" "Language-Team: de\n" "MIME-Version: 1.0\n" @@ -40,7 +40,7 @@ "um die gesamte Nachricht nochmal zu entschl?sseln. Danach k?nnen\n" "Sie das Attachment wieder ?ffenen." -#: src/common.c:145 +#: src/common.c:215 msgid "GpgOL - Save decrypted attachment" msgstr "GpgOL - Sichern der entschl?sselten Anlage" @@ -208,102 +208,106 @@ msgid "*** End Notation ***\n" msgstr "*** Ende Notation ***\n" -#: src/ext-commands.cpp:325 +#: src/ext-commands.cpp:408 msgid "&Decrypt and verify message" msgstr "Entschl?sseln/Pr?fen der Nachricht" -#: src/ext-commands.cpp:326 +#: src/ext-commands.cpp:409 msgid "&Verify signature" msgstr "&Unterschrift pr?fen" -#: src/ext-commands.cpp:327 +#: src/ext-commands.cpp:410 msgid "&Display crypto information" msgstr "~Krypto Informationen anzeigen" -#: src/ext-commands.cpp:353 +#: src/ext-commands.cpp:417 src/ext-commands.cpp:713 +msgid "Decrypt message and verify signature" +msgstr "Nachricht entschl?sseln und Unterschrift pr?fen" + +#: src/ext-commands.cpp:424 msgid "use S/MIME protocol" msgstr "S/MIME verwenden" -#: src/ext-commands.cpp:354 +#: src/ext-commands.cpp:425 msgid "&encrypt message with GnuPG" msgstr "Nachricht mit GnuPG verschl?sseln" -#: src/ext-commands.cpp:355 +#: src/ext-commands.cpp:426 msgid "&sign message with GnuPG" msgstr "Nachricht mit GnuPG unterschreiben" -#: src/ext-commands.cpp:397 +#: src/ext-commands.cpp:430 +msgid "Encrypt message with GnuPG" +msgstr "Nachricht mit GnuPG verschl?sseln" + +#: src/ext-commands.cpp:431 +msgid "Sign message with GnuPG" +msgstr "Nachricht mit GnuPG unterschreiben" + +#: src/ext-commands.cpp:444 msgid "GnuPG Certificate &Manager" msgstr "GnuPG Zertifikats&verwaltung" -#: src/ext-commands.cpp:548 +#: src/ext-commands.cpp:448 +msgid "Open the certificate manager" +msgstr "Die Zertifikatsverwaltung ?ffnen" + +#: src/ext-commands.cpp:590 msgid "Could not start certificate manager" msgstr "Die Zertifikatsverwaltung konnte nicht aufgerufen werden" -#: src/ext-commands.cpp:595 +#: src/ext-commands.cpp:641 msgid "Select this option to decrypt and verify the message." msgstr "" "W?hlen Sie diese Option um die Nachricht zu entschl?sseln bzw. zu " "verifizieren." -#: src/ext-commands.cpp:602 +#: src/ext-commands.cpp:648 msgid "Select this option to show information on the crypto status" msgstr "" "W?hlen Sie diese Option um Informationen ?ber den Krypto-Status der " "Nachricht anzuzeigen." -#: src/ext-commands.cpp:610 src/ext-commands.cpp:686 +#: src/ext-commands.cpp:656 src/ext-commands.cpp:732 msgid "Check the signature now and display the result" msgstr "Die digitale Unterschrift jetzt pr?fen und das Resultat anzeigen" -#: src/ext-commands.cpp:617 +#: src/ext-commands.cpp:663 msgid "Select this option to select the S/MIME protocol." msgstr "W?hlen Sie diese Option zum das S/MIME Protokoll auszuw?hlen." -#: src/ext-commands.cpp:624 +#: src/ext-commands.cpp:670 msgid "Select this option to encrypt the message." msgstr "W?hlen Sie diese Option zum Verschl?sseln der Nachricht." -#: src/ext-commands.cpp:631 +#: src/ext-commands.cpp:677 msgid "Select this option to sign the message." msgstr "W?hlen Sie diese Option zum Unterschreiben der Nachricht." -#: src/ext-commands.cpp:638 +#: src/ext-commands.cpp:684 msgid "Select this option to open the certificate manager" msgstr "W?hlen Sie diese Option zum die Zertifikatsverwaltung zu ?ffenen." -#: src/ext-commands.cpp:667 src/ext-commands.cpp:761 -msgid "Decrypt message and verify signature" -msgstr "Nachricht entschl?sseln und Unterschrift pr?fen" - -#: src/ext-commands.cpp:676 +#: src/ext-commands.cpp:722 msgid "Show S/MIME status info" msgstr "S/MIME Status Informationen anzeigen" -#: src/ext-commands.cpp:696 +#: src/ext-commands.cpp:742 msgid "Use S/MIME for sign/encrypt" msgstr "S/MIME zum signieren/verschl?sseln verwenden" -#: src/ext-commands.cpp:706 src/ext-commands.cpp:775 +#: src/ext-commands.cpp:752 msgid "Encrypt message with GPG" msgstr "Nachricht mit GnuPG unterschreiben" -#: src/ext-commands.cpp:716 src/ext-commands.cpp:789 +#: src/ext-commands.cpp:762 msgid "Sign message with GPG" msgstr "Nachricht mit GnuPG unterschreiben" -#: src/ext-commands.cpp:726 +#: src/ext-commands.cpp:772 msgid "Open the GpgOL certificate manager" msgstr "Zertifikatsverwaltung von GpgOL ?ffnen" -#: src/ext-commands.cpp:803 -msgid "Use the S/MIME protocol" -msgstr "S/MIME Unterst?tzung einschalten" - -#: src/ext-commands.cpp:815 -msgid "Open the certificate manager" -msgstr "Die Zertifikatsverwaltung ?ffnen" - #: src/mapihelp.cpp:1183 msgid "" "[The content of this message is not visible because it has been decrypted by " @@ -422,12 +426,12 @@ msgid "Ad&vanced.." msgstr "&Erweitert..." -#: src/olflange-dlgs.cpp:222 +#: src/olflange-dlgs.cpp:227 msgid "The default certificate may not contain any spaces." msgstr "" "Der Bezeichner f?r das Standardzertifikat darf keine Leerzeichen enthalten." -#: src/olflange-dlgs.cpp:244 +#: src/olflange-dlgs.cpp:249 msgid "" "You have enabled GpgOL's support for the S/MIME protocol.\n" "\n" @@ -446,7 +450,7 @@ "kann." #. TRANSLATORS: See the source for the full english text. -#: src/olflange-dlgs.cpp:287 +#: src/olflange-dlgs.cpp:292 msgid "-#GpgOLFullHelpText#-" msgstr "" "GpgOL ist ein Plugin f?r Microsoft Outlook, welches es erm?glicht\n" @@ -471,7 +475,7 @@ "Public License erhalten haben. Falls nicht, finden Sie diese\n" "unter der Webadresse ." -#: src/olflange-dlgs.cpp:293 +#: src/olflange-dlgs.cpp:298 #, c-format msgid "This is GpgOL version %s" msgstr "Dies ist GpgOL Version %s" @@ -635,6 +639,9 @@ msgid "S/MIME Verification Result" msgstr "S/MIME Pr?fungsresultat" +#~ msgid "Use the S/MIME protocol" +#~ msgstr "S/MIME Unterst?tzung einschalten" + #~ msgid "Debug-1 (open_inspector)" #~ msgstr "Debug-1 (Inspektor Fenster ?ffnen)" Modified: trunk/po/sv.po =================================================================== --- trunk/po/sv.po 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/po/sv.po 2007-10-22 15:31:09 UTC (rev 194) @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: GPGol\n" "Report-Msgid-Bugs-To: bug-gpgol at g10code.com\n" -"POT-Creation-Date: 2007-10-12 21:12+0200\n" +"POT-Creation-Date: 2007-10-22 17:20+0200\n" "PO-Revision-Date: 2006-12-12 23:52+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" @@ -39,7 +39,7 @@ "entire message again. Then open this attachment." msgstr "" -#: src/common.c:145 +#: src/common.c:215 #, fuzzy msgid "GpgOL - Save decrypted attachment" msgstr "GPG - Spara dekrypterad bilaga" @@ -206,108 +206,114 @@ msgid "*** End Notation ***\n" msgstr "*** Notation slut ***\n" -#: src/ext-commands.cpp:325 +#: src/ext-commands.cpp:408 msgid "&Decrypt and verify message" msgstr "&Dekryptera och validera meddelandet" -#: src/ext-commands.cpp:326 +#: src/ext-commands.cpp:409 #, fuzzy msgid "&Verify signature" msgstr "FELAKTIG signatur!" -#: src/ext-commands.cpp:327 +#: src/ext-commands.cpp:410 msgid "&Display crypto information" msgstr "" -#: src/ext-commands.cpp:353 +#: src/ext-commands.cpp:417 src/ext-commands.cpp:713 +msgid "Decrypt message and verify signature" +msgstr "Dekryptera meddelandet och validera signaturen" + +#: src/ext-commands.cpp:424 msgid "use S/MIME protocol" msgstr "" -#: src/ext-commands.cpp:354 +#: src/ext-commands.cpp:425 #, fuzzy msgid "&encrypt message with GnuPG" msgstr "Signera meddelandet med GPG" -#: src/ext-commands.cpp:355 +#: src/ext-commands.cpp:426 #, fuzzy msgid "&sign message with GnuPG" msgstr "Signera meddelandet med GPG" -#: src/ext-commands.cpp:397 +#: src/ext-commands.cpp:430 #, fuzzy +msgid "Encrypt message with GnuPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:431 +#, fuzzy +msgid "Sign message with GnuPG" +msgstr "Signera meddelandet med GPG" + +#: src/ext-commands.cpp:444 +#, fuzzy msgid "GnuPG Certificate &Manager" msgstr "GPG-nyckel&hanterare" -#: src/ext-commands.cpp:548 +#: src/ext-commands.cpp:448 +msgid "Open the certificate manager" +msgstr "" + +#: src/ext-commands.cpp:590 #, fuzzy msgid "Could not start certificate manager" msgstr "Kunde inte starta nyckelhanteraren" -#: src/ext-commands.cpp:595 +#: src/ext-commands.cpp:641 #, fuzzy msgid "Select this option to decrypt and verify the message." msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." -#: src/ext-commands.cpp:602 +#: src/ext-commands.cpp:648 #, fuzzy msgid "Select this option to show information on the crypto status" msgstr "V?lj det h?r alternativet f?r att signera meddelandet." -#: src/ext-commands.cpp:610 src/ext-commands.cpp:686 +#: src/ext-commands.cpp:656 src/ext-commands.cpp:732 msgid "Check the signature now and display the result" msgstr "" -#: src/ext-commands.cpp:617 +#: src/ext-commands.cpp:663 #, fuzzy msgid "Select this option to select the S/MIME protocol." msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." -#: src/ext-commands.cpp:624 +#: src/ext-commands.cpp:670 msgid "Select this option to encrypt the message." msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." -#: src/ext-commands.cpp:631 +#: src/ext-commands.cpp:677 msgid "Select this option to sign the message." msgstr "V?lj det h?r alternativet f?r att signera meddelandet." -#: src/ext-commands.cpp:638 +#: src/ext-commands.cpp:684 #, fuzzy msgid "Select this option to open the certificate manager" msgstr "V?lj det h?r alternativet f?r att kryptera meddelandet." -#: src/ext-commands.cpp:667 src/ext-commands.cpp:761 -msgid "Decrypt message and verify signature" -msgstr "Dekryptera meddelandet och validera signaturen" - -#: src/ext-commands.cpp:676 +#: src/ext-commands.cpp:722 msgid "Show S/MIME status info" msgstr "" -#: src/ext-commands.cpp:696 +#: src/ext-commands.cpp:742 msgid "Use S/MIME for sign/encrypt" msgstr "" -#: src/ext-commands.cpp:706 src/ext-commands.cpp:775 +#: src/ext-commands.cpp:752 #, fuzzy msgid "Encrypt message with GPG" msgstr "Signera meddelandet med GPG" -#: src/ext-commands.cpp:716 src/ext-commands.cpp:789 +#: src/ext-commands.cpp:762 msgid "Sign message with GPG" msgstr "Signera meddelandet med GPG" -#: src/ext-commands.cpp:726 +#: src/ext-commands.cpp:772 msgid "Open the GpgOL certificate manager" msgstr "" -#: src/ext-commands.cpp:803 -msgid "Use the S/MIME protocol" -msgstr "" - -#: src/ext-commands.cpp:815 -msgid "Open the certificate manager" -msgstr "" - #: src/mapihelp.cpp:1183 msgid "" "[The content of this message is not visible because it has been decrypted by " @@ -418,12 +424,12 @@ msgid "Ad&vanced.." msgstr "" -#: src/olflange-dlgs.cpp:222 +#: src/olflange-dlgs.cpp:227 #, fuzzy msgid "The default certificate may not contain any spaces." msgstr "Standardnyckeln f?r inte inneh?lla n?gra blanksteg." -#: src/olflange-dlgs.cpp:244 +#: src/olflange-dlgs.cpp:249 msgid "" "You have enabled GpgOL's support for the S/MIME protocol.\n" "\n" @@ -434,11 +440,11 @@ msgstr "" #. TRANSLATORS: See the source for the full english text. -#: src/olflange-dlgs.cpp:287 +#: src/olflange-dlgs.cpp:292 msgid "-#GpgOLFullHelpText#-" msgstr "" -#: src/olflange-dlgs.cpp:293 +#: src/olflange-dlgs.cpp:298 #, c-format msgid "This is GpgOL version %s" msgstr "" Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/ChangeLog 2007-10-22 15:31:09 UTC (rev 194) @@ -1,3 +1,49 @@ +2007-10-22 Werner Koch + + * engine-assuan.c (connect_uiserver): Try to start the server. + (get_uiserver_name, replace_dollar_s, get_quoted_socket_name): New. + + * main.c (REGKEY): Remove. + * common.h (GNUPG_REGKEY): New. + * common.c (default_homedir): Use it in place of a hard coded one. + (get_locale_dir): Ditto. + (gpgol_spawn_detached): New. + +2007-10-18 Werner Koch + + * common.c (get_system_check_bitmap): New. + + * decrypt.bmp, encrypt.bmp, sign.bmp, key_mana.bmp: Change + background color to pink and voila Outlook presents them + transparent. + + * logo.bmp: Cleaned up to use just one color. + * olflange-dlgs.cpp (GPGOptionsDlgProc): Do not use LoadImage. + +2007-10-16 Werner Koch + + * myexchext.h (EECMDID_): Add a few more of these constants. + * ext-commands.cpp (check_menu): New. + (toolbar_add_menu): Rename to .. + (add_menu): .. this. + (toolbar_from_tbe): Remove. + (add_toolbar): New. + (InstallCommands): Use new toolbar helper. + (QueryButtonInfo): Changed to use new toolbar helper. + (~GpgolExtCommands): New. + + * engine.c (engine_encrypt_start): Add arg R_PROTOCOL. + * engine-assuan.c (op_assuan_encrypt): Add arg R_USED_PROTOCOL and + ask the server for it. + * mimemaker.c (sink_encryption_write_b64): New. + (mime_encrypt): Add S/MIME support. + +2007-10-15 Werner Koch + + * engine-assuan.c (op_assuan_start_keymanager): New. + * engine.c (engine_start_keymanager): New. + * ext-commands.cpp (DoCommand): Call it. + 2007-10-12 Werner Koch * gpgol-rsrcs.rc: Remove. Modified: trunk/src/common.c =================================================================== --- trunk/src/common.c 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/common.c 2007-10-22 15:31:09 UTC (rev 194) @@ -5,9 +5,9 @@ * * 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 + * 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 @@ -38,33 +38,33 @@ /* The base-64 list used for base64 encoding. */ -static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"); +static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"); /* The reverse base-64 list used for base-64 decoding. */ static unsigned char const asctobin[256] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, - 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, - 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, - 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -79,32 +79,32 @@ /* Center the given window with the desktop window as the parent window. */ void -center_window (HWND childwnd, HWND style) -{ +center_window (HWND childwnd, HWND style) +{ HWND parwnd; - RECT rchild, rparent; + RECT rchild, rparent; HDC hdc; int wchild, hchild, wparent, hparent; int wscreen, hscreen, xnew, ynew; int flags = SWP_NOSIZE | SWP_NOZORDER; parwnd = GetDesktopWindow (); - GetWindowRect (childwnd, &rchild); - wchild = rchild.right - rchild.left; + GetWindowRect (childwnd, &rchild); + wchild = rchild.right - rchild.left; hchild = rchild.bottom - rchild.top; - GetWindowRect (parwnd, &rparent); - wparent = rparent.right - rparent.left; - hparent = rparent.bottom - rparent.top; - - hdc = GetDC (childwnd); - wscreen = GetDeviceCaps (hdc, HORZRES); - hscreen = GetDeviceCaps (hdc, VERTRES); - ReleaseDC (childwnd, hdc); - xnew = rparent.left + ((wparent - wchild) / 2); + GetWindowRect (parwnd, &rparent); + wparent = rparent.right - rparent.left; + hparent = rparent.bottom - rparent.top; + + hdc = GetDC (childwnd); + wscreen = GetDeviceCaps (hdc, HORZRES); + hscreen = GetDeviceCaps (hdc, VERTRES); + ReleaseDC (childwnd, hdc); + xnew = rparent.left + ((wparent - wchild) / 2); if (xnew < 0) xnew = 0; - else if ((xnew+wchild) > wscreen) + else if ((xnew+wchild) > wscreen) xnew = wscreen - wchild; ynew = rparent.top + ((hparent - hchild) / 2); if (ynew < 0) @@ -117,7 +117,77 @@ } +/* Return the system's bitmap of the check bar used which check boxes. + If CHECKED is set, this check mark is returned; if it is not set, + the one used for not-checked is returned. May return NULL on + error. Taken from an example in the platform reference. + Not used as of now. */ +HBITMAP +get_system_check_bitmap (int checked) +{ + COLORREF bg_color; + HBRUSH bg_brush, saved_dst_brush; + HDC src_dc, dst_dc; + WORD xsize, ysize; + HBITMAP result, saved_dst_bitmap, saved_src_bitmap, checkboxes; + BITMAP bitmap; + RECT rect; + + bg_color = GetSysColor (COLOR_MENU); + bg_brush = CreateSolidBrush (bg_color); + + src_dc = CreateCompatibleDC (NULL); + dst_dc = CreateCompatibleDC (src_dc); + + xsize = GetSystemMetrics (SM_CXMENUCHECK); + ysize = GetSystemMetrics (SM_CYMENUCHECK); + result = CreateCompatibleBitmap(src_dc, xsize, ysize); + + saved_dst_brush = SelectObject (dst_dc, bg_brush); + saved_dst_bitmap = SelectObject (dst_dc, result); + + PatBlt (dst_dc, 0, 0, xsize, ysize, PATCOPY); + + checkboxes = LoadBitmap (NULL, (LPTSTR)OBM_CHECKBOXES); + + saved_src_bitmap = SelectObject (src_dc, checkboxes); + + GetObject (checkboxes, sizeof (BITMAP), &bitmap); + rect.top = 0; + rect.bottom = (bitmap.bmHeight / 3); + if (checked) + { + /* Select row 1, column 1. */ + rect.left = 0; + rect.right = (bitmap.bmWidth / 4); + } + else + { + /* Select row 1, column 2. */ + rect.left = (bitmap.bmWidth / 4); + rect.right = (bitmap.bmWidth / 4) * 2; + } + + if ( ((rect.right - rect.left) > (int)xsize) + || ((rect.bottom - rect.top) > (int)ysize) ) + StretchBlt (dst_dc, 0, 0, xsize, ysize, src_dc, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, SRCCOPY); + else + BitBlt (dst_dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, + src_dc, rect.left, rect.top, SRCCOPY); + + SelectObject (src_dc, saved_src_bitmap); + SelectObject (dst_dc, saved_dst_brush); + result = SelectObject (dst_dc, saved_dst_bitmap); + + DeleteObject (bg_brush); + DeleteObject (src_dc); + DeleteObject (dst_dc); + return result; +} + + /* Return a filename to be used for saving an attachment. Returns a malloced string on success. HWND is the current Window and SRCNAME the filename to be used as suggestion. On error (i.e. cancel) NULL @@ -131,9 +201,9 @@ memset (fname, 0, sizeof (fname)); strncpy (fname, srcname, MAX_PATH-1); - fname[MAX_PATH] = 0; - + fname[MAX_PATH] = 0; + memset (&ofn, 0, sizeof (ofn)); ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = root; @@ -298,7 +368,7 @@ char *buffer, *p; size_t n; - for (s=string, n=0; *s; s++) + for (s=string, n=0; *s; s++) { n++; if (*s & 0x80) @@ -467,7 +537,7 @@ 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 @@ -475,16 +545,16 @@ 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) + 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); @@ -508,9 +578,8 @@ if (!dir || !*dir) { char *tmp; - - tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", - "HomeDir"); + + tmp = read_w32_registry_string (NULL, GNUPG_REGKEY, "HomeDir"); if (tmp && !*tmp) { free (tmp); @@ -524,7 +593,7 @@ else dir = xstrdup (dir); } - + return dir; } @@ -563,7 +632,7 @@ } else *d++ = *s++; - + return d - buffer; } @@ -597,15 +666,15 @@ if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t') continue; if (*s == '=') - { + { /* Pad character: stop */ if (idx == 1) - *d++ = val; + *d++ = val; state->stop_seen = 1; break; } - if ((c = asctobin[*(unsigned char *)s]) == 255) + if ((c = asctobin[*(unsigned char *)s]) == 255) { if (!state->invalid_encoding) log_debug ("%s: invalid base64 character %02X at pos %d skipped\n", @@ -614,22 +683,22 @@ continue; } - switch (idx) + switch (idx) { - case 0: + case 0: val = c << 2; break; - case 1: + case 1: val |= (c>>4)&3; *d++ = val; val = (c<<4)&0xf0; break; - case 2: + case 2: val |= (c>>2)&15; *d++ = val; val = (c<<6)&0xc0; break; - case 3: + case 3: val |= c&0x3f; *d++ = val; break; @@ -637,7 +706,7 @@ idx = (idx+1) % 4; } - + state->idx = idx; state->val = val; return d - buffer; @@ -660,7 +729,7 @@ *p++ = '='; *p++ = '-'; *p++ = '='; - for (i=0; i < BOUNDARYSIZE-6; i++) + for (i=0; i < BOUNDARYSIZE-6; i++) *p++ = bintoasc[rand () % 64]; *p++ = '='; *p++ = '-'; @@ -670,3 +739,52 @@ return buffer; } + +/* Fork and exec the program gioven in CMDLINE with /dev/null as + stdin, stdout and stderr. Returns 0 on success. */ +int +gpgol_spawn_detached (const char *cmdline) +{ + int rc; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; + STARTUPINFO si; + int cr_flags; + char *cmdline_copy; + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_SHOW; + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_NEW_PROCESS_GROUP + | DETACHED_PROCESS); + + cmdline_copy = xstrdup (cmdline); + rc = CreateProcess (NULL, /* No appliactionname, use CMDLINE. */ + cmdline_copy, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + ); + xfree (cmdline_copy); + if (!rc) + { + log_error_w32 (-1, "%s:%s: CreateProcess failed", SRCNAME, __func__); + return -1; + } + + CloseHandle (pi.hThread); + CloseHandle (pi.hProcess); + return 0; +} Modified: trunk/src/common.h =================================================================== --- trunk/src/common.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/common.h 2007-10-22 15:31:09 UTC (rev 194) @@ -33,6 +33,10 @@ #endif #endif +/* The Registry key used by GnuPg and closley related software. */ +#define GNUPG_REGKEY "Software\\GNU\\GnuPG" + + /* 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. */ @@ -141,6 +145,7 @@ /*-- common.c --*/ void set_global_hinstance (HINSTANCE hinst); void center_window (HWND childwnd, HWND style); +HBITMAP get_system_check_bitmap (int checked); char *get_save_filename (HWND root, const char *srcname); char *utf8_to_wincp (const char *string); @@ -155,7 +160,9 @@ #define BOUNDARYSIZE 20 char *generate_boundary (char *buffer); +int gpgol_spawn_detached (const char *cmdline); + /*-- recipient-dialog.c --*/ unsigned int recipient_dialog_box (gpgme_key_t **ret_rset); unsigned int recipient_dialog_box2 (gpgme_key_t *fnd, char **unknown, Modified: trunk/src/decrypt.bmp =================================================================== (Binary files differ) Modified: trunk/src/dialogs.h =================================================================== --- trunk/src/dialogs.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/dialogs.h 2007-10-22 15:31:09 UTC (rev 194) @@ -16,6 +16,7 @@ #define IDB_BANNER 3006 #define IDB_BANNER_HI 3007 #define IDB_SELECT_SMIME 3008 +#define IDB_KEY_MANAGER_PNG 3105 /* Ids used for the main config dialog. */ Modified: trunk/src/encrypt.bmp =================================================================== (Binary files differ) Modified: trunk/src/engine-assuan.c =================================================================== --- trunk/src/engine-assuan.c 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/engine-assuan.c 2007-10-22 15:31:09 UTC (rev 194) @@ -38,7 +38,11 @@ SRCNAME, __func__, __LINE__); \ } while (0) +/* How many times we will try to connect to a server after we have + started him. */ +#define FIREUP_RETRIES 10 + /* This is the buffer object used for the asynchronous reading of the status channel. */ struct status_buffer_s @@ -292,7 +296,110 @@ } +/* Same as get_socket_name but returns a malloced string with a quoted + filename. */ +static char * +get_quoted_socket_name (void) +{ + const char *sname = get_socket_name (); + const char *s; + char *buffer, *p; + size_t n; + for (n=2, s=sname; *s; s++, n++) + if (*s== '\"') + n++; + buffer = p = xmalloc (n+1); + *p++ = '\"'; + for (s=sname; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + return buffer; +} + + +/* Substitute all substrings "$s" in BUFFER by the value of the + default socket and replace all "$$" by "$". Free BUFFER if + necessary and return a newly malloced buffer. */ +static char * +replace_dollar_s (char *buffer) +{ + char *rover, *p; + + for (rover=buffer; (p = strchr (rover, '$')); ) + { + if (p[1] == '$') /* Just an escaped dollar sign. */ + { + memmove (p, p+1, strlen (p+1)+1); + rover = p + 1; + } + else if (p[1] == 's') /* Substitute with socket name. */ + { + char *value = get_quoted_socket_name (); + size_t n = p - buffer; + char *newbuf; + + newbuf = xmalloc (strlen (buffer) + strlen (value) + 1); + memcpy (newbuf, buffer, n); + strcpy (newbuf + n, value); + n += strlen (value); + strcpy (newbuf + n, p+2); + rover = newbuf + n; + xfree (buffer); + buffer = newbuf; + xfree (value); + } + else + rover = p + 1; + } + return buffer; +} + + + +/* Return the name of the default UI server. This name is used to + auto start an UI server if an initial connect failed. */ +static char * +get_uiserver_name (void) +{ + char *name = NULL; + char *dir, *uiserver, *p; + + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", GNUPG_REGKEY, + "Install Directory"); + if (dir) + { + uiserver = read_w32_registry_string (NULL, GNUPG_REGKEY, + "UI Server"); + if (!uiserver) + uiserver = xstrdup ("bin\\kleopatra.exe --uiserver-socket $s"); + + uiserver = replace_dollar_s (uiserver); + + /* FIXME: Very dirty work-around to make kleopatra find its + DLLs. */ + if (!strncmp (uiserver, "bin\\kleopatra.exe", 17)) + chdir (dir); + + name = xmalloc (strlen (dir) + strlen (uiserver) + 2); + strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver); + for (p=name; *p; p++) + if (*p == '/') + *p == '\\'; + xfree (uiserver); + xfree (dir); + } + + return name; +} + + + static gpg_error_t send_one_option (assuan_context_t ctx, const char *name, const char *value) { @@ -363,15 +470,65 @@ connect_uiserver (assuan_context_t *r_ctx, pid_t *r_pid, ULONG *r_cmdid, void *hwnd) { + static ULONG retry_counter; + ULONG retry_count; gpg_error_t err; assuan_context_t ctx; *r_ctx = NULL; *r_pid = (pid_t)(-1); *r_cmdid = 0; + retry: err = assuan_socket_connect (&ctx, get_socket_name (), -1); if (err) { + /* Let only one thread start an UI server but all allow threads + to check for a connection. Note that this is not really + correct as the maximum waiting time decreases with the number + of threads. However, it is unlikely that we have more than 2 + or 3 threads here - if at all more than one. */ + retry_count = InterlockedExchangeAdd (&retry_counter, 1); + if (retry_count < FIREUP_RETRIES) + { + if (!retry_count) + { + char *uiserver = get_uiserver_name (); + if (!uiserver) + { + log_error ("%s:%s: UI server not installed", + SRCNAME, __func__); + InterlockedExchange (&retry_counter, FIREUP_RETRIES); + retry_count = FIREUP_RETRIES; + } + else + { + log_debug ("%s:%s: UI server not running, starting `%s'", + SRCNAME, __func__, uiserver); + if (gpgol_spawn_detached (uiserver)) + { + /* Error; try again to connect in case the + server has been started in the meantime. + Make sure that we don't get here a second + time. */ + InterlockedExchange (&retry_counter, FIREUP_RETRIES); + } + xfree (uiserver); + } + } + if (retry_count < FIREUP_RETRIES) + { + log_debug ("%s:%s: waiting for UI server to come up", + SRCNAME, __func__); + Sleep (1000); + goto retry; + } + } + else + { + /* Avoid a retry counter overflow by limiting to the limit. */ + InterlockedExchange (&retry_counter, FIREUP_RETRIES); + } + log_error ("%s:%s: error connecting `%s': %s\n", SRCNAME, __func__, get_socket_name (), gpg_strerror (err)); } @@ -1123,6 +1280,27 @@ } +/* Callback used to get the protocool status line form a PREP_* + command. */ +static assuan_error_t +prep_foo_status_cb (void *opaque, const char *line) +{ + protocol_t *protocol = opaque; + + if (!strncmp (line, "PROTOCOL", 8) && (line[8]==' ' || !line[8])) + { + for (line += 8; *line == ' '; line++) + ; + if (strncmp (line, "OpenPGP", 7) && (line[7]==' '||!line[7])) + *protocol = PROTOCOL_OPENPGP; + else if (strncmp (line, "CMS", 3) && (line[3]==' '||!line[3])) + *protocol = PROTOCOL_SMIME; + } + return 0; +} + + + /* Note that this closure is called in the context of the async_worker_thread. */ @@ -1146,7 +1324,7 @@ op_assuan_encrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd, - char **recipients) + char **recipients, protocol_t *r_used_protocol) { gpg_error_t err; closure_data_t cld; @@ -1157,11 +1335,11 @@ pid_t pid; int i; char *p; + int detect_protocol; const char *protocol_name; - if (!(protocol_name = get_protocol_name (protocol))) - return gpg_error(GPG_ERR_INV_VALUE); - + detect_protocol = !(protocol_name = get_protocol_name (protocol)); + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); if (err) return err; @@ -1192,6 +1370,28 @@ goto leave; } + /* If the protocol has not been given, let the UI server tell us the + protocol to use. */ + if (detect_protocol) + { + protocol = PROTOCOL_UNKNOWN; + err = assuan_transact (ctx, "PREP_ENCRYPT", NULL, NULL, NULL, NULL, + prep_foo_status_cb, &protocol); + if (err) + { + if (gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD) + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + if ( !(protocol_name = get_protocol_name (protocol)) ) + { + err = gpg_error (GPG_ERR_INV_VALUE); + goto leave; + } + } + + *r_used_protocol = protocol; + /* Note: We don't use real descriptor passing but a hack: We duplicate the handle into the server process and the server then uses this handle. Eventually we should put this code into @@ -1507,3 +1707,22 @@ } + +/* Ask the server to fire up the key manager. */ +int +op_assuan_start_keymanager (void *hwnd) +{ + gpg_error_t err; + assuan_context_t ctx; + ULONG cmdid; + pid_t pid; + + err = connect_uiserver (&ctx, &pid, &cmdid, hwnd); + if (!err) + { + err = assuan_transact (ctx, "START_KEYMANAGER", + NULL, NULL, NULL, NULL, NULL, NULL); + assuan_disconnect (ctx); + } + return err; +} Modified: trunk/src/engine-assuan.h =================================================================== --- trunk/src/engine-assuan.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/engine-assuan.h 2007-10-22 15:31:09 UTC (rev 194) @@ -38,7 +38,7 @@ int op_assuan_encrypt (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t notify_data, void *hwnd, - char **recipients); + char **recipients, protocol_t *r_used_protocol); int op_assuan_sign (protocol_t protocol, gpgme_data_t indata, gpgme_data_t outdata, engine_filter_t filter, void *hwnd); @@ -50,9 +50,9 @@ gpgme_data_t data, const char *signature, engine_filter_t filter, void *hwnd); +int op_assuan_start_keymanager (void *hwnd); - #ifdef __cplusplus } #endif Modified: trunk/src/engine.c =================================================================== --- trunk/src/engine.c 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/engine.c 2007-10-22 15:31:09 UTC (rev 194) @@ -658,19 +658,28 @@ 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. */ + or engine_cancel. On return the protocol to be used is stored at + R_PROTOCOL. */ int engine_encrypt_start (engine_filter_t filter, - protocol_t protocol, char **recipients) + protocol_t req_protocol, char **recipients, + protocol_t *r_protocol) { gpg_error_t err; + protocol_t used_protocol; + *r_protocol = req_protocol; if (filter->use_assuan) - err = op_assuan_encrypt (protocol, filter->indata, filter->outdata, - filter, NULL, recipients); + { + err = op_assuan_encrypt (req_protocol, filter->indata, filter->outdata, + filter, NULL, recipients, &used_protocol); + if (!err) + *r_protocol = used_protocol; + } else - err = op_gpgme_encrypt (protocol, filter->indata, filter->outdata, + err = op_gpgme_encrypt (req_protocol, filter->indata, filter->outdata, filter, NULL, recipients); + return err; } @@ -746,6 +755,12 @@ } - - - +/* Fire up the key manager. Returns 0 on success. */ +int +engine_start_keymanager (void) +{ + if (use_assuan) + return op_assuan_start_keymanager (NULL); + else + return gpg_error (GPG_ERR_NOT_SUPPORTED); +} Modified: trunk/src/engine.h =================================================================== --- trunk/src/engine.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/engine.h 2007-10-22 15:31:09 UTC (rev 194) @@ -63,15 +63,18 @@ void engine_cancel (engine_filter_t filter); int engine_encrypt_start (engine_filter_t filter, - protocol_t protocol, char **recipients); + protocol_t req_protocol, char **recipients, + protocol_t *r_protocol); 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); +int engine_start_keymanager (void); + #ifdef __cplusplus } #endif Modified: trunk/src/ext-commands.cpp =================================================================== --- trunk/src/ext-commands.cpp 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/ext-commands.cpp 2007-10-22 15:31:09 UTC (rev 194) @@ -36,6 +36,7 @@ #include "olflange.h" #include "ol-ext-callback.h" #include "message.h" +#include "engine.h" #include "ext-commands.h" @@ -43,8 +44,28 @@ SRCNAME, __func__, __LINE__); \ } while (0) -static void toolbar_add_menu (LPEXCHEXTCALLBACK pEECB, - UINT FAR *pnCommandIDBase, ...) +/* An object to store information about active (installed) toolbar + buttons. */ +struct toolbar_info_s +{ + toolbar_info_t next; + + UINT button_id;/* The ID of the button as assigned by Outlook. */ + UINT bitmap; /* The bitmap of the button. */ + UINT cmd_id; /* The ID of the command to send on a click. */ + const char *desc;/* The description text. */ + ULONG context; /* Context under which this entry will be used. */ +}; + + +/* Keep copies of some bitmaps. */ +static int bitmaps_initialized; +static HBITMAP my_check_bitmap, my_uncheck_bitmap; + + + +static void add_menu (LPEXCHEXTCALLBACK pEECB, + UINT FAR *pnCommandIDBase, ...) #if __GNUC__ >= 4 __attribute__ ((sentinel)) #endif @@ -85,17 +106,30 @@ m_nCmdKeyManager = 0; m_nCmdDebug1 = 0; m_nCmdDebug2 = 0; - m_nToolbarButtonID1 = 0; - m_nToolbarButtonID2 = 0; - m_nToolbarButtonID3 = 0; - m_nToolbarBitmap1 = 0; - m_nToolbarBitmap2 = 0; - m_nToolbarBitmap3 = 0; + m_toolbar_info = NULL; m_hWnd = NULL; + + if (!bitmaps_initialized) + { + my_uncheck_bitmap = get_system_check_bitmap (0); + my_check_bitmap = get_system_check_bitmap (1); + bitmaps_initialized = 1; + } } +/* Destructor */ +GpgolExtCommands::~GpgolExtCommands (void) +{ + while (m_toolbar_info) + { + toolbar_info_t tmp = m_toolbar_info->next; + xfree (m_toolbar_info); + m_toolbar_info = tmp; + } +} + STDMETHODIMP GpgolExtCommands::QueryInterface (REFIID riid, LPVOID FAR * ppvObj) { @@ -109,32 +143,11 @@ } -/* Return the toolbar's window from the button entry array. On - success the handle of the window is return as well as the - corresponding index at R_IDX. On error NULL is returned and - the value at R_IDX is not changed. */ -static HWND -toolbar_from_tbe (LPTBENTRY pTBEArray, UINT nTBECnt, int *r_idx) -{ - int nTBIndex; - - for (nTBIndex = nTBECnt-1; nTBIndex > -1; --nTBIndex) - { - if (EETBID_STANDARD == pTBEArray[nTBIndex].tbid) - { - *r_idx = nTBIndex; - return pTBEArray[nTBIndex].hwnd; - } - } - return NULL; -} - /* Add a new menu. The variable entries are made up of pairs of strings and UINT *. A NULL is used to terminate this list. An empty string is translated to a separator menu item. */ static void -toolbar_add_menu (LPEXCHEXTCALLBACK pEECB, - UINT FAR *pnCommandIDBase, ...) +add_menu (LPEXCHEXTCALLBACK pEECB, UINT FAR *pnCommandIDBase, ...) { va_list arg_ptr; HMENU menu; @@ -142,6 +155,8 @@ UINT *cmdptr; va_start (arg_ptr, pnCommandIDBase); + /* We put all new entries into the tools menu. To make this work we + need to pass the id of an existing item from that menu. */ pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &menu, NULL, NULL, 0); while ( (string = va_arg (arg_ptr, const char *)) ) { @@ -154,6 +169,8 @@ else { AppendMenu (menu, MF_STRING, *pnCommandIDBase, string); +// SetMenuItemBitmaps (menu, *pnCommandIDBase, MF_BYCOMMAND, +// my_uncheck_bitmap, my_check_bitmap); if (cmdptr) *cmdptr = *pnCommandIDBase; (*pnCommandIDBase)++; @@ -163,7 +180,77 @@ } +static void +check_menu (LPEXCHEXTCALLBACK pEECB, UINT menu_id, int checked) +{ + HMENU menu; + + pEECB->GetMenuPos (EECMDID_ToolsCustomizeToolbar, &menu, NULL, NULL, 0); + CheckMenuItem (menu, menu_id, + MF_BYCOMMAND | (checked?MF_CHECKED:MF_UNCHECKED)); +} + +void +GpgolExtCommands::add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...) +{ + va_list arg_ptr; + const char *desc; + UINT bmapid; + UINT cmdid; + int tbeidx; + toolbar_info_t tb_info; + int rc; + + for (tbeidx = n_tbearr-1; tbeidx > -1; tbeidx--) + if (tbearr[tbeidx].tbid == EETBID_STANDARD) + break; + if (!(tbeidx > -1)) + { + log_error ("standard toolbar not found"); + return; + } + + SendMessage (tbearr[tbeidx].hwnd, TB_BUTTONSTRUCTSIZE, + (WPARAM)(int)sizeof (TBBUTTON), 0); + + + va_start (arg_ptr, n_tbearr); + + while ( (desc = va_arg (arg_ptr, const char *)) ) + { + bmapid = va_arg (arg_ptr, UINT); + cmdid = va_arg (arg_ptr, UINT); + + if (!*desc) + ; /* Empty description - ignore this item. */ + else + { + TBADDBITMAP tbab; + + tb_info = (toolbar_info_t)xcalloc (1, sizeof *tb_info); + tb_info->button_id = tbearr[tbeidx].itbbBase++; + + tbab.hInst = glob_hinst; + tbab.nID = bmapid; + rc = SendMessage (tbearr[tbeidx].hwnd, TB_ADDBITMAP,1,(LPARAM)&tbab); + if (rc == -1) + log_error_w32 (-1, "TB_ADDBITMAP failed for `%s'", desc); + tb_info->bitmap = rc; + tb_info->cmd_id = cmdid; + tb_info->desc = desc; + tb_info->context = m_lContext; + + tb_info->next = m_toolbar_info; + m_toolbar_info = tb_info; + } + } + va_end (arg_ptr); +} + + + + /* Called by Exchange to install commands and toolbar buttons. Returns S_FALSE to signal Exchange to continue calling extensions. */ STDMETHODIMP @@ -185,9 +272,6 @@ DISPPARAMS dispparams; VARIANT aVariant; int force_encrypt = 0; - int tb_idx; - HWND hwnd_toolbar; - TBADDBITMAP tbab; log_debug ("%s:%s: context=%s flags=0x%lx\n", SRCNAME, __func__, @@ -209,7 +293,7 @@ whether he really wants to do that. Note, that we can't optimize the code here by first reading the - body because this would pop up the securiy window, telling the + body because this would pop up the security window, telling the user that someone is trying to read this data. */ if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) @@ -301,7 +385,7 @@ ul_release (mdb); } - + /* Now install menu and toolbar items. */ if (m_lContext == EECONTEXT_READNOTEMESSAGE) { int need_dvm = 0; @@ -319,95 +403,50 @@ /* We always enable the verify button as it might be useful on an already decrypted message. */ - toolbar_add_menu - (pEECB, pnCommandIDBase, - "@", NULL, - need_dvm? _("&Decrypt and verify message"):"", &m_nCmdDecrypt, - _("&Verify signature"), &m_nCmdCheckSig, - _("&Display crypto information"), &m_nCmdShowInfo, - "@", NULL, - "Debug-1 (open_inspector)", &m_nCmdDebug1, - "Debug-2 (n/a)", &m_nCmdDebug2, + add_menu (pEECB, pnCommandIDBase, + "@", NULL, + need_dvm? _("&Decrypt and verify message"):"", &m_nCmdDecrypt, + _("&Verify signature"), &m_nCmdCheckSig, + _("&Display crypto information"), &m_nCmdShowInfo, + "@", NULL, + "Debug-1 (open_inspector)", &m_nCmdDebug1, + "Debug-2 (n/a)", &m_nCmdDebug2, NULL); - hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx); - if (hwnd_toolbar) - { - m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - - tbab.hInst = glob_hinst; - tbab.nID = IDB_DECRYPT; - m_nToolbarBitmap1 = SendMessage(hwnd_toolbar, TB_ADDBITMAP, - 1, (LPARAM)&tbab); - m_nToolbarButtonID2 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - } + add_toolbar (pTBEArray, nTBECnt, + _("Decrypt message and verify signature"), IDB_DECRYPT, m_nCmdDecrypt, + NULL, 0, 0); } - - if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) + else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) { - toolbar_add_menu - (pEECB, pnCommandIDBase, - "@", NULL, - opt.enable_smime? _("use S/MIME protocol"):"", &m_nCmdSelectSmime, - _("&encrypt message with GnuPG"), &m_nCmdEncrypt, - _("&sign message with GnuPG"), &m_nCmdSign, - NULL ); + add_menu (pEECB, pnCommandIDBase, + "@", NULL, + opt.enable_smime? _("use S/MIME protocol"):"", &m_nCmdSelectSmime, + _("&encrypt message with GnuPG"), &m_nCmdEncrypt, + _("&sign message with GnuPG"), &m_nCmdSign, + NULL ); + add_toolbar (pTBEArray, nTBECnt, + _("Encrypt message with GnuPG"), IDB_ENCRYPT, m_nCmdEncrypt, + _("Sign message with GnuPG"), IDB_SIGN, m_nCmdSign, + NULL, 0, 0); - hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx); - if (hwnd_toolbar) - { - m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - - tbab.hInst = glob_hinst; - tbab.nID = IDB_ENCRYPT; - m_nToolbarBitmap1 = SendMessage (hwnd_toolbar, TB_ADDBITMAP, - 1, (LPARAM)&tbab); - - m_nToolbarButtonID2 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - - tbab.nID = IDB_SIGN; - m_nToolbarBitmap2 = SendMessage (hwnd_toolbar, TB_ADDBITMAP, - 1, (LPARAM)&tbab); - - m_nToolbarButtonID3 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - - tbab.nID = IDB_SELECT_SMIME; - m_nToolbarBitmap3 = SendMessage (hwnd_toolbar, TB_ADDBITMAP, - 1, (LPARAM)&tbab); - } - m_pExchExt->m_gpgSelectSmime = opt.enable_smime && opt.smime_default; m_pExchExt->m_gpgEncrypt = opt.encrypt_default; m_pExchExt->m_gpgSign = opt.sign_default; if (force_encrypt) m_pExchExt->m_gpgEncrypt = true; } - - if (m_lContext == EECONTEXT_VIEWER) + else if (m_lContext == EECONTEXT_VIEWER) { - toolbar_add_menu - (pEECB, pnCommandIDBase, - "@", NULL, - _("GnuPG Certificate &Manager"), &m_nCmdKeyManager, - NULL); + add_menu (pEECB, pnCommandIDBase, + "@", NULL, + _("GnuPG Certificate &Manager"), &m_nCmdKeyManager, + NULL); - hwnd_toolbar = toolbar_from_tbe (pTBEArray, nTBECnt, &tb_idx); - if (hwnd_toolbar) - { - m_nToolbarButtonID1 = pTBEArray[tb_idx].itbbBase; - pTBEArray[tb_idx].itbbBase++; - - tbab.hInst = glob_hinst; - tbab.nID = IDB_KEY_MANAGER; - m_nToolbarBitmap1 = SendMessage(hwnd_toolbar, TB_ADDBITMAP, - 1, (LPARAM)&tbab); - } + add_toolbar (pTBEArray, nTBECnt, + _("Open the certificate manager"), IDB_KEY_MANAGER, m_nCmdKeyManager, + NULL, 0, 0); } return S_FALSE; } @@ -472,7 +511,7 @@ /* Closing on our own failed - pass it on. */ return S_FALSE; } - else if (nCommandID == 154) + else if (nCommandID == EECMDID_ComposeReplyToSender) { log_debug ("%s:%s: command Reply called\n", SRCNAME, __func__); /* What we might want to do is to call Reply, then GetInspector @@ -480,12 +519,12 @@ the quoted message and avoids the ugly msgcache. */ return S_FALSE; /* Pass it on. */ } - else if (nCommandID == 155) + else if (nCommandID == EECMDID_ComposeReplyToAll) { log_debug ("%s:%s: command ReplyAll called\n", SRCNAME, __func__); return S_FALSE; /* Pass it on. */ } - else if (nCommandID == 156) + else if (nCommandID == EECMDID_ComposeForward) { log_debug ("%s:%s: command Forward called\n", SRCNAME, __func__); return S_FALSE; /* Pass it on. */ @@ -535,18 +574,21 @@ && m_lContext == EECONTEXT_SENDNOTEMESSAGE) { m_pExchExt->m_gpgEncrypt = !m_pExchExt->m_gpgEncrypt; + check_menu (pEECB, m_nCmdEncrypt, m_pExchExt->m_gpgEncrypt); } - else if (nCommandID == m_nCmdSign + else if (nCommandID == m_nCmdSign && m_lContext == EECONTEXT_SENDNOTEMESSAGE) { m_pExchExt->m_gpgSign = !m_pExchExt->m_gpgSign; + check_menu (pEECB, m_nCmdSign, m_pExchExt->m_gpgSign); } else if (nCommandID == m_nCmdKeyManager && m_lContext == EECONTEXT_VIEWER) { - if (start_key_manager ()) - MessageBox (NULL, _("Could not start certificate manager"), - "GpgOL", MB_ICONERROR|MB_OK); + if (engine_start_keymanager ()) + if (start_key_manager ()) + MessageBox (NULL, _("Could not start certificate manager"), + "GpgOL", MB_ICONERROR|MB_OK); } else if (nCommandID == m_nCmdDebug1 && m_lContext == EECONTEXT_READNOTEMESSAGE) @@ -572,12 +614,16 @@ commands before the user sees them. This method is called frequently and should be written in a very efficient manner. */ STDMETHODIMP_(VOID) -GpgolExtCommands::InitMenu(LPEXCHEXTCALLBACK pEECB) +GpgolExtCommands::InitMenu(LPEXCHEXTCALLBACK eecb) { -#if 0 - log_debug ("%s:%s: context=%s\n", - SRCNAME, __func__, ext_context_name (m_lContext)); -#endif + HRESULT hr; + HMENU menu; + + hr = eecb->GetMenu (&menu); + if (FAILED(hr)) + return; /* Ooops. */ + CheckMenuItem (menu, m_nCmdEncrypt, MF_BYCOMMAND + | (m_pExchExt->m_gpgSign?MF_CHECKED:MF_UNCHECKED)); } @@ -735,7 +781,7 @@ /* Called by Exchange to get toolbar button infos. TOOLBARID is the toolbar identifier. BUTTONID is the toolbar button index. PTBB is - a pointer to toolbar button structure DESCRIPTION is a pointer to + a pointer to toolbar button structure. DESCRIPTION is a pointer to buffer receiving the text for the button. DESCRIPTION_SIZE is the maximum size of DESCRIPTION. FLAGS are flags which might have the EXCHEXT_UNICODE bit set. @@ -748,75 +794,41 @@ LPTSTR description, UINT description_size, ULONG flags) { - if (buttonid == m_nToolbarButtonID1 - && m_lContext == EECONTEXT_READNOTEMESSAGE) + toolbar_info_t tb_info; + + for (tb_info = m_toolbar_info; tb_info; tb_info = tb_info->next ) + if (tb_info->button_id == buttonid + && tb_info->context == m_lContext) + break; + if (!tb_info) + return S_FALSE; /* Not one of our toolbar buttons. */ + + pTBB->iBitmap = tb_info->bitmap; + pTBB->idCommand = tb_info->cmd_id; + pTBB->fsState = TBSTATE_ENABLED; + pTBB->fsStyle = TBSTYLE_BUTTON; + pTBB->dwData = 0; + pTBB->iString = -1; + lstrcpyn (description, tb_info->desc, strlen (tb_info->desc)); + + if (tb_info->cmd_id == m_nCmdEncrypt) { - pTBB->iBitmap = m_nToolbarBitmap1; - pTBB->idCommand = m_nCmdEncrypt; - pTBB->fsState = TBSTATE_ENABLED; - pTBB->fsStyle = TBSTYLE_BUTTON; - pTBB->dwData = 0; - pTBB->iString = -1; - lstrcpyn (description, - _("Decrypt message and verify signature"), - description_size); - } - else if (buttonid == m_nToolbarButtonID1 - && m_lContext == EECONTEXT_SENDNOTEMESSAGE) - { - pTBB->iBitmap = m_nToolbarBitmap1; - pTBB->idCommand = m_nCmdEncrypt; - pTBB->fsState = TBSTATE_ENABLED; + pTBB->fsStyle |= TBSTYLE_CHECK; if (m_pExchExt->m_gpgEncrypt) pTBB->fsState |= TBSTATE_CHECKED; - pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK; - pTBB->dwData = 0; - pTBB->iString = -1; - lstrcpyn (description, _("Encrypt message with GPG"), - description_size); } - else if (buttonid == m_nToolbarButtonID2 - && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + else if (tb_info->cmd_id == m_nCmdSign) { - pTBB->iBitmap = m_nToolbarBitmap2; - pTBB->idCommand = m_nCmdSign; - pTBB->fsState = TBSTATE_ENABLED; + pTBB->fsStyle |= TBSTYLE_CHECK; if (m_pExchExt->m_gpgSign) pTBB->fsState |= TBSTATE_CHECKED; - pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK; - pTBB->dwData = 0; - pTBB->iString = -1; - lstrcpyn (description, _("Sign message with GPG"), - description_size); } - else if (buttonid == m_nToolbarButtonID3 - && m_lContext == EECONTEXT_SENDNOTEMESSAGE) + else if (tb_info->cmd_id == m_nCmdSelectSmime) { - pTBB->iBitmap = m_nToolbarBitmap3; - pTBB->idCommand = m_nCmdSelectSmime; - pTBB->fsState = TBSTATE_ENABLED; + pTBB->fsStyle |= TBSTYLE_CHECK; if (m_pExchExt->m_gpgSelectSmime) pTBB->fsState |= TBSTATE_CHECKED; - pTBB->fsStyle = TBSTYLE_BUTTON | TBSTYLE_CHECK; - pTBB->dwData = 0; - pTBB->iString = -1; - lstrcpyn (description, _("Use the S/MIME protocol"), - description_size); } - else if (buttonid == m_nToolbarButtonID1 - && m_lContext == EECONTEXT_VIEWER) - { - pTBB->iBitmap = m_nToolbarBitmap1; - pTBB->idCommand = m_nCmdEncrypt; - pTBB->fsState = TBSTATE_ENABLED; - pTBB->fsStyle = TBSTYLE_BUTTON; - pTBB->dwData = 0; - pTBB->iString = -1; - lstrcpyn (description, _("Open the certificate manager"), - description_size); - } - else - return S_FALSE; return S_OK; } @@ -829,4 +841,3 @@ return S_OK; } - Modified: trunk/src/ext-commands.h =================================================================== --- trunk/src/ext-commands.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/ext-commands.h 2007-10-22 15:31:09 UTC (rev 194) @@ -21,6 +21,10 @@ #define EXT_COMMANDS_H +struct toolbar_info_s; +typedef struct toolbar_info_s *toolbar_info_t; + + /* GpgolExtCommands @@ -30,7 +34,8 @@ { public: GpgolExtCommands (GpgolExt* pParentInterface); - + virtual ~GpgolExtCommands (void); + private: ULONG m_lRef; ULONG m_lContext; @@ -45,16 +50,14 @@ UINT m_nCmdDebug1; UINT m_nCmdDebug2; - UINT m_nToolbarButtonID1; - UINT m_nToolbarButtonID2; - UINT m_nToolbarButtonID3; - UINT m_nToolbarBitmap1; - UINT m_nToolbarBitmap2; - UINT m_nToolbarBitmap3; + /* A list of all active toolbar items. */ + toolbar_info_t m_toolbar_info; HWND m_hWnd; GpgolExt* m_pExchExt; + + void add_toolbar (LPTBENTRY tbearr, UINT n_tbearr, ...); public: STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj); Modified: trunk/src/key_mana.bmp =================================================================== (Binary files differ) Modified: trunk/src/logo.bmp =================================================================== (Binary files differ) Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/main.c 2007-10-22 15:31:09 UTC (rev 194) @@ -31,9 +31,6 @@ #include "mymapi.h" -/* Registry key for this software. */ -#define REGKEY "Software\\GNU\\GnuPG" - /* The malloced name of the logfile and the logging stream. If LOGFILE is NULL, no logging is done. */ static char *logfile; @@ -441,7 +438,7 @@ char *p; char *dname; - instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", GNUPG_REGKEY, "Install Directory"); if (!instdir) return NULL; Modified: trunk/src/mimemaker.c =================================================================== --- trunk/src/mimemaker.c 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/mimemaker.c 2007-10-22 15:31:09 UTC (rev 194) @@ -62,6 +62,11 @@ void *cb_data; sink_t extrasink; int (*writefnc)(sink_t sink, const void *data, size_t datalen); +/* struct { */ +/* int idx; */ +/* unsigned char inbuf[4]; */ +/* int quads; */ +/* } b64; */ }; @@ -115,7 +120,6 @@ switch (protocol) { case PROTOCOL_UNKNOWN: - log_error ("fixme: automatic protocol selection is not yet supported"); return PROTOCOL_UNKNOWN; case PROTOCOL_OPENPGP: case PROTOCOL_SMIME: @@ -1343,6 +1347,102 @@ } +#if 0 /* Not used. */ +/* Sink write method used by mime_encrypt for writing Base64. */ +static int +sink_encryption_write_b64 (sink_t encsink, const void *data, size_t datalen) +{ + engine_filter_t filter = encsink->cb_data; + int rc; + const unsigned char *p; + unsigned char inbuf[4]; + int idx, quads; + char outbuf[6]; + size_t outbuflen; + + if (!filter) + { + log_error ("%s:%s: sink not setup for writing", SRCNAME, __func__); + return -1; + } + + idx = encsink->b64.idx; + assert (idx < 4); + memcpy (inbuf, encsink->b64.inbuf, idx); + quads = encsink->b64.quads; + + if (!data) /* Flush. */ + { + outbuflen = 0; + if (idx) + { + outbuf[0] = bintoasc[(*inbuf>>2)&077]; + if (idx == 1) + { + outbuf[1] = bintoasc[((*inbuf<<4)&060)&077]; + outbuf[2] = '='; + outbuf[3] = '='; + } + else + { + outbuf[1] = bintoasc[(((*inbuf<<4)&060)| + ((inbuf[1]>>4)&017))&077]; + outbuf[2] = bintoasc[((inbuf[1]<<2)&074)&077]; + outbuf[3] = '='; + } + outbuflen = 4; + quads++; + } + + if (quads) + { + outbuf[outbuflen++] = '\r'; + outbuf[outbuflen++] = '\n'; + } + + if (outbuflen && (rc = engine_filter (filter, outbuf, outbuflen))) + return rc; + /* Send the flush command to the filter. */ + if ((rc = engine_filter (filter, data, datalen))) + return rc; + } + else + { + for (p = data; datalen; p++, datalen--) + { + inbuf[idx++] = *p; + if (idx > 2) + { + idx = 0; + outbuf[0] = bintoasc[(*inbuf>>2)&077]; + 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]; + outbuflen = 4; + if (++quads >= (64/4)) + { + quads = 0; + outbuf[4] = '\r'; + outbuf[5] = '\n'; + outbuflen += 2; + } + if ((rc = engine_filter (filter, outbuf, outbuflen))) + return rc; + } + } + } + + encsink->b64.idx = idx; + memcpy (encsink->b64.inbuf, inbuf, idx); + encsink->b64.quads = quads; + + return 0; +} +#endif /*Not used.*/ + + /* Encrypt the MESSAGE. */ int mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients) @@ -1364,12 +1464,6 @@ memset (sink, 0, sizeof *sink); memset (encsink, 0, sizeof *encsink); - 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; @@ -1379,9 +1473,13 @@ will fail early. */ if (engine_create_filter (&filter, write_buffer_for_cb, sink)) goto failure; - if (engine_encrypt_start (filter, protocol, recipients)) + if (engine_encrypt_start (filter, protocol, recipients, &protocol)) goto failure; + protocol = check_protocol (protocol); + if (protocol == PROTOCOL_UNKNOWN) + goto failure; + /* Get the attachment info and the body. */ body = mapi_get_body (message, NULL); if (body && !*body) @@ -1398,33 +1496,51 @@ } /* 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))) + if (protocol == PROTOCOL_SMIME) + { + *boundary = 0; + rc = write_multistring (sink, + "MIME-Version: 1.0\r\n" + "Content-Type: application/pkcs7-mime;\r\n" + "\tsmime-type=enveloped-data;\r\n" + "\tname=\"smime.p7m\"\r\n" + "Content-Transfer-Encoding: base64\r\n", + NULL); + } + else + { + generate_boundary (boundary); + 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); + } + if (rc) goto failure; - /* 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; + if (protocol == PROTOCOL_OPENPGP) + { + /* 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; + } - /* 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 = filter; encsink->writefnc = sink_encryption_write; @@ -1467,10 +1583,10 @@ filter = NULL; /* Not valid anymore. */ encsink->cb_data = NULL; /* Not needed anymore. */ - /* Write the final boundary and finish the attachment. */ - if ((rc = write_boundary (sink, boundary, 1))) + /* Write the final boundary (for OpenPGP) and finish the attachment. */ + if (*boundary && (rc = write_boundary (sink, boundary, 1))) goto failure; - + if (close_mapi_attachment (&attach, sink)) goto failure; Modified: trunk/src/myexchext.h =================================================================== --- trunk/src/myexchext.h 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/myexchext.h 2007-10-22 15:31:09 UTC (rev 194) @@ -69,8 +69,15 @@ /* Command IDs. */ +#define EECMDID_Format 110 +#define EECMDID_FormatFont 111 +#define EECMDID_FormatParagraph 112 +#define EECMDID_Tools 120 #define EECMDID_ToolsCustomizeToolbar 134 #define EECMDID_ToolsOptions 136 +#define EECMDID_ComposeReplyToSender 154 +#define EECMDID_ComposeReplyToAll 155 +#define EECMDID_ComposeForward 156 /* Flag values for IExchExtAttachedFileEvents::OpenSzFile. */ Modified: trunk/src/olflange-dlgs.cpp =================================================================== --- trunk/src/olflange-dlgs.cpp 2007-10-12 19:22:35 UTC (rev 193) +++ trunk/src/olflange-dlgs.cpp 2007-10-22 15:31:09 UTC (rev 194) @@ -80,26 +80,31 @@ { case WM_INITDIALOG: { - HDC hdc = GetDC (hDlg); - if (hdc) - { - int bits_per_pixel = GetDeviceCaps (hdc, BITSPIXEL); - HBITMAP bitmap; + /* We don't use this anymore. Actually I don't know why we + used it at all. Note that this unused code has been + converted to use LoadImage instead of LoadBitmap. */ +/* HDC hdc = GetDC (hDlg); */ +/* if (hdc) */ +/* { */ +/* int bits_per_pixel = GetDeviceCaps (hdc, BITSPIXEL); */ +/* HANDLE bitmap; */ - ReleaseDC (hDlg, hdc); - if (bits_per_pixel > 15) - { - bitmap = LoadBitmap (glob_hinst, MAKEINTRESOURCE(IDB_BANNER)); - if (bitmap) - { - HBITMAP old = (HBITMAP) SendDlgItemMessage - (hDlg, IDC_BITMAP, STM_SETIMAGE, - IMAGE_BITMAP, (LPARAM)bitmap); - if (old) - DeleteObject (old); - } - } - } +/* if (bits_per_pixel > 15) */ +/* { */ +/* bitmap = LoadImage (glob_hinst, MAKEINTRESOURCE(IDB_BANNER), */ +/* IMAGE_BITMAP, 0, 0, */ +/* LR_CREATEDIBSECTION | LR_LOADTRANSPARENT); */ +/* if (bitmap) */ +/* { */ +/* HBITMAP old = (HBITMAP) SendDlgItemMessage */ +/* (hDlg, IDC_BITMAP, STM_SETIMAGE, */ +/* IMAGE_BITMAP, (LPARAM)bitmap); */ +/* if (old) */ +/* DeleteObject (old); */ +/* } */ +/* } */ +/* ReleaseDC (hDlg, hdc); */ +/* } */ EnableWindow (GetDlgItem (hDlg, IDC_ENCRYPT_TO), !!opt.enable_default_key); Modified: trunk/src/sign.bmp =================================================================== (Binary files differ) From cvs at cvs.gnupg.org Mon Oct 22 17:40:09 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 22 Oct 2007 17:40:09 +0200 Subject: [svn] GpgOL - r195 - tags Message-ID: Author: wk Date: 2007-10-22 17:40:00 +0200 (Mon, 22 Oct 2007) New Revision: 195 Added: tags/gpgol-0.10.1/ Log: release! Copied: tags/gpgol-0.10.1 (from rev 194, trunk) From cvs at cvs.gnupg.org Mon Oct 22 21:08:05 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 22 Oct 2007 21:08:05 +0200 Subject: [svn] GnuPG - r4600 - trunk/tools Message-ID: Author: wk Date: 2007-10-22 21:07:56 +0200 (Mon, 22 Oct 2007) New Revision: 4600 Modified: trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Replace popen by our own code to help with Windows long files (e.g. those with a space in the name). Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-21 16:07:13 UTC (rev 4599) +++ trunk/tools/ChangeLog 2007-10-22 19:07:56 UTC (rev 4600) @@ -1,3 +1,9 @@ +2007-10-22 Werner Koch + + * gpgconf-comp.c (retrieve_options_from_program): Replace use of + popen by our gnupg_spawn_process_fd. This is required because + popen under Windows can't handle long filenames. + 2007-10-19 Werner Koch * symcryptrun.c (confucius_get_pass): Use utf8 switching functions. Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-10-21 16:07:13 UTC (rev 4599) +++ trunk/tools/gpgconf-comp.c 2007-10-22 19:07:56 UTC (rev 4600) @@ -64,8 +64,6 @@ /* TODO: Components: Add more components and their options. Robustness: Do more validation. Call programs to do validation for us. - Don't use popen, as this will not tell us if the program had a - non-zero exit code. Add options to change backend binary path. Extract binary path for some backends from gpgsm/gpg config. */ @@ -1626,21 +1624,40 @@ static void retrieve_options_from_program (gc_component_t component, gc_backend_t backend) { - char *cmd_line; + gpg_error_t err; + int filedes[2]; + const char *pgmname; + const char *argv[2]; + int exitcode; + pid_t pid; char *line = NULL; size_t line_len = 0; ssize_t length; FILE *config; char *config_pathname; - cmd_line = xasprintf ("%s --gpgconf-list", - gc_backend[backend].module_name ? - gnupg_module_name (gc_backend[backend].module_name) : - gc_backend[backend].program ); + err = gnupg_create_inbound_pipe (filedes); + if (err) + gc_error (1, 0, _("error creating a pipe: %s\n"), gpg_strerror (err)); - config = popen (cmd_line, "r"); + pgmname = (gc_backend[backend].module_name + ? gnupg_module_name (gc_backend[backend].module_name) + : gc_backend[backend].program ); + argv[0] = "--gpgconf-list"; + argv[1] = NULL; + + err = gnupg_spawn_process_fd (pgmname, argv, -1, filedes[1], -1, &pid); + if (err) + { + close (filedes[0]); + close (filedes[1]); + gc_error (1, 0, "could not gather active options from `%s': %s", + pgmname, gpg_strerror (err)); + } + close (filedes[1]); + config = fdopen (filedes[0], "r"); if (!config) - gc_error (1, errno, "could not gather active options from %s", cmd_line); + gc_error (1, errno, "can't fdopen pipe for reading"); while ((length = read_line (config, &line, &line_len, NULL)) > 0) { @@ -1671,9 +1688,11 @@ errno = 0; flags = strtoul (linep, &tail, 0); if (errno) - gc_error (1, errno, "malformed flags in option %s from %s", line, cmd_line); + gc_error (1, errno, "malformed flags in option %s from %s", + line, pgmname); if (!(*tail == '\0' || *tail == ':' || *tail == ' ')) - gc_error (1, 0, "garbage after flags in option %s from %s", line, cmd_line); + gc_error (1, 0, "garbage after flags in option %s from %s", + line, pgmname); linep = end; } @@ -1701,7 +1720,7 @@ { if (option->active) gc_error (1, errno, "option %s returned twice from %s", - line, cmd_line); + line, pgmname); option->active = 1; option->flags |= flags; @@ -1710,11 +1729,16 @@ } } if (length < 0 || ferror (config)) - gc_error (1, errno, "error reading from %s", cmd_line); + gc_error (1, errno, "error reading from %s",pgmname); if (fclose (config) && ferror (config)) - gc_error (1, errno, "error closing %s", cmd_line); - xfree (cmd_line); + gc_error (1, errno, "error closing %s", pgmname); + err = gnupg_wait_process (pgmname, pid, &exitcode); + if (err) + gc_error (1, 0, "running %s failed (exitcode=%d): %s", + pgmname, exitcode, gpg_strerror (err)); + + /* At this point, we can parse the configuration file. */ config_pathname = get_config_pathname (component, backend); From cvs at cvs.gnupg.org Tue Oct 23 00:25:10 2007 From: cvs at cvs.gnupg.org (svn author marcus) Date: Tue, 23 Oct 2007 00:25:10 +0200 Subject: [svn] GpgEX - r36 - trunk/src Message-ID: Author: marcus Date: 2007-10-23 00:24:59 +0200 (Tue, 23 Oct 2007) New Revision: 36 Modified: trunk/src/ChangeLog trunk/src/client.cc trunk/src/exechelp.c trunk/src/exechelp.h Log: 2007-10-22 Marcus Brinkmann * exechelp.h (gpgex_spawn_detached): Change signature to just a command line. * exechelp.c: Rewritten. * client.cc (replace_dollar_s): New function. (default_uiserver_cmdline): Use it. (uiserver_connect): Change caller of gpgex_spawn_detached. Modified: trunk/src/ChangeLog =================================================================== --- trunk/src/ChangeLog 2007-10-16 22:50:46 UTC (rev 35) +++ trunk/src/ChangeLog 2007-10-22 22:24:59 UTC (rev 36) @@ -1,3 +1,12 @@ +2007-10-22 Marcus Brinkmann + + * exechelp.h (gpgex_spawn_detached): Change signature to just a + command line. + * exechelp.c: Rewritten. + * client.cc (replace_dollar_s): New function. + (default_uiserver_cmdline): Use it. + (uiserver_connect): Change caller of gpgex_spawn_detached. + 2007-10-17 Marcus Brinkmann * client.cc (default_uiserver_name): Fix check for dirty hack. Modified: trunk/src/client.cc =================================================================== --- trunk/src/client.cc 2007-10-16 22:50:46 UTC (rev 35) +++ trunk/src/client.cc 2007-10-22 22:24:59 UTC (rev 36) @@ -41,57 +41,140 @@ static const char * -default_uiserver_name (void) +default_socket_name (void) { static string name; if (name.size () == 0) { char *dir = NULL; - - dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, - "Install Directory"); + + dir = default_homedir (); if (dir) { - char *uiserver = NULL; - int uiserver_malloced = 1; - - uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server"); - if (!uiserver) - { - uiserver = "bin\\kleopatra.exe"; - uiserver_malloced = 0; - } + try { name = ((string) dir) + "\\S.uiserver"; } catch (...) {} + free ((void *) dir); + } + } - /* FIXME: Very dirty work-around to make kleopatra find its - DLLs. */ - if (!strcmp (uiserver, "bin\\kleopatra.exe")) - chdir (dir); + return name.c_str (); +} - try { name = ((string) dir) + "\\" + uiserver; } catch (...) {} - if (uiserver_malloced) - free (uiserver); - free ((void *) dir); +/* Substitute all substrings "$s" in BUFFER by the value of the + default socket and replace all "$$" by "$". Free BUFFER if + necessary and return a newly malloced buffer. */ +static char * +replace_dollar_s (char *str) +{ + int n; + char *src; + char *dst; + const char *socket_name = default_socket_name (); + int socket_name_len = strlen (socket_name); + char *new_str; + + n = 0; + src = str; + + while (*src) + { + if (*src == '$') + { + src++; + if (*src == '\0') + break; + else if (*src == 's') + /* Socket name and surrounding quotes. */ + n += socket_name_len + 2; + else + n++; } + else + n++; + src++; } + /* Terminating zero. */ + n++; - return name.c_str (); + new_str = (char *) malloc (n); + if (!new_str) + return NULL; + + src = str; + dst = new_str; + while (*src) + { + if (*src == '$') + { + src++; + if (*src == '\0') + break; + else if (*src == 's') + { + /* Socket name and surrounding quotes. */ + *(dst++) = '"'; + memcpy (dst, socket_name, socket_name_len); + dst += socket_name_len; + *(dst++) = '"'; + } + else + /* Pass through the next character. */ + *(dst++) = *src; + } + else + *(dst++) = *src; + src++; + } + /* Terminating zero. */ + *dst = '\0'; + + return new_str; } + static const char * -default_socket_name (void) +default_uiserver_cmdline (void) { static string name; if (name.size () == 0) { char *dir = NULL; - - dir = default_homedir (); + + dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY, + "Install Directory"); if (dir) { - try { name = ((string) dir) + "\\S.uiserver"; } catch (...) {} + char *uiserver = NULL; + char *old_uiserver = NULL; + int uiserver_malloced = 1; + + uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server"); + if (!uiserver) + { + uiserver = "bin\\kleopatra.exe --uiserver-socket $s"; + uiserver_malloced = 0; + } + + old_uiserver = uiserver; + uiserver = replace_dollar_s (old_uiserver); + if (uiserver_malloced) + free (old_uiserver); + if (!uiserver) + { + free ((void *) dir); + return NULL; + } + + /* FIXME: Very dirty work-around to make kleopatra find + its DLLs. */ + if (!strncmp (uiserver, "bin\\kleopatra.exe", 17)) + chdir (dir); + + try { name = ((string) dir) + "\\" + uiserver; } catch (...) {} + + free (uiserver); free ((void *) dir); } } @@ -184,16 +267,11 @@ rc = assuan_socket_connect (ctx, socket_name, -1); if (rc) { - const char *argv[3]; int count; (void) TRACE_LOG ("UI server not running, starting it"); - argv[0] = "--uiserver-socket"; - argv[1] = socket_name; - argv[2] = NULL; - - rc = gpgex_spawn_detached (default_uiserver_name (), argv); + rc = gpgex_spawn_detached (default_uiserver_cmdline ()); if (rc) return TRACE_GPGERR (rc); Modified: trunk/src/exechelp.c =================================================================== --- trunk/src/exechelp.c 2007-10-16 22:50:46 UTC (rev 35) +++ trunk/src/exechelp.c 2007-10-22 22:24:59 UTC (rev 36) @@ -38,99 +38,11 @@ #define DEBUG_W32_SPAWN 0 -/* Replacement function. */ - -#define stpcpy my_sptcpy - -static char * -stpcpy (char *d, const char *s) -{ - do - *d++ = *s; - while (*s++ != '\0'); - - return d - 1; -} - - -/* Helper function to build_w32_commandline. */ -static char * -build_w32_commandline_copy (char *buffer, const char *string) -{ - char *p = buffer; - const char *s; - - if (!*string) /* Empty string. */ - p = stpcpy (p, "\"\""); - else if (strpbrk (string, " \t\n\v\f\"")) - { - /* Need to do some kind of quoting. */ - p = stpcpy (p, "\""); - for (s=string; *s; s++) - { - *p++ = *s; - if (*s == '\"') - *p++ = *s; - } - *p++ = '\"'; - *p = 0; - } - else - p = stpcpy (p, string); - - return p; -} - -/* Build a command line for use with W32's CreateProcess. On success - CMDLINE gets the address of a newly allocated string. */ -static gpg_error_t -build_w32_commandline (const char *pgmname, const char * const *argv, - char **cmdline) -{ - int i, n; - const char *s; - char *buf, *p; - - *cmdline = NULL; - n = 0; - s = pgmname; - n += strlen (s) + 1 + 2; /* (1 space, 2 quotes) */ - for (; *s; s++) - if (*s == '\"') - n++; /* Need to double inner quotes. */ - for (i=0; (s=argv[i]); i++) - { - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ - for (; *s; s++) - if (*s == '\"') - n++; /* Need to double inner quotes. */ - } - n++; - - buf = p = malloc (n); - if (!buf) - return gpg_error_from_syserror (); - - p = build_w32_commandline_copy (p, pgmname); - for (i = 0; argv[i]; i++) - { - *p++ = ' '; - p = build_w32_commandline_copy (p, argv[i]); - } - - *cmdline = buf; - return 0; -} - - -/* Fork and exec the PGMNAME with /dev/null as stdin, stdout and - stderr. The arguments for the process are expected in the NULL - terminated array ARGV. The program name itself should not be - included there. Returns 0 on success or an error code. */ +/* Fork and exec the program with /dev/null as stdin, stdout and + stderr. Returns 0 on success or an error code. */ gpg_error_t -gpgex_spawn_detached (const char *pgmname, const char *const argv[]) +gpgex_spawn_detached (const char *cmdline) { - gpg_error_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { @@ -141,23 +53,10 @@ }; STARTUPINFO si; int cr_flags; - char *cmdline; - int i; - TRACE_BEG1 (DEBUG_ASSUAN, "gpgex_spawn_detached", pgmname, - "pgmname=%s", pgmname); - i = 0; - while (argv[i]) - { - TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); - i++; - } + TRACE_BEG1 (DEBUG_ASSUAN, "gpgex_spawn_detached", cmdline, + "cmdline=%s", cmdline); - /* Build the command line. */ - err = build_w32_commandline (pgmname, argv, &cmdline); - if (err) - return err; - /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr); sec_attr.nLength = sizeof sec_attr; @@ -173,12 +72,10 @@ cr_flags = (CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (GetCurrentProcess ()) | CREATE_NEW_PROCESS_GROUP - | DETACHED_PROCESS); + | DETACHED_PROCESS); - (void) TRACE_LOG2 ("CreateProcess, path=`%s' cmdline=`%s'\n", - pgmname, cmdline); - if (!CreateProcess (pgmname, /* pgmname; Program to start. */ - cmdline, /* Command line arguments. */ + if (!CreateProcess (NULL, /* pgmname; Program to start. */ + (char *) cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ &sec_attr, /* Thread security attributes. */ TRUE, /* Inherit handles. */ @@ -190,10 +87,8 @@ )) { (void) TRACE_LOG1 ("CreateProcess failed: %i\n", GetLastError ()); - free (cmdline); return gpg_error (GPG_ERR_GENERAL); } - free (cmdline); /* Process has been created suspended; resume it now. */ CloseHandle (pi.hThread); Modified: trunk/src/exechelp.h =================================================================== --- trunk/src/exechelp.h 2007-10-16 22:50:46 UTC (rev 35) +++ trunk/src/exechelp.h 2007-10-22 22:24:59 UTC (rev 36) @@ -30,12 +30,9 @@ #endif #endif -/* Fork and exec the PGMNAME with /dev/null as stdin, stdout and - stderr. The arguments for the process are expected in the NULL - terminated array ARGV. The program name itself should not be - included there. Returns 0 on success or an error code. */ -gpg_error_t gpgex_spawn_detached (const char *pgmname, - const char *const argv[]); +/* Fork and exec CMDLINE with /dev/null as stdin, stdout and stderr. + Returns 0 on success or an error code. */ +gpg_error_t gpgex_spawn_detached (const char *cmdline); #ifdef __cplusplus #if 0 { From cvs at cvs.gnupg.org Tue Oct 23 02:37:09 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Tue, 23 Oct 2007 02:37:09 +0200 Subject: [svn] GnuPG - r4601 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2007-10-23 02:36:59 +0200 (Tue, 23 Oct 2007) New Revision: 4601 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/gpg.c Log: * gpg.c (main): Disable --rfc2440-text and --force-v3-sigs by default. Enable --require-cross-certification by default. --openpgp (--rfc4880) is the same as --rfc2440 except with "--enable-dsa2 --no-rfc2440-text --escape-from-lines". Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-22 19:07:56 UTC (rev 4600) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-23 00:36:59 UTC (rev 4601) @@ -1,3 +1,10 @@ +2007-10-22 David Shaw + + * gpg.c (main): Disable --rfc2440-text and --force-v3-sigs by + default. Enable --require-cross-certification by default. + --openpgp (--rfc4880) is the same as --rfc2440 except with + "--enable-dsa2 --no-rfc2440-text --escape-from-lines". + 2007-10-21 David Shaw * misc.c (compliance_option_string, compliance_failure): Minor Modified: branches/STABLE-BRANCH-1-4/g10/gpg.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-22 19:07:56 UTC (rev 4600) +++ branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-23 00:36:59 UTC (rev 4601) @@ -1810,8 +1810,8 @@ opt.marginals_needed = 3; opt.max_cert_depth = 5; opt.pgp2_workarounds = 1; - opt.force_v3_sigs = 1; opt.escape_from = 1; + opt.flags.require_cross_cert = 1; opt.import_options=IMPORT_SK2PK; opt.export_options=EXPORT_ATTRIBUTES; opt.keyserver_options.import_options=IMPORT_REPAIR_PKS_SUBKEY_BUG; @@ -1825,7 +1825,6 @@ opt.min_cert_level=2; set_screen_dimensions(); opt.keyid_format=KF_SHORT; - opt.rfc2440_text=1; opt.def_sig_expire="0"; opt.def_cert_expire="0"; set_homedir ( default_homedir () ); @@ -2258,14 +2257,16 @@ break; case oOpenPGP: case oRFC4880: - /* Note these are the same defaults as CO_RFC2440. Update - this. */ + /* This is effectively the same as RFC2440, but with + "--enable-dsa2 --no-rfc2440-text + --escape-from-lines". */ opt.compliance = CO_RFC4880; - opt.rfc2440_text=1; + opt.flags.dsa2 = 1; + opt.rfc2440_text = 0; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; - opt.escape_from = 0; + opt.escape_from = 1; opt.force_v3_sigs = 0; opt.compress_keys = 0; /* not mandated, but we do it */ opt.compress_sigs = 0; /* ditto. */ @@ -2279,10 +2280,9 @@ opt.s2k_cipher_algo = CIPHER_ALGO_3DES; break; case oRFC2440: - /* TODO: When 2440bis becomes a RFC, set new values for - oOpenPGP. */ opt.compliance = CO_RFC2440; - opt.rfc2440_text=1; + opt.flags.dsa2 = 0; + opt.rfc2440_text = 1; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; opt.pgp2_workarounds = 0; From cvs at cvs.gnupg.org Tue Oct 23 05:00:31 2007 From: cvs at cvs.gnupg.org (svn author dshaw) Date: Tue, 23 Oct 2007 05:00:31 +0200 Subject: [svn] GnuPG - r4602 - branches/STABLE-BRANCH-1-4/g10 Message-ID: Author: dshaw Date: 2007-10-23 05:00:21 +0200 (Tue, 23 Oct 2007) New Revision: 4602 Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog branches/STABLE-BRANCH-1-4/g10/gpg.c Log: * gpg.c (main): Add --require-cross-certification to --openpgp/--rfc4880 mode. Modified: branches/STABLE-BRANCH-1-4/g10/ChangeLog =================================================================== --- branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-23 00:36:59 UTC (rev 4601) +++ branches/STABLE-BRANCH-1-4/g10/ChangeLog 2007-10-23 03:00:21 UTC (rev 4602) @@ -1,5 +1,8 @@ 2007-10-22 David Shaw + * gpg.c (main): Add --require-cross-certification to + --openpgp/--rfc4880 mode. + * gpg.c (main): Disable --rfc2440-text and --force-v3-sigs by default. Enable --require-cross-certification by default. --openpgp (--rfc4880) is the same as --rfc2440 except with Modified: branches/STABLE-BRANCH-1-4/g10/gpg.c =================================================================== --- branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-23 00:36:59 UTC (rev 4601) +++ branches/STABLE-BRANCH-1-4/g10/gpg.c 2007-10-23 03:00:21 UTC (rev 4602) @@ -2258,10 +2258,11 @@ case oOpenPGP: case oRFC4880: /* This is effectively the same as RFC2440, but with - "--enable-dsa2 --no-rfc2440-text - --escape-from-lines". */ + "--enable-dsa2 --no-rfc2440-text --escape-from-lines + --require-cross-certification". */ opt.compliance = CO_RFC4880; opt.flags.dsa2 = 1; + opt.flags.require_cross_cert = 1; opt.rfc2440_text = 0; opt.allow_non_selfsigned_uid = 1; opt.allow_freeform_uid = 1; From cvs at cvs.gnupg.org Tue Oct 23 13:15:35 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 23 Oct 2007 13:15:35 +0200 Subject: [svn] GnuPG - r4604 - trunk/tools Message-ID: Author: wk Date: 2007-10-23 13:15:26 +0200 (Tue, 23 Oct 2007) New Revision: 4604 Modified: trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c Log: Fixed wrong entry in the gpg-agent table. Modified: trunk/tools/ChangeLog =================================================================== --- trunk/tools/ChangeLog 2007-10-23 10:48:09 UTC (rev 4603) +++ trunk/tools/ChangeLog 2007-10-23 11:15:26 UTC (rev 4604) @@ -1,3 +1,9 @@ +2007-10-23 Werner Koch + + * gpgconf-comp.c (gc_options_gpg_agent): Repalce accidently used + GC_BACKEND_SCDAEMON. We should consider to create these tables + from plain files. + 2007-10-22 Werner Koch * gpgconf-comp.c (retrieve_options_from_program): Replace use of Modified: trunk/tools/gpgconf-comp.c =================================================================== --- trunk/tools/gpgconf-comp.c 2007-10-23 10:48:09 UTC (rev 4603) +++ trunk/tools/gpgconf-comp.c 2007-10-23 11:15:26 UTC (rev 4604) @@ -537,7 +537,7 @@ { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|FILE|check new passphrases against pattern in FILE"), - GC_ARG_TYPE_PATHNAME, GC_BACKEND_SCDAEMON }, + GC_ARG_TYPE_PATHNAME, GC_BACKEND_GPG_AGENT }, { "max-passphrase-days", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, "gnupg", N_("|N|expire the passphrase after N days"), From cvs at cvs.gnupg.org Tue Oct 23 20:13:40 2007 From: cvs at cvs.gnupg.org (svn author wk) Date: Tue, 23 Oct 2007 20:13:40 +0200 Subject: [svn] GnuPG - r4605 - in trunk: . doc doc/examples g10 tools Message-ID: Author: wk Date: 2007-10-23 20:13:27 +0200 (Tue, 23 Oct 2007) New Revision: 4605 Modified: trunk/NEWS trunk/doc/ChangeLog trunk/doc/examples/gpgconf.conf trunk/doc/tools.texi trunk/g10/call-agent.c trunk/tools/ChangeLog trunk/tools/gpgconf-comp.c trunk/tools/gpgconf.c trunk/tools/gpgconf.h Log: New option --list-config for gpgconf. Modified: trunk/NEWS =================================================================== --- trunk/NEWS 2007-10-23 11:15:26 UTC (rev 4604) +++ trunk/NEWS 2007-10-23 18:13:27 UTC (rev 4605) @@ -9,7 +9,9 @@ * Enhanced gpg-connect-agent with a small scripting language. + * New option --list-config for gpgconf. + Noteworthy changes in version 2.0.7 (2007-09-10) ------------------------------------------------ Modified: trunk/doc/ChangeLog =================================================================== --- trunk/doc/ChangeLog 2007-10-23 11:15:26 UTC (rev 4604) +++ trunk/doc/ChangeLog 2007-10-23 18:13:27 UTC (rev 4605) @@ -1,3 +1,7 @@ +2007-10-23 Werner Koch + + * tools.texi (Listing global options): New. + 2007-10-19 Werner Koch * tools.texi (Controlling gpg-connect-agent): Updated. Modified: trunk/doc/examples/gpgconf.conf =================================================================== --- trunk/doc/examples/gpgconf.conf 2007-10-23 11:15:26 UTC (rev 4604) +++ trunk/doc/examples/gpgconf.conf 2007-10-23 18:13:27 UTC (rev 4605) @@ -9,8 +9,8 @@ # white space character, are ignored. The line is separated by white # space into fields. The first field is used to match the user or # group and must start at the first column, the file is processes -# sequential until a matching rle is found. A rule may contain -# several lines, continuation lines are indicated by a indenting them. +# sequential until a matching rule is found. A rule may contain +# several lines; continuation lines are indicated by a indenting them. # # Syntax of a line: # |WS