Add support for RFC 4432 RSA key exchange, the patch for which has been
[u/mdw/putty] / config.c
index 1e5f8da..41bb494 100644 (file)
--- a/config.c
+++ b/config.c
@@ -256,6 +256,7 @@ static void kexlist_handler(union control *ctrl, void *dlg,
            { "Diffie-Hellman group 1",         KEX_DHGROUP1 },
            { "Diffie-Hellman group 14",        KEX_DHGROUP14 },
            { "Diffie-Hellman group exchange",  KEX_DHGEX },
+           { "RSA-based key exchange",         KEX_RSA },
            { "-- warn below here --",          KEX_WARN }
        };
 
@@ -383,7 +384,7 @@ struct sessionsaver_data {
  */
 static int load_selected_session(struct sessionsaver_data *ssd,
                                 char *savedsession,
-                                void *dlg, Config *cfg)
+                                void *dlg, Config *cfg, int *maybe_launch)
 {
     int i = dlg_listbox_index(ssd->listbox, dlg);
     int isdef;
@@ -392,13 +393,17 @@ static int load_selected_session(struct sessionsaver_data *ssd,
        return 0;
     }
     isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
-    load_settings(ssd->sesslist.sessions[i], !isdef, cfg);
+    load_settings(ssd->sesslist.sessions[i], cfg);
     if (!isdef) {
        strncpy(savedsession, ssd->sesslist.sessions[i],
                SAVEDSESSION_LEN);
        savedsession[SAVEDSESSION_LEN-1] = '\0';
+       if (maybe_launch)
+           *maybe_launch = TRUE;
     } else {
        savedsession[0] = '\0';
+       if (maybe_launch)
+           *maybe_launch = FALSE;
     }
     dlg_refresh(NULL, dlg);
     /* Restore the selection, which might have been clobbered by
@@ -464,6 +469,7 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
            dlg_listbox_select(ssd->listbox, dlg, top);
        }
     } else if (event == EVENT_ACTION) {
+       int mbl = FALSE;
        if (!ssd->midsession &&
            (ctrl == ssd->listbox ||
             (ssd->loadbutton && ctrl == ssd->loadbutton))) {
@@ -474,8 +480,8 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
             * double-click on the list box _and_ that session
             * contains a hostname.
             */
-           if (load_selected_session(ssd, savedsession, dlg, cfg) &&
-               (ctrl == ssd->listbox && cfg_launchable(cfg))) {
+           if (load_selected_session(ssd, savedsession, dlg, cfg, &mbl) &&
+               (mbl && ctrl == ssd->listbox && cfg_launchable(cfg))) {
                dlg_end(dlg, 1);       /* it's all over, and succeeded */
            }
        } else if (ctrl == ssd->savebutton) {
@@ -496,7 +502,7 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
                }
            }
             {
-                char *errmsg = save_settings(savedsession, !isdef, cfg);
+                char *errmsg = save_settings(savedsession, cfg);
                 if (errmsg) {
                     dlg_error_msg(dlg, errmsg);
                     sfree(errmsg);
@@ -533,12 +539,14 @@ static void sessionsaver_handler(union control *ctrl, void *dlg,
            if (dlg_last_focused(ctrl, dlg) == ssd->listbox &&
                !cfg_launchable(cfg)) {
                Config cfg2;
-               if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) {
+               int mbl = FALSE;
+               if (!load_selected_session(ssd, savedsession, dlg,
+                                          &cfg2, &mbl)) {
                    dlg_beep(dlg);
                    return;
                }
                /* If at this point we have a valid session, go! */
-               if (*cfg2.host) {
+               if (mbl && cfg_launchable(&cfg2)) {
                    *cfg = cfg2;       /* structure copy */
                    cfg->remote_cmd_ptr = NULL;
                    dlg_end(dlg, 1);
@@ -792,7 +800,29 @@ static void ttymodes_handler(union control *ctrl, void *dlg,
            char *p = cfg->ttymodes;
            int i = 0, len = lenof(cfg->ttymodes);
            while (*p) {
+               int multisel = dlg_listbox_index(td->listbox, dlg) < 0;
                if (dlg_listbox_issel(td->listbox, dlg, i)) {
+                   if (!multisel) {
+                       /* Populate controls with entry we're about to
+                        * delete, for ease of editing.
+                        * (If multiple entries were selected, don't
+                        * touch the controls.) */
+                       char *val = strchr(p, '\t');
+                       if (val) {
+                           int ind = 0;
+                           val++;
+                           while (ttymodes[ind]) {
+                               if (strlen(ttymodes[ind]) == val-p-1 &&
+                                   !strncmp(ttymodes[ind], p, val-p-1))
+                                   break;
+                               ind++;
+                           }
+                           dlg_listbox_select(td->modelist, dlg, ind);
+                           dlg_radiobutton_set(td->valradio, dlg,
+                                               (*val == 'V'));
+                           dlg_editbox_set(td->valbox, dlg, val+1);
+                       }
+                   }
                    memmove(p, p+strlen(p)+1, len - (strlen(p)+1));
                    i++;
                    continue;
@@ -866,7 +896,7 @@ static void environ_handler(union control *ctrl, void *dlg,
            if (i < 0) {
                dlg_beep(dlg);
            } else {
-               char *p, *q;
+               char *p, *q, *str;
 
                dlg_listbox_del(ed->listbox, dlg, i);
                p = cfg->environmt;
@@ -881,8 +911,20 @@ static void environ_handler(union control *ctrl, void *dlg,
                q = p;
                if (!*p)
                    goto disaster;
-               while (*p)
-                   p++;
+               /* Populate controls with the entry we're about to delete
+                * for ease of editing */
+               str = p;
+               p = strchr(p, '\t');
+               if (!p)
+                   goto disaster;
+               *p = '\0';
+               dlg_editbox_set(ed->varbox, dlg, str);
+               p++;
+               str = p;
+               dlg_editbox_set(ed->valbox, dlg, str);
+               p = strchr(p, '\0');
+               if (!p)
+                   goto disaster;
                p++;
                while (*p) {
                    while (*p)
@@ -995,7 +1037,8 @@ static void portfwd_handler(union control *ctrl, void *dlg,
            if (i < 0)
                dlg_beep(dlg);
            else {
-               char *p, *q;
+               char *p, *q, *src, *dst;
+               char dir;
 
                dlg_listbox_del(pfd->listbox, dlg, i);
                p = cfg->portfwd;
@@ -1010,8 +1053,42 @@ static void portfwd_handler(union control *ctrl, void *dlg,
                q = p;
                if (!*p)
                    goto disaster2;
-               while (*p)
+               /* Populate the controls with the entry we're about to
+                * delete, for ease of editing. */
+               {
+                   static const char *const afs = "A46";
+                   char *afp = strchr(afs, *p);
+                   int idx = afp ? afp-afs : 0;
+                   if (afp)
+                       p++;
+#ifndef NO_IPV6
+                   dlg_radiobutton_set(pfd->addressfamily, dlg, idx);
+#endif
+               }
+               {
+                   static const char *const dirs = "LRD";
+                   dir = *p;
+                   dlg_radiobutton_set(pfd->direction, dlg,
+                                       strchr(dirs, dir) - dirs);
+               }
+               p++;
+               if (dir != 'D') {
+                   src = p;
+                   p = strchr(p, '\t');
+                   if (!p)
+                       goto disaster2;
+                   *p = '\0';
                    p++;
+                   dst = p;
+               } else {
+                   src = p;
+                   dst = "";
+               }
+               p = strchr(p, '\0');
+               if (!p)
+                   goto disaster2;
+               dlg_editbox_set(pfd->sourcebox, dlg, src);
+               dlg_editbox_set(pfd->destbox, dlg, dst);
                p++;
                while (*p) {
                    while (*p)
@@ -1399,13 +1476,13 @@ void setup_config_box(struct controlbox *b, int midsession,
 
     s = ctrl_getset(b, "Window", "size", "Set the size of the window");
     ctrl_columns(s, 2, 50, 50);
-    c = ctrl_editbox(s, "Rows", 'r', 100,
-                    HELPCTX(window_size),
-                    dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
-    c->generic.column = 0;
     c = ctrl_editbox(s, "Columns", 'm', 100,
                     HELPCTX(window_size),
                     dlg_stdeditbox_handler, I(offsetof(Config,width)), I(-1));
+    c->generic.column = 0;
+    c = ctrl_editbox(s, "Rows", 'r', 100,
+                    HELPCTX(window_size),
+                    dlg_stdeditbox_handler, I(offsetof(Config,height)),I(-1));
     c->generic.column = 1;
     ctrl_columns(s, 1, 100);