/[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 137 by twoaday, Mon Jan 9 14:01:51 2006 UTC revision 273 by twoaday, Fri Dec 8 10:22:17 2006 UTC
# Line 1  Line 1 
1  /* wptGPG.cpp - GnuPG configuration  /* wptGPG.cpp - GnuPG configuration
2   *      Copyright (C) 2001-2005 Timo Schulz   *      Copyright (C) 2001-2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 43  Line 43 
43  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */  #define GPG_REG_EXE     "gpgProgram"    /* registry name for the binary. */
44  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */  #define GPG_REG_HOME    "HomeDir"       /* registry name of the home dir. */
45    
46  struct gpg_watcher_s {  /* Context to monitor GPG file changes. */
47      FILETIME    last_access;  struct gpg_monitor_s {
48        FILETIME    last_access;    /* last write access. */
49      FILETIME    access;      FILETIME    access;
50      char        *object;      char        *object;        /* name of the object. */
51      int         modified;      char        *fpath_object;  /* full path to the object. */
52        int         modified;       /* 1 = modified. */
53  };  };
54    typedef struct gpg_monitor_s *gpg_monitor_t;
55    
56    static const char *gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"};
57  /* 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];  
58  static int gpg_table_count = DIM (gpg_table);  static int gpg_table_count = DIM (gpg_table);
59    
60  int idea_available = 0;  int idea_available = 0; /* if the IDEA extension is available. */
61    
62    
63  static int check_keyring (char ** r_path);  static int check_keyring (char ** r_path);
64    
# Line 65  static int check_keyring (char ** r_path Line 67  static int check_keyring (char ** r_path
67  char*  char*
68  multi_gnupg_path (int strict)  multi_gnupg_path (int strict)
69  {  {
70      static char buf[256+64];      static char buf[MAX_PATH+64];
71      BOOL ec;      BOOL ec;
72    
73      /* MSDN: buf must be at least MAX_PATH=256 bytes */      /* MSDN: buf must be at least MAX_PATH=256 bytes */
# Line 92  get_gnupg_path (void) Line 94  get_gnupg_path (void)
94      char *path;      char *path;
95    
96      path = get_reg_entry_gpg (GPG_REG_HOME);      path = get_reg_entry_gpg (GPG_REG_HOME);
97      if (path) {      if (path && dir_exist_check (path) == 0)
98          if (dir_exist_check (path) == 0)          return path;
99              return path;      free_if_alloc (path);
100          free_if_alloc (path);      return multi_gnupg_path (1);
     }  
     path = multi_gnupg_path (1);  
     return path;  
101  }  }
102    
103    
# Line 106  get_gnupg_path (void) Line 105  get_gnupg_path (void)
105     A value of NULL indicates an error. */     A value of NULL indicates an error. */
106  char*  char*
107  get_gnupg_cfgfile (void)  get_gnupg_cfgfile (void)
108  {      {
109      char *p = NULL;      char *optfile;
110      char *optfile = NULL;      char *path;
     char *path = NULL;  
     size_t nlen = 0;  
111    
112      path = get_gnupg_path ();      path = get_gnupg_path ();
113      if (!path)      if (!path)
114          return NULL;          return NULL;
115      p = get_reg_entry_gpg ("OptFile");      optfile = make_filename (path, GPG_CONF, NULL);
     if (p && !strcmp (p, "")) {  
         nlen = strlen (path) + 64;  
         optfile = new char[nlen + 1];  
         if (!optfile)  
             BUG (0);  
         _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
     }  
     else if (p) {  
         nlen = strlen( p ) + 4;  
         optfile = new char[nlen + 1];  
         if (!optfile)  
             BUG (NULL);  
         _snprintf (optfile, nlen, "%s", p);  
     }  
     else {  
         nlen = strlen (path) + 64;  
         optfile = new char[nlen + 1];  
         if( !optfile)  
             BUG (NULL);  
         _snprintf (optfile, nlen, "%s\\"GPG_CONF, path);  
     }  
116      free_if_alloc (path);      free_if_alloc (path);
117      free_if_alloc (p);  
118      return optfile;      return optfile;
119  }  }
120    
121    
122    static char*
123    get_keyring_from_conf (const char *fname, int pub)
124    {
125        config_file_t opt;
126        conf_option_t e;
127        char *kring = NULL;
128        int rc;
129    
130        rc = parse_config (fname, &opt);
131        if (rc)
132            return NULL;
133        if (pub)
134            e = conf_find_option (opt, "keyring");
135        else
136            e = conf_find_option (opt, "secret-keyring");
137        if (e != NULL)
138            kring = m_strdup (e->val);
139        release_config (opt);
140    
141        return kring;
142    }
143    
144    
145  /* 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
146     keyring is return, otherwise the secret keyring. */     keyring is return, otherwise the secret keyring. */
147  char*  char*
148  get_gnupg_keyring (int pub, int strict)  get_gnupg_keyring (int pub, int strict)
149  {      {    
150      char *optfile = NULL;      char *optfile;
151      char *path = NULL;      char *path;
152      char *keyring = NULL;      char *keyring;
153    
154      path = get_gnupg_path ();      path = get_gnupg_path ();
155      if (!path)      if (!path)
# Line 164  get_gnupg_keyring (int pub, int strict) Line 163  get_gnupg_keyring (int pub, int strict)
163          free_if_alloc (path);          free_if_alloc (path);
164          return keyring;          return keyring;
165      }      }
166      if (file_exist_check (keyring) || pub && get_file_size (keyring) == 0) {      if (file_exist_check (keyring) ||
167            pub && get_file_size (keyring) == 0) {
168          free_if_alloc (keyring);          free_if_alloc (keyring);
169          optfile = make_filename (path, GPG_CONF, NULL);          optfile = make_filename (path, GPG_CONF, NULL);
170          keyring = get_gnupg_keyring_from_options (optfile, pub);          keyring = get_keyring_from_conf (optfile, pub);
171            free_if_alloc (optfile);
172      }      }
173      free_if_alloc (path);      free_if_alloc (path);
174      free_if_alloc (optfile);      
175      return keyring;      return keyring;
176  }  }
177    
# Line 178  get_gnupg_keyring (int pub, int strict) Line 179  get_gnupg_keyring (int pub, int strict)
179  /* 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
180     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
181     appended string 'gpg.exe' is used. */     appended string 'gpg.exe' is used. */
   
 /* FIXME:  Use gpgme's engine info here. */  
182  char*  char*
183  get_gnupg_prog (void)  get_gnupg_prog (void)
184  {      {    
185      char *p;      char *path;
186      char *pgm = NULL;      char *pgm;
187    
188      p = get_reg_entry_gpg (GPG_REG_EXE);      pgm = get_reg_entry_gpg (GPG_REG_EXE);
189      if (!p) {      if (pgm)
190          char *path = get_gnupg_path ();          return pgm;
191          if (!path)      path = get_gnupg_path ();
192              return NULL;      if (!path)
193          pgm = make_filename (path, "gpg", "exe");          return NULL;    
194          free_if_alloc (path);      pgm = make_filename (path, "gpg", "exe");
195      }      free_if_alloc (path);
     else {  
         pgm = m_strdup (p);  
         free_if_alloc (p);  
     }  
196      return pgm;      return pgm;
197  }  }
198    
# Line 205  get_gnupg_prog (void) Line 200  get_gnupg_prog (void)
200  /* Retrieve the first usable secret key from cache.  /* Retrieve the first usable secret key from cache.
201     If no usable was found, @ret_no_useable is 1.     If no usable was found, @ret_no_useable is 1.
202     Return value: the keyid of the secret key. */     Return value: the keyid of the secret key. */
203  static char *  static char*
204  default_key_from_cache (int *ret_no_useable)  default_key_from_cache (int *ret_no_useable)
205  {  {    
206        gpgme_key_t key, pk;
207        gpg_keycache_t sec, pub;
208      const char *s;      const char *s;
209      char *keyid = NULL;      char *keyid = NULL;
     gpgme_key_t key;  
     gpg_keycache_t sec = keycache_get_ctx (0);  
210    
211      if (!sec)      sec = keycache_get_ctx (0);
212          BUG (0);      pub = keycache_get_ctx (1);
213      gpg_keycache_rewind (sec);      gpg_keycache_rewind (sec);
214      while (!gpg_keycache_next_key (sec, 1, &key)) {      while (!gpg_keycache_next_key (sec, 1, &key)) {
215          if (key_is_useable (key)) {          if (key_is_useable (key) && !get_pubkey (key->subkeys->keyid, &pk)) {
216              s = key->subkeys->keyid;              s = key->subkeys->keyid;
217              if (s)                  if (s)
218                  keyid = m_strdup (s+8);                  keyid = m_strdup (s+8);
219              break;              break;
220          }          }
221      }      }
# Line 235  default_key_from_cache (int *ret_no_usea Line 230  default_key_from_cache (int *ret_no_usea
230     Return value: 0 on success. */     Return value: 0 on success. */
231  int  int
232  gnupg_load_config (void)  gnupg_load_config (void)
233  {  {    
234      int rc;      config_file_t opt;
235      gpg_optfile_t opt;      char *conf;
236      gpg_option_t o;      int rc = 0;
237      char *conf = get_gnupg_cfgfile ();      
238        conf = get_gnupg_cfgfile ();
239      if (!conf)      if (!conf)
240          return -1;          return -1;
241      rc = parse_gpg_options (conf, &opt);      if (parse_config (conf, &opt)) {
     if (rc) {  
242          free_if_alloc (conf);          free_if_alloc (conf);
243          return -1;          return -1;
244      }      }
     o = find_option (opt, "ask-cert-level");  
     if (o)  
         reg_prefs.gpg.ask_cert_level = 1;  
     release_gpg_options (opt);  
245      free_if_alloc (conf);      free_if_alloc (conf);
246      return 0;      if (conf_find_option (opt, "ask-cert-level"))
247            reg_prefs.gpg.ask_cert_level = 1;
248        if (conf_find_option (opt, "ask-cert-expire"))
249            reg_prefs.gpg.ask_cert_expire = 1;
250        /* The 'textmode' option for GPG is useful for text files
251           but it breaks the output of any binary data. Thus we return
252           a warning here to inform the user that binary output is broken. */
253        if (conf_find_option (opt, "textmode"))
254            rc = -2;
255        release_config (opt);
256    
257        return rc;
258    }
259    
260    
261    /* handle the case the user added a '!' to force a subkey. */
262    static char*
263    extract_keyid (const char *val)
264    {    
265        size_t len = strlen (val);
266    
267        if (len > 1 && val[len-1] == '!')
268            return substr (val, 0, len-1);
269        return m_strdup (val);
270  }  }
271    
272    
273    /* Return the default key.
274       This can be either a substring or a key ID. */
275  char*  char*
276  get_gnupg_default_key (void)  get_gnupg_default_key (void)
277  {      {    
278      gpg_optfile_t opt = NULL;      config_file_t opt = NULL;
279      gpg_option_t e;      conf_option_t e;
280      char * keyid = NULL, * optfile = NULL;      char *keyid = NULL, *optfile = NULL;
281      int no_usable=0, rc = 0;      int no_usable=0;
282    
283      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
284      if (!optfile)      if (!optfile)
285          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
286      rc = parse_gpg_options (optfile, &opt);      if (parse_config (optfile, &opt)) {
     if (rc) {  
287          free_if_alloc (optfile);          free_if_alloc (optfile);
288          return default_key_from_cache (&no_usable);          return default_key_from_cache (&no_usable);
289      }      }
290      e = find_option( opt, "default-key" );      /* First we search for config entries which specify a default key. */
291      if ( e )      e = conf_find_option (opt, "default-key");
292          keyid = m_strdup( e->val );      if (!e)
293      if( !e ) {          e = conf_find_option (opt, "local-user");
294          e = find_option( opt, "local-user" );      if (e)
295          if( e )          keyid = extract_keyid (e->val);
296              keyid = m_strdup( e->val );  
     }  
     if( !e ) {  
         e = find_option( opt, "encrypt-to" );  
         if( e )  
             keyid = m_strdup( e->val );  
     }  
297      free_if_alloc (optfile);      free_if_alloc (optfile);
298      release_gpg_options (opt);      release_config (opt);
299    
300        /* If no entry in the config has been found, we get a key
301           from the key cache. */
302      if (!keyid)      if (!keyid)
303          keyid = default_key_from_cache (&no_usable);          keyid = default_key_from_cache (&no_usable);
304      return keyid;      return keyid;
305  } /* get_gnupg_default_key */  }
306    
307    
308  /* Check if GPG4WIN is available and if so, use the  /* Check if GPG4WIN is available and if so, use the
# Line 334  parse_version_nr (const char *buf, int * Line 345  parse_version_nr (const char *buf, int *
345      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
346          tmp[i++] = *buf++;          tmp[i++] = *buf++;
347      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
348      *major = atol( tmp );      *major = atoi (tmp);
349      i=0;      i=0;
350      while (buf && *buf != '.' && i < 8)      while (buf && *buf != '.' && i < 8)
351          tmp[i++] = *buf++;          tmp[i++] = *buf++;
352      tmp[i] = 0; buf++;      tmp[i] = 0; buf++;
353      *minor = atol (tmp);      *minor = atoi (tmp);
354      i=0;      i=0;
355      while (buf && isdigit (*buf) && i < 8)      while (buf && isdigit (*buf) && i < 8)
356          tmp[i++] = *buf++;          tmp[i++] = *buf++;
357      tmp[i] = 0;      tmp[i] = 0;
358      *patch = atol (tmp);      *patch = atoi (tmp);
359      return 0;      return 0;
360  }  }
361    
# Line 364  check_gnupg_engine (const char *need_gpg Line 375  check_gnupg_engine (const char *need_gpg
375      int rc = 1;      int rc = 1;
376    
377      /* Convert the needed GPG version to the integer format. */      /* Convert the needed GPG version to the integer format. */
378      rc = parse_version_nr (need_gpg_ver,      if (parse_version_nr (need_gpg_ver,
379                             &need_major, &need_minor, &need_patch);                            &need_major, &need_minor, &need_patch))
380      if (rc)          return 1;
         return rc;  
381            
382      gpgme_new (&ctx);      gpgme_new (&ctx);
383      inf = gpgme_ctx_get_engine_info (ctx);      inf = gpgme_ctx_get_engine_info (ctx);
# Line 377  check_gnupg_engine (const char *need_gpg Line 387  check_gnupg_engine (const char *need_gpg
387      }      }
388    
389      /* 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. */
390      if (gpg_get_version (&eng))      if (gpg_get_version (&eng)) {
391            gpgme_release (ctx);
392          return -1;          return -1;
393        }
394      if (strstr (eng, "IDEA"))      if (strstr (eng, "IDEA"))
395          idea_available = 1;          idea_available = 1;
396      free (eng);      safe_free (eng);
397      rc = parse_version_nr (inf->version, &major, &minor, &patch);      if (parse_version_nr (inf->version, &major, &minor, &patch)) {
     if (rc) {  
398          gpgme_release (ctx);          gpgme_release (ctx);
399          return rc;          return 1;
400      }      }
401        gpgme_release (ctx);
402    
403      if (major > need_major)      if (major > need_major)
404          rc = 0;          rc = 0;
# Line 404  check_gnupg_engine (const char *need_gpg Line 416  check_gnupg_engine (const char *need_gpg
416  }  }
417    
418    
419  int  /* Count the keyring entries in the gpg.conf file.
420  check_gnupg_cfgfile (const char *fname, int *r_secrings, int *r_pubrings)     Return value: 0 on success. */
421    static int
422    cfgfile_count_keyrings (const char *fname, int *r_secrings, int *r_pubrings)
423  {  {
424      gpg_optfile_t opt;          config_file_t opt;    
425      gpg_option_t e;      conf_option_t e;
     int rc = 0;  
426    
427      *r_secrings = 0;      *r_secrings = 0;
428      *r_pubrings = 0;      *r_pubrings = 0;
     rc = parse_gpg_options( fname, &opt );  
     if( rc )  
         return WPTERR_FILE_OPEN;  
429    
430      for( e = opt->list; e; e = e->next ) {      if (parse_config (fname, &opt))
431          if( !strcmp( e->name, "secret-keyring" ) ) {          return WPTERR_FILE_OPEN;
432              if( !file_exist_check( e->val ) )      for (e = opt->list; e; e = e->next) {
433            if (!strcmp (e->name, "secret-keyring")) {
434                if (!file_exist_check (e->val))
435                  r_secrings[0]++;                  r_secrings[0]++;
436          }          }
437          else if( !strcmp( e->name, "keyring" ) ) {          else if (!strcmp (e->name, "keyring")) {
438              if( !file_exist_check( e->val ) )              if (!file_exist_check (e->val))
439                  r_pubrings[0]++;                  r_pubrings[0]++;
440          }          }
441      }      }
442      release_gpg_options( opt );      release_config (opt);
443      return 0;      return 0;
444  } /* check_gnupg_cfgfile */  }
445    
446    
447  /* Usually GPG creates the pubring.gpg, secring.gpg on  /* Usually GPG creates the pubring.gpg, secring.gpg on
# Line 439  static void Line 451  static void
451  create_empty_keyring (int _pub)  create_empty_keyring (int _pub)
452  {  {
453      char *name;      char *name;
454      FILE *f;      FILE *fp;
455    
456      name = get_gnupg_keyring (_pub, 0);      name = get_gnupg_keyring (_pub, 0);
457      if (file_exist_check (name) != 0) {      if (name && file_exist_check (name) != 0) {
458          f = fopen (name, "ab");          fp = fopen (name, "ab");
459          if (f != NULL)          if (fp != NULL)
460              fclose (f);              fclose (fp);
461      }      }
462      free_if_alloc (name);      free_if_alloc (name);
463  }  }
# Line 478  gnupg_access_files (void) Line 490  gnupg_access_files (void)
490              return WPTERR_GPG_KEYRINGS;              return WPTERR_GPG_KEYRINGS;
491          rc = file_exist_check (optfile);          rc = file_exist_check (optfile);
492          if (!rc && get_file_size (optfile) > 0) {          if (!rc && get_file_size (optfile) > 0) {
493              rc = check_gnupg_cfgfile (optfile, &secrings, &pubrings);              rc = cfgfile_count_keyrings (optfile, &secrings, &pubrings);
494              if (!rc && secrings && pubrings) {              if (!rc && secrings > 0 && pubrings > 0) {
495                  free_if_alloc (optfile);                  free_if_alloc (optfile);
496                  return 0; /* found two keyrings in the option file */                  return 0; /* found two keyrings in the option file */
497              }              }
# Line 499  gnupg_access_files (void) Line 511  gnupg_access_files (void)
511    
512    
513  static int  static int
514  create_gpg_options (void)  create_gpg_conf (void)
515  {  {
516      FILE *fp;      FILE *fp;
517      char *s, *optfile;      char *s, *optfile;
518    
519      s = get_gnupg_path ();      s = get_gnupg_path ();
520      if( s == NULL )      if (!s)
521          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
522      optfile = make_filename (s, GPG_CONF, NULL);      optfile = make_filename (s, GPG_CONF, NULL);
523      fp = fopen (optfile, "wb");      fp = fopen (optfile, "wb");
524      if (fp == NULL) {        if (!fp) {
525          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
526          goto fail;          goto fail;
527      }      }
# Line 520  fail: Line 532  fail:
532      free_if_alloc (s);      free_if_alloc (s);
533      free_if_alloc (optfile);      free_if_alloc (optfile);
534      return 0;      return 0;
535  } /* create_gpg_options */  }
536    
537    
538  /*  /* Return the contents of the options file as a char buf. */
539   * Return the contents of the options file as a char buf.  char*
  */  
 char *  
540  get_gnupg_config (void)  get_gnupg_config (void)
541  {  {
542      FILE * fp;      FILE *fp;
543      char * p = NULL, * optfile = NULL;      char *p = NULL, *optfile = NULL;
544      int fsize, rc = 0;      int fsize;
545                    
546      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
547      if( optfile == NULL )      if (!optfile)
548          return NULL;          return NULL;
549      fsize = get_file_size( optfile );      fsize = get_file_size (optfile);
550      if( !fsize ) {      if (!fsize) {
551          rc = create_gpg_options( );          if (create_gpg_conf ())
         if ( rc )  
552              return NULL;              return NULL;
553          fsize = get_file_size( optfile );          fsize = get_file_size (optfile);
554      }      }
555      if( fsize > 100000 )      if (fsize > 100000)
556          goto leave; /* too large */          goto leave; /* too large */
557      p = new char[fsize+1];      p = new char[fsize+1];
558      if( p == NULL )      if (!p)
559          BUG( NULL );          BUG (NULL);
560      fp = fopen( optfile, "rb" );      fp = fopen( optfile, "rb" );
561      if( fp == NULL ) {      if (!fp) {
562          free_if_alloc( p );          free_if_alloc (p);
563          return NULL;          return NULL;
564      }      }
565      fread( p, 1, fsize, fp );      fread (p, 1, fsize, fp);
566      fclose( fp );      fclose (fp);
567      p[fsize] = '\0';      p[fsize] = '\0';
568      free_if_alloc( optfile );      free_if_alloc (optfile);
569    
570  leave:  leave:
571      return p;      return p;
572  } /* get_gnupg_config */  }
573    
574    
575    /* Set the default key in the gpg.conf.
576       If @key is NULL, the entry will be deleted. */
577  int  int
578  set_gnupg_default_key (const char * key)  set_gnupg_default_key (const char *key)
579  {  {
580      gpg_optfile_t opt;      config_file_t opt;
581      gpg_option_t e;      conf_option_t e;
582      char *optfile = NULL;      char *optfile = NULL;
583      int rc = 0;      int rc = 0;
584    
585      optfile = get_gnupg_cfgfile ();      optfile = get_gnupg_cfgfile ();
586      if (!optfile)      if (!optfile)
587          return -1;          return WPTERR_FILE_OPEN;
588      rc = parse_gpg_options (optfile, &opt);      rc = parse_config (optfile, &opt);
589      if( rc ) {      if (rc) {
590          free_if_alloc (optfile);          free_if_alloc (optfile);
591          return -1;          return WPTERR_GENERAL;
592      }      }
593      e = find_option (opt, "default-key");      e = conf_find_option (opt, "default-key");
594      if (e) {      if (e && !key)
595            e->used = 0;
596        else if (e) {
597          free_if_alloc (e->val);          free_if_alloc (e->val);
598          e->val = m_strdup (key);          e->val = m_strdup (key);
599          e->used = 1;          e->used = 1;
600      }      }
601      else      else if (key)
602          add_entry (opt, ENTRY_MULTI, "default-key", key);          conf_add_entry (opt, ENTRY_MULTI, "default-key", key);
603      rc = commit_gpg_options (optfile, opt);      rc = commit_config (optfile, opt);
604    
605      free_if_alloc (optfile);      free_if_alloc (optfile);
606      release_gpg_options (opt);      release_config (opt);
   
607      return rc;      return rc;
608  } /* set_gnupg_default_key */  }
609    
610    
611  /*  /* Set the contents of the options file. */
  * Set the contents of the options file.  
  */  
612  int  int
613  set_gnupg_options( const char *buf, size_t buflen )  set_gnupg_options (const char *buf, size_t buflen)
614  {  {
615      FILE *fp;        FILE *fp;  
616      char *optfile = NULL;      char *optfile;
617    
618      optfile = get_gnupg_cfgfile( );      optfile = get_gnupg_cfgfile ();
619      if( optfile == NULL )      if (!optfile)
620          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
621    
622      fp = fopen( optfile, "wb" );      fp = fopen (optfile, "wb");
623      if( fp == NULL ) {      if (!fp) {
624          free_if_alloc( optfile );          free_if_alloc (optfile);
625          return WPTERR_FILE_CREAT;          return WPTERR_FILE_CREAT;
626      }      }
627      fwrite( buf, 1, buflen, fp );      fwrite (buf, 1, buflen, fp);
628      fclose( fp );      fclose (fp);
629      free_if_alloc( optfile );      free_if_alloc (optfile);
630      return 0;      return 0;
631  } /* set_gnupg_options */  }
632    
633  /*  
634   * Check if the line contains a valid GPG argument.  /* Check if the parameter for the option @buf is an existing file name.
635   */     Return value: 0 on success. */
636    static int
637    check_arg_file_exist (const char *buf)
638    {
639        const char *s = "load-extension ";
640    
641        /* XXX: this is a bit of a kludge because we just
642                detect errors for 'load-extension'. */
643        if (!strncmp (buf, s, strlen (s)))
644            buf += strlen (s);
645        else
646            return 0;
647        return file_exist_check (buf);
648    }
649    
650    
651    /* Check if the line contains a valid GPG argument. */
652  static int  static int
653  check_line( const char *buf )  check_line (const char *buf)
654  {  {
655      int j, len;      int j, len;
656      int rc = 0;      int rc = 0;
657    
658      if( *buf == '#' || *buf == '\r' || *buf == '\n' )      if (*buf == '#' || *buf == '\r' || *buf == '\n')
659          return 1;          return 1;
660      rc = 0;      for (j = 0; valid_gpg_args[j]; j++) {
661      for ( j = 0; valid_gpg_args[j]; j++ ) {          len = strlen (valid_gpg_args[j]);
662          len = strlen( valid_gpg_args[j] );          if (!strncmp (valid_gpg_args[j], buf, len))
663          if( !strncmp( valid_gpg_args[j], buf, len ) )              rc = 1;
             rc = 1;      
664      }      }
   
665      return rc;      return rc;
666  } /* check_line */  }
667    
668    
669  int  int
670  check_gnupg_options( const char *buf )  check_gnupg_options (const char *buf, int showerr)
671  {  {
672      char line[1024];      char line[1024];
673      int nbytes = 0;      int nbytes = 0, lineno=0;
674      unsigned j;      unsigned j;
675                    
676      for ( j = 0; j<strlen( buf ) && j < sizeof(line); j++ ) {      for  (j = 0; j < strlen (buf) && j < DIM (line); j++) {
677          line[nbytes++] = buf[j];          line[nbytes++] = buf[j];
678          if ( buf[j] == '\n' || j == ( strlen( buf ) - 1 ) ) {          if (buf[j] == '\n' || j == (strlen (buf) - 1)) {
679              line[nbytes] = '\0';              line[nbytes] = '\0';
680              if( !check_line( line ) ) {              lineno++;
681                  msg_box( NULL, line, "options", MB_OK );              if (!check_line (line)) {
682                    if (showerr)
683                        log_box ("GPG Config File", MB_ERR,
684                                 "gpg.conf:%d: invalid keyword '%s'",
685                                 lineno, line);
686                  return 1;                        return 1;      
687              }              }
688                if (check_arg_file_exist (line))
689                    return WPTERR_FILE_EXIST;
690              nbytes = 0;              nbytes = 0;
691          }                }
692      }      }
   
693      return 0;      return 0;
694  } /* check_gnupg_options */  }
695    
696    
697  /* Store the last access of the file inside the watcher @ctx. */  /* Store the last access of the file inside the watcher @ctx. */
698  static int  static int
699  get_last_gnupg_access (gpg_watcher_s *ctx)  get_last_gnupg_access (gpg_monitor_t ctx)
700  {  {
701      HANDLE fd;      HANDLE fd;
     char *path;  
     char *file;  
702    
703      path = get_gnupg_path ();      fd = CreateFile (ctx->fpath_object, GENERIC_READ, FILE_SHARE_READ,
704      file =  make_filename (path, ctx->object, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
705      fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);      if (fd == INVALID_HANDLE_VALUE)
     if (fd == INVALID_HANDLE_VALUE) {  
         free_if_alloc (path);  
         free_if_alloc (file);  
706          return WPTERR_FILE_OPEN;          return WPTERR_FILE_OPEN;
     }  
707      GetFileTime (fd, NULL, NULL, &ctx->access);      GetFileTime (fd, NULL, NULL, &ctx->access);
708      CloseHandle (fd);      CloseHandle (fd);
     free_if_alloc (path);  
     free_if_alloc (file);  
709      return 0;      return 0;
710  }  }
711    
712    
713  /* Check if the file inside watcher @ctx was modified. */  /* Check if the file inside watcher @ctx was modified. */
714  static void  static void
715  check_last_gnupg_access (gpg_watcher_s *ctx)  check_last_gnupg_access (gpg_monitor_t ctx)
716  {                {              
717      ctx->modified = 0;      ctx->modified = 0;
718    
719      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&      if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime &&
720          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)          ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime)
721          ctx->modified = 1;          ctx->modified = 1;
722        
     /* XXX: find a better way. without it, winpt --keymanager loads  
             the key cache twice. */  
723      if (ctx->last_access.dwLowDateTime == 0)      if (ctx->last_access.dwLowDateTime == 0)
724          ctx->modified = 0;          ctx->modified = 0;
725    
# Line 709  check_last_gnupg_access (gpg_watcher_s * Line 728  check_last_gnupg_access (gpg_watcher_s *
728  }  }
729    
730    
731  /* Init GPG watcher table for all monitored files. */  /* Init GPG monitor table for all monitored files. */
732  void  void
733  init_gnupg_table (void)  init_gnupg_table (void)
734  {        {      
735      char *p;      char *path;
736      int j;      int j;
737    
738        path = get_gnupg_path ();
739      for (j = 0; j < gpg_table_count; j++) {      for (j = 0; j < gpg_table_count; j++) {
740          p = gpg_table[j].object = m_strdup (gpg_objs[j]);          gpg_table[j].object = m_strdup (gpg_objs[j]);
741          if (!p)          gpg_table[j].fpath_object = make_filename (path, gpg_objs[j], NULL);
             BUG (NULL);  
742          memset (&gpg_table[j].access, 0, sizeof (FILETIME));          memset (&gpg_table[j].access, 0, sizeof (FILETIME));
743          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));          memset (&gpg_table[j].last_access, 0, sizeof (FILETIME));
744          gpg_table[j].modified = 0;          gpg_table[j].modified = 0;
745      }      }
746        free_if_alloc (path);
747  }  }
748    
749    
750    /* Release the GPG monitor table. */
751  void  void
752  free_gnupg_table (void)  free_gnupg_table (void)
753  {  {
754      int j;      int j;
755    
756      for (j=0; j < gpg_table_count; j++)      for (j=0; j < gpg_table_count; j++) {
757          free_if_alloc (gpg_table[j].object);          free_if_alloc (gpg_table[j].object);
758            free_if_alloc (gpg_table[j].fpath_object);
759        }
760  }  }
761    
762    
763  /* Return the amount of files modified since the last call. */  /* Return the amount of files modified since the last call. */
764  int  int
765  keyring_check_last_access (void)  keyring_check_last_access (void)
766  {        {
767      int rc, j;      int nfiles;
768        int pos;
769    
770      rc = 0;      nfiles = 0;
771      for (j = 0; j < gpg_table_count; j++) {      for (pos = 0; pos < gpg_table_count; pos++) {
772          get_last_gnupg_access (&gpg_table[j]);          get_last_gnupg_access (&gpg_table[pos]);
773          check_last_gnupg_access (&gpg_table[j]);          check_last_gnupg_access (&gpg_table[pos]);
774          if (gpg_table[j].modified)          if (gpg_table[pos].modified)
775              rc++;                    nfiles++;
776      }      }
777    
778      return rc;      return nfiles;
779  }  }
780    
781    
# Line 774  gnupg_check_file_ext (const char *fname, Line 798  gnupg_check_file_ext (const char *fname,
798              *r_type = PGP_SIG;              *r_type = PGP_SIG;
799          return "SIGNED";          return "SIGNED";
800      }      }
801      else if  (!stricmp (file_ext, ".gpg") || !stricmp (file_ext, ".pgp")) {      else if  (!stricmp (file_ext, ".gpg") ||
802                  !stricmp (file_ext, ".pgp")) {
803          if (r_type)          if (r_type)
804              *r_type = PGP_MESSAGE;              *r_type = PGP_MESSAGE;
805          return "ENCRYPTED";          return "ENCRYPTED";
# Line 783  gnupg_check_file_ext (const char *fname, Line 808  gnupg_check_file_ext (const char *fname,
808  }  }
809    
810    
 char*  
 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;  
 }  
   
   
811    
812  /* XXX: does not work with write-protected floppies */  /* Check if the device file @fname is stored on, is write-protected. */
813  static int  static int
814  my_access (const char *fname)  my_access (const char *fname)
815  {  {
816      HANDLE hd;      HANDLE hd;
817    
818      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,      hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE,
819                       NULL, OPEN_EXISTING, 0, NULL);                       NULL, OPEN_EXISTING, 0, NULL);
820      if (hd == INVALID_HANDLE_VALUE)      if (hd == INVALID_HANDLE_VALUE)
# Line 833  gpg_check_permissions (int showmsg) Line 836  gpg_check_permissions (int showmsg)
836      int failed = 0, ans=0, attrs=0;      int failed = 0, ans=0, attrs=0;
837    
838      p = get_gnupg_path ();      p = get_gnupg_path ();
839      if (check_keyring (&p) && p) {      if (p && check_keyring (&p)) {
840          name = make_filename (p, "pubring", "gpg");          name = make_filename (p, "pubring", "gpg");
841          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {          if ((attrs=GetFileAttributes (name)) & FILE_ATTRIBUTE_READONLY) {
842              ans = msg_box (NULL,              ans = msg_box (NULL,
# Line 877  gpg_check_permissions (int showmsg) Line 880  gpg_check_permissions (int showmsg)
880  int  int
881  gnupg_check_homedir (void)  gnupg_check_homedir (void)
882  {        {      
883      char *homedir = NULL;      char *homedir;
884      int val = 0;      int val;
885      int rc = 0;      int rc = 0;
886    
887    #ifdef WINPT_MOBILE
888        return 0;
889    #endif
890    
891      homedir = get_reg_entry_gpg (GPG_REG_HOME);      homedir = get_reg_entry_gpg (GPG_REG_HOME);
892      if (!homedir)      if (!homedir)
893          homedir = multi_gnupg_path (0);          homedir = multi_gnupg_path (0);
# Line 905  gnupg_check_homedir (void) Line 912  gnupg_check_homedir (void)
912  int  int
913  gnupg_copy_keyrings (void)  gnupg_copy_keyrings (void)
914  {  {
915      const char * pring, * sring;      const char *pring, *sring;
916      char * file = NULL, * path = NULL;      char *file = NULL, *path = NULL;
917      int id = 0, rc = 0;      int id = 0, rc = 0;
918      HWND hwnd;      HWND hwnd;
919            
# Line 915  gnupg_copy_keyrings (void) Line 922  gnupg_copy_keyrings (void)
922          return WPTERR_GENERAL;          return WPTERR_GENERAL;
923      hwnd = GetDesktopWindow ();      hwnd = GetDesktopWindow ();
924    
925      pring = get_fileopen_dlg (hwnd, _("Please choose your public keyring"),      pring = get_fileopen_dlg (hwnd, _("Please choose your Public Keyring"),
926                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0",NULL);
927      if (!pring) {      if (!pring) {
928          msg_box (hwnd, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR);          msg_box (hwnd, _("No keyring was chosen. Exit."),
929                     _("WinPT Error"), MB_ERR);
930          free_if_alloc (path);          free_if_alloc (path);
931          return WPTERR_GENERAL;          return WPTERR_GENERAL;
932      }      }
933      file = make_filename (path, "pubring", "gpg");      file = make_filename (path, "pubring", "gpg");
934      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
935          id = msg_box (hwnd, _("Overwrite old public keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old public keyring?"),
936                          "WinPT", MB_INFO|MB_YESNO);
937          if (id == IDNO)          if (id == IDNO)
938              goto fail;              goto fail;
939      }      }
# Line 935  gnupg_copy_keyrings (void) Line 944  gnupg_copy_keyrings (void)
944      }      }
945      free_if_alloc (file);      free_if_alloc (file);
946    
947      sring = get_fileopen_dlg (hwnd, _("Please choose your secret keyring"),      sring = get_fileopen_dlg (hwnd, _("Please choose your Secret Keyring"),
948                                _("GPG Keyrings (*.gpg)\0*.gpg\0\0"), NULL);                                "GPG Keyrings (*.gpg)\0*.gpg\0\0", NULL);
949      if (!sring) {      if (!sring) {
950          msg_box( NULL, _("No keyring was chosen. Exit."), _("WinPT Error"), MB_ERR );          msg_box (NULL, _("No keyring was chosen. Exit."),
951                     _("WinPT Error"), MB_ERR);
952          return WPTERR_GENERAL;          return WPTERR_GENERAL;
953      }      }
954      file = make_filename (path, "secring", "gpg");      file = make_filename (path, "secring", "gpg");
955      if (file_exist_check (file) == 0) {      if (file_exist_check (file) == 0) {
956          id = msg_box (hwnd, _("Overwrite old secret keyring?"), "WinPT", MB_INFO|MB_YESNO);          id = msg_box (hwnd, _("Overwrite old secret keyring?"),
957          if( id == IDNO )                        "WinPT", MB_INFO|MB_YESNO);
958            if (id == IDNO)
959              goto fail;              goto fail;
960      }      }
961      if (!CopyFile (sring, file, FALSE)) {      if (!CopyFile (sring, file, FALSE)) {
962          msg_box( NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);          msg_box (NULL, _("Could not copy file."), _("WinPT Error"), MB_ERR);
963          rc = WPTERR_FILE_READ;          rc = WPTERR_FILE_READ;
964      }      }
965    
# Line 956  fail: Line 967  fail:
967      free_if_alloc (file);      free_if_alloc (file);
968      free_if_alloc (path);      free_if_alloc (path);
969      return rc;      return rc;
970  } /* gnupg_import_keyrings */  }
971    
972    
973  /* Backup the gpg.conf file. */  /* Backup the gpg.conf file. */
974  void  void
975  gnupg_backup_options (void)  gnupg_backup_options (void)
976  {  {
977      char *cfgfile = NULL;      char *cfgfile;
978      char bak[512];      char bak[MAX_PATH+32];
979    
980      cfgfile = get_gnupg_cfgfile ();      cfgfile = get_gnupg_cfgfile ();
981      if (!cfgfile)      if (!cfgfile)
# Line 979  static int Line 990  static int
990  backup_one_file (const char *srcpath, const char *srcn,  backup_one_file (const char *srcpath, const char *srcn,
991                   const char *dstpath, const char *dstn)                   const char *dstpath, const char *dstn)
992  {  {
993      char * src, * dst;      char *src, *dst;
994      BOOL rc;      BOOL rc;
995    
996      src = make_filename (srcpath, srcn, "gpg");      src = make_filename (srcpath, srcn, "gpg");
     if (!src)  
         BUG (NULL);  
997      dst = make_filename (dstpath, dstn, "gpg");      dst = make_filename (dstpath, dstn, "gpg");
     if (!dst)  
         BUG (NULL);  
998      rc = CopyFile (src, dst, FALSE);      rc = CopyFile (src, dst, FALSE);
999      free_if_alloc (src);      free_if_alloc (src);
1000      free_if_alloc (dst);      free_if_alloc (dst);
1001      if (!rc)      if (!rc) {
     {  
1002          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);          log_box (_("Backup"), MB_ERR, _("Backup keyring \"%s\" failed"), srcn);
1003          return WPTERR_GENERAL;          return WPTERR_GENERAL;
1004      }      }
1005      return 0;      return 0;
1006  } /* backup_one_file */  }
1007    
1008    
1009  /* Figure out first public keyring which is not empty.  /* Figure out first public keyring which is not empty.
# Line 1012  check_keyring (char **r_path) Line 1018  check_keyring (char **r_path)
1018      if (!*r_path)      if (!*r_path)
1019          return 0;          return 0;
1020      p = make_filename (*r_path, "pubring", "gpg");      p = make_filename (*r_path, "pubring", "gpg");
1021      if (!p || get_file_size (p) <= 0)      if (get_file_size (p) <= 0)
1022          return 0;          return 0;
1023    
1024      opt = get_gnupg_cfgfile ();      opt = get_gnupg_cfgfile ();
1025      if (!opt)      if (!opt)
1026          BUG (0);          BUG (0);
1027      name = get_gnupg_keyring_from_options (opt, 1);      name = get_keyring_from_conf (opt, 1);
1028      free_if_alloc (opt);      free_if_alloc (opt);
1029      free_if_alloc (p);      free_if_alloc (p);
1030      if (!name)      if (!name)
# Line 1042  static char* Line 1048  static char*
1048  get_backup_name (const char *templ)  get_backup_name (const char *templ)
1049  {  {
1050      struct tm *tm;      struct tm *tm;
1051        const char *fmt;
1052      char *p;      char *p;
1053      time_t t;      time_t t;
1054    
1055      t = time (NULL);      t = time (NULL);
1056      tm = localtime (&t);      tm = localtime (&t);
1057      p = new char [strlen (templ) + 8 + 1];      fmt = "%s-%d";
1058        p = new char [strlen (templ) + strlen (fmt) + 8 + 1];
1059      if (!p)      if (!p)
1060          BUG (0);          BUG (0);
1061      sprintf (p, "%s-%d", templ, tm->tm_wday % 3);      sprintf (p, fmt, templ, tm->tm_wday % 3);
1062      return p;      return p;
1063  }  }
1064    
1065    
1066  /* Make backups of all keyrings. The public key ring is  /* Make backups of all keyrings. The public key ring is rotated like
1067     rotated like this pubring-%d.gpg. */     this pubring-%d.gpg.
1068       If @auto_backup is false, no action is performed.
1069       @include_secr indicated if the backup includes the secret keyring. */
1070  void  void
1071  gnupg_backup_keyrings (void)  gnupg_backup_keyrings (int auto_backup, int backup_mode, int include_secr)
1072  {  {
1073      char *srcpath = NULL, *dstpath = NULL;      char *srcpath, *dstpath;
1074      char *name=NULL;      char *name;
1075      int rc, bakmode=0;      int rc;
1076    
1077      if (!reg_prefs.auto_backup)      if (!auto_backup)
1078          return;          return;
     bakmode = reg_prefs.backup.mode;  
1079      srcpath = get_gnupg_path ();      srcpath = get_gnupg_path ();
1080      check_keyring (&srcpath);      check_keyring (&srcpath);
1081      if (bakmode == 1) {      if (backup_mode == 1) {
1082          dstpath = multi_gnupg_path (1);          /* If the backup mode uses the home directory the source
1083               and destination folder will be the same. */
1084            dstpath = get_gnupg_path ();
1085          check_keyring (&dstpath);          check_keyring (&dstpath);
1086      }      }
1087      else if (bakmode == 2) {      else if (backup_mode == 2) {
1088          char *tmpfile;          char *tmpfile;
1089          FILE *fp;          FILE *fp;
1090    
1091          dstpath = m_strdup (reg_prefs.backup.path);          dstpath = m_strdup (reg_prefs.backup.path);
         if (!dstpath)  
             BUG (0);  
1092          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");          tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp");
1093          fp = fopen (tmpfile, "wb");          fp = fopen (tmpfile, "wb");
1094          if (!fp)          if (!fp)
1095              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,              rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL,
1096                            _("The backup drive '%s' does not seems to accessable.\n"                            _("The backup drive '%s' does not seems to be accessable.\n"
1097                              "Please insert/check the drive to continue."), dstpath);                              "Please insert/check the drive to continue."), dstpath);
1098          else {          else {
1099              rc = 0;              rc = 0;
1100              fclose (fp);              fclose (fp);
1101              remove (tmpfile);              DeleteFile (tmpfile);
1102          }          }
1103          free_if_alloc (tmpfile);          free_if_alloc (tmpfile);
1104          if (!fp || rc == IDCANCEL)          if (!fp || rc == IDCANCEL) {
1105                free_if_alloc (dstpath);
1106                free_if_alloc (srcpath);
1107              return;              return;
1108            }
1109      }      }
1110      else {      else {
1111          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), bakmode);          log_box (_("Backup"), MB_ERR, _("Invalid backup mode %d"), backup_mode);
1112            free_if_alloc (srcpath);
1113          return;          return;
1114      }      }
1115      name = get_backup_name ("pubring-bak");      name = get_backup_name ("pubring-bak");
1116      rc = backup_one_file (srcpath, "pubring", dstpath, name);      rc = backup_one_file (srcpath, "pubring", dstpath, name);
1117      if (!rc)      if (!rc && include_secr)
1118          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");          rc = backup_one_file (srcpath, "secring", dstpath, "secring-bak");
1119      free_if_alloc (name);      free_if_alloc (name);
1120      free_if_alloc (srcpath);      free_if_alloc (srcpath);
# Line 1109  gnupg_backup_keyrings (void) Line 1122  gnupg_backup_keyrings (void)
1122  }  }
1123    
1124    
 /* Display GPG error from file if possible. */  
 void  
 gnupg_display_error (void)  
 {        
     char tmpath[512], * errstr;  
     size_t size = 0;  
     FILE * fp;  
   
     GetTempPath (sizeof tmpath - 32, (tmpath));  
     strcat (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);  
 }  
   
   
   
1125  /* check that the requested GPG keyring exist and.  /* check that the requested GPG keyring exist and.
1126     Return value: 0 for success. */     Return value: 0 for success. */
1127  int  int

Legend:
Removed from v.137  
changed lines
  Added in v.273

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26