/[winpt]/trunk/Src/wptGPG.cpp
ViewVC logotype

Diff of /trunk/Src/wptGPG.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 222 by twoaday, Thu Jun 1 08:30:46 2006 UTC revision 407 by twoaday, Mon Feb 6 19:26:03 2012 UTC
# Line 1  Line 1 
1  /* wptGPG.cpp - GnuPG configuration  /* wptGPG.cpp - GnuPG configuration
2   *      Copyright (C) 2001-2006 Timo Schulz   *      Copyright (C) 2001-2009 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 12  Line 12 
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   * General Public License for more details.   * 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  
15   */   */
16  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
17  #include <config.h>  #include <config.h>
# Line 30  Line 26 
26  #include <time.h>  #include <time.h>
27    
28  #include "wptGPG.h"  #include "wptGPG.h"
29  #include "wptGpgCmds.h"  #include "wptGPGME.h"
30  #include "wptGPGOptSkel.h"  #include "wptGPGCmds.h"
31  #include "wptTypes.h"  #include "wptTypes.h"
32  #include "wptNLS.h"  #include "wptNLS.h"
33  #include "wptRegistry.h"  #include "wptRegistry.h"
# Line 43  Line 39 
39  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
40  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
41    
42  struct gpg_watcher_s {  /* Context to monitor GPG file changes. */
43      FILETIME    last_access;  struct gpg_monitor_s {
44        FILETIME    last_access;    /* last write access. */
45      FILETIME    access;      FILETIME    access;
46      char        *object;      char        *object;        /* name of the object. */
47      int         modified;      char        *fpath_object;  /* full path to the object. */
48        int         modified;       /* 1 = modified. */
49  };  };
50    typedef struct gpg_monitor_s *gpg_monitor_t;
51    
52    static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
53  /* XXX need to watch for gpg.conf due to the fact keyring entries could be changed */  static gpg_monitor_s gpg_table[3];
 static const char * gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};  
 static gpg_watcher_s gpg_table[3];  
54  static int gpg_table_count = DIM (gpg_table);  static int gpg_table_count = DIM (gpg_table);
55    
56  int idea_available = 0;  int idea_available = 0; /* if the IDEA extension is available. */
57    
58    
59  static int check_keyring (char ** r_path);  static int check_keyring (char ** r_path);
60    
# Line 65  static int check_keyring (char ** r_path Line 63  static int check_keyring (char ** r_path
63  char*  char*
64  multi_gnupg_path (int strict)  multi_gnupg_path (int strict)
65  {  {
66      static char buf[256+64];      static char buf[MAX_PATH+64];
     BOOL ec;  
67    
68      /* MSDN: buf must be at least MAX_PATH=256 bytes */      /* MSDN: buf must be at least MAX_PATH=256 bytes */
69      memset (buf, 0, sizeof (buf));      memset (buf, 0, sizeof (buf));
70      /* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */      if (!SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE)) {
71      ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE);          log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed with: %d\r\n",
     if (ec != 1) {  
         log_debug ("multi_gnupg_path: SHGetSpecialFolderPath() failed\r\n",  
72                     (int)GetLastError ());                     (int)GetLastError ());
73          return NULL;          return NULL;
74      }      }
# Line 89  multi_gnupg_path (int strict) Line 84  multi_gnupg_path (int strict)
84  char*  char*
85  get_gnupg_path (void)  get_gnupg_path (void)
86  {  {
87      char *path;      char *path = get_reg_entry_gpg (GPG_REG_HOME);
88        if (path && dir_exist_check (path) == 0)
89      path = get_reg_entry_gpg (GPG_REG_HOME);          return path;
90      if (path) {      free_if_alloc (path);
91          if (dir_exist_check (path) == 0)      return multi_gnupg_path (1);
             return path;  
         free_if_alloc (path);  
     }  
     path = multi_gnupg_path (1);  
     return path;  
92  }  }
93    
94    
# Line 106  get_gnupg_path (void) Line 96  get_gnupg_path (void)
96     A value of NULL indicates an error. */     A value of NULL indicates an error. */
97  char*  char*
98  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
99  {      {
100      char *p = NULL;      char *path = get_gnupg_path ();
     char *optfile = NULL;  
     char *path = NULL;  
     size_t nlen = 0;  
   
     path = get_gnupg_path ();  
101      if (!path)      if (!path)
102          return NULL;          return NULL;
103      nlen = strlen (path) + 64;      char *optfile = make_filename (path, GPG_CONF, NULL);
     optfile = new char[nlen + 1];  
     if (!optfile)  
         BUG (NULL);      
     _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
   
104      free_if_alloc (path);      free_if_alloc (path);
105      free_if_alloc (p);  
106      return optfile;      return optfile;
107  }  }
108    
109    
110    static char*
111    get_keyring_from_conf (const char *fname, int pub)
112    {
113        config_file_t opt;
114        conf_option_t e;
115        char *kring = NULL;
116    
117        if (parse_config (fname, &opt))
118            return NULL;
119        if (pub)
120            e = conf_find_option (opt, "keyring");
121        else
122            e = conf_find_option (opt, "secret-keyring");
123        if (e != NULL)
124            kring = m_strdup (e->val);
125        release_config (opt);
126    
127        return kring;
128    }
129    
130    
131  /* Return the full path of the keyring. If @pub is 1, the public  /* Return the full path of the keyring. If @pub is 1, the public
132     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
133  char*  char*
134  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
135  {      {    
136      char *optfile = NULL;      char *optfile;
137      char *path = NULL;      char *path;
138      char *keyring = NULL;      char *keyring;
139    
140      path = get_gnupg_path ();      path = get_gnupg_path ();
141      if (!path)      if (!path)
# Line 148  get_gnupg_keyring (int pub, int strict) Line 149  get_gnupg_keyring (int pub, int strict)
149          free_if_alloc (path);          free_if_alloc (path);
150          return keyring;          return keyring;
151      }      }
152      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      if (file_exist_check (keyring) ||
153            (pub && get_file_size (keyring) == 0)) {
154          free_if_alloc (keyring);          free_if_alloc (keyring);
155          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
156          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
157            free_if_alloc (optfile);
158      }      }
159      free_if_alloc (path);      free_if_alloc (path);
160      free_if_alloc (optfile);      
161      return keyring;      return keyring;
162  }  }
163    
# Line 162  get_gnupg_keyring (int pub, int strict) Line 165  get_gnupg_keyring (int pub, int strict)
165  /* Return the full path (with the gpg exe name). First the registry is scanned  /* Return the full path (with the gpg exe name). First the registry is scanned
166     for the entry 'gpgProgram'. If it wasn't set, the default path is the     for the entry 'gpgProgram'. If it wasn't set, the default path is the
167     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
168  char*  char*
169  get_gnupg_prog (void)  get_gnupg_prog (void)
170  {      {    
171      char *p;      char *path;
172      char *pgm = NULL;      char *pgm;
173    
174      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
175      if (!p) {      if (pgm)
176          char *path = get_gnupg_path ();          return pgm;
177          if (!path)      path = get_gnupg_path ();
178              return NULL;      if (!path)
179          pgm = make_filename (path, "gpg", "exe");          return NULL;    
180          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
181      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
182      return pgm;      return pgm;
183  }  }
184    
# Line 189  get_gnupg_prog (void) Line 186  get_gnupg_prog (void)
186  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
187     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
188     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
189  static char *  static char*
190  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
191  {      {    
192      gpgme_key_t key, pk;      gpgme_key_t key, pk;
# Line 198  default_key_from_cache (int *ret_no_usea Line 195  default_key_from_cache (int *ret_no_usea
195      char *keyid = NULL;      char *keyid = NULL;
196    
197      sec = keycache_get_ctx (0);      sec = keycache_get_ctx (0);
     if (!sec)  
         BUG (0);  
198      pub = keycache_get_ctx (1);      pub = keycache_get_ctx (1);
199      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
200      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
# Line 211  default_key_from_cache (int *ret_no_usea Line 206  default_key_from_cache (int *ret_no_usea
206          }          }
207      }      }
208      if (!keyid)      if (!keyid)
209          *ret_no_useable = 1;              *ret_no_useable = 1;
210      return keyid;      return keyid;
211  }  }
212    
# Line 221  default_key_from_cache (int *ret_no_usea Line 216  default_key_from_cache (int *ret_no_usea
216     Return value: 0 on success. */     Return value: 0 on success. */
217  int  int
218  gnupg_load_config (void)  gnupg_load_config (void)
219  {  {    
220      int rc;      config_file_t opt;
     gpg_optfile_t opt;  
     gpg_option_t o;  
221      char *conf;      char *conf;
222        int rc = 0;
223            
224      conf = get_gnupg_cfgfile ();      conf = get_gnupg_cfgfile ();
225      if (!conf)      if (!conf)
226          return -1;          return -1;
227      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
228          free_if_alloc (conf);          free_if_alloc (conf);
229          return -1;          return -1;
230      }      }
231      o = find_option (opt, "ask-cert-level");      free_if_alloc (conf);
232      if (o)      if (conf_find_option (opt, "ask-cert-level"))
233          reg_prefs.gpg.ask_cert_level = 1;          reg_prefs.gpg.ask_cert_level = 1;
234      o = find_option (opt, "ask-cert-expire");      if (conf_find_option (opt, "ask-cert-expire"))
     if (o)  
235          reg_prefs.gpg.ask_cert_expire = 1;          reg_prefs.gpg.ask_cert_expire = 1;
236      release_gpg_options (opt);      /* The 'textmode' option for GPG is useful for text files
237      free_if_alloc (conf);         but it breaks the output of any binary data. Thus we return
238      return 0;         a warning here to inform the user that binary output is broken. */
239        if (conf_find_option (opt, "textmode"))
240            rc = -2;
241        release_config (opt);
242    
243        return rc;
244  }  }
245    
246    
# Line 253  extract_keyid (const char *val) Line 250  extract_keyid (const char *val)
250  {      {    
251      size_t len = strlen (val);      size_t len = strlen (val);
252    
253      if (len > 1 && val[len-1] == '!') {      if (len > 1 && val[len-1] == '!')
254          char *p = new char[len+1];          return substr (val, 0, len-1);
         if (!p)  
             BUG (0);  
         memset (p, 0, len+1);  
         memcpy (p, val, len-1);  
         return p;  
     }  
255      return m_strdup (val);      return m_strdup (val);
256  }  }
257    
258    
259    /* Return the default key.
260       This can be either a substring or a key ID. */
261  char*  char*
262  get_gnupg_default_key (void)  get_gnupg_default_key (void)
263  {      {    
264      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
265      gpg_option_t e;      conf_option_t e;
266      char *keyid = NULL, *optfile = NULL;      char *keyid = NULL, *optfile = NULL;
267      int no_usable=0, rc = 0;      int no_usable=0;
268    
269      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
270      if (!optfile)      if (!optfile)
271          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
272      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
273          free_if_alloc (optfile);          free_if_alloc (optfile);
274          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
275      }      }
276      e = find_option (opt, "default-key");      /* First we search for config entries which specify a default key. */
277        e = conf_find_option (opt, "default-key");
278      if (!e)      if (!e)
279          e = find_option (opt, "local-user");          e = conf_find_option (opt, "local-user");
280      if (e)      if (e)
281          keyid = extract_keyid (e->val);          keyid = extract_keyid (e->val);
282    
283      free_if_alloc (optfile);      free_if_alloc (optfile);
284      release_gpg_options (opt);      release_config (opt);
285    
286        /* If no entry in the config has been found, we get a key
287           from the key cache. */
288      if (!keyid)      if (!keyid)
289          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
290      return keyid;      return keyid;
# Line 327  check_gnupg_prog (void) Line 323  check_gnupg_prog (void)
323    
324  static int  static int
325  parse_version_nr (const char *buf, int *major, int *minor, int *patch)  parse_version_nr (const char *buf, int *major, int *minor, int *patch)
326  {  {  
327      char tmp[8];      char *p;
328      int i;      char *tmp = m_strdup(buf);
329            
330      i=0;      int pos = 0;
331      while (buf && *buf != '.' && i < 8)      while ((p = strsep(&tmp, ".")) != NULL) {
332          tmp[i++] = *buf++;          switch (++pos) {
333      tmp[i] = 0; buf++;          case 1: *major = atoi (p); break;
334      *major = atoi (tmp);          case 2: *minor = atoi (p); break;
335      i=0;          case 3: *patch = atoi (p); break;
336      while (buf && *buf != '.' && i < 8)          }
337          tmp[i++] = *buf++;      }
338      tmp[i] = 0; buf++;      delete[] tmp;  
339      *minor = atoi (tmp);      if (pos != 3)
340      i=0;          return -1;  
     while (buf && isdigit (*buf) && i < 8)  
         tmp[i++] = *buf++;  
     tmp[i] = 0;  
     *patch = atoi (tmp);  
341      return 0;      return 0;
342  }  }
343    
# Line 357  int Line 349  int
349  check_gnupg_engine (const char *need_gpg_ver,  check_gnupg_engine (const char *need_gpg_ver,
350                      int *r_major, int *r_minor, int *r_patch)                      int *r_major, int *r_minor, int *r_patch)
351  {  {
     gpgme_ctx_t ctx;  
352      gpgme_engine_info_t inf;      gpgme_engine_info_t inf;
353      char *eng = NULL;      char *eng = NULL;
354      int major=0, minor=0, patch=0;      int major=0, minor=0, patch=0;
# Line 369  check_gnupg_engine (const char *need_gpg Line 360  check_gnupg_engine (const char *need_gpg
360                            &need_major, &need_minor, &need_patch))                            &need_major, &need_minor, &need_patch))
361          return 1;          return 1;
362            
363      gpgme_new (&ctx);      if (gpgme_get_engine_info (&inf))
364      inf = gpgme_ctx_get_engine_info (ctx);       return -1;
     if (!inf) {  
         gpgme_release (ctx);  
         return -1;  
     }  
365    
366      /* We need to exec GPG again to find out if IDEA is available. */      /* We need to exec GPG again to find out if IDEA is available. */
367      if (gpg_get_version (&eng))      if (gpg_get_version (&eng))
368          return -1;       return -1;
369      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
370          idea_available = 1;          idea_available = 1;
371      safe_free (eng);      safe_free (eng);
372      if (parse_version_nr (inf->version, &major, &minor, &patch)) {    
373          gpgme_release (ctx);      if (parse_version_nr (inf->version, &major, &minor, &patch))
374          return 1;          return 1;
     }  
     gpgme_release (ctx);  
375    
376      if (major > need_major)      if (major > need_major)
377          rc = 0;          rc = 0;
# Line 404  check_gnupg_engine (const char *need_gpg Line 389  check_gnupg_engine (const char *need_gpg
389  }  }
390    
391    
392  int  /* Count the keyring entries in the gpg.conf file.
393  check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)     Return value: 0 on success. */
394    static int
395    cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
396  {  {
397      gpg_optfile_t opt;          config_file_t opt;    
398      gpg_option_t e;      conf_option_t e;
399    
400      *r_secrings = 0;      *r_secrings = 0;
401      *r_pubrings = 0;      *r_pubrings = 0;
     if (parse_gpg_options (fname, &opt))  
         return WPTERR_FILE_OPEN;  
402    
403        if (parse_config (fname, &opt))
404            return WPTERR_FILE_OPEN;
405      for (e = opt->list; e; e = e->next) {      for (e = opt->list; e; e = e->next) {
406          if (!strcmp( e->name, "secret-keyring")) {          if (!strcmp (e->name, "secret-keyring")) {
407              if (!file_exist_check (e->val))              if (!file_exist_check (e->val))
408                  r_secrings[0]++;                  r_secrings[0]++;
409          }          }
# Line 425  check_gnupg_cfgfile (const char *fname, Line 412  check_gnupg_cfgfile (const char *fname,
412                  r_pubrings[0]++;                  r_pubrings[0]++;
413          }          }
414      }      }
415      release_gpg_options (opt);      release_config (opt);
416      return 0;      return 0;
417  }  }
418    
# Line 436  check_gnupg_cfgfile (const char *fname, Line 423  check_gnupg_cfgfile (const char *fname,
423  static void  static void
424  create_empty_keyring (int _pub)  create_empty_keyring (int _pub)
425  {  {
426      char *name;      char *name = get_gnupg_keyring (_pub, 0);
     FILE *fp;  
   
     name = get_gnupg_keyring (_pub, 0);  
427      if (name && file_exist_check (name) != 0) {      if (name && file_exist_check (name) != 0) {
428          fp = fopen (name, "ab");          FILE *fp = fopen (name, "ab");
429          if (fp != NULL)          if (fp != NULL)
430              fclose (fp);              fclose (fp);
431      }      }
# Line 476  gnupg_access_files (void) Line 460  gnupg_access_files (void)
460              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
461          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
462          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
463              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
464              if (!rc && secrings > 0 && pubrings > 0) {              if (!rc && secrings > 0 && pubrings > 0) {
465                  free_if_alloc (optfile);                  free_if_alloc (optfile);
466                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
# Line 496  gnupg_access_files (void) Line 480  gnupg_access_files (void)
480  }  }
481    
482    
 static int  
 create_gpg_options (void)  
 {  
     FILE *fp;  
     char *s, *optfile;  
   
     s = get_gnupg_path ();  
     if (!s)  
         return WPTERR_FILE_CREAT;  
     optfile = make_filename (s, GPG_CONF, NULL);  
     fp = fopen (optfile, "wb");  
     if (!fp) {  
         return WPTERR_FILE_CREAT;  
         goto fail;  
     }  
     fwrite (options_skel, 1, strlen (options_skel), fp);  
     fclose (fp);  
   
 fail:  
     free_if_alloc (s);  
     free_if_alloc (optfile);  
     return 0;  
 }  
   
483    
484  /* Return the contents of the options file as a char buf. */  /* Return the contents of the options file as a char buf. */
485  char*  char*
486  get_gnupg_config (void)  get_gnupg_config (void)
487  {  {
488      FILE *fp;      FILE *fp;
489      char *p = NULL, *optfile = NULL;      char *p = NULL, *optfile;
490      int fsize, rc = 0;      int fsize;
491                    
492      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
493      if (optfile == NULL)      if (!optfile)
494          return NULL;          return NULL;
495      fsize = get_file_size (optfile);      fsize = get_file_size (optfile);
496      if (!fsize) {      if (fsize < 1 || fsize > 100000)
497          rc = create_gpg_options ();          goto leave; /* too large or does not exist */
498          if (rc)      
499              return NULL;      fp = fopen (optfile, "rb");
500          fsize = get_file_size (optfile);      if (!fp)
501      }          goto leave;
     if (fsize > 100000)  
         goto leave; /* too large */  
502      p = new char[fsize+1];      p = new char[fsize+1];
503      if (!p)      if (!p)
504          BUG (NULL);          BUG (NULL);
     fp = fopen( optfile, "rb" );  
     if (!fp) {  
         free_if_alloc (p);  
         return NULL;  
     }  
505      fread (p, 1, fsize, fp);      fread (p, 1, fsize, fp);
506      fclose (fp);      fclose (fp);
507      p[fsize] = '\0';      p[fsize] = '\0';
508      free_if_alloc (optfile);      
   
509  leave:  leave:
510        free_if_alloc (optfile);
511      return p;      return p;
512  }  }
513    
# Line 564  leave: Line 517  leave:
517  int  int
518  set_gnupg_default_key (const char *key)  set_gnupg_default_key (const char *key)
519  {  {
520      gpg_optfile_t opt;      config_file_t opt;
521      gpg_option_t e;      conf_option_t e;
522      char *optfile = NULL;      char *optfile = NULL;
523      int rc = 0;      int rc = 0;
524    
525      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
526      if (!optfile)      if (!optfile)
527          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
528      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
529      if (rc) {      if (rc) {
530          free_if_alloc (optfile);          free_if_alloc (optfile);
531          return WPTERR_GENERAL;          return WPTERR_GENERAL;
532      }      }
533      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
534      if (e && !key)      if (e && !key)
535          e->used = 0;          e->used = 0;
536      else if (e) {      else if (e) {
# Line 586  set_gnupg_default_key (const char *key) Line 539  set_gnupg_default_key (const char *key)
539          e->used = 1;          e->used = 1;
540      }      }
541      else if (key)      else if (key)
542          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
543      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
544    
545      free_if_alloc (optfile);      free_if_alloc (optfile);
546      release_gpg_options (opt);      release_config (opt);
   
547      return rc;      return rc;
548  }  }
549    
550    
551  /* Set the contents of the options file. */  /* Set the contents of the options file. */
552  int  int
553  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
554  {  {
555      FILE *fp;        FILE *fp;  
556      char *optfile = NULL;      char *optfile;
557    
558      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
559      if( optfile == NULL )      if (!optfile)
560          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
561    
562      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
563      if( fp == NULL ) {      if (!fp) {
564          free_if_alloc( optfile );          free_if_alloc (optfile);
565          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
566      }      }
567      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
568      fclose( fp );      fclose (fp);
569      free_if_alloc( optfile );      free_if_alloc (optfile);
570      return 0;      return 0;
571  } /* set_gnupg_options */  }
572    
573  /*  
574   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
575   */     Return value: 0 on success. */
576    static int
577    check_arg_file_exist (const char *buf)
578    {
579        const char *s = "load-extension ";
580    
581        /* XXX: this is a bit of a kludge because we just
582                detect errors for 'load-extension'. */
583        if (!strncmp (buf, s, strlen (s)))
584            buf += strlen (s);
585        else
586            return 0;
587        return file_exist_check (buf);
588    }
589    
590    
591    /* Check if the line contains a valid GPG argument. */
592  static int  static int
593  check_line( const char *buf )  check_line (const char *buf)
594  {  {
595      int j, len;      int j, len;
596      int rc = 0;      int rc = 0;
597    
598      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
599          return 1;          return 1;
600      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
601      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
602          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
603          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
604      }      }
   
605      return rc;      return rc;
606  } /* check_line */  }
607    
608    
609  int  int
610  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
611  {  {
612      char line[1024];      char line[1024];
613      int nbytes = 0;      int nbytes = 0, lineno=0;
614      unsigned j;      unsigned j;
615                    
616      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
617          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
618          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
619              line[nbytes] = '\0';              line[nbytes] = '\0';
620              if( !check_line( line ) ) {              lineno++;
621                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
622                    if (showerr)
623                        log_box ("GPG Config File", MB_ERR,
624                                 "gpg.conf:%d: invalid keyword '%s'",
625                                 lineno, line);
626                  return 1;                        return 1;      
627              }              }
628                if (check_arg_file_exist (line))
629                    return WPTERR_FILE_EXIST;
630              nbytes = 0;              nbytes = 0;
631          }                }
632      }      }
   
633      return 0;      return 0;
634  } /* check_gnupg_options */  }
635    
636    
637  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
638  static int  static int
639  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
640  {  {
641      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
642    
643      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
644      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
645      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL,      if (fd == INVALID_HANDLE_VALUE)
                      OPEN_ALWAYS, 0, NULL);  
     if (fd == INVALID_HANDLE_VALUE) {  
         free_if_alloc (path);  
         free_if_alloc (file);  
646          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
647      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
648      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
649      return 0;      return 0;
650  }  }
651    
652    
653  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
654  static void  static void
655  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
656  {                {              
657      ctx->modified = 0;      ctx->modified = 0;
658    
659      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
660          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
661          ctx->modified = 1;          ctx->modified = 1;
662        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
663      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
664          ctx->modified = 0;          ctx->modified = 0;
665    
# Line 708  check_last_gnupg_access (gpg_watcher_s * Line 668  check_last_gnupg_access (gpg_watcher_s *
668  }  }
669    
670    
671  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
672  void  void
673  init_gnupg_table (void)  init_gnupg_table (void)
674  {        {      
675      char *p;      char *path;
676      int j;      int j;
677    
678        path = get_gnupg_path ();
679      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
680          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
681          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
682          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
683          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
684          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
685      }      }
686        free_if_alloc (path);
687  }  }
688    
689    
690    /* Release the GPG monitor table. */
691  void  void
692  free_gnupg_table (void)  free_gnupg_table (void)
693  {  {
694      int j;      for (int j=0; j < gpg_table_count; j++) {
   
     for (j=0; j < gpg_table_count; j++)  
695          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
696            free_if_alloc (gpg_table[j].fpath_object);
697        }
698  }  }
699    
700    
701  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
702  int  int
703  keyring_check_last_access (void)  keyring_check_last_access (void)
704  {        {
705      int rc, j;      int nfiles;
706    
707      rc = 0;      nfiles = 0;
708      for (j = 0; j < gpg_table_count; j++) {      for (int pos = 0; pos < gpg_table_count; pos++) {
709          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
710          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
711          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
712              rc++;                    nfiles++;
713      }      }
714    
715      return rc;      return nfiles;
716  }  }
717    
718    
# Line 773  gnupg_check_file_ext (const char *fname, Line 735  gnupg_check_file_ext (const char *fname,
735              *r_type = PGP_SIG;              *r_type = PGP_SIG;
736          return "SIGNED";          return "SIGNED";
737      }      }
738      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
739                  !stricmp (file_ext, ".pgp")) {
740          if (r_type)          if (r_type)
741              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
742          return "ENCRYPTED";          return "ENCRYPTED";
# Line 782  gnupg_check_file_ext (const char *fname, Line 745  gnupg_check_file_ext (const char *fname,
745  }  }
746    
747    
748  char*  /* Check if the device where file @fname is stored on, is write-protected. */
 get_gnupg_keyring_from_options (const char * fname, int pub)  
 {  
     gpg_optfile_t opt;  
     gpg_option_t e;  
     char * kring = NULL;  
     int rc = 0;  
   
     rc = parse_gpg_options (fname, &opt);  
     if (rc)  
         return NULL;  
     if (pub)  
         e = find_option (opt, "keyring");  
     else  
         e = find_option (opt, "secret-keyring");  
     if (e)  
         kring = m_strdup (e->val);  
     release_gpg_options (opt);  
   
     return kring;  
 }  
   
   
   
 /* XXX: does not work with write-protected floppies */  
749  static int  static int
750  my_access (const char *fname)  check_file_access (const char *fname, int mode)
751  {  {
752      HANDLE hd;      HANDLE hd;
753      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,  
754        if (!mode)
755            mode = FILE_SHARE_WRITE;
756        hd = CreateFile (fname, GENERIC_WRITE, mode,
757                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
758      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
759          return -1;          return -1;
# Line 819  my_access (const char *fname) Line 761  my_access (const char *fname)
761      return 0;      return 0;
762  }  }
763    
764        
765    /* Check the device where the file @fname is stored on, is either
766       write-protected or if the file is already opened by another process
767       exclusively. And as a result, we cannot use the file for output. */
768    int
769    gpg_check_file_permissions (const char *fname, int mode)
770    {
771        int api_mode;
772        
773        switch (mode) {
774        case 0: api_mode = FILE_SHARE_READ; break;
775        case 1: api_mode = FILE_SHARE_WRITE; break;
776        case 2: api_mode = FILE_SHARE_WRITE|FILE_SHARE_READ; break;
777        default: api_mode = FILE_SHARE_READ; break;
778        }
779    
780        return check_file_access (fname, api_mode);
781    }
782    
783    
784  /* Check the file permissions of the public keyring.  /* Check the file permissions of the public keyring.
785     If @showmsg is 1 output a message in case of errors.     If @showmsg is 1 output a message in case of errors.
# Line 853  gpg_check_permissions (int showmsg) Line 814  gpg_check_permissions (int showmsg)
814                  failed = 1;                  failed = 1;
815              }              }
816          }          }
817          if (my_access (name)) {          if (gpg_check_file_permissions (name, 1)) {
818              if (showmsg)              if (showmsg)
819                  msg_box (NULL,                  msg_box (NULL,
820                  _("You do not have file access to modify the contents of\n"                  _("You do not have file access to modify the contents of\n"
# Line 876  gpg_check_permissions (int showmsg) Line 837  gpg_check_permissions (int showmsg)
837  int  int
838  gnupg_check_homedir (void)  gnupg_check_homedir (void)
839  {        {      
840      char *homedir = NULL;      char *homedir;
841      int val = 0;      int val;
842      int rc = 0;      int rc = 0;
843    
844      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
# Line 902  gnupg_check_homedir (void) Line 863  gnupg_check_homedir (void)
863    
864    
865  int  int
866    gnupg_import_keypair (void)
867    {
868        const char *file;
869        gpgme_error_t err;
870        GPGME gpgme;
871        HWND hwnd = GetDesktopWindow ();
872    
873        file = get_fileopen_dlg (hwnd, _("Please choose your Key Pair"),
874                                 "GPG Key File (*.gpg)\0*.gpg\0"
875                                 "GPG Armored Key File (*.asc)\0*.asc\0\0",
876                                 NULL);
877        if (file == NULL)
878            return WPTERR_FILE_OPEN;
879        err = gpgme.importFromFile (file);
880        if (err)
881            msg_box (hwnd, gpgme_strerror (err), _("WinPT Error"), MB_ERR);
882        else
883            msg_box (hwnd, _("Key pair successfully imported."), "WinPT", MB_OK);
884        return 0;
885    }
886    
887    int
888  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
889  {  {
890      const char * pring, * sring;      const char *pring, *sring;
891      char * file = NULL, * path = NULL;      char *file = NULL, *path;
892      int id = 0, rc = 0;      int id, rc = 0;
893      HWND hwnd;      HWND hwnd;
894            
895      path = get_gnupg_path ();      path = get_gnupg_path ();
# Line 915  gnupg_copy_keyrings (void) Line 898  gnupg_copy_keyrings (void)
898      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
899    
900      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
901                                "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
902      if (!pring) {      if (!pring) {
903          msg_box (hwnd, _("No keyring was chosen. Exit."),          msg_box (hwnd, _("No keyring was chosen. Exit."),
904                   _("WinPT Error"), MB_ERR);                   _("WinPT Error"), MB_ERR);
905          free_if_alloc (path);          free_if_alloc (path);
906          return WPTERR_GENERAL;          return WPTERR_GENERAL;
907      }      }
908      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
909      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
910          id = msg_box (hwnd, _("Overwrite old public keyring?"),          id = msg_box (hwnd, _("Overwrite old public keyring?"),
911                        "WinPT", MB_INFO|MB_YESNO);                        "WinPT", MB_INFO|MB_YESNO);
912          if (id == IDNO)          if (id == IDNO)
913              goto fail;              goto fail;
914      }      }
915      if (!CopyFile (pring, file, FALSE)) {      if (!CopyFile (pring, file, FALSE)) {
916          msg_box (hwnd, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("Could not copy public keyring."),
917                     _("WinPT Error"), MB_ERR);
918          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
919          goto fail;          goto fail;
920      }      }
# Line 951  gnupg_copy_keyrings (void) Line 935  gnupg_copy_keyrings (void)
935              goto fail;              goto fail;
936      }      }
937      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
938          msg_box (NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy secret keyring."), _("WinPT Error"), MB_ERR);
939          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
940      }      }
941    
# Line 966  fail: Line 950  fail:
950  void  void
951  gnupg_backup_options (void)  gnupg_backup_options (void)
952  {  {
953      char *cfgfile = NULL;      char bak[MAX_PATH+32];
     char bak[512];  
954    
955      cfgfile = get_gnupg_cfgfile ();      char *cfgfile = get_gnupg_cfgfile ();
956      if (!cfgfile)      if (!cfgfile)
957          return;          return;
958      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);      _snprintf (bak, DIM (bak)-1, "%s.bak", cfgfile);
# Line 986  backup_one_file (const char *srcpath, co Line 969  backup_one_file (const char *srcpath, co
969      BOOL rc;      BOOL rc;
970    
971      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
972      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
973      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
974      free_if_alloc (src);      free_if_alloc (src);
975      free_if_alloc (dst);      free_if_alloc (dst);
# Line 1014  check_keyring (char **r_path) Line 993  check_keyring (char **r_path)
993      if (!*r_path)      if (!*r_path)
994          return 0;          return 0;
995      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
996      if (!p || get_file_size (p) <= 0)      if (get_file_size (p) <= 0)
997          return 0;          return 0;
998    
999      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
1000      if (!opt)      if (!opt)
1001          BUG (0);          BUG (0);
1002      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
1003      free_if_alloc (opt);      free_if_alloc (opt);
1004      free_if_alloc (p);      free_if_alloc (p);
1005      if (!name)      if (!name)
# Line 1044  static char* Line 1023  static char*
1023  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1024  {  {
1025      struct tm *tm;      struct tm *tm;
1026        const char *fmt;
1027      char *p;      char *p;
1028      time_t t;      time_t t;
1029    
1030      t = time (NULL);      t = time (NULL);
1031      tm = localtime (&t);      tm = localtime (&t);
1032      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1033        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1034      if (!p)      if (!p)
1035          BUG (0);          BUG (0);
1036      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1037      return p;      return p;
1038  }  }
1039    
# Line 1064  get_backup_name (const char *templ) Line 1045  get_backup_name (const char *templ)
1045  void  void
1046  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1047  {  {
1048      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1049      char *name=NULL;      char *name;
1050      int rc;      int rc;
1051    
1052      if (!auto_backup)      if (!auto_backup)
# Line 1073  gnupg_backup_keyrings (int auto_backup, Line 1054  gnupg_backup_keyrings (int auto_backup,
1054      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1055      check_keyring (&srcpath);      check_keyring (&srcpath);
1056      if (backup_mode == 1) {      if (backup_mode == 1) {
1057          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1058               and destination folder will be the same. */
1059            dstpath = get_gnupg_path ();
1060          check_keyring (&dstpath);          check_keyring (&dstpath);
1061      }      }
1062      else if (backup_mode == 2) {      else if (backup_mode == 2) {
# Line 1081  gnupg_backup_keyrings (int auto_backup, Line 1064  gnupg_backup_keyrings (int auto_backup,
1064          FILE *fp;          FILE *fp;
1065    
1066          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1067          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1068          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1069          if (!fp)          if (!fp)
1070              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1071                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1072                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1073          else {          else {
1074              rc = 0;              rc = 0;
1075              fclose (fp);              fclose (fp);
1076              remove (tmpfile);              DeleteFile (tmpfile);
1077          }          }
1078          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1079          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1080                free_if_alloc (dstpath);
1081                free_if_alloc (srcpath);
1082              return;              return;
1083            }
1084      }      }
1085      else {      else {
1086          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1087            free_if_alloc (srcpath);
1088          return;          return;
1089      }      }
1090      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
# Line 1112  gnupg_backup_keyrings (int auto_backup, Line 1097  gnupg_backup_keyrings (int auto_backup,
1097  }  }
1098    
1099    
 /* Display GPG error from file if possible. */  
 void  
 gnupg_display_error (void)  
 {        
     char tmpath[512], *errstr;  
     size_t size = 0;  
     FILE *fp;  
   
     get_temp_name (tmpath, sizeof (tmpath), "gpg_stderr");  
     size = get_file_size (tmpath);  
     if (file_exist_check (tmpath) || size <= 0)  
         return;  
     fp = fopen( tmpath, "rb" );  
     if (!fp) {  
         msg_box (NULL, _("No GPG error description available."),  
                  _("GPG Error"), MB_INFO);  
         return;  
     }  
     errstr = new char[size+1];  
     if (!errstr)  
         BUG (0);  
     fread (errstr, 1, size, fp);  
     errstr[size] = '\0';  
     fclose (fp);  
     msg_box (NULL, errstr, _("GPG Error"), MB_INFO);  
     free_if_alloc (errstr);  
 }  
   
   
   
1100  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1101     Return value: 0 for success. */     Return value: 0 for success. */
1102  int  int

Legend:
Removed from v.222  
changed lines
  Added in v.407

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26