[Winpt-commits] r181 - trunk/Src

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Mar 14 12:01:38 CET 2006


Author: twoaday
Date: 2006-03-14 12:01:22 +0100 (Tue, 14 Mar 2006)
New Revision: 181

Added:
   trunk/Src/wptHTTP.cpp
   trunk/Src/wptSafeEditCtrl.cpp
Removed:
   trunk/Src/wptHTTP.c
Modified:
   trunk/Src/ChangeLog
   trunk/Src/Makefile.am
   trunk/Src/WinPT-en.rc
   trunk/Src/WinPT.cpp
   trunk/Src/resource.h
   trunk/Src/wptClipVerifyDlg.cpp
   trunk/Src/wptCommonDlg.cpp
   trunk/Src/wptGPG.cpp
   trunk/Src/wptGPGME.cpp
   trunk/Src/wptGPGPrefsDlg.cpp
   trunk/Src/wptGPGUtil.cpp
   trunk/Src/wptKeyCache.cpp
   trunk/Src/wptKeyEdit.cpp
   trunk/Src/wptKeyEditCB.cpp
   trunk/Src/wptKeyEditDlgs.cpp
   trunk/Src/wptKeyManager.cpp
   trunk/Src/wptKeyManagerDlg.cpp
   trunk/Src/wptKeyPropsDlg.cpp
   trunk/Src/wptKeylist.cpp
   trunk/Src/wptKeyserver.cpp
   trunk/Src/wptKeyserverDlg.cpp
   trunk/Src/wptKeysignDlg.cpp
   trunk/Src/wptListView.cpp
   trunk/Src/wptPassphraseCB.cpp
   trunk/Src/wptPassphraseDlg.cpp
   trunk/Src/wptPreferencesDlg.cpp
   trunk/Src/wptRegistry.cpp
   trunk/Src/wptSymEnc.cpp
   trunk/Src/wptUTF8.cpp
   trunk/Src/wptW32API.cpp
Log:
2006-03-12  Timo Schulz  <ts at g10code.de>
 
        * wptGPG.cpp (gnupg_load_config): Search for 'ask-cert-expire'.
        * wptKeyPropsDlg.cpp (display_key_info): Automatically update
        sym algorithm preferences if needed.
        * wptKeysignDlg.cpp (date_is_today): New.
        (keysign_dlg_proc): Only allow to set cert expire date if
        the option was found.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Allow to set
        'ask-cert-expire'.
         



Modified: trunk/Src/ChangeLog
===================================================================
--- trunk/Src/ChangeLog	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/ChangeLog	2006-03-14 11:01:22 UTC (rev 181)
@@ -1,3 +1,52 @@
+2006-03-12  Timo Schulz  <ts at g10code.de>
+
+	* wptGPG.cpp (gnupg_load_config): Search for 'ask-cert-expire'.
+	* wptKeyPropsDlg.cpp (display_key_info): Automatically update
+	sym algorithm preferences if needed.
+	* wptKeysignDlg.cpp (date_is_today): New.
+	(keysign_dlg_proc): Only allow to set cert expire date if
+	the option was found.
+	* wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Allow to set
+	'ask-cert-expire'.
+	
+2006-03-10  Timo Schulz  <ts at g10code.de>
+
+	* wptHTTP.c: deleted.
+	* wptHTTP.cpp (wHTTP): Transformed old code into an object.
+	* wptKeyManager.cpp (km_http_import): Use new code.
+	(km_refresh_one_key): Use preferred keyserver if possible.
+	* wptComonDlg.cpp (check_URL): Better conformance checking.
+	* wptKeyEditCB.cpp (cmd_keyserver_handler): By default
+	set keyserver for all userids.
+	* wptKeyManagerDlg.cpp (keymanager_dlg_proc): Enable code
+	to set preferred keyserver.
+	* wptKeyCache.cpp (decode_subpacket): New.
+	(gpg_keycache_update_attr): New.
+	* wptGPGUtil.cpp (gpg_find_key_subpacket): New.
+	* wptKeyEditDlgs.cpp (keyedit_set_pref_keyserver): Use
+	-1 as an index for all userids.
+	
+2006-03-07  Timo Schulz  <ts at g10code.de>
+
+	* WinPT.cpp (set_default_keyserver): New.
+	* wptKeyserver.cpp (kserver_set_socket_timeout): New.
+	(kserver_set_default_keyserver): Initialize default settings
+	if needed.
+	* wptSymEnc.cpp (gpg_encrypt_symmetric): Disallow empty passwords.
+	* wptPassphraseDlg.cpp (request_passphrase): Handle new flag.
+	(passphrase_dlg_proc): Support new safe edit window procedure.
+	* wptPassphraseCB.cpp (passphrase_callback_proc): Likewise.
+	* wptPreferencesDlg.cpp (prefs_dlg_proc): Flush passphrase cache
+	if user disable it.
+	* wptKeylist.cpp (keylist_build): Do not scale images but use
+	original size.
+	* wptListView.cpp (listview_set_image_list): New size params.
+	Change all callers.
+	
+2006-03-01  Timo Schulz  <ts at g10code.de>
+
+	* wptW32API.cpp (set_clip_text): Free all memory.
+	
 2006-02-27  Timo Schulz  <twoaday at freakmail.de>
 
 	* wptSOCKS.cpp (socks_handshake): New.

Modified: trunk/Src/Makefile.am
===================================================================
--- trunk/Src/Makefile.am	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/Makefile.am	2006-03-14 11:01:22 UTC (rev 181)
@@ -89,7 +89,7 @@
 	wptGPGME.cpp \
 	wptGPGParser.cpp \
 	wptHotkey.cpp \
-	wptHTTP.c \
+	wptHTTP.cpp \
 	wptImagelist.cpp \
 	wptImportList.cpp \
 	wptKeylist.cpp \
@@ -120,7 +120,8 @@
 	wptGPGMEData.cpp \
 	wptGroupManager.cpp \
 	wptGPGMEWrapper.cpp \
-	wptSOCKS.cpp
+	wptSOCKS.cpp \
+	wptSafeEditCtrl.cpp
 
 
 WinPT_SOURCES = $(resource_files) $(dialog_files) $(code_files)

Modified: trunk/Src/WinPT-en.rc
===================================================================
--- trunk/Src/WinPT-en.rc	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/WinPT-en.rc	2006-03-14 11:01:22 UTC (rev 181)
@@ -337,8 +337,8 @@
     CONTROL         "List1",IDC_KEYSERVER_LIST,"SysListView32",LVS_REPORT | 
                     LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | 
                     WS_BORDER | WS_TABSTOP,6,5,208,133
-    LTEXT           "HTTP proxy: none",IDC_KEYSERVER_PROXY,6,145,146,9
-    PUSHBUTTON      "C&hange",IDC_KEYSERVER_PROXSETT,168,145,46,10
+    LTEXT           "Proxy: none",IDC_KEYSERVER_PROXY,6,145,146,9
+    PUSHBUTTON      "C&hange",IDC_KEYSERVER_PROXSETT,168,142,46,13
     GROUPBOX        "",IDC_STATIC,5,157,209,36
     LTEXT           "Please enter the key ID or email address you search for",
                     IDC_KEYSERVER_INFO,8,165,199,8
@@ -476,39 +476,42 @@
     PUSHBUTTON      "&Cancel",IDCANCEL,227,188,54,15
 END
 
-IDD_WINPT_GPGPREFS DIALOG DISCARDABLE  0, 0, 222, 226
+IDD_WINPT_GPGPREFS DIALOG DISCARDABLE  0, 0, 222, 242
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "GnuPG Preferences"
 FONT 8, "MS Sans Serif"
 BEGIN
-    GROUPBOX        "",IDC_STATIC,5,4,208,67
     LTEXT           "GnuPG home directory  (where both keyrings are located)",
-                    IDC_GPGPREFS_HOMEINF,12,12,181,8
+                    IDC_GPGPREFS_HOMEINF,12,12,196,8
     EDITTEXT        IDC_GPGPREFS_HOMEDIR,12,22,152,12,ES_AUTOHSCROLL
     PUSHBUTTON      "Browse...",IDC_GPGPREFS_HOMEDLG,167,21,41,14
     LTEXT           "GnuPG exe file location (full path with added gpg.exe)",
-                    IDC_GPGPREFS_EXEINF,12,41,170,8
+                    IDC_GPGPREFS_EXEINF,12,41,192,8
     EDITTEXT        IDC_GPGPREFS_EXEDIR,12,52,152,12,ES_AUTOHSCROLL
     PUSHBUTTON      "Browse...",IDC_GPGREFS_EXEDLG,167,51,41,14
+    GROUPBOX        "",IDC_STATIC,5,4,208,67
     GROUPBOX        "",IDC_STATIC,6,76,209,37
     LTEXT           "Locale directory (to access the translation files)",
-                    IDC_GPGPREFS_LOCALINF,12,85,148,8
+                    IDC_GPGPREFS_LOCALINF,12,85,180,8
     EDITTEXT        IDC_GPGPREFS_LOCALE,12,96,152,12,ES_AUTOHSCROLL
     PUSHBUTTON      "Browse...",IDC_GPGPREFS_LOCDLG,167,95,41,14
     CONTROL         "&Overwrite default settings",IDC_GPGPREFS_OVRDEFAULT,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,115,121,10
     GROUPBOX        "General GPG options",IDC_GPGPREFS_ALLOPTINF,5,130,210,
-                    74
+                    86
     CONTROL         "Ask for the signature class during key sign",
                     IDC_GPGPREFS_ASKLEVEL,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,11,144,166,10
-    LTEXT           "Comment in armored files",IDC_GPGPREFS_CMTINF,11,157,
+                    WS_TABSTOP,11,144,189,10
+    CONTROL         "Allow to set an expiration date for signatures",
+                    IDC_GPGPREFS_ASKEXPIRE,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,11,156,188,9
+    LTEXT           "Comment in armored files",IDC_GPGPREFS_CMTINF,11,170,
                     124,8
-    EDITTEXT        IDC_GPGPREFS_COMMENT,11,168,188,12,ES_AUTOHSCROLL
-    LTEXT           "Encrypt to this key",IDC_GPGPREFS_ENCINF,11,187,66,8
-    EDITTEXT        IDC_GPGPREFS_ENCTO,78,185,121,13,ES_AUTOHSCROLL
-    PUSHBUTTON      "&OK",IDC_GPGPREFS_SAVE,101,207,55,14
-    PUSHBUTTON      "&Cancel",IDCANCEL,159,206,55,14
+    EDITTEXT        IDC_GPGPREFS_COMMENT,11,181,188,12,ES_AUTOHSCROLL
+    LTEXT           "Encrypt to this key",IDC_GPGPREFS_ENCINF,11,200,66,8
+    EDITTEXT        IDC_GPGPREFS_ENCTO,78,198,121,13,ES_AUTOHSCROLL
+    PUSHBUTTON      "&OK",IDC_GPGPREFS_SAVE,101,223,55,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,159,223,55,14
 END
 
 IDD_WINPT_IMPORT DIALOG DISCARDABLE  0, 0, 321, 118
@@ -1513,7 +1516,7 @@
         LEFTMARGIN, 3
         RIGHTMARGIN, 215
         TOPMARGIN, 4
-        BOTTOMMARGIN, 221
+        BOTTOMMARGIN, 237
     END
 
     IDD_WINPT_IMPORT, DIALOG
@@ -2182,7 +2185,7 @@
         MENUITEM "&Disable",                    ID_KEYCTX_DISABLE
         MENUITEM "Set Implicit &Trust",         ID_KEYCTX_MAXTRUST, GRAYED
         MENUITEM SEPARATOR
-        MENUITEM "Set preferred Keyserver URL", ID_KEYCTX_SETPREFKS, GRAYED
+        MENUITEM "Set preferred Keyserver",     ID_KEYCTX_SETPREFKS
         MENUITEM "Re&fresh from Keyserver",     ID_KEYCTX_RECVFROM
         POPUP "Send to Keyserver"
         BEGIN

Modified: trunk/Src/WinPT.cpp
===================================================================
--- trunk/Src/WinPT.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/WinPT.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -70,7 +70,8 @@
 /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
 void
 gpg_set_debug_mode (int val)
-{	
+{
+    /* XXX: create the file in $user\$temp */
     if (val)
 	putenv ("GPGME_DEBUG=5:gpgme.dbg");
     else
@@ -376,6 +377,25 @@
 }
 
 
+void
+set_default_keyserver (void)
+{
+    char *host = get_reg_entry_keyserver ("Default");
+    char *str_port = get_reg_entry_keyserver ("Default_Port");
+    WORD port = HKP_PORT;
+
+    if (!host)
+	keyserver_set_default (NULL, 0);
+    else {
+	if (str_port && *str_port)
+	    port = atoi (str_port);
+	keyserver_set_default (host, port);
+    }
+    free_if_alloc (host);
+    free_if_alloc (str_port);
+}
+
+
 /* Main entry point. */
 int WINAPI
 WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
@@ -451,7 +471,7 @@
 	mobile = 1;
     }
 
-    set_default_kserver ();
+    set_default_keyserver ();
     load_gettext (winpt_inst_found);
 
     if (!mobile) {

Modified: trunk/Src/resource.h
===================================================================
--- trunk/Src/resource.h	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/resource.h	2006-03-14 11:01:22 UTC (rev 181)
@@ -641,6 +641,7 @@
 #define IDC_PROXY_PROTOINF              1516
 #define IDC_PROXY_PROTO                 1517
 #define IDC_PROXY_AUTHINF               1518
+#define IDC_GPGPREFS_ASKEXPIRE          1520
 #define ID_GPG_ENCRYPT                  40003
 #define ID_GPG_DECRYPT                  40004
 #define ID_GPG_SIGN                     40005
@@ -821,7 +822,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        245
 #define _APS_NEXT_COMMAND_VALUE         40186
-#define _APS_NEXT_CONTROL_VALUE         1519
+#define _APS_NEXT_CONTROL_VALUE         1521
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

Modified: trunk/Src/wptClipVerifyDlg.cpp
===================================================================
--- trunk/Src/wptClipVerifyDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptClipVerifyDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -149,7 +149,7 @@
     gpg_keycache_t kc = NULL;
     gpgme_ctx_t c=NULL;
     const char *det_data=NULL;
-    u16 port = HKP_PORT;
+    WORD port = HKP_PORT;
     int rc = 0, det_len=0;
     
     switch( msg ) {

Modified: trunk/Src/wptCommonDlg.cpp
===================================================================
--- trunk/Src/wptCommonDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptCommonDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -1,5 +1,5 @@
 /* wptCommonDlg.cpp
- *	Copyright (C) 2004, 2005 Timo Schulz
+ *	Copyright (C) 2004, 2005, 2006 Timo Schulz
  *
  * This file is part of WinPT.
  *
@@ -22,6 +22,7 @@
 #endif
 
 #include <windows.h>
+#include <ctype.h>
 
 #include "resource.h"
 
@@ -37,11 +38,25 @@
 static int
 check_URL (const char *buf)
 {
-    /* XXX: be more strict */
+    size_t i;
+    const char *allowed = "-./#_:";
+
+    if (strncmp (buf, "http://", 7))
+	return -1;
     if (!strchr (buf, ':'))
 	return -1;
     if (!strstr (buf, "//"))
 	return -1;
+    if (strstr (buf, " "))
+	return -1;
+    buf += 7;
+    for (i=0; i < strlen (buf); i++) {
+	if (isalpha (buf[i]) || isdigit (buf[i]))
+	    continue;
+	if (!strchr (allowed, buf[i]))
+	    return -1;
+    }
+
     return 0;
 }
 
@@ -59,12 +74,8 @@
 	    BUG (0);
 	if (ctx->desc != NULL)
 	    SetWindowText (dlg, ctx->desc);
-	else
-	    SetWindowText (dlg, _("HTTP Key Import"));
 	if (ctx->title != NULL)
 	    SetDlgItemText (dlg, IDC_HTTP_TITLE, ctx->title);
-	else
-	    SetDlgItemText (dlg, IDC_HTTP_TITLE, _("Enter URL to retrieve the public key"));
 	SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
 	SetForegroundWindow (dlg);
 	break;
@@ -103,7 +114,9 @@
     if (!ctx)
 	BUG (0);
     memset (ctx, 0, sizeof *ctx);
-    ctx->check = 1;	
+    ctx->check = 1;
+    ctx->desc = _("HTTP Key Import");
+    ctx->title = _("Enter URL to retrieve the public key");
     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_HTTP, root,
 		    http_dlg_proc, (LPARAM)ctx);
     return ctx;

Modified: trunk/Src/wptGPG.cpp
===================================================================
--- trunk/Src/wptGPG.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptGPG.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -243,6 +243,9 @@
     o = find_option (opt, "ask-cert-level");
     if (o)
 	reg_prefs.gpg.ask_cert_level = 1;
+    o = find_option (opt, "ask-cert-expire");
+    if (o)
+	reg_prefs.gpg.ask_cert_expire = 1;
     release_gpg_options (opt);
     free_if_alloc (conf);
     return 0;

Modified: trunk/Src/wptGPGME.cpp
===================================================================
--- trunk/Src/wptGPGME.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptGPGME.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -123,10 +123,10 @@
     p = get_reg_entry (HKEY_CURRENT_USER, "Software\\WinPT", "nKeys");
     if (p && *p != ' ') {
 	val = atoi (p);
-	free_if_alloc (p);
-	memset (&pfx, 0, sizeof (pfx));
+	free_if_alloc (p);	
     }
 
+    memset (&pfx, 0, sizeof (pfx));
     /* Release old contexts first. */
     keycache_release (0);
 
@@ -141,7 +141,7 @@
     if (!err)
 	err = gpg_keycache_init (sec, NULL, 1);
     if (!err && pubring && *pubring)
-	err = gpg_keycache_prepare( pub, pubring, NULL);
+	err = gpg_keycache_prepare (pub, pubring, NULL);
     if (!err && secring && * secring)
 	err = gpg_keycache_prepare (sec, NULL, secring);
     if (!err)
@@ -177,7 +177,7 @@
 	*r_key = NULL;
     cache = keycache_get_ctx (mode);
     if (!cache)
-	BUG( NULL );
+	BUG (0);
     if (!c)
 	err = gpg_keycache_find_key (cache, keyid, 0, r_key);
     else

Modified: trunk/Src/wptGPGPrefsDlg.cpp
===================================================================
--- trunk/Src/wptGPGPrefsDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptGPGPrefsDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -146,6 +146,7 @@
         SetDlgItemText ( dlg, IDC_GPGPREFS_LOCALINF,
                         _("Locale directory (to access the translation files)"));
 	SetDlgItemText (dlg, IDC_GPGPREFS_ASKLEVEL, _("Ask for the signature class during key sign"));
+	SetDlgItemText (dlg, IDC_GPGPREFS_ASKEXPIRE, _("Allow to set an expiration date for signatures"));
 	SetDlgItemText (dlg, IDC_GPGPREFS_CMTINF, _("Comment in armored files"));
 	SetDlgItemText (dlg, IDC_GPGPREFS_ENCINF, _("Encrypt to this key"));
 	SetDlgItemText (dlg, IDC_GPGPREFS_ALLOPTINF, _("General GPG options"));
@@ -166,6 +167,8 @@
 	    parse_gpg_options (p, &opt);
 	    free_if_alloc (p);
 	    if (opt) {
+		if (find_option (opt, "ask-cert-expire"))
+		    CheckDlgButton (dlg, IDC_GPGPREFS_ASKEXPIRE, BST_CHECKED);
 		if (find_option (opt, "ask-cert-level"))
 		    CheckDlgButton (dlg, IDC_GPGPREFS_ASKLEVEL, BST_CHECKED);
 		e = find_option (opt, "comment");
@@ -271,6 +274,15 @@
 		delete_option (opt, "ask-cert-level");
 		reg_prefs.gpg.ask_cert_level = 0;
 	    }
+	    if (IsDlgButtonChecked (dlg, IDC_GPGPREFS_ASKEXPIRE)) {
+		modify_entry (opt, ENTRY_SINGLE, "ask-cert-expire", NULL);
+		reg_prefs.gpg.ask_cert_expire = 1;
+	    }
+	    else {
+		delete_option (opt, "ask-cert-expire");
+		reg_prefs.gpg.ask_cert_expire = 0;
+	    }
+
 	    n = GetDlgItemText(dlg, IDC_GPGPREFS_COMMENT, t, sizeof t - 1);
             if (n > 0)
 		modify_entry (opt, ENTRY_MULTI, "comment", t);

Modified: trunk/Src/wptGPGUtil.cpp
===================================================================
--- trunk/Src/wptGPGUtil.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptGPGUtil.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -773,7 +773,7 @@
 	case PKT_SECRET_KEY:
 	    quit = 1;
 	    break;
-	    
+
 	default:
 	    break;
 	}
@@ -804,3 +804,44 @@
 	err = file_extract_recipient (file, r_list);
     return err;
 }
+
+
+/* Try to find a subpacket with the given id @subpktid
+   inside the key @key.
+   Return value: 0 on success. */
+gpgme_error_t
+gpg_find_key_subpacket (const char *key, int subpktid,
+			char **value)
+{
+    gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
+    const char *fmt;
+    const char *spk;
+    char *p, *cmd;
+    HANDLE out;
+
+    *value = NULL;
+    p = read_gpg_program ();
+    fmt = "%s --with-colons --list-options show-sig-subpackets=%d --list-sigs %s";
+    cmd = (char*)calloc (1, strlen (fmt) + strlen (p) + strlen (key) + 32 + 1);
+    sprintf (cmd, fmt, p, subpktid, key);
+
+    out = create_tmpfile ("gpg_subpackets");
+    if (create_process (cmd, NULL, out, NULL))
+	err = gpg_error (GPG_ERR_INTERNAL);
+
+    free (p);
+    free (cmd);
+
+    p = map_tmpfile (out, NULL);
+    if (p && (spk=strstr (p, "spk"))) {
+	char *end = strstr (spk, "\n");
+	if (end) {
+	    *value = (char*)calloc (1, (end-spk)+1);
+	    memcpy (*value, spk, (end-spk)-1);
+	}
+    }
+
+    free (p);
+    CloseHandle (out);
+    return err;
+}

Deleted: trunk/Src/wptHTTP.c
===================================================================
--- trunk/Src/wptHTTP.c	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptHTTP.c	2006-03-14 11:01:22 UTC (rev 181)
@@ -1,496 +0,0 @@
-/* wptHTTP.c - Generic HTTP support
- *	Copyright (C) 2004, 2005 Timo Schulz
- *
- * This file is part of WinPT.
- *
- * WinPT 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.
- *  
- * WinPT 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 WinPT; if not, write to the Free Software Foundation, 
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <windows.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "wptHTTP.h"
-#include "wptTypes.h"
-#include "wptErrors.h"
-
-
-static int parse_headers (int fd, http_head_t *r_head);
-
-
-static int
-http_head_new (http_head_t * head, const char * val)
-{
-    http_head_t h;
-    
-    h = calloc (1, sizeof *h + strlen (val) + 1);
-    if (!h)
-	BUG (0);
-    strcpy (h->d, val);
-    *head = h;
-    return 0;
-}
-
-
-static void
-http_head_free (http_head_t head)
-{
-    http_head_t h;
-    
-    while (head) {
-	h = head->next;
-	free (head);
-	head = h;
-    }
-}
-
-
-static void
-http_head_add (http_head_t root, http_head_t node)
-{
-    http_head_t n;
-    
-    for (n = root; n->next; n=n->next)
-	;
-    n->next = node;
-}
-
-
-static http_head_t
-http_head_find (http_head_t root, const char * name,
-                const char ** val)
-{
-    http_head_t n;
-    
-    for (n = root; n; n = n->next) {
-	if (strlen (n->d) >= strlen (name) &&
-	    !strncmp (n->d, name, strlen (name))) {
-            *val = n->d + strlen (name);
-	    return n;
-        }
-    }
-    return NULL;
-}
-
-
-static int
-http_connect (const char * host, int port, int * r_fd)
-{
-    struct hostent * hp;
-    struct sockaddr_in srv;
-    unsigned long addr = 0;
-    int i = 1;
-    int fd;
-    
-    *r_fd = 0;
-    memset (&srv, 0, sizeof srv);
-    srv.sin_port = htons ((unsigned short)port);
-    srv.sin_family = AF_INET;
-    
-    if (isalpha (*host)) {
-	hp = gethostbyname (host);
-	if (hp == NULL)
-	    return WPTERR_WINSOCK_CONNECT;
-	memcpy (&srv.sin_addr, hp->h_addr, hp->h_length);
-    }
-    else {
-	addr = inet_addr (host);
-	if (addr == -1)
-	    return WPTERR_WINSOCK_CONNECT;
-	memcpy (&srv.sin_addr, &addr, sizeof addr);
-    }
-	    
-    fd = socket (AF_INET, SOCK_STREAM, 0);
-    if (fd < 0)
-	return WPTERR_WINSOCK_SOCKET;
-
-    if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&i, sizeof i)) {
-	closesocket (fd);
-	return WPTERR_WINSOCK_SOCKET;
-    }
-    
-    if (connect (fd, (struct sockaddr *)&srv, sizeof srv)) {
-	closesocket (fd);
-	return WPTERR_WINSOCK_CONNECT;
-    }
-    
-    *r_fd = fd;
-    return 0;
-}
-
-
-static int
-http_close (int fd)
-{
-    closesocket (fd);
-    return 0;
-}
-
-
-static int
-http_data_avail (int fd)
-{
-    struct timeval tv;
-    fd_set inp;
-    int n;
-
-    FD_ZERO (&inp);
-    FD_SET (fd, &inp);
-    tv.tv_sec = 1;
-    tv.tv_usec = 0;
-
-    n = select (fd+1, &inp, NULL, NULL, &tv);
-    if (n && FD_ISSET (fd, &inp))
-        return n;
-    return 0;
-}
-
-
-static int
-http_read_line (int fd, char * buf, size_t nbuf,
-                int nonblock, int * nn, int * eof)
-{
-    char c;
-    int n, i;
-    
-    if (nn)
-	*nn = 0;
-    if (eof)
-        *eof = 0;
-    i = 0;
-    do {
-        if (nonblock == 1 && http_data_avail (fd) == 0) {
-            buf[i++] = '\0';
-            i = -1;
-            break;
-        }
-	n = recv (fd, &c, 1, 0);
-	if (n == -1)
-	    break;
-	if (n == 0 || nbuf == 0 || c == '\n') {
-	    if (n == 0) {
-                if (eof)
-                    *eof = 1;
-                buf[i++] = '\0';
-	    }
-            else {
-                buf[i++] = c;
-                buf[i] = '\0';
-            }
-            break;
-	}
-        else {
-            buf[i++] = c;
-            nbuf--;
-        }
-    } while (n > 0 && i != -1);
-    
-    if (nn)
-	*nn = i;
-    return 0;
-}
-
-
-static int
-http_send_req (int fd, const char * host, const char * url)
-{
-    char * p;
-    int n;
-    
-    if (*url == '/')
-    	url++;
-    if (url == NULL)
-    	url = "";
-    p = malloc (strlen (url) + strlen (host) + 64);
-    if (p == NULL)
-	BUG (0);
-    sprintf (p, "GET /%s HTTP/1.1\r\n"
-	        "Host: %s\r\n"
-	        "\r\n"
-	        "\r\n",
-	     url, host);
-    n = send (fd, p, strlen (p), 0);
-    free (p);
-    if (n == -1)
-	return SOCKET_ERROR;
-    return 0;
-}
-
-
-int
-http_send_request2 (const char * url, http_hd_t * r_hd)
-{
-    http_hd_t hd;
-    char * host = NULL, * p;
-    char tmpbuf[512];
-    int rc;
-
-    memset (tmpbuf, 0, 512);
-    strncpy (tmpbuf, url, 512);
-    
-    if (strlen (url) < 10 || strncmp (url, "http://", 7))
-        return WPTERR_GENERAL;
-    url += 7;
-    p = strtok (tmpbuf+7, "/");
-    if (p == NULL)
-        return WPTERR_GENERAL;
-    host = strdup (p);
-    if (host == NULL)
-        BUG (0);
-    p = strchr (url, '/');
-    if (p == NULL) {
-        free (host);
-        return WPTERR_GENERAL;
-    }
-    rc = http_send_request (host, 80, p+1, &hd);
-    *r_hd = hd;
-    free (host);
-    return rc;
-}
-
-
-int
-http_send_request (const char * host, int port, const char * url,
-                   http_hd_t * r_hd)
-{
-    http_hd_t hd;
-    int rc;
-
-    http_hd_new (&hd);
-    rc = http_connect (host, port, &hd->fd);
-    if (!rc)
-        rc = http_send_req (hd->fd, host, url);
-    if (r_hd)
-        *r_hd = hd;
-    else
-        http_hd_free (hd);
-    return rc;
-}
-
-
-int
-http_req_new (http_req_t * ctx)
-{
-    http_req_t c;
-    c = calloc (1, sizeof * c);
-    if (c == NULL)
-        BUG (0);
-    *ctx = c;
-    return 0;
-}
-
-
-void
-http_req_free (http_req_t ctx)
-{
-    if (!ctx)
-        return;
-    http_head_free (ctx->head);
-    if (ctx->url)
-        free (ctx->url);
-    free (ctx);
-}
-
-
-static int
-parse_statline (const char * buf, int * code)
-{
-    int tmp = 0;
-    
-    if (strlen (buf) < 8 ||
-        (strncmp (buf, "HTTP/1.", 7)))
-	return WPTERR_GENERAL;
-    buf += 8; /* skip HTTP/1.x */
-    buf++;    /* white space */
-    tmp = atoi (buf);
-    if (tmp == 0)
-	return WPTERR_GENERAL;
-    *code = tmp;
-    buf += 3;
-    buf++; /* whitespace */
-    return 0;
-}
-
-
-static int
-parse_headers (int fd, http_head_t * r_head)
-{
-    http_head_t h, head = NULL;
-    char buf[300];
-    int nn;
-    int rc;
-    
-    do  {
-	rc = http_read_line (fd, buf, 299, 1, &nn, NULL);
-	if (rc)
-	    return rc;
-	if (nn == 2)
-	    break; /* reach empty line */
-	http_head_new (&h, buf);
-	if (head == NULL)
-	    head = h;
-	else
-	    http_head_add (head, h);
-    } while (rc == 0);
-    if (r_head)
-        *r_head = head;
-    else
-        http_head_free (head);
-    return 0;
-}
-
-
-static int
-read_binary (int fd, int nlen, FILE * out)
-{
-    char buf[1024+1];
-    int n;
-
-    do
-    {
-        n = recv (fd, buf, nlen > 1024? 1024 : nlen, 0);
-        if (n == -1)
-	    return SOCKET_ERROR;
-        if (n == 0)
-            break;
-        nlen -= n;
-        fwrite (buf, 1, n, out);
-    } while (nlen > 0);
-    return 0;
-}
-
-
-static int
-parse_data (int fd, http_head_t head, FILE * out)
-{
-    http_head_t h;
-    const char * s = "Content-Length: ", * val;
-    char buf[1024+1];
-    int nlen = 0, nn = 0, n, eof=0;
-    int rc;
-    
-    h = http_head_find (head, s, &val);
-    if (h)
-	nlen = atoi (val);
-    else {
-        h = http_head_find (head, "Connection: ", &val);
-        if (h == NULL || strncmp (val, "close", 4))
-            return WPTERR_GENERAL;
-    }
-
-    h = http_head_find (head, "Content-Type: ", &val);
-    if (h == NULL)
-        return WPTERR_GENERAL;
-    if (strncmp (val, "text", 4))
-        return read_binary (fd, nlen, out);
-    
-    do {
-	rc = http_read_line (fd, buf, 1024, 1, &n, &eof);
-	if (rc)
-	    return rc;
-	if (n > 0)
-	    fwrite (buf, 1, n, out);
-        if (nlen > 0) {
-            nn += n;
-            if (nlen == nn)
-                break;
-        }
-    } while (eof == 0);
-    return 0;
-}
-
-
-static int
-check_status (int code, int * statcode)
-{
-    if (code != HTTP_STAT_200) {
-        if (statcode)
-            *statcode = code;
-        if (code == HTTP_STAT_400 ||
-            code == HTTP_STAT_403 ||
-            code == HTTP_STAT_404 ||
-            code == HTTP_STAT_405)
-            return WPTERR_GENERAL;
-    }
-    return 0;
-}
-
-
-int
-http_parse_response (http_hd_t hd, int * statcode)
-{
-    char buf[300];
-    int rc;
-    int code = 0, nn = 0;
-
-    if (statcode)
-        *statcode = 0;
-    rc = http_read_line (hd->fd, buf, 299, 1, &nn, NULL);
-    if (rc)
-	return rc;
-    rc = parse_statline (buf, &code);
-    if (rc)
-	return rc;
-    rc = check_status (code, statcode);
-    if (rc)
-        return rc;
-    rc = parse_headers (hd->fd, &hd->head);
-    if (rc)
-	return rc;
-    return 0;
-}
-
-
-int
-http_parse_data (http_hd_t hd, FILE * out)
-{
-    int rc = 0;
-    rc = parse_data (hd->fd, hd->head, out);
-    http_close (hd->fd);    
-    return rc;
-}
-
-
-int
-http_hd_new (http_hd_t * r_hd)
-{
-    http_hd_t hd;
-
-    if (!r_hd)
-        return -1;
-    hd = calloc (1, sizeof * hd);
-    if (hd == NULL)
-        abort ();
-    *r_hd = hd;
-    return 0;
-}
-
-
-void
-http_hd_free (http_hd_t hd)
-{
-    if (!hd)
-        return;
-    http_head_free (hd->head);
-    http_close (hd->fd);
-    free (hd);
-}

Added: trunk/Src/wptHTTP.cpp
===================================================================
--- trunk/Src/wptHTTP.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptHTTP.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -0,0 +1,592 @@
+/* wptHTTP.cpp - Generic HTTP support
+ *      Copyright (C) 2004, 2005, 2006 Timo Schulz
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT 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.
+ *  
+ * WinPT 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 WinPT; if not, write to the Free Software Foundation, 
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "wptHTTP.h"
+#include "wptTypes.h"
+#include "wptErrors.h"
+
+#define free_if_malloc(buf) if ((buf)) { free ((buf)); (buf) = NULL; }
+
+/* Empty constructur to allow advanced requests. */
+wHTTP::wHTTP (void)
+{
+    reset ();
+}
+
+
+/* Constructur to allow alternative syntax. */
+wHTTP::wHTTP (const char *_host, int _port, const char *_url)
+{
+    reset ();
+    this->host = strdup (_host);
+    this->port = _port;
+    this->url = strdup (_url);
+    if (!sendRequest (_host, _port, _url))
+	parseResponse (&statcode);
+
+}
+
+
+/* Standard constructur. */
+wHTTP::wHTTP (const char *_url)
+{
+    reset ();
+    extractHostInfo (_url, &this->host, &this->url);
+    /* XXX: if the connection fails, return the error code to the user. */
+    if (!sendRequest (this->host, this->port, this->url))
+	parseResponse (&statcode);
+}
+
+
+/* Reset object contents for first use. */
+void
+wHTTP::reset (void)
+{
+    ver = 1;
+    port = 80;
+    host = url = NULL;
+    req_headers = resp_headers = NULL;
+    fd = statcode = 0;
+    method = HTTP_GET;
+    nleft = -1;
+}
+
+
+/* Perform a HTTP 'HEAD' request. */
+int
+wHTTP::head (const char *_url)
+{
+    free_if_malloc (host);
+    free_if_malloc (url);
+
+    extractHostInfo (_url, &this->host, &this->url);
+    method = HTTP_HEAD;
+
+    if (!sendRequest (host, port, url))
+	parseResponse (&statcode);
+
+    return 0;
+}
+
+
+/* Perform a HTTP 'GET' request. */
+int
+wHTTP::get (const char *_url)
+{
+    free_if_malloc (host);
+    free_if_alloc (url);
+
+    extractHostInfo (_url, &this->host, &this->url);
+
+    method = HTTP_GET;
+    if (!sendRequest (this->host, this->port, this->url))
+	parseResponse (&statcode);
+
+    return 0;
+}
+
+
+/* Return HTTP status code. */
+int 
+wHTTP::getStatusCode (void)
+{
+    return statcode;
+}
+
+
+/* Return MIME content type. */
+const char*
+wHTTP::getContentType (void)
+{
+    const char *type = NULL;
+
+    findHeader (resp_headers, "Content-Type", &type);
+    return type;
+}
+
+
+/* Return content length. */
+unsigned int
+wHTTP::getContentLength (void)
+{
+    const char *len = NULL;
+
+    if (findHeader (resp_headers, "Content-Length", &len))
+	return strtoul (len, NULL, 10);
+    return 0;
+}
+
+
+void
+wHTTP::addHeader (http_head_t *root, const char *val)
+{
+    http_head_t n, t;
+    
+    t = (http_head_t)calloc (1, sizeof *t+strlen (val)+2);
+    if (!t)
+	BUG (0);
+    strcpy (t->d, val);
+
+    if (!*root)
+	*root = t;
+    else {
+	for (n = *root; n->next; n=n->next)
+	    ;
+	n->next = t;
+    }
+}
+
+
+bool
+wHTTP::findHeader (http_head_t root, 
+		   const char *name, const char **val)
+{
+    http_head_t n;
+    char *p;
+    
+    *val = NULL;
+    for (n = root; n; n = n->next) {
+	if (strlen (n->d) >= strlen (name) &&
+	    strstr (n->d, name)) {
+	    p = strchr (n->d, ':');
+            *val = p? n->d + (p - n->d + 1 + 1) : NULL;
+	    return true;
+        }
+    }
+    return false;
+}
+
+
+int
+wHTTP::connect (const char *_host, int _port)
+{
+    struct hostent *hp;
+    struct sockaddr_in srv;
+    unsigned long addr = 0;
+    int i = 1;
+
+    memset (&srv, 0, sizeof srv);
+    srv.sin_port = htons ((unsigned short)_port);
+    srv.sin_family = AF_INET;
+    
+    if (isalpha (*_host)) {
+	hp = gethostbyname (_host);
+	if (!hp)
+	    return WPTERR_WINSOCK_CONNECT;
+	memcpy (&srv.sin_addr, hp->h_addr, hp->h_length);
+    }
+    else {
+	addr = inet_addr (_host);
+	if (addr == INADDR_NONE)
+	    return WPTERR_WINSOCK_CONNECT;
+	memcpy (&srv.sin_addr, &addr, sizeof addr);
+    }
+	    
+    fd = socket (AF_INET, SOCK_STREAM, 0);
+    if (fd < 0)
+	return WPTERR_WINSOCK_SOCKET;
+
+    if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, 
+		    (const char*)&i, sizeof i)) {
+	closesocket (fd);
+	fd = 0;
+	return WPTERR_WINSOCK_SOCKET;
+    }
+    
+    if (::connect (fd, (struct sockaddr *)&srv, sizeof srv)) {
+	closesocket (fd);
+	fd = 0;
+	return WPTERR_WINSOCK_CONNECT;
+    }
+
+    return 0;
+}
+
+
+int
+wHTTP::isDataAvailable (int _fd)
+{
+    struct timeval tv;
+    fd_set inp;
+    int n;
+
+    FD_ZERO (&inp);
+    FD_SET (_fd, &inp);
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+
+    n = select (_fd+1, &inp, NULL, NULL, &tv);
+    if (n && FD_ISSET (_fd, &inp))
+        return n;
+    return 0;
+}
+
+
+int
+wHTTP::readLine (char *buf, unsigned int nbuf,
+                 int nonblock, int *nn, int *eof)
+{
+    char c;
+    int n, i;
+    
+    if (nn)
+	*nn = 0;
+    if (eof)
+        *eof = 0;
+    i = 0;
+    do {
+        if (nonblock == 1 && isDataAvailable (fd) == 0) {
+            buf[i++] = '\0';
+            i = -1;
+            break;
+        }
+	n = recv (fd, &c, 1, 0);
+	if (n == -1)
+	    break;
+	if (n == 0 || nbuf == 0 || c == '\n') {
+	    if (n == 0) {
+                if (eof)
+                    *eof = 1;
+                buf[i++] = '\0';
+	    }
+            else {
+                buf[i++] = c;
+                buf[i] = '\0';
+            }
+            break;
+	}
+        else {
+            buf[i++] = c;
+            nbuf--;
+        }
+    } while (n > 0 && i != -1);
+    
+    if (nn)
+	*nn = i;
+    return 0;
+}
+
+
+
+/* Extract the host from the given url @url. Return the host in
+   @host and also return the resource part of the url in @new_url. */
+int
+wHTTP::extractHostInfo (const char *_url, char **_host, char **new_url)
+{
+    char *p;
+    char tmpbuf[512];
+
+    *_host = NULL;
+    *new_url = NULL;
+
+    /* XXX: do not use static buffers. */
+    memset (tmpbuf, 0, sizeof (tmpbuf));
+    strncpy (tmpbuf, _url, 512);
+    
+    p = "http://";
+    if (strlen (_url) < 10 || strncmp (_url, p, 7))
+        return WPTERR_GENERAL;
+    _url += strlen (p);
+    p = strtok (tmpbuf+7, "/");
+    if (!p)
+        return WPTERR_GENERAL;
+    *_host = strdup (p);
+    p = strchr (_url, '/');
+    if (!p) {
+	free_if_malloc (*_host);
+        return WPTERR_GENERAL;
+    }
+    *new_url = strdup (p);
+    return 0;
+}
+
+
+/* Add a request header. */
+int 
+wHTTP::addRequestHeader (const char *name, const char *val)
+{
+    char *p;
+    char *fmt = "%s: %s";
+
+    p = (char*) malloc (strlen (name)+strlen (val)+strlen (fmt)+1);
+    sprintf (p, fmt, name, val);
+    addHeader (&req_headers, p);
+    free_if_malloc (p);
+
+    return 0;
+}
+
+
+void 
+wHTTP::setVersion (int _ver)
+{
+    if (_ver > 9)
+	_ver = 0;
+    this->ver = _ver;
+}
+
+
+int
+wHTTP::addRequestHeader (const char *name, unsigned int val)
+{
+    char buf[32];
+
+    sprintf (buf, "%lu", (DWORD)val);
+    return addRequestHeader (name, buf);
+}
+
+
+/* Prepare the request resource @url and send 
+   it to host @host (port @port). */
+int
+wHTTP::sendRequest (const char *_host, int _port, const char *_url)
+{
+    const char *id[] = {"GET", "HEAD", "PUT", "POST"};
+    http_head_t h;
+    const char *h_head;
+    char *p;
+    int n;
+    int rc;
+
+    if (!this->fd) {
+	rc = connect (_host, _port);
+	if (rc)
+	    return rc;
+    }
+
+    if (*_url == '/')
+    	url++;
+    if (_url == NULL)
+    	_url = "";
+
+    addRequestHeader ("Host", _host);
+    if (ver < 1)
+	addRequestHeader ("Connection", "close");
+
+    n = 0;
+    for (h = req_headers; h; h = h->next)
+	n += strlen (h->d) + 2 + 1;
+
+    h_head = "%s /%s HTTP/1.%d\r\n";
+    p = (char*)calloc (1, strlen (id[method]) + strlen (h_head)
+			  + strlen (url) + n + 2 + 1 + 4);
+    if (!p)
+	BUG (0);
+    sprintf (p, h_head, id[method], url, ver);
+    for (h = req_headers; h; h = h->next) {
+	strcat (p, h->d);
+	strcat (p, "\r\n");
+    }
+    strcat (p, "\r\n");
+    printf ("p='%s'\n", p);
+    n = send (fd, p, strlen (p), 0);
+    free_if_malloc (p);
+    return n > 0? 0 : WPTERR_GENERAL;
+}
+
+
+/* Parse all response resp_headers. */
+int
+wHTTP::parseHeaders (http_head_t *r_head)
+{
+    char buf[300];
+    int nn;
+    int rc;
+    
+    if (!r_head)
+	return WPTERR_GENERAL;
+
+    do  {
+	rc = readLine (buf, 299, 1, &nn, NULL);
+	if (rc)
+	    return rc;
+	if (nn == 2)
+	    break; /* reach empty line */
+	addHeader (r_head, buf);
+    } while (rc == 0);
+    return 0;
+}
+
+
+/* Read data from the response and write it to @out. */
+int
+wHTTP::readData (FILE *out)
+{
+    const char *val;
+    char buf[1024+1];
+    int nlen = 0, nn = 0, n, eof=0;
+    int rc = 0;
+    
+    if (this->fd == 0 || this->resp_headers == NULL)
+	return -1;
+
+    nlen = getContentLength ();
+    if (nlen == 0) {
+        if (!findHeader (resp_headers, "Connection", &val) ||
+	    strnicmp (val, "close", 4))
+            return WPTERR_GENERAL;
+    }
+
+    val = getContentType ();
+    if (!val)
+        return WPTERR_GENERAL;
+    if (strnicmp (val, "text", 4)) { /* binary */
+	do {
+	    n = recv (fd, buf, nlen > 1024? 1024 : nlen, 0);
+	    if (n == -1)
+		return SOCKET_ERROR;
+	    if (n == 0)
+		break;
+	    nlen -= n;
+	    fwrite (buf, 1, n, out);
+	} while (nlen > 0);
+	return 0;
+    }
+
+    do {
+	rc = readLine (buf, 1024, 1, &n, &eof);
+	if (rc)
+	    return rc;
+	if (n > 0)
+	    fwrite (buf, 1, n, out);
+        if (nlen > 0) {
+            nn += n;
+            if (nlen == nn)
+                break;
+        }
+    } while (eof == 0);
+
+    return 0;
+}
+
+
+/* Parse the HTTP response line. */
+int
+wHTTP::parseResponse (int *_statcode)
+{
+    http_head_t n;
+    const char *tmp, *p;
+    char buf[300];
+    int code = 0, nn = 0;
+    int rc;
+
+    *_statcode = 0;
+    rc = readLine (buf, 299, 1, &nn, NULL);
+    if (rc)
+	return rc;
+
+    tmp = "HTTP/1.";
+    if (strlen (buf) < 8 || strncmp (buf, tmp, strlen (tmp)))
+	return WPTERR_GENERAL;
+    p = buf;
+    p += strlen (tmp)+1 + 1; /* skip HTTP/1.x and WS */
+    *_statcode = atoi (p);
+    if (tmp == 0)
+	return WPTERR_GENERAL;
+    p += 3 + 1; /* number + WS */
+
+    if (code == HTTP_STAT_400 ||            
+	code == HTTP_STAT_403 ||
+	code == HTTP_STAT_404 ||
+	code == HTTP_STAT_405)
+	return WPTERR_GENERAL;
+
+    while (resp_headers) {
+	n = resp_headers->next;
+	free (resp_headers);
+	resp_headers = n;
+    }
+    resp_headers = NULL;
+    rc = parseHeaders (&resp_headers);
+    if (rc)
+	return rc;
+    return 0;
+}
+
+
+/* Destroy HTTP object. */
+wHTTP::~wHTTP (void)
+{
+
+    http_head_t h;
+    
+    while (resp_headers) {
+	h = resp_headers->next;
+	free (resp_headers);
+	resp_headers = h;
+    }
+    while (req_headers) {
+	h = req_headers->next;
+	free (req_headers);
+	req_headers = h;
+    }
+    free_if_malloc (url);
+    free_if_malloc (host);
+    if (fd != 0)
+	closesocket (fd);
+}
+
+
+int
+wHTTP::read (void *buf, unsigned int buflen)
+{
+    int n;
+
+    if (this->fd == 0 || this->resp_headers == NULL)
+	return -1;
+    if (method != HTTP_GET)
+	return -1;
+
+    if (nleft == -1)
+	nleft = getContentLength ();
+    if ((int)buflen > nleft)
+	buflen = nleft;
+    if (nleft == 0)
+	return -1;
+
+    n = recv (fd, (char*)buf, (int)buflen, 0);
+    if (n > 0) {
+	nleft -= n;
+	if (nleft < 0) nleft = 0;
+    }
+    return n;
+}
+
+
+int
+wHTTP::write (const void *buf, unsigned buflen)
+{
+    if (this->fd == 0)
+	return -1;
+    if (method == HTTP_GET || method == HTTP_HEAD)
+	return -1;
+    return send (fd, (const char*)buf, (int)buflen, 0);
+}

Modified: trunk/Src/wptKeyCache.cpp
===================================================================
--- trunk/Src/wptKeyCache.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyCache.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -36,6 +36,7 @@
 #include "wptErrors.h"
 #include "wptW32API.h"
 #include "wptGPG.h"
+#include "wptTypes.h"
 
 
 /* Attribute list which holds the image data. */
@@ -49,6 +50,7 @@
 typedef struct attr_list_s *attr_list_t;
 
 
+/* Free attribute list @ctx. */
 void
 free_attr_list (attr_list_t ctx)
 {
@@ -81,6 +83,8 @@
 	buffer = buf+9+10;
 	pos = 0;
 	c = (attr_list_t)calloc (1, sizeof *c);
+	if (!c)
+	    BUG (0);
 	p = strtok (buffer, " ");
 	while (p != NULL) {
 	    switch (pos) {
@@ -102,7 +106,6 @@
 	    pos++;
 	    p = strtok (NULL, " ");
 	}
-	/*printf ("id=%s octets=%d flags=%d\n", c->fpr, c->octets, c->flags);*/
 	if (!*ctx)
 	    *ctx = c;
 	else {
@@ -111,6 +114,8 @@
 	    t->next = c;
 	}
 	c->d = (unsigned char*)malloc (c->octets);
+	if (!c->d)
+	    BUG (0);
 	memcpy (c->d, data, c->octets);
 	data += c->octets;
 	datlen -= c->octets;
@@ -173,6 +178,8 @@
 
     gpg_iobuf_ioctl (inp, 3, 1, NULL);
     pkt = (PACKET*)calloc (1, sizeof *pkt);
+    if (!pkt)
+	BUG (0);
     gpg_init_packet (pkt);
     while (gpg_parse_packet (inp, pkt) != -1) {
 	if (pkt->pkttype == PKT_SECRET_KEY) {
@@ -216,6 +223,8 @@
     fnd->attrib.flags = dat->flags;
     fnd->attrib.len = dat->octets;
     fnd->attrib.d = (unsigned char*)malloc (dat->octets);
+    if (!fnd->attrib.d)
+	BUG (0);
     memcpy (fnd->attrib.d, dat->d, dat->octets);
     return 0;
 }
@@ -267,6 +276,8 @@
     gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
 
     pkt = (PACKET*)calloc (1, sizeof * pkt);
+    if (!pkt)
+	BUG (0);
     gpg_init_packet (pkt);
     while (gpg_parse_packet (inp, pkt) != -1) {
 	if (pkt->pkttype == PKT_PUBLIC_KEY) {
@@ -302,7 +313,7 @@
 	    else if (nsym > 0) {
 		c->sym_prefs = (unsigned char*)calloc (1, nsym+1);
 		if (!c->sym_prefs)
-		    return gpg_error (GPG_ERR_ENOMEM);
+		    BUG (0);
 		memcpy (c->sym_prefs, sym_prefs, nsym);
 	    }
 	}
@@ -344,7 +355,7 @@
 	return gpg_error (GPG_ERR_INV_ARG);
     ctx = (gpg_keycache_t)calloc (1, sizeof *ctx);
     if (!ctx)
-        return gpg_error (GPG_ERR_ENOMEM);
+        BUG (0);
     ctx->secret = 0;
     ctx->pos = 0;
     *r_ctx = ctx;
@@ -365,6 +376,7 @@
         c2 = c->next;
 	gpgme_key_release (c->key);
 	c->key = NULL;
+	safe_free (c->pref_keyserver);
 	safe_free (c->sym_prefs);
 	safe_free (c->attrib.d);
 	safe_free (c->card_type);
@@ -404,7 +416,7 @@
     
     c = (struct keycache_s*)calloc (1, sizeof *c);
     if (!c)
-        return gpg_error (GPG_ERR_ENOMEM);
+        BUG (0);
     c->gloflags.is_protected = 1; /*default: assume protection. */
     c->key = key;
     if (!ctx->item)
@@ -682,7 +694,7 @@
 	pos++;
     p = (unsigned char*)calloc (1, pos+1);
     if (!p)
-	abort ();
+	BUG (0);
     memcpy (p, prefs, pos);
     return p;
 }
@@ -779,6 +791,7 @@
     return err;
 }
 
+
 /* Search for a key with the pattern @pattern and mark
    this key as the default signing key if found.
    Return value: 0 on success. */
@@ -821,4 +834,98 @@
 }
 
 
+static gpgme_error_t
+decode_subpacket (const char *subpkt_data, int *type,
+		  char **out, WORD *outlen)
+{
+    char tmp[128], *p = tmp, *val;
+    char *enc;
+    size_t pos = 0, i=0;
 
+    /* example: spk:24:1:21:http%3A//subkeys.pgp.de */
+    *outlen = 0;
+    *out = NULL;
+    
+    if (strncmp (subpkt_data, "spk:", 4))
+	return gpg_error (GPG_ERR_NO_DATA);
+
+    strncpy (tmp, subpkt_data, 62);
+    val = strtok (tmp, ":");
+    while (val != NULL) {
+	switch (pos++) {
+	case 0:
+	    break;
+
+	case 1: 
+	    if (type)
+		*type = atoi (val);
+	    break;
+
+	case 2:
+	    break;
+
+	case 3:
+	    *outlen = atoi (val);
+	    break;
+
+	case 4:
+	    enc = strdup (val);
+	    break;
+	}
+	val = strtok (NULL, ":");
+    }
+    if (!enc)
+	return gpg_error (GPG_ERR_NO_DATA);;
+    *out = (char*)calloc (1, strlen (enc)+1);
+    for (pos = 0; pos < strlen (enc); pos++) {
+	if (enc[pos] == '%' && enc[pos+1] == '%')
+	    (*out)[i++] = '%';
+	else if (enc[pos] == '%') {
+	    char tmp[3];
+	    tmp[0] = enc[++pos];
+	    tmp[1] = enc[++pos];
+	    tmp[2] = 0;
+	    (*out)[i++] = (char)strtoul (tmp, NULL, 16);
+	}
+	else
+	    (*out)[i++] = enc[pos];
+    }
+    (*out)[i] = 0;
+    free (enc);
+    return 0;
+}
+
+
+/* If the attribute given in @attr is not set in the
+   key cache object, try to update it. */
+gpgme_error_t
+gpg_keycache_update_attr (struct keycache_s *item,
+			  int attr, int force)
+{
+    gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
+    char *val = NULL;
+    WORD n = 0;    
+
+    switch (attr) {
+    case KC_ATTR_PREFSYM:
+	if (!force && item->sym_prefs)
+	    break;
+	safe_free (item->sym_prefs);
+	err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
+	if (!err && val != NULL)
+	    err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n);
+	break;
+
+    case KC_ATTR_PREFKSERV:
+	if (!force && item->pref_keyserver)
+	    break;
+	safe_free (item->pref_keyserver);
+	err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val);
+	if (!err && val != NULL)
+	    err = decode_subpacket (val, NULL, &item->pref_keyserver, &n);
+	break;
+    }
+    safe_free (val);
+    return err;
+}
+

Modified: trunk/Src/wptKeyEdit.cpp
===================================================================
--- trunk/Src/wptKeyEdit.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyEdit.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -816,6 +816,7 @@
 }
 
 /* Set the preferred keyserver for the given key to @url.
+   If @_uid_index is -1, set the keyserver for all user-ids.
    Return value: 0 on success. */
 gpgme_error_t
 GpgKeyEdit::setPreferredKeyserver (int _uid_index, const char *_url)

Modified: trunk/Src/wptKeyEditCB.cpp
===================================================================
--- trunk/Src/wptKeyEditCB.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyEditCB.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -48,9 +48,12 @@
     static char buf[32];
 
     if (!ctx->cmd_sent && !strcmp (key, "keyedit.prompt")) {
+	int uid = ctx->getUseridIndex ();
 	ctx->cmd_sent = 1;
-	sprintf (buf, "uid %d", ctx->getUseridIndex ());
-	return buf;
+	if (uid != -1) {
+	    sprintf (buf, "uid %d", ctx->getUseridIndex ());
+	    return buf;
+	}
     }
     if (!strcmp (key, "keyedit.prompt") && !ctx->cnt) {
 	ctx->cnt = 1;
@@ -58,7 +61,7 @@
     }
     if (!strcmp (key, "keyedit.add_keyserver"))
 	return ctx->url;
-    if ( !strcmp (key, "keyedit.confirm_keyserver"))
+    if (!strcmp (key, "keyedit.confirm_keyserver"))
 	return "Y";
     if (!strcmp (key, "passphrase.enter"))
 	return ctx->pass;

Modified: trunk/Src/wptKeyEditDlgs.cpp
===================================================================
--- trunk/Src/wptKeyEditDlgs.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyEditDlgs.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -875,13 +875,13 @@
 	ke->setPassphrase (pass);
     else
 	ke->setNoPassphrase (true);
-    err = ke->setPreferredKeyserver (0 /* XXX */, url->url);
+    err = ke->setPreferredKeyserver (-1, url->url);
     if (!err)
 	msg_box (dlg, _("Preferred keyserver successfully set."), _("Key Edit"), MB_OK);
 
     sfree_if_alloc (pass);
     delete ke;
-    delete url;    
+    delete url;
     return err == 0? 0 : WPTERR_GENERAL;
 }
 

Modified: trunk/Src/wptKeyManager.cpp
===================================================================
--- trunk/Src/wptKeyManager.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyManager.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -530,10 +530,9 @@
 int
 km_http_import (HWND dlg, const char *url)
 {
-    http_hd_t hd;
     FILE *fp;
+    wHTTP *hd;
     char tmpfile[500];
-    int statcode;
     int rc = 0;
 
     if (strncmp (url, "http://", 7)) {
@@ -549,19 +548,19 @@
 	return WPTERR_FILE_CREAT;
     }
 
-    /* parse URL */
-    rc = http_send_request2 (url, &hd);
-    if (!rc)
-	rc = http_parse_response (hd, &statcode);
-    if (!rc)
-	rc = http_parse_data (hd, fp);
-    http_hd_free (hd);
-    fclose (fp);
-    if (rc) {	
-	msg_box (dlg, winpt_strerror (rc), _("Key Import HTTP"), MB_ERR);
+    hd = new wHTTP (url);
+    if (hd->getStatusCode () == HTTP_STAT_200)
+	hd->readData (fp);
+    else {
+	log_box (_("Key Import HTTP"), MB_ERR, 
+		 _("Could not fetch key from URL: %s"), url);
 	rc = WPTERR_GENERAL;
     }
-    km_file_import (dlg, tmpfile, NULL, NULL);
+
+    delete hd;
+    fclose (fp);
+    if (!rc)
+	km_file_import (dlg, tmpfile, NULL, NULL);
     DeleteFile (tmpfile);
     return rc;
 }
@@ -817,7 +816,8 @@
 
 /* Send the select key in @lv to the keyserver @host:@port. */
 int
-km_send_to_keyserver (listview_ctrl_t lv, HWND dlg, const char *host, u16 port)
+km_send_to_keyserver (listview_ctrl_t lv, HWND dlg, 
+		      const char *host, WORD port)
 {
     gpgme_key_t key;
     int id;
@@ -891,13 +891,17 @@
 }
 
 
+/* Refresh the selected key in the listview @lv at position @pos.
+   Legal flags are 0 = single key. */
 static void
 km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos, int flags)
 {
+    winpt_key_s pk;
     gpgme_key_t key;
+    const char *pref_kserv = default_keyserver;
     char keyid[16+1];
     int idx, err = 0;
-
+    
     if (pos != 0)
 	idx = pos;
     else
@@ -906,8 +910,13 @@
 	key = (gpgme_key_t)listview_get_item2 (lv, idx);
 	if (!key)
 	    BUG (0);
+	/* In single refresh mode, try to use the users preferred keyserver. */
+	if (flags == 0 &&
+	    !winpt_get_pubkey (key->subkeys->keyid+8, &pk) &&
+	    !gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFKSERV, 0))
+	    pref_kserv = pk.ext->pref_keyserver;
 	_snprintf (keyid, sizeof (keyid)-1, "%s", key->subkeys->keyid+8);
-	err = hkp_recv_key (dlg, default_keyserver, default_keyserver_port, 
+	err = hkp_recv_key (dlg, pref_kserv, default_keyserver_port,
 			    keyid, 0, flags);
 	/* if we receive just a single key (no refresh mode), update it. */
 	if (!flags && !err)

Modified: trunk/Src/wptKeyManagerDlg.cpp
===================================================================
--- trunk/Src/wptKeyManagerDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyManagerDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -1692,7 +1692,7 @@
 
 	case ID_KEYMISC_IMPORT_HTTP:
 	    url = (struct URL_ctx_s*)get_http_file_dlg (dlg);
-	    if (url->cancel == 0) {
+	    if (url && url->cancel == 0) {
 		km_http_import (dlg, url->url);
 		refresh_keylist (kmi);
 	    }
@@ -1811,7 +1811,9 @@
 	    if (!key)
 		BUG (NULL);
 	    memset (&k, 0, sizeof (k));
-	    k.keyid = key->subkeys->keyid+8;
+	    strncpy (k.tmp_keyid, key->subkeys->keyid+8, 8);
+	    k.keyid = k.tmp_keyid;
+	    k.is_protected = km_check_if_protected (kmi->lv, kmi->lv_idx);
 	    keyedit_set_pref_keyserver (&k, dlg);
 	    break;
 

Modified: trunk/Src/wptKeyPropsDlg.cpp
===================================================================
--- trunk/Src/wptKeyPropsDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyPropsDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -208,7 +208,7 @@
 {    
     static char buf[64];
 
-    if (!k->ext->card_type)
+    if (!k->ext || !k->ext->card_type)
 	return "";
     _snprintf (buf, sizeof (buf)-1, _("Card-Type: %s\r\n"), k->ext->card_type);
     return buf;
@@ -220,24 +220,22 @@
 static void
 display_key_info (HWND dlg, winpt_key_t k, gpgme_key_t *r_key)
 {
-    struct winpt_key_s k2;
-    gpgme_key_t sk, key;
+    gpgme_key_t key;
+    struct winpt_key_s pk, sk;
     char info[512];
     const char *inf;
-    u32 created, expires;
+    DWORD created, expires;
 
-    memset (&k2, 0, sizeof (k2));	
-    if (k->key_pair)
-	winpt_get_seckey (k->keyid, &k2);
-    else    
-	winpt_get_pubkey (k->keyid, &k2);
-    sk = k2.ctx;
-    if (sk)
-	k->is_protected = k2.is_protected;
-    if (get_pubkey (k->keyid, &key))
-	BUG (0);    
-    created = key->subkeys->timestamp;	
-    expires = key->subkeys->expires;    
+    memset (&pk, 0, sizeof (pk));
+    if (winpt_get_pubkey (k->keyid, &pk))
+	BUG (0);
+    gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFSYM, 0);
+    memset (&sk, 0, sizeof (sk));	
+    if (k->key_pair && !winpt_get_seckey (k->keyid, &sk))
+	k->is_protected = sk.is_protected;
+    key = pk.ext->key;
+    created = key->subkeys->timestamp;
+    expires = key->subkeys->expires;
     _snprintf (info, DIM (info)-1,
                _("Type: %s\r\n"
                "Key ID: %s\r\n"
@@ -255,8 +253,8 @@
                get_key_created (created),
 	       get_key_expire_date (expires),
                get_validity (key), 
-	       get_pref_cipher (&k2),
-	       get_card_type (&k2));
+	       get_pref_cipher (&pk),
+	       get_card_type (&sk));
 
     SetDlgItemText (dlg, IDC_KEYPROPS_INFO, info);
     SetDlgItemText (dlg, IDC_KEYPROPS_FPR, get_key_fpr (key));  
@@ -289,7 +287,7 @@
 	SetDlgItemText (dlg, IDC_KEYPROPS_REVOKERS, _("&Revokers"));
 	SetDlgItemText (dlg, IDC_KEYPROPS_CHANGE_PWD, _("Change &Password"));
 	SetDlgItemText (dlg, IDC_KEYPROPS_OTINF, _("Ownertrust"));
-
+	
 	display_key_info (dlg, k, &key);
 	if (!keyprops_load_photo (dlg, key, &valid)) {
 	    k->has_photo = 1;	

Modified: trunk/Src/wptKeylist.cpp
===================================================================
--- trunk/Src/wptKeylist.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeylist.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -592,7 +592,7 @@
 	listview_set_chkbox_style (lv);
     ico[0] = LoadIcon (glob_hinst, (LPCTSTR)IDI_PUBKEY);
     ico[1] = LoadIcon (glob_hinst, (LPCTSTR)IDI_KEYPAIR);
-    listview_set_image_list (lv, ico, 2);
+    listview_set_image_list (lv, 22, 14, ico, 2);
     listview_del_all_items (lv);
 
     *r_lv = lv;

Modified: trunk/Src/wptKeyserver.cpp
===================================================================
--- trunk/Src/wptKeyserver.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyserver.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -37,10 +37,9 @@
 #include "wptGPG.h"
 #include "wptRegistry.h"
 
+/* just map net_errno to a winsock error. */
 #define net_errno ((int)WSAGetLastError ())
 
-static char base64code[] =
-  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 keyserver server[MAX_KEYSERVERS] = {0};
 keyserver_proxy_s proxy = {0};
@@ -70,11 +69,15 @@
 char *default_keyserver = NULL;
 WORD default_keyserver_port = 0;
 
+/* Default socket timeout. */
+static int default_socket_timeout = 10;
 
 /* Basic64 encode the input @inbuf to @outbuf. */
 static void
 base64_encode (const char *inbuf, char *outbuf)
-{	
+{
+    char base64code[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     int index = 0, temp = 0, res = 0;
     int i = 0, inputlen = 0, len = 0;
     
@@ -213,13 +216,13 @@
    Return value: 0 on success. */
 static int
 sock_read (int fd, char *buf, int buflen, int *nbytes)
-{	
+{
     DWORD nread;
     int nleft = buflen;
     int rc, n = 0;
 
     while (nleft > 0) {
-	if (n >= 10)
+	if (n >= default_socket_timeout)
 	    return WPTERR_WINSOCK_TIMEOUT;
 	rc = sock_select (fd, 1);
 	if (rc == SOCKET_ERROR)
@@ -304,23 +307,6 @@
 }
 
 
-/* Set the default keyserver. */
-void
-set_default_kserver (void)
-{
-    char *p = get_reg_entry_keyserver ("Default");
-    free_if_alloc (default_keyserver);
-    default_keyserver = p && *p != ' ' ? p : m_strdup (DEF_HKP_KEYSERVER);
-    p = get_reg_entry_keyserver ("Default_Port");
-    if (p && *p) {
-	default_keyserver_port = (WORD)strtoul (p, NULL, 10);
-	free_if_alloc (p);
-    }
-    else
-	default_keyserver_port = HKP_PORT;
-}
-
-
 /* Initialize the Winsock2 interface.*/
 int
 wsock_init (void)
@@ -331,7 +317,6 @@
 	log_debug ("wsock_init: WSAStartup failed ec=%d\r\n", net_errno);
 	return WPTERR_WINSOCK_INIT;
     }
-    set_default_kserver ();
     return 0;
 }
 
@@ -348,7 +333,7 @@
     free_if_alloc (p);
     free_if_alloc (default_keyserver);
     for (i=0; i < MAX_KEYSERVERS; i++) {
-	if (server[i].used)
+	if (server[i].used && server[i].name != NULL)
 	    free_if_alloc (server[i].name);
     }
     kserver_proxy_release (&proxy);
@@ -378,6 +363,16 @@
 }
 
 
+/* Set default socket timeout for all reading operations. */
+void
+kserver_set_socket_timeout (int nsec)
+{
+    if (nsec < 0)
+	nsec = 0;
+    default_socket_timeout = nsec;
+}
+
+
 /* Return the last keyserver error as a string. */
 const char*
 kserver_strerror (void)
@@ -504,13 +499,17 @@
 void
 keyserver_set_default (const char *hostname, WORD port)
 {
-    if (hostname) {
+    if (hostname != NULL) {
 	free_if_alloc (default_keyserver);
 	default_keyserver = m_strdup (hostname);
 	if (!default_keyserver)
 	    BUG (0);
 	default_keyserver_port = port;
     }
+    if (!port)
+	port = HKP_PORT;
+    if (!default_keyserver)
+	default_keyserver = m_strdup (DEF_HKP_KEYSERVER);
     server[0].name =  m_strdup (default_keyserver);
     server[0].used = 1;
     server[0].port = port;

Modified: trunk/Src/wptKeyserverDlg.cpp
===================================================================
--- trunk/Src/wptKeyserverDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeyserverDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -326,14 +326,14 @@
 static void
 set_proxy (HWND dlg)
 {
-    char t[512];
+    char buf[384];
 
     if (proxy.host)
-	_snprintf (t, sizeof (t)-1, "%s proxy: \"%s:%d\"",
+	_snprintf (buf, sizeof (buf)-1, "%s proxy: \"%s:%d\"",
 		   name_from_proto (proxy.proto), proxy.host, proxy.port);
     else
-        strcpy (t, "Proxy: none");
-    SetDlgItemText (dlg, IDC_KEYSERVER_PROXY, t);
+        strcpy (buf, _("Proxy: none"));
+    SetDlgItemText (dlg, IDC_KEYSERVER_PROXY, buf);
 }
 
 
@@ -346,13 +346,13 @@
 }
 
 
-static u16 inline
+static WORD inline
 kserver_get_port (listview_ctrl_t lv)
 {
     char buf[16];
 
     listview_get_item_text (lv, kserver_get_pos (lv), KS_COL_PORT, buf, 15);
-    return (u16)strtoul (buf, NULL, 10);
+    return (WORD)strtoul (buf, NULL, 10);
 }
 
 
@@ -366,7 +366,7 @@
     p = get_reg_entry_keyserver ("Default");
     if (!p)
 	return;
-    for (i = 0; i < listview_count_items( lv, 0); i++ ) {
+    for (i = 0; i < listview_count_items (lv, 0); i++) {
 	listview_get_item_text (lv, i, KS_COL_NAME, buf, sizeof (buf)-1);
 	if (!strncmp (p, buf, strlen (p))) {
 	    listview_add_sub_item (lv, i, KS_COL_DEFAULT, "x");
@@ -402,7 +402,7 @@
     i = kserver_get_port (lv);
     sprintf (port, "%d", i);
     set_reg_entry_keyserver ("Default_Port", port);
-    keyserver_set_default (buf, (u16)i);
+    keyserver_set_default (buf, (WORD)i);
     return 0;
 }
 
@@ -426,7 +426,7 @@
     lv->ctrl = hwnd;
     for (j=0; keyserver[j].fieldname; j++)
         listview_add_column (lv, &keyserver[j]);
-    listview_set_image_list (lv, ico, 1);
+    listview_set_image_list (lv, 16, 16, ico, 1);
     for (j = 0; j<MAX_KEYSERVERS; j++) {
 	if (!server[j].used)
 	    continue;

Modified: trunk/Src/wptKeysignDlg.cpp
===================================================================
--- trunk/Src/wptKeysignDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptKeysignDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -23,6 +23,7 @@
 
 #include <windows.h>
 #include <commctrl.h>
+#include <time.h>
 
 #include "resource.h"
 #include "wptGPG.h"
@@ -218,6 +219,23 @@
 }
 
 
+/* Check if the given system time @st points to today. */
+static int
+date_is_today (SYSTEMTIME *st)
+{
+    time_t t;
+    struct tm *tm;
+
+    t = time (NULL);
+    tm = localtime (&t);
+    if (st->wDay == tm->tm_mday &&
+	st->wYear == tm->tm_year+1900 &&
+	st->wMonth == tm->tm_mon+1)
+	return -1;
+    return 0;
+}
+
+
 /* Dialog box procedure to sign a key. */
 BOOL CALLBACK
 keysign_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -279,6 +297,8 @@
 	    EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_SHOWIMG), TRUE);
 	if (!reg_prefs.gpg.ask_cert_level)
 	    EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_ASKLEVEL), FALSE);
+	if (!reg_prefs.gpg.ask_cert_expire)
+	    EnableWindow (GetDlgItem (dlg, IDC_KEYSIGN_EXPSIG), FALSE);
 	CheckDlgButton (dlg, IDC_KEYSIGN_HIDE, BST_CHECKED);
         SetForegroundWindow (dlg);
 	h = GetDlgItem (dlg, IDC_KEYSIGN_PASSPHRASE);
@@ -330,8 +350,14 @@
 		    type = GPG_EDITKEY_NRLSIGN;
 	    }
 	    if (IsDlgButtonChecked (dlg, IDC_KEYSIGN_EXPSIG)) {
-		expires = 1;
 		DateTime_GetSystemtime (GetDlgItem (dlg, IDC_KEYSIGN_EXPIRES), &st);
+		if (date_is_today (&st)) {
+		    msg_box (dlg, _("You cannot select today as the expiration date."),
+			     _("Key Signing"), MB_INFO);
+		    return TRUE;
+		}
+		else
+		    expires = 1;
 		sprintf (keymsg, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
 	    }
 

Modified: trunk/Src/wptListView.cpp
===================================================================
--- trunk/Src/wptListView.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptListView.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -410,12 +410,16 @@
 
 
 void
-listview_set_image_list (listview_ctrl_t ctx, HICON *ico, DWORD nicons)
+listview_set_image_list (listview_ctrl_t ctx, int cx, int cy, 
+			 HICON *ico, DWORD nicons)
 {
     HIMAGELIST hil;
     DWORD i;
 
-    hil = ImageList_Create (16, 16, ILC_COLOR8|ILC_MASK, nicons, 1);
+    if (cx == 0 || cy == 0)
+	cx = cy = 16;
+
+    hil = ImageList_Create (cx, cy, ILC_COLOR8|ILC_MASK, nicons, 1);
     ImageList_SetBkColor (hil, CLR_NONE);
     for (i=0; i < nicons; i++)
 	ImageList_AddIcon (hil, ico[i]);    

Modified: trunk/Src/wptPassphraseCB.cpp
===================================================================
--- trunk/Src/wptPassphraseCB.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptPassphraseCB.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -43,7 +43,7 @@
 
 const char* get_symkey_algo (int algo);
 
-#define item_ctrl_id( cmd ) \
+#define item_ctrl_id(cmd) \
     ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)
 
 #define item_ctrl_id2(cmd) \
@@ -76,6 +76,14 @@
     int n;
 
     switch (msg) {
+    case WM_ACTIVATE:
+	safe_edit_control_init (dlg, item_ctrl_id (c->gpg_cmd));
+	break;
+
+    case WM_DESTROY:
+	safe_edit_control_free (dlg, item_ctrl_id (c->gpg_cmd));
+	break;
+
     case WM_INITDIALOG:
 	c = (passphrase_cb_s *)lparam;
 	if (!c)
@@ -208,7 +216,8 @@
 		    c->pwd = new char[n+2];
 		    if (!c->pwd)
 			BUG (NULL);
-		    GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, n+1);
+		    SafeGetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), 
+					c->pwd, n+1);
 		}
 		res = gpgme_op_decrypt_result (c->gpg);
 		if (!res)
@@ -392,7 +401,7 @@
 	}
 	else if (uid_hint)
 	    parse_gpg_description (uid_hint, passphrase_info, 
-				   c->info, sizeof c->info - 1);
+				   c->info, sizeof (c->info) - 1);
 	if (c->gpg_cmd == GPG_CMD_DECRYPT) {
 	    rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,
 				 (HWND)c->hwnd, passphrase_callback_proc,

Modified: trunk/Src/wptPassphraseDlg.cpp
===================================================================
--- trunk/Src/wptPassphraseDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptPassphraseDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -41,6 +41,7 @@
     int strict;	    /* do a simple check how good the passphrase is. */
     int repeat;	    /* Indicate last try was wrong. */   
     int cancel;	    /* 1 if user cancelled operation. */
+    int not_empty;
 };
 
 
@@ -48,7 +49,7 @@
 static BOOL CALLBACK
 passwd_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
 {
-    static passphrase_s * pwd;
+    static passphrase_s *pwd;
     int nbytes;
     
     switch (msg) {
@@ -71,6 +72,14 @@
 	center_window (dlg, NULL);
         SetForegroundWindow (dlg);
         return FALSE;
+
+    case WM_ACTIVATE:
+	safe_edit_control_init (dlg, IDC_PASSWD_PWD);
+	break;
+
+    case WM_DESTROY:
+	safe_edit_control_free (dlg, IDC_PASSWD_PWD);
+	break;
         
     case WM_COMMAND:
 	if (HIWORD (wparam) == BN_CLICKED && 
@@ -84,7 +93,13 @@
         switch (LOWORD (wparam)) {
         case IDOK:
             pwd->cancel = 0;
-            nbytes = GetDlgItemText (dlg, IDC_PASSWD_PWD, pwd->pwd, DIM (pwd->pwd)-1);
+	    nbytes = SafeGetDlgItemText (dlg, IDC_PASSWD_PWD, 
+					 pwd->pwd, DIM (pwd->pwd)-1);
+	    if (!nbytes && pwd->not_empty) {
+		msg_box (dlg, _("Please enter a passphrase."), _("Passphrase Dialog"), MB_ERR);
+		return TRUE;
+	    }
+
             if (!nbytes)
                 strcpy (pwd->pwd, "");
 	    else if (pwd->strict && check_passwd_quality (pwd->pwd, 0)) {
@@ -129,6 +144,7 @@
     }
     pass.repeat = flags & PASSDLG_INIT? 0 : 1;
     pass.strict = flags & PASSDLG_STRICT? 1 : 0;
+    pass.not_empty = flags & PASSDLG_NOTEMPTY? 1: 0;
     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_PASSWD, glob_hwnd,
 		    passwd_dlg_proc, (LPARAM)&pass);
     if (pass.cancel == 1) {

Modified: trunk/Src/wptPreferencesDlg.cpp
===================================================================
--- trunk/Src/wptPreferencesDlg.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptPreferencesDlg.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -250,8 +250,10 @@
 
         case IDOK:
             rc = GetDlgItemInt (dlg, IDC_PREFS_CACHETIME, NULL, FALSE);
-            if (rc <= 0)
+            if (rc <= 0) {
                 reg_prefs.cache_time = 0;
+		agent_flush_cache ();
+	    }
             else if (rc > 720) {
                 msg_box( dlg, _("Please enter a value that is between 1-720.\nIt is not "
 				"a good idea to cache the passphrase more than 12 hours."),

Modified: trunk/Src/wptRegistry.cpp
===================================================================
--- trunk/Src/wptRegistry.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptRegistry.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -693,8 +693,8 @@
 char*
 get_reg_entry_keyserver (const char *name)
 {
-    char * p = get_reg_entry (HKEY_CURRENT_USER, WINPT_REG"\\Keyserver", name);
-    if (p && !strcmp (p, "")) {
+    char *p = get_reg_entry (HKEY_CURRENT_USER, WINPT_REG"\\Keyserver", name);
+    if (p && (!strcmp (p, "") || strlen (p) == 0)) {
 	free_if_alloc (p);
 	return NULL;
     }
@@ -712,7 +712,7 @@
 get_reg_entry_keyserver_int (const char *key)
 {
     char *p;
-    int val;
+    int val = 0;
 
     p = get_reg_entry_keyserver (key);
     if (p && *p)

Added: trunk/Src/wptSafeEditCtrl.cpp
===================================================================
--- trunk/Src/wptSafeEditCtrl.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptSafeEditCtrl.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -0,0 +1,249 @@
+/* wptSafeEditCtrl.cpp - Safe edit control for passwords
+ *	Copyright (C) 2006 Timo Schulz, g10 Code GmbH
+ *
+ * This file is part of WinPT.
+ *
+ * WinPT 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.
+ * 
+ * WinPT 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 WinPT; if not, write to the Free Software Foundation, 
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <richedit.h>
+#include "resource.h"
+
+#include "wptTypes.h"
+#include "wptW32API.h"
+
+/* New message to retrieve text. */
+#define WM_SAFE_GETTEXT (WM_USER+11)
+
+/* Hook context. */
+struct hook_ctx_s {
+    HHOOK keyb;	    /* handle for the keyboard. */
+    HHOOK cbt;	    /* handle for computer based training (CBT) */
+};
+typedef struct hook_ctx_s *hook_ctx_t;
+
+/* Subclassing context. */
+struct subclass_ctx_s {
+    WNDPROC new_wnd_fnc;    /* old window procedure. */
+    WNDPROC old_wnd_fnc;    /* new window procedure. */
+    HWND wnd;		    /* window handle that is subclassed. */
+    void *opaque;
+};
+typedef struct subclass_ctx_s *subclass_ctx_t;
+
+
+/* Dummy hook procedure to avoid channing. */
+static LRESULT CALLBACK 
+dummy_hook_proc (int code, WPARAM wparam, LPARAM lparam)
+{
+    return FALSE;
+}
+
+
+/* Set dummy hooks to prevent that the control is monitored
+   by some external hook functions. */
+static hook_ctx_t
+install_dummy_hooks (void)
+{
+    hook_ctx_t hc;
+
+    hc = (hook_ctx_t)calloc (1, sizeof *hc);
+    if (!hc)
+	return NULL;
+    hc->cbt = SetWindowsHookEx (WH_CBT, dummy_hook_proc,
+				 GetModuleHandle (NULL), 0);
+    if (hc->cbt == NULL) {
+	free (hc);
+	return NULL;
+    }
+    hc->keyb = SetWindowsHookEx (WH_KEYBOARD, dummy_hook_proc,
+				 GetModuleHandle (NULL), 0);
+    if (hc->keyb == NULL) {
+	free (hc);
+	return NULL;
+    }
+    return hc;
+}
+
+
+/* Remove dummy hooks and free memory. */
+static void
+deinstall_dummy_hooks (hook_ctx_t hc)
+{
+    UnhookWindowsHookEx (hc->cbt);
+    UnhookWindowsHookEx (hc->keyb);
+    free (hc);
+}
+
+
+/* Filtered window procedure for the passphrase edit control. */
+static LRESULT CALLBACK 
+safe_edit_dlg_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    static subclass_ctx_t ctx = NULL;
+
+    /* XXX: filter all messages which were not send from 
+            the current process. */
+
+    if (ctx == NULL)
+	ctx = (subclass_ctx_t)GetWindowLong (hwnd, GWL_USERDATA);
+
+    switch (msg) {
+    case WM_CUT:
+    case WM_COPY:
+    case WM_PASTE:
+	/* do not allow to copy or paste the inserted text. */
+	return TRUE;
+
+    case WM_KEYUP:
+    case WM_KEYDOWN:
+	/* XXX: maybe in a future release, we might want to provide
+	        our own buffer implementation. */
+
+	/* ignore 'end' and 'home' to make text selection more difficult. */
+	if ((int)wparam == VK_END || (int)wparam == VK_HOME)
+	    return TRUE;
+	break;
+
+    case WM_GETTEXT:
+	/* disallow normal gettext message. */
+	return TRUE;
+
+    case WM_SAFE_GETTEXT:
+	{ /* transform WM_GETTEXT request into EM_GETLINE request. */
+	    char *buffer = (char*)wparam;
+	    int n;
+	    buffer[0] = (char)lparam;
+	    n = SendMessage (hwnd, EM_GETLINE, 0, wparam);
+	    buffer[n] = 0;
+	}
+	break;
+
+    case EM_GETLINE:
+	break;
+
+    case WM_LBUTTONDBLCLK:
+    case WM_RBUTTONUP:
+    case WM_RBUTTONDOWN:
+	/* prevent that the popup menu is displayed. */
+	return TRUE;
+
+    case EM_SETSEL:
+    case EM_SCROLLCARET:
+    case EM_FINDTEXT:
+    case EM_FINDTEXTEX:
+    case EM_GETSELTEXT:
+    case EM_PASTESPECIAL:
+    case EM_GETTEXTRANGE:
+    case EM_STREAMIN:
+    case EM_STREAMOUT:
+	/* disallow message which could be used to copy the text. */
+	return TRUE;
+    }
+
+    return CallWindowProc (ctx->old_wnd_fnc, hwnd, msg, wparam, lparam);
+}
+
+
+/* Sublclass the window in the dialog @dlg with the id @ctrlid.
+   @new_wnd_fnc is the new window procedure. */   
+static int
+subclass_window (HWND dlg, int ctrlid, WNDPROC new_wnd_fnc,
+		 subclass_ctx_t *r_ctx)
+{
+    subclass_ctx_t ctx;
+
+    *r_ctx = NULL;
+    ctx = (subclass_ctx_t)calloc (1, sizeof *ctx);
+    if (!ctx)
+	return -1;
+    ctx->wnd = GetDlgItem (dlg, ctrlid);
+    ctx->new_wnd_fnc = new_wnd_fnc;
+    ctx->old_wnd_fnc = (WNDPROC)GetWindowLong (ctx->wnd, GWL_WNDPROC);
+    if (!ctx->old_wnd_fnc) {
+	free (ctx);
+	return -1;
+    }
+    SetLastError (0);
+    SetWindowLong (ctx->wnd, GWL_WNDPROC, (LONG)new_wnd_fnc);
+    if (GetLastError () != 0) {
+	free (ctx);
+	return -1;
+    }
+    SetLastError (0);
+    SetWindowLong (ctx->wnd, GWL_USERDATA, (LONG)ctx);
+    if (GetLastError () != 0) {
+	free (ctx);
+	return -1;
+    }
+    if (r_ctx)
+	*r_ctx = ctx;
+    return 0;
+}
+
+
+/* Restore the old window procedure for the subclassed control
+   and free the memory. */
+static void
+subclass_free_memory (HWND dlg, int ctrlid)
+{
+    subclass_ctx_t ctx;
+    HWND wnd;
+
+    wnd = GetDlgItem (dlg, ctrlid);
+    ctx = (subclass_ctx_t)GetWindowLong (wnd, GWL_USERDATA);
+    SetWindowLong (ctx->wnd, GWL_WNDPROC, (LONG)ctx->old_wnd_fnc);
+    if (ctx != NULL)
+	free (ctx);
+}
+
+
+/* Init subclassing to provide a safer edit control
+   for the dialog @dlg control @ctlid. */
+void
+safe_edit_control_init (HWND dlg, int ctlid)
+{
+    subclass_ctx_t ctx;
+
+    subclass_window (dlg, ctlid,  safe_edit_dlg_proc, &ctx);
+    if (ctx != NULL)
+	ctx->opaque = install_dummy_hooks ();
+}
+
+
+/* Reset subclassing for the edit control @ctlid. */
+void
+safe_edit_control_free (HWND dlg, int ctlid)
+{
+    subclass_ctx_t ctx;
+    HWND wnd;
+
+    wnd = GetDlgItem (dlg, ctlid);
+    ctx = (subclass_ctx_t)GetWindowLong (wnd, GWL_USERDATA);
+    if (ctx != NULL && ctx->opaque != NULL)
+	deinstall_dummy_hooks ((hook_ctx_t)ctx->opaque);
+    subclass_free_memory (dlg, ctlid);
+}
+
+
+UINT
+SafeGetDlgItemText (HWND dlg, int id, char *buf, int buflen)
+{
+    /* XXX: use memset (buf, 0, buflen)? */
+    SendDlgItemMessage (dlg, id, WM_SAFE_GETTEXT, (WPARAM)buf, (LPARAM)buflen);
+    return strlen (buf);
+}

Modified: trunk/Src/wptSymEnc.cpp
===================================================================
--- trunk/Src/wptSymEnc.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptSymEnc.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -69,7 +69,8 @@
     char *pass = NULL;
     int cancel = 0;
     
-    pass = request_passphrase2 (_("Symmetric Encryption"), 0, &cancel);
+    pass = request_passphrase2 (_("Symmetric Encryption"), 
+				PASSDLG_NOTEMPTY, &cancel);
     if (cancel)
 	return 0;
     rc = gpgme_new (&ctx);

Modified: trunk/Src/wptUTF8.cpp
===================================================================
--- trunk/Src/wptUTF8.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptUTF8.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -33,7 +33,7 @@
 #include "wptErrors.h"
 
 
-static u16 latin2_unicode[128] = {
+static WORD latin2_unicode[128] = {
     0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
     0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,
     0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
@@ -54,7 +54,7 @@
 
 
 static const char *active_charset_name = "iso-8859-1";
-static u16 *active_charset = NULL;
+static WORD *active_charset = NULL;
 static int no_translation = 0;
 
 
@@ -127,7 +127,7 @@
       buffer = (char *)malloc( length + 1 );
       for(p=(byte *)buffer, s=(byte *)string; *s; s++ ) {
           if( *s & 0x80 ) {            
-              u16 val = active_charset[ *s & 0x7f ];
+              WORD val = active_charset[ *s & 0x7f ];
               if( val < 0x0800 ) {                
                   *p++ = 0xc0 | ( (val >> 6) & 0x1f );
                   *p++ = 0x80 | (  val & 0x3f );

Modified: trunk/Src/wptW32API.cpp
===================================================================
--- trunk/Src/wptW32API.cpp	2006-03-06 14:41:58 UTC (rev 180)
+++ trunk/Src/wptW32API.cpp	2006-03-14 11:01:22 UTC (rev 181)
@@ -246,11 +246,12 @@
     
     GlobalUnlock (clipmem);
     SetClipboardData (CF_TEXT, clipmem);
+    GlobalFree (clipmem);
     
 leave:
     CloseClipboard ();
     return rc;
-} /* set_clip_text */
+}
 
 
 /* Append or prepend some text to the clipboard contents.



More information about the Winpt-commits mailing list