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

Diff of /trunk/Src/wptKeyPropsDlg.cpp

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

revision 33 by twoaday, Tue Oct 25 07:46:20 2005 UTC revision 181 by twoaday, Tue Mar 14 11:01:22 2006 UTC
# Line 1  Line 1 
1  /* wptKeyPropsDlg.cpp - WinPT key properties dialog  /* wptKeyPropsDlg.cpp - WinPT key properties dialog
2   *      Copyright (C) 2000, 2001, 2002, 2003, 2005 Timo Schulz   *      Copyright (C) 2000, 2001, 2002, 2003, 2005, 2006 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
6   * WinPT is free software; you can redistribute it and/or modify   * WinPT is free software; you can redistribute it and/or modify
7   * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
8   * the Free Software Foundation; either version 2 of the License, or   * the Free Software Foundation; either version 2 of the License, or
9   * (at your option) any later version.   * (at your option) any later version.
10   *   *
11   * WinPT is distributed in the hope that it will be useful,   * WinPT is distributed in the hope that it will be useful,
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   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.   * GNU General Public License for more details.
15   *   *
16   * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
17   * along with WinPT; if not, write to the Free Software Foundation,   * along with WinPT; if not, write to the Free Software Foundation,
18   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19   */   */
20    #ifdef HAVE_CONFIG_H
21  #include <windows.h>  #include <config.h>
22    #endif
23  #include "../resource.h"  
24  #include "wptErrors.h"  #include <windows.h>
25  #include "wptGPG.h"  
26  #include "wptCommonCtl.h"  #include "resource.h"
27  #include "wptContext.h" /* for passphrase_s */  #include "wptErrors.h"
28  #include "wptNLS.h"  #include "wptGPG.h"
29  #include "wptDlgs.h"  #include "wptCommonCtl.h"
30  #include "wptTypes.h"  #include "wptContext.h" /* for passphrase_s */
31  #include "wptKeylist.h"  #include "wptNLS.h"
32  #include "wptW32API.h"  #include "wptDlgs.h"
33  #include "wptVersion.h"  #include "wptTypes.h"
34  #include "wptKeyEdit.h"  #include "wptKeylist.h"
35    #include "wptW32API.h"
36  static void  #include "wptVersion.h"
37  do_change_ownertrust (winpt_key_t k, const char *s)  #include "wptKeyEdit.h"
38  {  
39      char ot[64];  
40        /* Check that the key is not expired or revoked. */
41      if( strstr( s, "ultimate" ) ) {  static int
42          listview_get_item_text (k->callback.ctl, k->callback.idx, 5, ot, DIM (ot)-1);  do_check_key (gpgme_key_t key)
43          strcpy (ot, "Ultimate");  {
44          listview_add_sub_item (k->callback.ctl, k->callback.idx, 5, ot);      int okay = 0;
45          /* fixme: If we switch back from Ultimate to a lower level */      okay = key->expired;
46      }      if (!okay)
47  }          okay = key->revoked;
48        return okay;
49    }
50  /* Check that the key is not expired or revoked. */  
51  static int  
52  do_check_key (gpgme_key_t key)  /* Convert a trust integer into a string representation. */
53  {  static const char*
54      int okay = 0;  ownertrust_to_string (int val, bool is_keypair)
55      okay = key->expired;  {
56      if (!okay)      const char *inf;
57          okay = key->revoked;      int id = val;
58      return okay;  
59  }      switch (id) {
60        case 1: inf = _("Don't know");         break;
61        case 2: inf = _("I do NOT trust");     break;
62  /* Convert a trust integer into a string representation. */      case 3: inf = _("I trust marginally"); break;
63  static const char*      case 4: inf = _("I trust fully");      break;
64  ownertrust_to_string (int val)      case 5:
65  {      case 6:
66      const char * inf;          if (is_keypair)
67      int id = val;              inf = _("I trust ultimately (implicit)");
68      switch (id) {          else
69      case 1: inf = _("Don't know");         break;              inf = _("I trust ultimately"); break;
70      case 2: inf = _("I do NOT trust");     break;      default:inf = _("Unknown");            break;
71      case 3: inf = _("I trust marginally"); break;      }
72      case 4: inf = _("I trust fully");      break;      
73      case 5:      return inf;
74      case 6: inf = _("I trust ultimately"); break;  }
75      default:inf = _("Unknown");            break;  
76      }  
77        /* Generate a unique temp name for the photo which
78      return inf;     depends on the dialog handle and return it. */
79  }  static const char*
80    get_photo_tmpname (HWND dlg)
81    {
82  #define PHOTO_TMPNAME "winpt_temp_photo.jpg"      static char buf[MAX_PATH+128+1];
83        char name[64];
84  /* Load the photo from the key @key */  
85  static int      _snprintf (name, sizeof (name)-1, "winpt_photo_%08lX.tmp", (DWORD)dlg);
86  keyprops_load_photo (gpgme_key_t key, gpgme_validity_t *r_valid)      get_temp_name (buf, DIM (buf), name);
87  {      return buf;
88      winpt_key_s k;  }
89      FILE *f;  
90      const BYTE *img;  
91      DWORD imglen = 0;  static void
92      int pos=0;  draw_nophoto_img (HWND dlg)
93    {
94      winpt_get_pubkey (key->subkeys->keyid, &k);      /*..
95      img = k.ext->attrib.d;      n = DrawText (hdc, "No Photo-ID", -1, &r, DT_LEFT);
96      imglen = k.ext->attrib.len;          ..*/
97      if (!k.ext->attrib.validity)  }
98          get_uat_validity (key->subkeys->keyid, &k.ext->attrib.validity);  
99      *r_valid = k.ext->attrib.validity;  
100    /* Load the photo from the key @key */
101      if (!img || !imglen)  static int
102          return -1;  keyprops_load_photo (HWND dlg, gpgme_key_t key, gpgme_validity_t *r_valid)
103      f = fopen (PHOTO_TMPNAME, "wb");  {
104      if (f) {      winpt_key_s k;
105          for (pos = 0; img[pos] != 0x10; pos++)      FILE *f;
106                  ;      const BYTE *img;
107          pos += 16;      DWORD imglen = 0;
108          fwrite (img + pos, 1, imglen - pos, f);      int pos=0;
109          fwrite (img, 1, imglen, f);  
110          fclose (f);      winpt_get_pubkey (key->subkeys->keyid, &k);
111      }      img = k.ext->attrib.d;
112      return 0;      imglen = k.ext->attrib.len;
113  }      if (!k.ext->attrib.validity)
114            get_uat_validity (key->subkeys->keyid, &k.ext->attrib.validity);
115        *r_valid = k.ext->attrib.validity;
116  /* Display the photo in the image control in the dialog @dlg. */  
117  static int      if (!img || !imglen) {
118  keyprops_show_photo (HWND dlg)          draw_nophoto_img (dlg);
119  {          return -1;
120      RECT r;          }
121      POINT p;  
122      HWND h;      f = fopen (get_photo_tmpname (dlg), "wb");
123        if (f) {
124      h = GetDlgItem (dlg, IDC_KEYPROPS_IMG);          //for (pos = 0; img[pos] != 0x10; pos++)
125      GetWindowRect (h, &r);          //      ;
126      p.x = r.left + 5;          pos += 16;
127      p.y = r.top - 2;          fwrite (img + pos, 1, imglen - pos, f);
128      memset (&p, 0, sizeof (p));          fclose (f);
129      PTD_jpg_show (h, &p, PHOTO_TMPNAME);      }
130            return 0;
131      return 0;  }
132  }  
133    
134    /* Display the photo in the image control in the dialog @dlg. */
135  /* Return string representation of the key validity. @key. */  static int
136  static const char*  keyprops_show_photo (HWND dlg)
137  get_validity (gpgme_key_t key)  {
138  {      RECT r;    
139      int val;      POINT p;
140      val = key->expired;      HWND h;
141      if (val)  
142          return _("Expired");          h = GetDlgItem (dlg, IDC_KEYPROPS_IMG);
143      val = key->revoked;      GetWindowRect (h, &r);
144      if (val)      p.x = r.left + 5;
145          return _("Revoked");      p.y = r.top - 2;
146      return get_key_trust2 (NULL, key->uids->validity, 0, 0);      memset (&p, 0, sizeof (p));
147  }      PTD_jpg_show (h, &p, get_photo_tmpname (dlg));
148        
149        return 0;
150  /* Return the preferred sym. algorithm from @key as a string. */  }
151  static const char*  
152  get_pref_cipher (winpt_key_t k)  
153  {  /* Return string representation of the key validity. @key. */
154      const char *sym_prefs=NULL;      static const char*
155    get_validity (gpgme_key_t key)
156      if (k->is_v3)  {
157          return "IDEA";      int val;
158      if (!k->ext->sym_prefs)      val = key->expired;
159          return "3DES";      if (val)
160      switch (*k->ext->sym_prefs) {          return _("Expired");    
161      case 1: return "IDEA";      val = key->revoked;
162      case 2: return "3DES";      if (val)
163      case 3: return "CAST5";          return _("Revoked");
164      case 4: return "Blowfish";      val = key->disabled;
165      case 7:      if (val)
166      case 8:          return _("Disabled");
167      case 9: return "AES";      return get_key_trust2 (NULL, key->uids->validity, 0, 0);
168      case 10:return "Twofish";  }
169      }  
170      return "Unknown";  
171  }  /* Return the preferred sym. algorithm from @key as a string. */
172    static const char*
173    get_pref_cipher (winpt_key_t k)
174  /* Return true if the key has designated revokers. */  {
175  static bool      if (k->is_v3)
176  check_for_desig_rev (gpgme_key_t key)          return "IDEA";
177  {      if (!k->ext->sym_prefs)
178      winpt_key_s k;          return "3DES";
179      memset (&k, 0, sizeof (k));      switch (*k->ext->sym_prefs) {
180      if (!winpt_get_pubkey (key->subkeys->keyid, &k))      case 1: return "IDEA";
181          return k.ext->gloflags.has_desig_rev? true : false;      case 2: return "3DES";
182      return false;      case 3: return "CAST5";
183  }      case 4: return "Blowfish";
184        case 7:
185        case 8:
186  /* Print information (name) of the smart card. */      case 9: return "AES";
187  static const char*      case 10:return "Twofish";
188  get_card_type (winpt_key_t k)      }
189  {          return "Unknown";
190      static char buf[64];  }
191    
192      if (!k->ext->card_type)  
193          return "";  /* Return true if the key has designated revokers. */
194      _snprintf (buf, sizeof (buf)-1, _("Card-Type: %s\r\n"), k->ext->card_type);  static bool
195      return buf;  check_for_desig_rev (gpgme_key_t key)
196  }  {
197        winpt_key_s k;
198        memset (&k, 0, sizeof (k));
199  /* Display the key information for key @k.      if (!winpt_get_pubkey (key->subkeys->keyid, &k))
200     Return value: gpgme key on success. */          return k.ext->gloflags.has_desig_rev? true : false;
201  static void      return false;
202  display_key_info (HWND dlg, winpt_key_t k, gpgme_key_t *r_key)  }
203  {  
204      struct winpt_key_s k2;  
205      gpgme_key_t sk, key;  /* Print information (name) of the smart card. */
206      char info[512];  static const char*
207      const char *inf;  get_card_type (winpt_key_t k)
208      u32 created, expires;      {    
209        static char buf[64];
210      memset (&k2, 0, sizeof (k2));        
211      if (k->key_pair)      if (!k->ext || !k->ext->card_type)
212          winpt_get_seckey (k->keyid, &k2);          return "";
213      else          _snprintf (buf, sizeof (buf)-1, _("Card-Type: %s\r\n"), k->ext->card_type);
214          winpt_get_pubkey (k->keyid, &k2);      return buf;
215      sk = k2.ctx;          }
216      if (sk)  
217          k->is_protected = k2.is_protected;  
218      if (get_pubkey (k->keyid, &key))  /* Display the key information for key @k.
219          BUG (0);         Return value: gpgme key on success. */
220      created = key->subkeys->timestamp;    static void
221      expires = key->subkeys->expires;      display_key_info (HWND dlg, winpt_key_t k, gpgme_key_t *r_key)
222      _snprintf (info, DIM (info)-1,  {
223                 _("Type: %s\r\n"      gpgme_key_t key;
224                 "Key ID: %s\r\n"      struct winpt_key_s pk, sk;
225                 "Algorithm: %s\r\n"      char info[512];
226                 "Size: %s\r\n"      const char *inf;
227                 "Created: %s\r\n"      DWORD created, expires;
228                 "Expires: %s\r\n"  
229                 "Validity: %s\r\n"      memset (&pk, 0, sizeof (pk));
230                 "Cipher: %s\r\n"      if (winpt_get_pubkey (k->keyid, &pk))
231                 "%s\r\n"),          BUG (0);
232                 get_key_type (key),      gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFSYM, 0);
233                 k->keyid,      memset (&sk, 0, sizeof (sk));      
234                 get_key_algo (key, 0),      if (k->key_pair && !winpt_get_seckey (k->keyid, &sk))
235                 get_key_size (key, 0),          k->is_protected = sk.is_protected;
236                 get_key_created (created),      key = pk.ext->key;
237                 get_key_expire_date (expires),      created = key->subkeys->timestamp;
238                 get_validity (key),      expires = key->subkeys->expires;
239                 get_pref_cipher (&k2),      _snprintf (info, DIM (info)-1,
240                 get_card_type (&k2));                 _("Type: %s\r\n"
241                   "Key ID: %s\r\n"
242      SetDlgItemText (dlg, IDC_KEYPROPS_INFO, info);                 "Algorithm: %s\r\n"
243      SetDlgItemText (dlg, IDC_KEYPROPS_FPR, get_key_fpr (key));                   "Size: %s bits\r\n"
244      inf = ownertrust_to_string (key->owner_trust);                 "Created: %s\r\n"
245      SetDlgItemText (dlg, IDC_KEYPROPS_OT, inf);                 "Expires: %s\r\n"
246                   "Validity: %s\r\n"
247      *r_key = key;                 "Cipher: %s\r\n"
248  }                 "%s\r\n"),
249                   get_key_type (key),
250                   k->keyid,
251  /* Dialog box procedure to show the key properties. */                 get_key_algo (key, 0),
252  BOOL CALLBACK                 get_key_size (key, 0),
253  keyprops_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)                 get_key_created (created),
254  {                 get_key_expire_date (expires),
255      static winpt_key_t k;                 get_validity (key),
256      static gpgme_key_t key;                 get_pref_cipher (&pk),
257      static int has_photo = 0;                 get_card_type (&sk));
258      gpgme_validity_t valid;  
259      refresh_cache_s rcs = {0};      SetDlgItemText (dlg, IDC_KEYPROPS_INFO, info);
260      const char *inf;      SetDlgItemText (dlg, IDC_KEYPROPS_FPR, get_key_fpr (key));  
261      int cancel = 0;      inf = ownertrust_to_string (key->owner_trust, k->key_pair);
262      int rc;      SetDlgItemText (dlg, IDC_KEYPROPS_OT, inf);
263        
264      switch (msg) {      *r_key = key;
265      case WM_INITDIALOG:  }
266          if (!lparam)  
267              dlg_fatal_error (dlg, "Could not get dialog param!");  
268          k = (winpt_key_t)lparam;  /* Dialog box procedure to show the key properties. */
269          #ifndef LANG_DE  BOOL CALLBACK
270          SetWindowText (dlg, _("Key Properties"));  keyprops_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
271          SetDlgItemText (dlg, IDC_KEYPROPS_OT_CHANGE, _("&Change"));  {
272          SetDlgItemText (dlg, IDC_KEYPROPS_REVOKERS, _("&Revokers"));      static winpt_key_t k;
273          SetDlgItemText (dlg, IDC_KEYPROPS_CHANGE_PWD, _("Change &Passwd"));      static gpgme_key_t key;
274          SetDlgItemText (dlg, IDC_KEYPROPS_OTINF, _("Ownertrust"));      gpgme_validity_t valid;
275          #endif        const char *inf;
276        int rc;
277          display_key_info (dlg, k, &key);      
278          if (!keyprops_load_photo (key, &valid)) {      /* XXX: static variable (k) prevent that the dialog can
279              has_photo = 1;                    be opened twice. */
280              if (valid != 0 && valid < GPGME_VALIDITY_MARGINAL)      switch (msg) {
281                  SetDlgItemText (dlg, IDC_KEYPROPS_IMGINF, _("Photo-ID not checked."));      case WM_INITDIALOG:
282          }          if (!lparam)
283          if (k->key_pair)              dlg_fatal_error (dlg, "Could not get dialog param!");
284              EnableWindow (GetDlgItem (dlg, IDC_KEYPROPS_CHANGE_PWD), TRUE);          k = (winpt_key_t)lparam;
285          if (check_for_desig_rev (key))          SetWindowText (dlg, _("Key Properties"));
286              EnableWindow (GetDlgItem (dlg, IDC_KEYPROPS_REVOKERS), TRUE);          SetDlgItemText (dlg, IDC_KEYPROPS_OT_CHANGE, _("&Change"));
287          center_window (dlg, NULL);          SetDlgItemText (dlg, IDC_KEYPROPS_REVOKERS, _("&Revokers"));
288          SetForegroundWindow (dlg);                SetDlgItemText (dlg, IDC_KEYPROPS_CHANGE_PWD, _("Change &Password"));
289          return TRUE;          SetDlgItemText (dlg, IDC_KEYPROPS_OTINF, _("Ownertrust"));
290            
291      case WM_DESTROY:          display_key_info (dlg, k, &key);
292          has_photo = 0;          if (!keyprops_load_photo (dlg, key, &valid)) {
293          unlink (PHOTO_TMPNAME);              k->has_photo = 1;  
294          break;              if (valid < GPGME_VALIDITY_MARGINAL)
295                          SetDlgItemText (dlg, IDC_KEYPROPS_IMGINF, _("Photo-ID not validated."));
296      case WM_PAINT:          }
297          if (has_photo)          if (k->key_pair)
298              keyprops_show_photo (dlg);              EnableWindow (GetDlgItem (dlg, IDC_KEYPROPS_CHANGE_PWD), TRUE);
299          break;          if (check_for_desig_rev (key))
300                EnableWindow (GetDlgItem (dlg, IDC_KEYPROPS_REVOKERS), TRUE);
301      case WM_SYSCOMMAND:          if (key->revoked || key->expired)
302          if (LOWORD (wparam) == SC_CLOSE)              EnableWindow (GetDlgItem (dlg, IDC_KEYPROPS_OT_CHANGE), FALSE);
303              EndDialog (dlg, TRUE);          center_window (dlg, NULL);
304          return FALSE;          SetForegroundWindow (dlg);      
305                    return TRUE;
306      case WM_COMMAND:  
307          switch (LOWORD (wparam)) {      case WM_DESTROY:
308          case IDOK:          remove (get_photo_tmpname (dlg));
309              EndDialog (dlg, TRUE);          break;
310              return TRUE;        
311                    case WM_PAINT:
312          case IDC_KEYPROPS_OT_CHANGE:          if (k->has_photo)
313              if (do_check_key (key)) {              keyprops_show_photo (dlg);
314                  msg_box (dlg, _("The status of this key is 'revoked' or 'expired'.\n"          break;
315                                  "You cannot change the ownertrust of such keys."),  
316                                  _("WinPT Warning"), MB_ERR);      case WM_SYSCOMMAND:
317                  return TRUE;          if (LOWORD (wparam) == SC_CLOSE)
318              }              EndDialog (dlg, FALSE);
319              if( !k->key_pair && key->uids->validity < 3 ) {          return FALSE;
320                  rc = msg_box( dlg, _("This is a non-valid key.\n"          
321                                       "Modifying the ownertrust has no effect on such keys.\n\n"      case WM_COMMAND:
322                                       "Do you really want to continue?"),          switch (LOWORD (wparam)) {
323                                       _("WinPT Warning"), MB_ICONWARNING|MB_YESNO );          case IDOK:
324                  if (rc == IDNO)              EndDialog (dlg, TRUE);
325                      return TRUE;              return TRUE;
326              }  
327              //GetDlgItemText (dlg, IDC_KEYPROPS_OT, info, sizeof info -1);          case IDCANCEL:
328              dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,              EndDialog (dlg, FALSE);
329                                dlg, (DLGPROC)keyedit_ownertrust_dlg_proc,              return TRUE;
330                                (LPARAM)k, _("Change Ownertrust"),              
331                                IDS_WINPT_KEYEDIT_OWNERTRUST);          case IDC_KEYPROPS_OT_CHANGE:
332              if (k->callback.new_val == -1) { /* Cancel */              if (do_check_key (key)) {
333                  EndDialog (dlg, FALSE);                  msg_box (dlg, _("The status of this key is 'revoked' or 'expired'.\n"
334                  break;                                  "You cannot change the ownertrust of such keys."),
335              }                                  _("WinPT Warning"), MB_ERR);
336                    return TRUE;
337              inf = ownertrust_to_string (k->callback.new_val);              }
338              do_change_ownertrust (k, inf);              if (!k->key_pair && key->uids->validity < 3) {
339              SetDlgItemText (dlg, IDC_KEYPROPS_OT, inf);                  rc = msg_box (dlg, _("This is a non-valid key.\n"
340              msg_box (dlg, _("Ownertrust successfully changed."),                                       "Modifying the ownertrust has no effect on such keys.\n\n"
341                       _("GnuPG Status"), MB_OK);                                       "Do you really want to continue?"),
342                                                     _("WinPT Warning"), MB_ICONWARNING|MB_YESNO);
343              /* reload only the keylist */                  if (rc == IDNO)
344              rcs.kr_reload = 1; rcs.kr_update = 1;                      return TRUE;
345              rcs.tr_update = 0;              }
346              DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, dlg,              rc = dialog_box_param (glob_hinst,
347                              keycache_dlg_proc, (LPARAM)&rcs);                                     (LPCSTR)IDD_WINPT_KEYEDIT_OWNERTRUST,
348              return TRUE;                                      dlg, keyedit_ownertrust_dlg_proc,
349                                                   (LPARAM)k, _("Change Ownertrust"),
350          case IDC_KEYPROPS_CHANGE_PWD:                                      IDS_WINPT_KEYEDIT_OWNERTRUST);
351              keyedit_change_passwd (k, dlg);                      if (rc == FALSE) /* Cancel */
352              return TRUE;                  return TRUE;
353    
354          case IDC_KEYPROPS_REVOKERS:              inf = ownertrust_to_string (k->callback.new_val, k->key_pair);
355              dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKERS, dlg,              SetDlgItemText (dlg, IDC_KEYPROPS_OT, inf);
356                                key_revokers_dlg_proc, (LPARAM)key, _("Key Revokers"),              msg_box (dlg, _("Ownertrust successfully changed."),
357                                IDS_WINPT_KEY_REVOKERS);                       _("GnuPG Status"), MB_OK);
358              break;              k->update = 1;
359          }              return TRUE;
360      }              
361                case IDC_KEYPROPS_CHANGE_PWD:
362      return FALSE;              keyedit_change_passwd (k, dlg);        
363  }              return TRUE;
364    
365            case IDC_KEYPROPS_REVOKERS:
366                k->update = dialog_box_param (
367                    glob_hinst, (LPCTSTR)IDD_WINPT_KEYREVOKERS, dlg,
368                    key_revokers_dlg_proc, (LPARAM)key,
369                    _("Key Revokers"), IDS_WINPT_KEY_REVOKERS);
370                break;
371            }
372        }
373        
374        return FALSE;
375    }

Legend:
Removed from v.33  
changed lines
  Added in v.181

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26