Fix typos
[TortoiseGit.git] / src / TortoisePlink / SETTINGS.C
blob6f4f7d99fbc0842bf53ea6b3fbf4e1fab1c61b90
1 /*\r
2  * settings.c: read and write saved sessions. (platform-independent)\r
3  */\r
4 \r
5 #include <assert.h>\r
6 #include <stdio.h>\r
7 #include <stdlib.h>\r
8 #include "putty.h"\r
9 #include "storage.h"\r
10 #ifndef NO_GSSAPI\r
11 #include "ssh/gssc.h"\r
12 #include "ssh/gss.h"\r
13 #endif\r
16 /* The cipher order given here is the default order. */\r
17 static const struct keyvalwhere ciphernames[] = {\r
18     { "aes",        CIPHER_AES,             -1, -1 },\r
19     { "chacha20",   CIPHER_CHACHA20,        CIPHER_AES, +1 },\r
20     { "aesgcm",     CIPHER_AESGCM,          CIPHER_CHACHA20, +1 },\r
21     { "3des",       CIPHER_3DES,            -1, -1 },\r
22     { "WARN",       CIPHER_WARN,            -1, -1 },\r
23     { "des",        CIPHER_DES,             -1, -1 },\r
24     { "blowfish",   CIPHER_BLOWFISH,        -1, -1 },\r
25     { "arcfour",    CIPHER_ARCFOUR,         -1, -1 },\r
26 };\r
28 /* The default order here is sometimes overridden by the backward-\r
29  * compatibility warts in load_open_settings(), and should be kept\r
30  * in sync with those. */\r
31 static const struct keyvalwhere kexnames[] = {\r
32     { "ntru-curve25519",    KEX_NTRU_HYBRID, -1, +1 },\r
33     { "ecdh",               KEX_ECDH,       -1, +1 },\r
34     /* This name is misleading: it covers both SHA-256 and SHA-1 variants */\r
35     { "dh-gex-sha1",        KEX_DHGEX,      -1, -1 },\r
36     /* Again, this covers both SHA-256 and SHA-1, despite the name: */\r
37     { "dh-group14-sha1",    KEX_DHGROUP14,  -1, -1 },\r
38     /* This one really is only SHA-1, though: */\r
39     { "dh-group1-sha1",     KEX_DHGROUP1,   KEX_WARN, +1 },\r
40     { "rsa",                KEX_RSA,        KEX_WARN, -1 },\r
41     /* Larger fixed DH groups: prefer the larger 15 and 16 over 14,\r
42      * but by default the even larger 17 and 18 go below 16.\r
43      * Rationale: diminishing returns of improving the DH strength are\r
44      * outweighed by increased CPU cost. Group 18 is painful on a slow\r
45      * machine. Users can override if they need to. */\r
46     { "dh-group15-sha512",  KEX_DHGROUP15,  KEX_DHGROUP14, -1 },\r
47     { "dh-group16-sha512",  KEX_DHGROUP16,  KEX_DHGROUP15, -1 },\r
48     { "dh-group17-sha512",  KEX_DHGROUP17,  KEX_DHGROUP16, +1 },\r
49     { "dh-group18-sha512",  KEX_DHGROUP18,  KEX_DHGROUP17, +1 },\r
50     { "WARN",               KEX_WARN,       -1, -1 }\r
51 };\r
53 static const struct keyvalwhere hknames[] = {\r
54     { "ed25519",    HK_ED25519,             -1, +1 },\r
55     { "ed448",      HK_ED448,               -1, +1 },\r
56     { "ecdsa",      HK_ECDSA,               -1, -1 },\r
57     { "dsa",        HK_DSA,                 -1, -1 },\r
58     { "rsa",        HK_RSA,                 -1, -1 },\r
59     { "WARN",       HK_WARN,                -1, -1 },\r
60 };\r
62 /*\r
63  * All the terminal modes that we know about for the "TerminalModes"\r
64  * setting. (Also used by config.c for the drop-down list.)\r
65  * This is currently precisely the same as the set in\r
66  * ssh/ttymode-list.h, but could in principle differ if other backends\r
67  * started to support tty modes (e.g., the pty backend).\r
68  * The set of modes in in this array is currently significant for\r
69  * settings migration from old versions; if they change, review the\r
70  * gppmap() invocation for "TerminalModes".\r
71  */\r
72 const char *const ttymodes[] = {\r
73     "INTR",     "QUIT",     "ERASE",    "KILL",     "EOF",\r
74     "EOL",      "EOL2",     "START",    "STOP",     "SUSP",\r
75     "DSUSP",    "REPRINT",  "WERASE",   "LNEXT",    "FLUSH",\r
76     "SWTCH",    "STATUS",   "DISCARD",  "IGNPAR",   "PARMRK",\r
77     "INPCK",    "ISTRIP",   "INLCR",    "IGNCR",    "ICRNL",\r
78     "IUCLC",    "IXON",     "IXANY",    "IXOFF",    "IMAXBEL",\r
79     "IUTF8",    "ISIG",     "ICANON",   "XCASE",    "ECHO",\r
80     "ECHOE",    "ECHOK",    "ECHONL",   "NOFLSH",   "TOSTOP",\r
81     "IEXTEN",   "ECHOCTL",  "ECHOKE",   "PENDIN",   "OPOST",\r
82     "OLCUC",    "ONLCR",    "OCRNL",    "ONOCR",    "ONLRET",\r
83     "CS7",      "CS8",      "PARENB",   "PARODD",   NULL\r
84 };\r
86 static int default_protocol, default_port;\r
87 void settings_set_default_protocol(int newval) { default_protocol = newval; }\r
88 void settings_set_default_port(int newval) { default_port = newval; }\r
90 /*\r
91  * Convenience functions to access the backends[] array\r
92  * (which is only present in tools that manage settings).\r
93  */\r
95 const struct BackendVtable *backend_vt_from_name(const char *name)\r
96 {\r
97     const struct BackendVtable *const *p;\r
98     for (p = backends; *p != NULL; p++)\r
99         if (!strcmp((*p)->id, name))\r
100             return *p;\r
101     return NULL;\r
104 const struct BackendVtable *backend_vt_from_proto(int proto)\r
106     const struct BackendVtable *const *p;\r
107     for (p = backends; *p != NULL; p++)\r
108         if ((*p)->protocol == proto)\r
109             return *p;\r
110     return NULL;\r
113 char *get_remote_username(Conf *conf)\r
115     char *username = conf_get_str(conf, CONF_username);\r
116     if (*username) {\r
117         return dupstr(username);\r
118     } else if (conf_get_bool(conf, CONF_username_from_env)) {\r
119         /* Use local username. */\r
120         return get_username();     /* might still be NULL */\r
121     } else {\r
122         return NULL;\r
123     }\r
126 static char *gpps_raw(settings_r *sesskey, const char *name, const char *def)\r
128     char *ret = read_setting_s(sesskey, name);\r
129     if (!ret)\r
130         ret = platform_default_s(name);\r
131     if (!ret)\r
132         ret = def ? dupstr(def) : NULL;   /* permit NULL as final fallback */\r
133     return ret;\r
136 static void gpps(settings_r *sesskey, const char *name, const char *def,\r
137                  Conf *conf, int primary)\r
139     char *val = gpps_raw(sesskey, name, def);\r
140     conf_set_str(conf, primary, val);\r
141     sfree(val);\r
144 /*\r
145  * gppfont and gppfile cannot have local defaults, since the very\r
146  * format of a Filename or FontSpec is platform-dependent. So the\r
147  * platform-dependent functions MUST return some sort of value.\r
148  */\r
149 static void gppfont(settings_r *sesskey, const char *name,\r
150                     Conf *conf, int primary)\r
152     FontSpec *result = read_setting_fontspec(sesskey, name);\r
153     if (!result)\r
154         result = platform_default_fontspec(name);\r
155     conf_set_fontspec(conf, primary, result);\r
156     fontspec_free(result);\r
158 static void gppfile(settings_r *sesskey, const char *name,\r
159                     Conf *conf, int primary)\r
161     Filename *result = read_setting_filename(sesskey, name);\r
162     if (!result)\r
163         result = platform_default_filename(name);\r
164     conf_set_filename(conf, primary, result);\r
165     filename_free(result);\r
168 static bool gppb_raw(settings_r *sesskey, const char *name, bool def)\r
170     def = platform_default_b(name, def);\r
171     return sesskey ? read_setting_i(sesskey, name, def) != 0 : def;\r
174 static void gppb(settings_r *sesskey, const char *name, bool def,\r
175                  Conf *conf, int primary)\r
177     conf_set_bool(conf, primary, gppb_raw(sesskey, name, def));\r
180 static int gppi_raw(settings_r *sesskey, const char *name, int def)\r
182     def = platform_default_i(name, def);\r
183     return read_setting_i(sesskey, name, def);\r
186 static void gppi(settings_r *sesskey, const char *name, int def,\r
187                  Conf *conf, int primary)\r
189     conf_set_int(conf, primary, gppi_raw(sesskey, name, def));\r
192 /*\r
193  * Read a set of name-value pairs in the format we occasionally use:\r
194  *   NAME\tVALUE\0NAME\tVALUE\0\0 in memory\r
195  *   NAME=VALUE,NAME=VALUE, in storage\r
196  * If there's no "=VALUE" (e.g. just NAME,NAME,NAME) then those keys\r
197  * are mapped to the empty string.\r
198  */\r
199 static bool gppmap(settings_r *sesskey, const char *name,\r
200                    Conf *conf, int primary)\r
202     char *buf, *p, *q, *key, *val;\r
204     /*\r
205      * Start by clearing any existing subkeys of this key from conf.\r
206      */\r
207     while ((key = conf_get_str_nthstrkey(conf, primary, 0)) != NULL)\r
208         conf_del_str_str(conf, primary, key);\r
210     /*\r
211      * Now read a serialised list from the settings and unmarshal it\r
212      * into its components.\r
213      */\r
214     buf = gpps_raw(sesskey, name, NULL);\r
215     if (!buf)\r
216         return false;\r
218     p = buf;\r
219     while (*p) {\r
220         q = buf;\r
221         val = NULL;\r
222         while (*p && *p != ',') {\r
223             int c = *p++;\r
224             if (c == '=')\r
225                 c = '\0';\r
226             if (c == '\\')\r
227                 c = *p++;\r
228             *q++ = c;\r
229             if (!c)\r
230                 val = q;\r
231         }\r
232         if (*p == ',')\r
233             p++;\r
234         if (!val)\r
235             val = q;\r
236         *q = '\0';\r
238         if (primary == CONF_portfwd && strchr(buf, 'D') != NULL) {\r
239             /*\r
240              * Backwards-compatibility hack: dynamic forwardings are\r
241              * indexed in the data store as a third type letter in the\r
242              * key, 'D' alongside 'L' and 'R' - but really, they\r
243              * should be filed under 'L' with a special _value_,\r
244              * because local and dynamic forwardings both involve\r
245              * _listening_ on a local port, and are hence mutually\r
246              * exclusive on the same port number. So here we translate\r
247              * the legacy storage format into the sensible internal\r
248              * form, by finding the D and turning it into a L.\r
249              */\r
250             char *newkey = dupstr(buf);\r
251             *strchr(newkey, 'D') = 'L';\r
252             conf_set_str_str(conf, primary, newkey, "D");\r
253             sfree(newkey);\r
254         } else {\r
255             conf_set_str_str(conf, primary, buf, val);\r
256         }\r
257     }\r
258     sfree(buf);\r
260     return true;\r
263 /*\r
264  * Write a set of name/value pairs in the above format, or just the\r
265  * names if include_values is false.\r
266  */\r
267 static void wmap(settings_w *sesskey, char const *outkey, Conf *conf,\r
268                  int primary, bool include_values)\r
270     char *buf, *p, *key, *realkey;\r
271     const char *val, *q;\r
272     int len;\r
274     len = 1;                           /* allow for NUL */\r
276     for (val = conf_get_str_strs(conf, primary, NULL, &key);\r
277          val != NULL;\r
278          val = conf_get_str_strs(conf, primary, key, &key))\r
279         len += 2 + 2 * (strlen(key) + strlen(val));   /* allow for escaping */\r
281     buf = snewn(len, char);\r
282     p = buf;\r
284     for (val = conf_get_str_strs(conf, primary, NULL, &key);\r
285          val != NULL;\r
286          val = conf_get_str_strs(conf, primary, key, &key)) {\r
288         if (primary == CONF_portfwd && !strcmp(val, "D")) {\r
289             /*\r
290              * Backwards-compatibility hack, as above: translate from\r
291              * the sensible internal representation of dynamic\r
292              * forwardings (key "L<port>", value "D") to the\r
293              * conceptually incoherent legacy storage format (key\r
294              * "D<port>", value empty).\r
295              */\r
296             char *L;\r
298             realkey = key;             /* restore it at end of loop */\r
299             val = "";\r
300             key = dupstr(key);\r
301             L = strchr(key, 'L');\r
302             if (L) *L = 'D';\r
303         } else {\r
304             realkey = NULL;\r
305         }\r
307         if (p != buf)\r
308             *p++ = ',';\r
309         for (q = key; *q; q++) {\r
310             if (*q == '=' || *q == ',' || *q == '\\')\r
311                 *p++ = '\\';\r
312             *p++ = *q;\r
313         }\r
314         if (include_values) {\r
315             *p++ = '=';\r
316             for (q = val; *q; q++) {\r
317                 if (*q == '=' || *q == ',' || *q == '\\')\r
318                     *p++ = '\\';\r
319                 *p++ = *q;\r
320             }\r
321         }\r
323         if (realkey) {\r
324             free(key);\r
325             key = realkey;\r
326         }\r
327     }\r
328     *p = '\0';\r
329     write_setting_s(sesskey, outkey, buf);\r
330     sfree(buf);\r
333 static int key2val(const struct keyvalwhere *mapping,\r
334                    int nmaps, char *key)\r
336     int i;\r
337     for (i = 0; i < nmaps; i++)\r
338         if (!strcmp(mapping[i].s, key)) return mapping[i].v;\r
339     return -1;\r
342 static const char *val2key(const struct keyvalwhere *mapping,\r
343                            int nmaps, int val)\r
345     int i;\r
346     for (i = 0; i < nmaps; i++)\r
347         if (mapping[i].v == val) return mapping[i].s;\r
348     return NULL;\r
351 /*\r
352  * Helper function to parse a comma-separated list of strings into\r
353  * a preference list array of values. Any missing values are added\r
354  * to the end and duplicates are weeded.\r
355  * XXX: assumes vals in 'mapping' are small +ve integers\r
356  */\r
357 static void gprefs_from_str(const char *str,\r
358                             const struct keyvalwhere *mapping, int nvals,\r
359                             Conf *conf, int primary)\r
361     char *commalist = dupstr(str);\r
362     char *p, *q;\r
363     int i, j, n, v, pos;\r
364     unsigned long seen = 0;            /* bitmap for weeding dups etc */\r
366     /*\r
367      * Go through that list and convert it into values.\r
368      */\r
369     n = 0;\r
370     p = commalist;\r
371     while (1) {\r
372         while (*p && *p == ',') p++;\r
373         if (!*p)\r
374             break;                     /* no more words */\r
376         q = p;\r
377         while (*p && *p != ',') p++;\r
378         if (*p) *p++ = '\0';\r
380         v = key2val(mapping, nvals, q);\r
381         if (v != -1 && !(seen & (1 << v))) {\r
382             seen |= (1 << v);\r
383             conf_set_int_int(conf, primary, n, v);\r
384             n++;\r
385         }\r
386     }\r
388     sfree(commalist);\r
390     /*\r
391      * Now go through 'mapping' and add values that weren't mentioned\r
392      * in the list we fetched. We may have to loop over it multiple\r
393      * times so that we add values before other values whose default\r
394      * positions depend on them.\r
395      */\r
396     while (n < nvals) {\r
397         for (i = 0; i < nvals; i++) {\r
398             assert(mapping[i].v >= 0);\r
399             assert(mapping[i].v < 32);\r
401             if (!(seen & (1 << mapping[i].v))) {\r
402                 /*\r
403                  * This element needs adding. But can we add it yet?\r
404                  */\r
405                 if (mapping[i].vrel != -1 && !(seen & (1 << mapping[i].vrel)))\r
406                     continue;          /* nope */\r
408                 /*\r
409                  * OK, we can work out where to add this element, so\r
410                  * do so.\r
411                  */\r
412                 if (mapping[i].vrel == -1) {\r
413                     pos = (mapping[i].where < 0 ? n : 0);\r
414                 } else {\r
415                     for (j = 0; j < n; j++)\r
416                         if (conf_get_int_int(conf, primary, j) ==\r
417                             mapping[i].vrel)\r
418                             break;\r
419                     assert(j < n);     /* implied by (seen & (1<<vrel)) */\r
420                     pos = (mapping[i].where < 0 ? j : j+1);\r
421                 }\r
423                 /*\r
424                  * And add it.\r
425                  */\r
426                 for (j = n-1; j >= pos; j--)\r
427                     conf_set_int_int(conf, primary, j+1,\r
428                                      conf_get_int_int(conf, primary, j));\r
429                 conf_set_int_int(conf, primary, pos, mapping[i].v);\r
430                 seen |= (1 << mapping[i].v);\r
431                 n++;\r
432             }\r
433         }\r
434     }\r
437 /*\r
438  * Read a preference list.\r
439  */\r
440 static void gprefs(settings_r *sesskey, const char *name, const char *def,\r
441                    const struct keyvalwhere *mapping, int nvals,\r
442                    Conf *conf, int primary)\r
444     /*\r
445      * Fetch the string which we'll parse as a comma-separated list.\r
446      */\r
447     char *value = gpps_raw(sesskey, name, def);\r
448     gprefs_from_str(value, mapping, nvals, conf, primary);\r
449     sfree(value);\r
452 /*\r
453  * Write out a preference list.\r
454  */\r
455 static void wprefs(settings_w *sesskey, const char *name,\r
456                    const struct keyvalwhere *mapping, int nvals,\r
457                    Conf *conf, int primary)\r
459     char *buf, *p;\r
460     int i, maxlen;\r
462     for (maxlen = i = 0; i < nvals; i++) {\r
463         const char *s = val2key(mapping, nvals,\r
464                                 conf_get_int_int(conf, primary, i));\r
465         if (s) {\r
466             maxlen += (maxlen > 0 ? 1 : 0) + strlen(s);\r
467         }\r
468     }\r
470     buf = snewn(maxlen + 1, char);\r
471     p = buf;\r
473     for (i = 0; i < nvals; i++) {\r
474         const char *s = val2key(mapping, nvals,\r
475                                 conf_get_int_int(conf, primary, i));\r
476         if (s) {\r
477             p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);\r
478         }\r
479     }\r
481     assert(p - buf == maxlen);\r
482     *p = '\0';\r
484     write_setting_s(sesskey, name, buf);\r
486     sfree(buf);\r
489 static void write_setting_b(settings_w *handle, const char *key, bool value)\r
491     write_setting_i(handle, key, value ? 1 : 0);\r
494 static void write_clip_setting(settings_w *sesskey, const char *savekey,\r
495                                Conf *conf, int confkey, int strconfkey)\r
497     int val = conf_get_int(conf, confkey);\r
498     switch (val) {\r
499       case CLIPUI_NONE:\r
500       default:\r
501         write_setting_s(sesskey, savekey, "none");\r
502         break;\r
503       case CLIPUI_IMPLICIT:\r
504         write_setting_s(sesskey, savekey, "implicit");\r
505         break;\r
506       case CLIPUI_EXPLICIT:\r
507         write_setting_s(sesskey, savekey, "explicit");\r
508         break;\r
509       case CLIPUI_CUSTOM: {\r
510         char *sval = dupcat("custom:", conf_get_str(conf, strconfkey));\r
511         write_setting_s(sesskey, savekey, sval);\r
512         sfree(sval);\r
513         break;\r
514       }\r
515     }\r
518 static void read_clip_setting(settings_r *sesskey, char *savekey,\r
519                               int def, Conf *conf, int confkey, int strconfkey)\r
521     char *setting = read_setting_s(sesskey, savekey);\r
522     int val;\r
524     conf_set_str(conf, strconfkey, "");\r
525     if (!setting) {\r
526         val = def;\r
527     } else if (!strcmp(setting, "implicit")) {\r
528         val = CLIPUI_IMPLICIT;\r
529     } else if (!strcmp(setting, "explicit")) {\r
530         val = CLIPUI_EXPLICIT;\r
531     } else if (!strncmp(setting, "custom:", 7)) {\r
532         val = CLIPUI_CUSTOM;\r
533         conf_set_str(conf, strconfkey, setting + 7);\r
534     } else {\r
535         val = CLIPUI_NONE;\r
536     }\r
537     conf_set_int(conf, confkey, val);\r
538     sfree(setting);\r
541 char *save_settings(const char *section, Conf *conf)\r
543     struct settings_w *sesskey;\r
544     char *errmsg;\r
546     sesskey = open_settings_w(section, &errmsg);\r
547     if (!sesskey)\r
548         return errmsg;\r
549     save_open_settings(sesskey, conf);\r
550     close_settings_w(sesskey);\r
551     return NULL;\r
554 void save_open_settings(settings_w *sesskey, Conf *conf)\r
556     int i;\r
557     const char *p;\r
559     write_setting_i(sesskey, "Present", 1);\r
560     write_setting_s(sesskey, "HostName", conf_get_str(conf, CONF_host));\r
561     write_setting_filename(sesskey, "LogFileName", conf_get_filename(conf, CONF_logfilename));\r
562     write_setting_i(sesskey, "LogType", conf_get_int(conf, CONF_logtype));\r
563     write_setting_i(sesskey, "LogFileClash", conf_get_int(conf, CONF_logxfovr));\r
564     write_setting_b(sesskey, "LogFlush", conf_get_bool(conf, CONF_logflush));\r
565     write_setting_b(sesskey, "LogHeader", conf_get_bool(conf, CONF_logheader));\r
566     write_setting_b(sesskey, "SSHLogOmitPasswords", conf_get_bool(conf, CONF_logomitpass));\r
567     write_setting_b(sesskey, "SSHLogOmitData", conf_get_bool(conf, CONF_logomitdata));\r
568     p = "raw";\r
569     {\r
570         const struct BackendVtable *vt =\r
571             backend_vt_from_proto(conf_get_int(conf, CONF_protocol));\r
572         if (vt)\r
573             p = vt->id;\r
574     }\r
575     write_setting_s(sesskey, "Protocol", p);\r
576     write_setting_i(sesskey, "PortNumber", conf_get_int(conf, CONF_port));\r
577     /* The CloseOnExit numbers are arranged in a different order from\r
578      * the standard FORCE_ON / FORCE_OFF / AUTO. */\r
579     write_setting_i(sesskey, "CloseOnExit", (conf_get_int(conf, CONF_close_on_exit)+2)%3);\r
580     write_setting_b(sesskey, "WarnOnClose", !!conf_get_bool(conf, CONF_warn_on_close));\r
581     write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60);      /* minutes */\r
582     write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60);  /* seconds */\r
583     write_setting_b(sesskey, "TCPNoDelay", conf_get_bool(conf, CONF_tcp_nodelay));\r
584     write_setting_b(sesskey, "TCPKeepalives", conf_get_bool(conf, CONF_tcp_keepalives));\r
585     write_setting_s(sesskey, "TerminalType", conf_get_str(conf, CONF_termtype));\r
586     write_setting_s(sesskey, "TerminalSpeed", conf_get_str(conf, CONF_termspeed));\r
587     wmap(sesskey, "TerminalModes", conf, CONF_ttymodes, true);\r
589     /* Address family selection */\r
590     write_setting_i(sesskey, "AddressFamily", conf_get_int(conf, CONF_addressfamily));\r
592     /* proxy settings */\r
593     write_setting_s(sesskey, "ProxyExcludeList", conf_get_str(conf, CONF_proxy_exclude_list));\r
594     write_setting_i(sesskey, "ProxyDNS", (conf_get_int(conf, CONF_proxy_dns)+2)%3);\r
595     write_setting_b(sesskey, "ProxyLocalhost", conf_get_bool(conf, CONF_even_proxy_localhost));\r
596     write_setting_i(sesskey, "ProxyMethod", conf_get_int(conf, CONF_proxy_type));\r
597     write_setting_s(sesskey, "ProxyHost", conf_get_str(conf, CONF_proxy_host));\r
598     write_setting_i(sesskey, "ProxyPort", conf_get_int(conf, CONF_proxy_port));\r
599     write_setting_s(sesskey, "ProxyUsername", conf_get_str(conf, CONF_proxy_username));\r
600     write_setting_s(sesskey, "ProxyPassword", conf_get_str(conf, CONF_proxy_password));\r
601     write_setting_s(sesskey, "ProxyTelnetCommand", conf_get_str(conf, CONF_proxy_telnet_command));\r
602     write_setting_i(sesskey, "ProxyLogToTerm", conf_get_int(conf, CONF_proxy_log_to_term));\r
603     wmap(sesskey, "Environment", conf, CONF_environmt, true);\r
604     write_setting_s(sesskey, "UserName", conf_get_str(conf, CONF_username));\r
605     write_setting_b(sesskey, "UserNameFromEnvironment", conf_get_bool(conf, CONF_username_from_env));\r
606     write_setting_s(sesskey, "LocalUserName", conf_get_str(conf, CONF_localusername));\r
607     write_setting_b(sesskey, "NoPTY", conf_get_bool(conf, CONF_nopty));\r
608     write_setting_b(sesskey, "Compression", conf_get_bool(conf, CONF_compression));\r
609     write_setting_b(sesskey, "TryAgent", conf_get_bool(conf, CONF_tryagent));\r
610     write_setting_b(sesskey, "AgentFwd", conf_get_bool(conf, CONF_agentfwd));\r
611 #ifndef NO_GSSAPI\r
612     write_setting_b(sesskey, "GssapiFwd", conf_get_bool(conf, CONF_gssapifwd));\r
613 #endif\r
614     write_setting_b(sesskey, "ChangeUsername", conf_get_bool(conf, CONF_change_username));\r
615     wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);\r
616     wprefs(sesskey, "KEX", kexnames, KEX_MAX, conf, CONF_ssh_kexlist);\r
617     wprefs(sesskey, "HostKey", hknames, HK_MAX, conf, CONF_ssh_hklist);\r
618     write_setting_b(sesskey, "PreferKnownHostKeys", conf_get_bool(conf, CONF_ssh_prefer_known_hostkeys));\r
619     write_setting_i(sesskey, "RekeyTime", conf_get_int(conf, CONF_ssh_rekey_time));\r
620 #ifndef NO_GSSAPI\r
621     write_setting_i(sesskey, "GssapiRekey", conf_get_int(conf, CONF_gssapirekey));\r
622 #endif\r
623     write_setting_s(sesskey, "RekeyBytes", conf_get_str(conf, CONF_ssh_rekey_data));\r
624     write_setting_b(sesskey, "SshNoAuth", conf_get_bool(conf, CONF_ssh_no_userauth));\r
625     write_setting_b(sesskey, "SshNoTrivialAuth", conf_get_bool(conf, CONF_ssh_no_trivial_userauth));\r
626     write_setting_b(sesskey, "SshBanner", conf_get_bool(conf, CONF_ssh_show_banner));\r
627     write_setting_b(sesskey, "AuthTIS", conf_get_bool(conf, CONF_try_tis_auth));\r
628     write_setting_b(sesskey, "AuthKI", conf_get_bool(conf, CONF_try_ki_auth));\r
629 #ifndef NO_GSSAPI\r
630     write_setting_b(sesskey, "AuthGSSAPI", conf_get_bool(conf, CONF_try_gssapi_auth));\r
631     write_setting_b(sesskey, "AuthGSSAPIKEX", conf_get_bool(conf, CONF_try_gssapi_kex));\r
632     wprefs(sesskey, "GSSLibs", gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);\r
633     write_setting_filename(sesskey, "GSSCustom", conf_get_filename(conf, CONF_ssh_gss_custom));\r
634 #endif\r
635     write_setting_b(sesskey, "SshNoShell", conf_get_bool(conf, CONF_ssh_no_shell));\r
636     write_setting_i(sesskey, "SshProt", conf_get_int(conf, CONF_sshprot));\r
637     write_setting_s(sesskey, "LogHost", conf_get_str(conf, CONF_loghost));\r
638     write_setting_b(sesskey, "SSH2DES", conf_get_bool(conf, CONF_ssh2_des_cbc));\r
639     write_setting_filename(sesskey, "PublicKeyFile", conf_get_filename(conf, CONF_keyfile));\r
640     write_setting_filename(sesskey, "DetachedCertificate", conf_get_filename(conf, CONF_detached_cert));\r
641     write_setting_s(sesskey, "AuthPlugin", conf_get_str(conf, CONF_auth_plugin));\r
642     write_setting_s(sesskey, "RemoteCommand", conf_get_str(conf, CONF_remote_cmd));\r
643     write_setting_b(sesskey, "RFCEnviron", conf_get_bool(conf, CONF_rfc_environ));\r
644     write_setting_b(sesskey, "PassiveTelnet", conf_get_bool(conf, CONF_passive_telnet));\r
645     write_setting_b(sesskey, "BackspaceIsDelete", conf_get_bool(conf, CONF_bksp_is_delete));\r
646     write_setting_b(sesskey, "RXVTHomeEnd", conf_get_bool(conf, CONF_rxvt_homeend));\r
647     write_setting_i(sesskey, "LinuxFunctionKeys", conf_get_int(conf, CONF_funky_type));\r
648     write_setting_i(sesskey, "ShiftedArrowKeys", conf_get_int(conf, CONF_sharrow_type));\r
649     write_setting_b(sesskey, "NoApplicationKeys", conf_get_bool(conf, CONF_no_applic_k));\r
650     write_setting_b(sesskey, "NoApplicationCursors", conf_get_bool(conf, CONF_no_applic_c));\r
651     write_setting_b(sesskey, "NoMouseReporting", conf_get_bool(conf, CONF_no_mouse_rep));\r
652     write_setting_b(sesskey, "NoRemoteResize", conf_get_bool(conf, CONF_no_remote_resize));\r
653     write_setting_b(sesskey, "NoAltScreen", conf_get_bool(conf, CONF_no_alt_screen));\r
654     write_setting_b(sesskey, "NoRemoteWinTitle", conf_get_bool(conf, CONF_no_remote_wintitle));\r
655     write_setting_b(sesskey, "NoRemoteClearScroll", conf_get_bool(conf, CONF_no_remote_clearscroll));\r
656     write_setting_i(sesskey, "RemoteQTitleAction", conf_get_int(conf, CONF_remote_qtitle_action));\r
657     write_setting_b(sesskey, "NoDBackspace", conf_get_bool(conf, CONF_no_dbackspace));\r
658     write_setting_b(sesskey, "NoRemoteCharset", conf_get_bool(conf, CONF_no_remote_charset));\r
659     write_setting_b(sesskey, "ApplicationCursorKeys", conf_get_bool(conf, CONF_app_cursor));\r
660     write_setting_b(sesskey, "ApplicationKeypad", conf_get_bool(conf, CONF_app_keypad));\r
661     write_setting_b(sesskey, "NetHackKeypad", conf_get_bool(conf, CONF_nethack_keypad));\r
662     write_setting_b(sesskey, "AltF4", conf_get_bool(conf, CONF_alt_f4));\r
663     write_setting_b(sesskey, "AltSpace", conf_get_bool(conf, CONF_alt_space));\r
664     write_setting_b(sesskey, "AltOnly", conf_get_bool(conf, CONF_alt_only));\r
665     write_setting_b(sesskey, "ComposeKey", conf_get_bool(conf, CONF_compose_key));\r
666     write_setting_b(sesskey, "CtrlAltKeys", conf_get_bool(conf, CONF_ctrlaltkeys));\r
667 #ifdef OSX_META_KEY_CONFIG\r
668     write_setting_b(sesskey, "OSXOptionMeta", conf_get_bool(conf, CONF_osx_option_meta));\r
669     write_setting_b(sesskey, "OSXCommandMeta", conf_get_bool(conf, CONF_osx_command_meta));\r
670 #endif\r
671     write_setting_b(sesskey, "TelnetKey", conf_get_bool(conf, CONF_telnet_keyboard));\r
672     write_setting_b(sesskey, "TelnetRet", conf_get_bool(conf, CONF_telnet_newline));\r
673     write_setting_i(sesskey, "LocalEcho", conf_get_int(conf, CONF_localecho));\r
674     write_setting_i(sesskey, "LocalEdit", conf_get_int(conf, CONF_localedit));\r
675     write_setting_s(sesskey, "Answerback", conf_get_str(conf, CONF_answerback));\r
676     write_setting_b(sesskey, "AlwaysOnTop", conf_get_bool(conf, CONF_alwaysontop));\r
677     write_setting_b(sesskey, "FullScreenOnAltEnter", conf_get_bool(conf, CONF_fullscreenonaltenter));\r
678     write_setting_b(sesskey, "HideMousePtr", conf_get_bool(conf, CONF_hide_mouseptr));\r
679     write_setting_b(sesskey, "SunkenEdge", conf_get_bool(conf, CONF_sunken_edge));\r
680     write_setting_i(sesskey, "WindowBorder", conf_get_int(conf, CONF_window_border));\r
681     write_setting_i(sesskey, "CurType", conf_get_int(conf, CONF_cursor_type));\r
682     write_setting_b(sesskey, "BlinkCur", conf_get_bool(conf, CONF_blink_cur));\r
683     write_setting_i(sesskey, "Beep", conf_get_int(conf, CONF_beep));\r
684     write_setting_i(sesskey, "BeepInd", conf_get_int(conf, CONF_beep_ind));\r
685     write_setting_filename(sesskey, "BellWaveFile", conf_get_filename(conf, CONF_bell_wavefile));\r
686     write_setting_b(sesskey, "BellOverload", conf_get_bool(conf, CONF_bellovl));\r
687     write_setting_i(sesskey, "BellOverloadN", conf_get_int(conf, CONF_bellovl_n));\r
688     write_setting_i(sesskey, "BellOverloadT", conf_get_int(conf, CONF_bellovl_t)\r
689 #ifdef PUTTY_UNIX_PLATFORM_H\r
690                     * 1000\r
691 #endif\r
692                     );\r
693     write_setting_i(sesskey, "BellOverloadS", conf_get_int(conf, CONF_bellovl_s)\r
694 #ifdef PUTTY_UNIX_PLATFORM_H\r
695                     * 1000\r
696 #endif\r
697                     );\r
698     write_setting_i(sesskey, "ScrollbackLines", conf_get_int(conf, CONF_savelines));\r
699     write_setting_b(sesskey, "DECOriginMode", conf_get_bool(conf, CONF_dec_om));\r
700     write_setting_b(sesskey, "AutoWrapMode", conf_get_bool(conf, CONF_wrap_mode));\r
701     write_setting_b(sesskey, "LFImpliesCR", conf_get_bool(conf, CONF_lfhascr));\r
702     write_setting_b(sesskey, "CRImpliesLF", conf_get_bool(conf, CONF_crhaslf));\r
703     write_setting_b(sesskey, "DisableArabicShaping", conf_get_bool(conf, CONF_no_arabicshaping));\r
704     write_setting_b(sesskey, "DisableBidi", conf_get_bool(conf, CONF_no_bidi));\r
705     write_setting_b(sesskey, "WinNameAlways", conf_get_bool(conf, CONF_win_name_always));\r
706     write_setting_s(sesskey, "WinTitle", conf_get_str(conf, CONF_wintitle));\r
707     write_setting_i(sesskey, "TermWidth", conf_get_int(conf, CONF_width));\r
708     write_setting_i(sesskey, "TermHeight", conf_get_int(conf, CONF_height));\r
709     write_setting_fontspec(sesskey, "Font", conf_get_fontspec(conf, CONF_font));\r
710     write_setting_i(sesskey, "FontQuality", conf_get_int(conf, CONF_font_quality));\r
711     write_setting_i(sesskey, "FontVTMode", conf_get_int(conf, CONF_vtmode));\r
712     write_setting_b(sesskey, "UseSystemColours", conf_get_bool(conf, CONF_system_colour));\r
713     write_setting_b(sesskey, "TryPalette", conf_get_bool(conf, CONF_try_palette));\r
714     write_setting_b(sesskey, "ANSIColour", conf_get_bool(conf, CONF_ansi_colour));\r
715     write_setting_b(sesskey, "Xterm256Colour", conf_get_bool(conf, CONF_xterm_256_colour));\r
716     write_setting_b(sesskey, "TrueColour", conf_get_bool(conf, CONF_true_colour));\r
717     write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_style)-1);\r
719     for (i = 0; i < 22; i++) {\r
720         char buf[20], buf2[30];\r
721         sprintf(buf, "Colour%d", i);\r
722         sprintf(buf2, "%d,%d,%d",\r
723                 conf_get_int_int(conf, CONF_colours, i*3+0),\r
724                 conf_get_int_int(conf, CONF_colours, i*3+1),\r
725                 conf_get_int_int(conf, CONF_colours, i*3+2));\r
726         write_setting_s(sesskey, buf, buf2);\r
727     }\r
728     write_setting_b(sesskey, "RawCNP", conf_get_bool(conf, CONF_rawcnp));\r
729     write_setting_b(sesskey, "UTF8linedraw", conf_get_bool(conf, CONF_utf8linedraw));\r
730     write_setting_b(sesskey, "PasteRTF", conf_get_bool(conf, CONF_rtf_paste));\r
731     write_setting_i(sesskey, "MouseIsXterm", conf_get_int(conf, CONF_mouse_is_xterm));\r
732     write_setting_b(sesskey, "RectSelect", conf_get_bool(conf, CONF_rect_select));\r
733     write_setting_b(sesskey, "PasteControls", conf_get_bool(conf, CONF_paste_controls));\r
734     write_setting_b(sesskey, "MouseOverride", conf_get_bool(conf, CONF_mouse_override));\r
735     for (i = 0; i < 256; i += 32) {\r
736         char buf[20], buf2[256];\r
737         int j;\r
738         sprintf(buf, "Wordness%d", i);\r
739         *buf2 = '\0';\r
740         for (j = i; j < i + 32; j++) {\r
741             sprintf(buf2 + strlen(buf2), "%s%d",\r
742                     (*buf2 ? "," : ""),\r
743                     conf_get_int_int(conf, CONF_wordness, j));\r
744         }\r
745         write_setting_s(sesskey, buf, buf2);\r
746     }\r
747     write_setting_b(sesskey, "MouseAutocopy",\r
748                     conf_get_bool(conf, CONF_mouseautocopy));\r
749     write_clip_setting(sesskey, "MousePaste", conf,\r
750                        CONF_mousepaste, CONF_mousepaste_custom);\r
751     write_clip_setting(sesskey, "CtrlShiftIns", conf,\r
752                        CONF_ctrlshiftins, CONF_ctrlshiftins_custom);\r
753     write_clip_setting(sesskey, "CtrlShiftCV", conf,\r
754                        CONF_ctrlshiftcv, CONF_ctrlshiftcv_custom);\r
755     write_setting_s(sesskey, "LineCodePage", conf_get_str(conf, CONF_line_codepage));\r
756     write_setting_b(sesskey, "CJKAmbigWide", conf_get_bool(conf, CONF_cjk_ambig_wide));\r
757     write_setting_b(sesskey, "UTF8Override", conf_get_bool(conf, CONF_utf8_override));\r
758     write_setting_s(sesskey, "Printer", conf_get_str(conf, CONF_printer));\r
759     write_setting_b(sesskey, "CapsLockCyr", conf_get_bool(conf, CONF_xlat_capslockcyr));\r
760     write_setting_b(sesskey, "ScrollBar", conf_get_bool(conf, CONF_scrollbar));\r
761     write_setting_b(sesskey, "ScrollBarFullScreen", conf_get_bool(conf, CONF_scrollbar_in_fullscreen));\r
762     write_setting_b(sesskey, "ScrollOnKey", conf_get_bool(conf, CONF_scroll_on_key));\r
763     write_setting_b(sesskey, "ScrollOnDisp", conf_get_bool(conf, CONF_scroll_on_disp));\r
764     write_setting_b(sesskey, "EraseToScrollback", conf_get_bool(conf, CONF_erase_to_scrollback));\r
765     write_setting_i(sesskey, "LockSize", conf_get_int(conf, CONF_resize_action));\r
766     write_setting_b(sesskey, "BCE", conf_get_bool(conf, CONF_bce));\r
767     write_setting_b(sesskey, "BlinkText", conf_get_bool(conf, CONF_blinktext));\r
768     write_setting_b(sesskey, "X11Forward", conf_get_bool(conf, CONF_x11_forward));\r
769     write_setting_s(sesskey, "X11Display", conf_get_str(conf, CONF_x11_display));\r
770     write_setting_i(sesskey, "X11AuthType", conf_get_int(conf, CONF_x11_auth));\r
771     write_setting_filename(sesskey, "X11AuthFile", conf_get_filename(conf, CONF_xauthfile));\r
772     write_setting_b(sesskey, "LocalPortAcceptAll", conf_get_bool(conf, CONF_lport_acceptall));\r
773     write_setting_b(sesskey, "RemotePortAcceptAll", conf_get_bool(conf, CONF_rport_acceptall));\r
774     wmap(sesskey, "PortForwardings", conf, CONF_portfwd, true);\r
775     write_setting_i(sesskey, "BugIgnore1", 2-conf_get_int(conf, CONF_sshbug_ignore1));\r
776     write_setting_i(sesskey, "BugPlainPW1", 2-conf_get_int(conf, CONF_sshbug_plainpw1));\r
777     write_setting_i(sesskey, "BugRSA1", 2-conf_get_int(conf, CONF_sshbug_rsa1));\r
778     write_setting_i(sesskey, "BugIgnore2", 2-conf_get_int(conf, CONF_sshbug_ignore2));\r
779     write_setting_i(sesskey, "BugHMAC2", 2-conf_get_int(conf, CONF_sshbug_hmac2));\r
780     write_setting_i(sesskey, "BugDeriveKey2", 2-conf_get_int(conf, CONF_sshbug_derivekey2));\r
781     write_setting_i(sesskey, "BugRSAPad2", 2-conf_get_int(conf, CONF_sshbug_rsapad2));\r
782     write_setting_i(sesskey, "BugPKSessID2", 2-conf_get_int(conf, CONF_sshbug_pksessid2));\r
783     write_setting_i(sesskey, "BugRekey2", 2-conf_get_int(conf, CONF_sshbug_rekey2));\r
784     write_setting_i(sesskey, "BugMaxPkt2", 2-conf_get_int(conf, CONF_sshbug_maxpkt2));\r
785     write_setting_i(sesskey, "BugOldGex2", 2-conf_get_int(conf, CONF_sshbug_oldgex2));\r
786     write_setting_i(sesskey, "BugWinadj", 2-conf_get_int(conf, CONF_sshbug_winadj));\r
787     write_setting_i(sesskey, "BugChanReq", 2-conf_get_int(conf, CONF_sshbug_chanreq));\r
788     write_setting_i(sesskey, "BugRSASHA2CertUserauth", 2-conf_get_int(conf, CONF_sshbug_rsa_sha2_cert_userauth));\r
789     write_setting_i(sesskey, "BugDropStart", 2-conf_get_int(conf, CONF_sshbug_dropstart));\r
790     write_setting_i(sesskey, "BugFilterKexinit", 2-conf_get_int(conf, CONF_sshbug_filter_kexinit));\r
791     write_setting_b(sesskey, "StampUtmp", conf_get_bool(conf, CONF_stamp_utmp));\r
792     write_setting_b(sesskey, "LoginShell", conf_get_bool(conf, CONF_login_shell));\r
793     write_setting_b(sesskey, "ScrollbarOnLeft", conf_get_bool(conf, CONF_scrollbar_on_left));\r
794     write_setting_fontspec(sesskey, "BoldFont", conf_get_fontspec(conf, CONF_boldfont));\r
795     write_setting_fontspec(sesskey, "WideFont", conf_get_fontspec(conf, CONF_widefont));\r
796     write_setting_fontspec(sesskey, "WideBoldFont", conf_get_fontspec(conf, CONF_wideboldfont));\r
797     write_setting_b(sesskey, "ShadowBold", conf_get_bool(conf, CONF_shadowbold));\r
798     write_setting_i(sesskey, "ShadowBoldOffset", conf_get_int(conf, CONF_shadowboldoffset));\r
799     write_setting_s(sesskey, "SerialLine", conf_get_str(conf, CONF_serline));\r
800     write_setting_i(sesskey, "SerialSpeed", conf_get_int(conf, CONF_serspeed));\r
801     write_setting_i(sesskey, "SerialDataBits", conf_get_int(conf, CONF_serdatabits));\r
802     write_setting_i(sesskey, "SerialStopHalfbits", conf_get_int(conf, CONF_serstopbits));\r
803     write_setting_i(sesskey, "SerialParity", conf_get_int(conf, CONF_serparity));\r
804     write_setting_i(sesskey, "SerialFlowControl", conf_get_int(conf, CONF_serflow));\r
805     write_setting_s(sesskey, "WindowClass", conf_get_str(conf, CONF_winclass));\r
806     write_setting_b(sesskey, "ConnectionSharing", conf_get_bool(conf, CONF_ssh_connection_sharing));\r
807     write_setting_b(sesskey, "ConnectionSharingUpstream", conf_get_bool(conf, CONF_ssh_connection_sharing_upstream));\r
808     write_setting_b(sesskey, "ConnectionSharingDownstream", conf_get_bool(conf, CONF_ssh_connection_sharing_downstream));\r
809     wmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys, false);\r
811     /*\r
812      * SUPDUP settings\r
813      */\r
814     write_setting_s(sesskey, "SUPDUPLocation", conf_get_str(conf, CONF_supdup_location));\r
815     write_setting_i(sesskey, "SUPDUPCharset", conf_get_int(conf, CONF_supdup_ascii_set));\r
816     write_setting_b(sesskey, "SUPDUPMoreProcessing", conf_get_bool(conf, CONF_supdup_more));\r
817     write_setting_b(sesskey, "SUPDUPScrolling", conf_get_bool(conf, CONF_supdup_scroll));\r
820 bool load_settings(const char *section, Conf *conf)\r
822     settings_r *sesskey;\r
824     sesskey = open_settings_r(section);\r
825     bool exists = (sesskey != NULL);\r
826     load_open_settings(sesskey, conf);\r
827     close_settings_r(sesskey);\r
829     if (exists && conf_launchable(conf))\r
830         add_session_to_jumplist(section);\r
832     return exists;\r
835 void load_open_settings(settings_r *sesskey, Conf *conf)\r
837     int i;\r
838     char *prot;\r
840     conf_set_bool(conf, CONF_ssh_subsys, false); /* FIXME: load this properly */\r
841     conf_set_str(conf, CONF_remote_cmd, "");\r
842     conf_set_str(conf, CONF_remote_cmd2, "");\r
843     conf_set_str(conf, CONF_ssh_nc_host, "");\r
845     gpps(sesskey, "HostName", "", conf, CONF_host);\r
846     gppfile(sesskey, "LogFileName", conf, CONF_logfilename);\r
847     gppi(sesskey, "LogType", 0, conf, CONF_logtype);\r
848     gppi(sesskey, "LogFileClash", LGXF_ASK, conf, CONF_logxfovr);\r
849     gppb(sesskey, "LogFlush", true, conf, CONF_logflush);\r
850     gppb(sesskey, "LogHeader", true, conf, CONF_logheader);\r
851     gppb(sesskey, "SSHLogOmitPasswords", true, conf, CONF_logomitpass);\r
852     gppb(sesskey, "SSHLogOmitData", false, conf, CONF_logomitdata);\r
854     prot = gpps_raw(sesskey, "Protocol", "default");\r
855     conf_set_int(conf, CONF_protocol, default_protocol);\r
856     conf_set_int(conf, CONF_port, default_port);\r
857     {\r
858         const struct BackendVtable *vt = backend_vt_from_name(prot);\r
859         if (vt) {\r
860             conf_set_int(conf, CONF_protocol, vt->protocol);\r
861             gppi(sesskey, "PortNumber", default_port, conf, CONF_port);\r
862         }\r
863     }\r
864     sfree(prot);\r
866     /* Address family selection */\r
867     gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, conf, CONF_addressfamily);\r
869     /* The CloseOnExit numbers are arranged in a different order from\r
870      * the standard FORCE_ON / FORCE_OFF / AUTO. */\r
871     i = gppi_raw(sesskey, "CloseOnExit", 1); conf_set_int(conf, CONF_close_on_exit, (i+1)%3);\r
872     gppb(sesskey, "WarnOnClose", true, conf, CONF_warn_on_close);\r
873     {\r
874         /* This is two values for backward compatibility with 0.50/0.51 */\r
875         int pingmin, pingsec;\r
876         pingmin = gppi_raw(sesskey, "PingInterval", 0);\r
877         pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);\r
878         conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);\r
879     }\r
880     gppb(sesskey, "TCPNoDelay", true, conf, CONF_tcp_nodelay);\r
881     gppb(sesskey, "TCPKeepalives", false, conf, CONF_tcp_keepalives);\r
882     gpps(sesskey, "TerminalType", "xterm", conf, CONF_termtype);\r
883     gpps(sesskey, "TerminalSpeed", "38400,38400", conf, CONF_termspeed);\r
884     if (gppmap(sesskey, "TerminalModes", conf, CONF_ttymodes)) {\r
885         /*\r
886          * Backwards compatibility with old saved settings.\r
887          *\r
888          * From the invention of this setting through 0.67, the set of\r
889          * terminal modes was fixed, and absence of a mode from this\r
890          * setting meant the user had explicitly removed it from the\r
891          * UI and we shouldn't send it.\r
892          *\r
893          * In 0.68, the IUTF8 mode was added, and in handling old\r
894          * settings we inadvertently removed the ability to not send\r
895          * a mode. Any mode not mentioned was treated as if it was\r
896          * set to 'auto' (A).\r
897          *\r
898          * After 0.68, we added explicit notation to the setting format\r
899          * when the user removes a known terminal mode from the list.\r
900          *\r
901          * So: if any of the modes from the original set is missing, we\r
902          * assume this was an intentional removal by the user and add\r
903          * an explicit removal ('N'); but if IUTF8 (or any other mode\r
904          * added after 0.67) is missing, we assume that its absence is\r
905          * due to the setting being old rather than intentional, and\r
906          * add it with its default setting.\r
907          *\r
908          * (This does mean that if a 0.68 user explicitly removed IUTF8,\r
909          * we add it back; but removing IUTF8 had no effect in 0.68, so\r
910          * we're preserving behaviour, which is the best we can do.)\r
911          */\r
912         for (i = 0; ttymodes[i]; i++) {\r
913             if (!conf_get_str_str_opt(conf, CONF_ttymodes, ttymodes[i])) {\r
914                 /* Mode not mentioned in setting. */\r
915                 const char *def;\r
916                 if (!strcmp(ttymodes[i], "IUTF8")) {\r
917                     /* Any new modes we add in future should be treated\r
918                      * this way too. */\r
919                     def = "A";  /* same as new-setting default below */\r
920                 } else {\r
921                     /* One of the original modes. Absence is probably\r
922                      * deliberate. */\r
923                     def = "N";  /* don't send */\r
924                 }\r
925                 conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], def);\r
926             }\r
927         }\r
928     } else {\r
929         /* This hardcodes a big set of defaults in any new saved\r
930          * sessions. Let's hope we don't change our mind. */\r
931         for (i = 0; ttymodes[i]; i++)\r
932             conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");\r
933     }\r
935     /* proxy settings */\r
936     gpps(sesskey, "ProxyExcludeList", "", conf, CONF_proxy_exclude_list);\r
937     i = gppi_raw(sesskey, "ProxyDNS", 1); conf_set_int(conf, CONF_proxy_dns, (i+1)%3);\r
938     gppb(sesskey, "ProxyLocalhost", false, conf, CONF_even_proxy_localhost);\r
939     gppi(sesskey, "ProxyMethod", -1, conf, CONF_proxy_type);\r
940     if (conf_get_int(conf, CONF_proxy_type) == -1) {\r
941         int i;\r
942         i = gppi_raw(sesskey, "ProxyType", 0);\r
943         if (i == 0)\r
944             conf_set_int(conf, CONF_proxy_type, PROXY_NONE);\r
945         else if (i == 1)\r
946             conf_set_int(conf, CONF_proxy_type, PROXY_HTTP);\r
947         else if (i == 3)\r
948             conf_set_int(conf, CONF_proxy_type, PROXY_TELNET);\r
949         else if (i == 4)\r
950             conf_set_int(conf, CONF_proxy_type, PROXY_CMD);\r
951         else {\r
952             i = gppi_raw(sesskey, "ProxySOCKSVersion", 5);\r
953             if (i == 5)\r
954                 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS5);\r
955             else\r
956                 conf_set_int(conf, CONF_proxy_type, PROXY_SOCKS4);\r
957         }\r
958     }\r
959     gpps(sesskey, "ProxyHost", "proxy", conf, CONF_proxy_host);\r
960     gppi(sesskey, "ProxyPort", 80, conf, CONF_proxy_port);\r
961     gpps(sesskey, "ProxyUsername", "", conf, CONF_proxy_username);\r
962     gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);\r
963     gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",\r
964          conf, CONF_proxy_telnet_command);\r
965     gppi(sesskey, "ProxyLogToTerm", FORCE_OFF, conf, CONF_proxy_log_to_term);\r
966     gppmap(sesskey, "Environment", conf, CONF_environmt);\r
967     gpps(sesskey, "UserName", "", conf, CONF_username);\r
968     gppb(sesskey, "UserNameFromEnvironment", false,\r
969          conf, CONF_username_from_env);\r
970     gpps(sesskey, "LocalUserName", "", conf, CONF_localusername);\r
971     gppb(sesskey, "NoPTY", false, conf, CONF_nopty);\r
972     gppb(sesskey, "Compression", false, conf, CONF_compression);\r
973     gppb(sesskey, "TryAgent", true, conf, CONF_tryagent);\r
974     gppb(sesskey, "AgentFwd", false, conf, CONF_agentfwd);\r
975     gppb(sesskey, "ChangeUsername", false, conf, CONF_change_username);\r
976 #ifndef NO_GSSAPI\r
977     gppb(sesskey, "GssapiFwd", false, conf, CONF_gssapifwd);\r
978 #endif\r
979     gprefs(sesskey, "Cipher", "\0",\r
980            ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);\r
981     {\r
982         /* Backward-compatibility: before 0.58 (when the "KEX"\r
983          * preference was first added), we had an option to\r
984          * disable gex under the "bugs" panel after one report of\r
985          * a server which offered it then choked, but we never got\r
986          * a server version string or any other reports. */\r
987         const char *default_kexes,\r
988                    *normal_default = "ecdh,dh-gex-sha1,dh-group18-sha512,dh-group17-sha512,dh-group16-sha512,dh-group15-sha512,dh-group14-sha1,rsa,"\r
989                        "WARN,dh-group1-sha1",\r
990                    *bugdhgex2_default = "ecdh,dh-group18-sha512,dh-group17-sha512,dh-group16-sha512,dh-group15-sha512,dh-group14-sha1,rsa,"\r
991                        "WARN,dh-group1-sha1,dh-gex-sha1";\r
992         char *raw;\r
993         i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);\r
994         if (i == FORCE_ON)\r
995             default_kexes = bugdhgex2_default;\r
996         else\r
997             default_kexes = normal_default;\r
998         /* Migration: after 0.67 we decided we didn't like\r
999          * dh-group1-sha1. If it looks like the user never changed\r
1000          * the defaults, quietly upgrade their settings to demote it.\r
1001          * (If they did, they're on their own.) */\r
1002         raw = gpps_raw(sesskey, "KEX", default_kexes);\r
1003         assert(raw != NULL);\r
1004         /* Lack of 'ecdh' tells us this was saved by 0.58-0.67\r
1005          * inclusive. If it was saved by a later version, we need\r
1006          * to leave it alone. */\r
1007         if (strcmp(raw, "dh-group14-sha1,dh-group1-sha1,rsa,"\r
1008                    "WARN,dh-gex-sha1") == 0) {\r
1009             /* Previously migrated from BugDHGEx2. */\r
1010             sfree(raw);\r
1011             raw = dupstr(bugdhgex2_default);\r
1012         } else if (strcmp(raw, "dh-gex-sha1,dh-group14-sha1,"\r
1013                           "dh-group1-sha1,rsa,WARN") == 0) {\r
1014             /* Untouched old default setting. */\r
1015             sfree(raw);\r
1016             raw = dupstr(normal_default);\r
1017         }\r
1018         /* (For the record: after 0.70, the default algorithm list\r
1019          * very briefly contained the string 'gss-sha1-krb5'; this was\r
1020          * never used in any committed version of code, but was left\r
1021          * over from a pre-commit version of GSS key exchange.\r
1022          * Mentioned here as it is remotely possible that it will turn\r
1023          * up in someone's saved settings in future.) */\r
1025         gprefs_from_str(raw, kexnames, KEX_MAX, conf, CONF_ssh_kexlist);\r
1026         sfree(raw);\r
1027     }\r
1028     gprefs(sesskey, "HostKey", "ed25519,ecdsa,rsa,dsa,WARN",\r
1029            hknames, HK_MAX, conf, CONF_ssh_hklist);\r
1030     gppb(sesskey, "PreferKnownHostKeys", true, conf, CONF_ssh_prefer_known_hostkeys);\r
1031     gppi(sesskey, "RekeyTime", 60, conf, CONF_ssh_rekey_time);\r
1032 #ifndef NO_GSSAPI\r
1033     gppi(sesskey, "GssapiRekey", GSS_DEF_REKEY_MINS, conf, CONF_gssapirekey);\r
1034 #endif\r
1035     gpps(sesskey, "RekeyBytes", "1G", conf, CONF_ssh_rekey_data);\r
1036     {\r
1037         /* SSH-2 only by default */\r
1038         int sshprot = gppi_raw(sesskey, "SshProt", 3);\r
1039         /* Old sessions may contain the values corresponding to the fallbacks\r
1040          * we used to allow; migrate them */\r
1041         if (sshprot == 1)      sshprot = 0; /* => "SSH-1 only" */\r
1042         else if (sshprot == 2) sshprot = 3; /* => "SSH-2 only" */\r
1043         conf_set_int(conf, CONF_sshprot, sshprot);\r
1044     }\r
1045     gpps(sesskey, "LogHost", "", conf, CONF_loghost);\r
1046     gppb(sesskey, "SSH2DES", false, conf, CONF_ssh2_des_cbc);\r
1047     gppb(sesskey, "SshNoAuth", false, conf, CONF_ssh_no_userauth);\r
1048     gppb(sesskey, "SshNoTrivialAuth", false, conf, CONF_ssh_no_trivial_userauth);\r
1049     gppb(sesskey, "SshBanner", true, conf, CONF_ssh_show_banner);\r
1050     gppb(sesskey, "AuthTIS", false, conf, CONF_try_tis_auth);\r
1051     gppb(sesskey, "AuthKI", true, conf, CONF_try_ki_auth);\r
1052 #ifndef NO_GSSAPI\r
1053     gppb(sesskey, "AuthGSSAPI", true, conf, CONF_try_gssapi_auth);\r
1054     gppb(sesskey, "AuthGSSAPIKEX", true, conf, CONF_try_gssapi_kex);\r
1055     gprefs(sesskey, "GSSLibs", "\0",\r
1056            gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);\r
1057     gppfile(sesskey, "GSSCustom", conf, CONF_ssh_gss_custom);\r
1058 #endif\r
1059     gppb(sesskey, "SshNoShell", false, conf, CONF_ssh_no_shell);\r
1060     gppfile(sesskey, "PublicKeyFile", conf, CONF_keyfile);\r
1061     gppfile(sesskey, "DetachedCertificate", conf, CONF_detached_cert);\r
1062     gpps(sesskey, "AuthPlugin", "", conf, CONF_auth_plugin);\r
1063     gpps(sesskey, "RemoteCommand", "", conf, CONF_remote_cmd);\r
1064     gppb(sesskey, "RFCEnviron", false, conf, CONF_rfc_environ);\r
1065     gppb(sesskey, "PassiveTelnet", false, conf, CONF_passive_telnet);\r
1066     gppb(sesskey, "BackspaceIsDelete", true, conf, CONF_bksp_is_delete);\r
1067     gppb(sesskey, "RXVTHomeEnd", false, conf, CONF_rxvt_homeend);\r
1068     gppi(sesskey, "LinuxFunctionKeys", 0, conf, CONF_funky_type);\r
1069     gppi(sesskey, "ShiftedArrowKeys", SHARROW_APPLICATION, conf,\r
1070          CONF_sharrow_type);\r
1071     gppb(sesskey, "NoApplicationKeys", false, conf, CONF_no_applic_k);\r
1072     gppb(sesskey, "NoApplicationCursors", false, conf, CONF_no_applic_c);\r
1073     gppb(sesskey, "NoMouseReporting", false, conf, CONF_no_mouse_rep);\r
1074     gppb(sesskey, "NoRemoteResize", false, conf, CONF_no_remote_resize);\r
1075     gppb(sesskey, "NoAltScreen", false, conf, CONF_no_alt_screen);\r
1076     gppb(sesskey, "NoRemoteWinTitle", false, conf, CONF_no_remote_wintitle);\r
1077     gppb(sesskey, "NoRemoteClearScroll", false,\r
1078          conf, CONF_no_remote_clearscroll);\r
1079     {\r
1080         /* Backward compatibility */\r
1081         int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);\r
1082         /* We deliberately interpret the old setting of "no response" as\r
1083          * "empty string". This changes the behaviour, but hopefully for\r
1084          * the better; the user can always recover the old behaviour. */\r
1085         gppi(sesskey, "RemoteQTitleAction",\r
1086              no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,\r
1087              conf, CONF_remote_qtitle_action);\r
1088     }\r
1089     gppb(sesskey, "NoDBackspace", false, conf, CONF_no_dbackspace);\r
1090     gppb(sesskey, "NoRemoteCharset", false, conf, CONF_no_remote_charset);\r
1091     gppb(sesskey, "ApplicationCursorKeys", false, conf, CONF_app_cursor);\r
1092     gppb(sesskey, "ApplicationKeypad", false, conf, CONF_app_keypad);\r
1093     gppb(sesskey, "NetHackKeypad", false, conf, CONF_nethack_keypad);\r
1094     gppb(sesskey, "AltF4", true, conf, CONF_alt_f4);\r
1095     gppb(sesskey, "AltSpace", false, conf, CONF_alt_space);\r
1096     gppb(sesskey, "AltOnly", false, conf, CONF_alt_only);\r
1097     gppb(sesskey, "ComposeKey", false, conf, CONF_compose_key);\r
1098     gppb(sesskey, "CtrlAltKeys", true, conf, CONF_ctrlaltkeys);\r
1099 #ifdef OSX_META_KEY_CONFIG\r
1100     gppb(sesskey, "OSXOptionMeta", true, conf, CONF_osx_option_meta);\r
1101     gppb(sesskey, "OSXCommandMeta", false, conf, CONF_osx_command_meta);\r
1102 #endif\r
1103     gppb(sesskey, "TelnetKey", false, conf, CONF_telnet_keyboard);\r
1104     gppb(sesskey, "TelnetRet", true, conf, CONF_telnet_newline);\r
1105     gppi(sesskey, "LocalEcho", AUTO, conf, CONF_localecho);\r
1106     gppi(sesskey, "LocalEdit", AUTO, conf, CONF_localedit);\r
1107     gpps(sesskey, "Answerback", "PuTTY", conf, CONF_answerback);\r
1108     gppb(sesskey, "AlwaysOnTop", false, conf, CONF_alwaysontop);\r
1109     gppb(sesskey, "FullScreenOnAltEnter", false,\r
1110          conf, CONF_fullscreenonaltenter);\r
1111     gppb(sesskey, "HideMousePtr", false, conf, CONF_hide_mouseptr);\r
1112     gppb(sesskey, "SunkenEdge", false, conf, CONF_sunken_edge);\r
1113     gppi(sesskey, "WindowBorder", 1, conf, CONF_window_border);\r
1114     gppi(sesskey, "CurType", 0, conf, CONF_cursor_type);\r
1115     gppb(sesskey, "BlinkCur", false, conf, CONF_blink_cur);\r
1116     /* pedantic compiler tells me I can't use conf, CONF_beep as an int * :-) */\r
1117     gppi(sesskey, "Beep", 1, conf, CONF_beep);\r
1118     gppi(sesskey, "BeepInd", 0, conf, CONF_beep_ind);\r
1119     gppfile(sesskey, "BellWaveFile", conf, CONF_bell_wavefile);\r
1120     gppb(sesskey, "BellOverload", true, conf, CONF_bellovl);\r
1121     gppi(sesskey, "BellOverloadN", 5, conf, CONF_bellovl_n);\r
1122     i = gppi_raw(sesskey, "BellOverloadT", 2*TICKSPERSEC\r
1123 #ifdef PUTTY_UNIX_PLATFORM_H\r
1124                                    *1000\r
1125 #endif\r
1126                                    );\r
1127     conf_set_int(conf, CONF_bellovl_t, i\r
1128 #ifdef PUTTY_UNIX_PLATFORM_H\r
1129                  / 1000\r
1130 #endif\r
1131                  );\r
1132     i = gppi_raw(sesskey, "BellOverloadS", 5*TICKSPERSEC\r
1133 #ifdef PUTTY_UNIX_PLATFORM_H\r
1134                                    *1000\r
1135 #endif\r
1136                                    );\r
1137     conf_set_int(conf, CONF_bellovl_s, i\r
1138 #ifdef PUTTY_UNIX_PLATFORM_H\r
1139                  / 1000\r
1140 #endif\r
1141                  );\r
1142     gppi(sesskey, "ScrollbackLines", 2000, conf, CONF_savelines);\r
1143     gppb(sesskey, "DECOriginMode", false, conf, CONF_dec_om);\r
1144     gppb(sesskey, "AutoWrapMode", true, conf, CONF_wrap_mode);\r
1145     gppb(sesskey, "LFImpliesCR", false, conf, CONF_lfhascr);\r
1146     gppb(sesskey, "CRImpliesLF", false, conf, CONF_crhaslf);\r
1147     gppb(sesskey, "DisableArabicShaping", false, conf, CONF_no_arabicshaping);\r
1148     gppb(sesskey, "DisableBidi", false, conf, CONF_no_bidi);\r
1149     gppb(sesskey, "WinNameAlways", true, conf, CONF_win_name_always);\r
1150     gpps(sesskey, "WinTitle", "", conf, CONF_wintitle);\r
1151     gppi(sesskey, "TermWidth", 80, conf, CONF_width);\r
1152     gppi(sesskey, "TermHeight", 24, conf, CONF_height);\r
1153     gppfont(sesskey, "Font", conf, CONF_font);\r
1154     gppi(sesskey, "FontQuality", FQ_DEFAULT, conf, CONF_font_quality);\r
1155     gppi(sesskey, "FontVTMode", VT_UNICODE, conf, CONF_vtmode);\r
1156     gppb(sesskey, "UseSystemColours", false, conf, CONF_system_colour);\r
1157     gppb(sesskey, "TryPalette", false, conf, CONF_try_palette);\r
1158     gppb(sesskey, "ANSIColour", true, conf, CONF_ansi_colour);\r
1159     gppb(sesskey, "Xterm256Colour", true, conf, CONF_xterm_256_colour);\r
1160     gppb(sesskey, "TrueColour", true, conf, CONF_true_colour);\r
1161     i = gppi_raw(sesskey, "BoldAsColour", 1); conf_set_int(conf, CONF_bold_style, i+1);\r
1163     for (i = 0; i < 22; i++) {\r
1164         static const char *const defaults[] = {\r
1165             "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",\r
1166             "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",\r
1167             "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",\r
1168             "85,85,255", "187,0,187", "255,85,255", "0,187,187",\r
1169             "85,255,255", "187,187,187", "255,255,255"\r
1170         };\r
1171         char buf[20], *buf2;\r
1172         int c0, c1, c2;\r
1173         sprintf(buf, "Colour%d", i);\r
1174         buf2 = gpps_raw(sesskey, buf, defaults[i]);\r
1175         if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {\r
1176             conf_set_int_int(conf, CONF_colours, i*3+0, c0);\r
1177             conf_set_int_int(conf, CONF_colours, i*3+1, c1);\r
1178             conf_set_int_int(conf, CONF_colours, i*3+2, c2);\r
1179         }\r
1180         sfree(buf2);\r
1181     }\r
1182     gppb(sesskey, "RawCNP", false, conf, CONF_rawcnp);\r
1183     gppb(sesskey, "UTF8linedraw", false, conf, CONF_utf8linedraw);\r
1184     gppb(sesskey, "PasteRTF", false, conf, CONF_rtf_paste);\r
1185     gppi(sesskey, "MouseIsXterm", 0, conf, CONF_mouse_is_xterm);\r
1186     gppb(sesskey, "RectSelect", false, conf, CONF_rect_select);\r
1187     gppb(sesskey, "PasteControls", false, conf, CONF_paste_controls);\r
1188     gppb(sesskey, "MouseOverride", true, conf, CONF_mouse_override);\r
1189     for (i = 0; i < 256; i += 32) {\r
1190         static const char *const defaults[] = {\r
1191             "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",\r
1192             "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",\r
1193             "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",\r
1194             "1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",\r
1195             "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",\r
1196             "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",\r
1197             "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",\r
1198             "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"\r
1199         };\r
1200         char buf[20], *buf2, *p;\r
1201         int j;\r
1202         sprintf(buf, "Wordness%d", i);\r
1203         buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);\r
1204         p = buf2;\r
1205         for (j = i; j < i + 32; j++) {\r
1206             char *q = p;\r
1207             while (*p && *p != ',')\r
1208                 p++;\r
1209             if (*p == ',')\r
1210                 *p++ = '\0';\r
1211             conf_set_int_int(conf, CONF_wordness, j, atoi(q));\r
1212         }\r
1213         sfree(buf2);\r
1214     }\r
1215     gppb(sesskey, "MouseAutocopy", CLIPUI_DEFAULT_AUTOCOPY,\r
1216          conf, CONF_mouseautocopy);\r
1217     read_clip_setting(sesskey, "MousePaste", CLIPUI_DEFAULT_MOUSE,\r
1218                       conf, CONF_mousepaste, CONF_mousepaste_custom);\r
1219     read_clip_setting(sesskey, "CtrlShiftIns", CLIPUI_DEFAULT_INS,\r
1220                       conf, CONF_ctrlshiftins, CONF_ctrlshiftins_custom);\r
1221     read_clip_setting(sesskey, "CtrlShiftCV", CLIPUI_NONE,\r
1222                       conf, CONF_ctrlshiftcv, CONF_ctrlshiftcv_custom);\r
1223     /*\r
1224      * The empty default for LineCodePage will be converted later\r
1225      * into a plausible default for the locale.\r
1226      */\r
1227     gpps(sesskey, "LineCodePage", "", conf, CONF_line_codepage);\r
1228     gppb(sesskey, "CJKAmbigWide", false, conf, CONF_cjk_ambig_wide);\r
1229     gppb(sesskey, "UTF8Override", true, conf, CONF_utf8_override);\r
1230     gpps(sesskey, "Printer", "", conf, CONF_printer);\r
1231     gppb(sesskey, "CapsLockCyr", false, conf, CONF_xlat_capslockcyr);\r
1232     gppb(sesskey, "ScrollBar", true, conf, CONF_scrollbar);\r
1233     gppb(sesskey, "ScrollBarFullScreen", false,\r
1234          conf, CONF_scrollbar_in_fullscreen);\r
1235     gppb(sesskey, "ScrollOnKey", false, conf, CONF_scroll_on_key);\r
1236     gppb(sesskey, "ScrollOnDisp", true, conf, CONF_scroll_on_disp);\r
1237     gppb(sesskey, "EraseToScrollback", true, conf, CONF_erase_to_scrollback);\r
1238     gppi(sesskey, "LockSize", 0, conf, CONF_resize_action);\r
1239     gppb(sesskey, "BCE", true, conf, CONF_bce);\r
1240     gppb(sesskey, "BlinkText", false, conf, CONF_blinktext);\r
1241     gppb(sesskey, "X11Forward", false, conf, CONF_x11_forward);\r
1242     gpps(sesskey, "X11Display", "", conf, CONF_x11_display);\r
1243     gppi(sesskey, "X11AuthType", X11_MIT, conf, CONF_x11_auth);\r
1244     gppfile(sesskey, "X11AuthFile", conf, CONF_xauthfile);\r
1246     gppb(sesskey, "LocalPortAcceptAll", false, conf, CONF_lport_acceptall);\r
1247     gppb(sesskey, "RemotePortAcceptAll", false, conf, CONF_rport_acceptall);\r
1248     gppmap(sesskey, "PortForwardings", conf, CONF_portfwd);\r
1249     i = gppi_raw(sesskey, "BugIgnore1", 0); conf_set_int(conf, CONF_sshbug_ignore1, 2-i);\r
1250     i = gppi_raw(sesskey, "BugPlainPW1", 0); conf_set_int(conf, CONF_sshbug_plainpw1, 2-i);\r
1251     i = gppi_raw(sesskey, "BugRSA1", 0); conf_set_int(conf, CONF_sshbug_rsa1, 2-i);\r
1252     i = gppi_raw(sesskey, "BugIgnore2", 0); conf_set_int(conf, CONF_sshbug_ignore2, 2-i);\r
1253     {\r
1254         int i;\r
1255         i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);\r
1256         if (2-i == AUTO) {\r
1257             i = gppi_raw(sesskey, "BuggyMAC", 0);\r
1258             if (i == 1)\r
1259                 conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);\r
1260         }\r
1261     }\r
1262     i = gppi_raw(sesskey, "BugDeriveKey2", 0); conf_set_int(conf, CONF_sshbug_derivekey2, 2-i);\r
1263     i = gppi_raw(sesskey, "BugRSAPad2", 0); conf_set_int(conf, CONF_sshbug_rsapad2, 2-i);\r
1264     i = gppi_raw(sesskey, "BugPKSessID2", 0); conf_set_int(conf, CONF_sshbug_pksessid2, 2-i);\r
1265     i = gppi_raw(sesskey, "BugRekey2", 0); conf_set_int(conf, CONF_sshbug_rekey2, 2-i);\r
1266     i = gppi_raw(sesskey, "BugMaxPkt2", 0); conf_set_int(conf, CONF_sshbug_maxpkt2, 2-i);\r
1267     i = gppi_raw(sesskey, "BugOldGex2", 0); conf_set_int(conf, CONF_sshbug_oldgex2, 2-i);\r
1268     i = gppi_raw(sesskey, "BugWinadj", 0); conf_set_int(conf, CONF_sshbug_winadj, 2-i);\r
1269     i = gppi_raw(sesskey, "BugChanReq", 0); conf_set_int(conf, CONF_sshbug_chanreq, 2-i);\r
1270     i = gppi_raw(sesskey, "BugRSASHA2CertUserauth", 0); conf_set_int(conf, CONF_sshbug_rsa_sha2_cert_userauth, 2-i);\r
1271     i = gppi_raw(sesskey, "BugDropStart", 1); conf_set_int(conf, CONF_sshbug_dropstart, 2-i);\r
1272     i = gppi_raw(sesskey, "BugFilterKexinit", 1); conf_set_int(conf, CONF_sshbug_filter_kexinit, 2-i);\r
1273     conf_set_bool(conf, CONF_ssh_simple, false);\r
1274     gppb(sesskey, "StampUtmp", true, conf, CONF_stamp_utmp);\r
1275     gppb(sesskey, "LoginShell", true, conf, CONF_login_shell);\r
1276     gppb(sesskey, "ScrollbarOnLeft", false, conf, CONF_scrollbar_on_left);\r
1277     gppb(sesskey, "ShadowBold", false, conf, CONF_shadowbold);\r
1278     gppfont(sesskey, "BoldFont", conf, CONF_boldfont);\r
1279     gppfont(sesskey, "WideFont", conf, CONF_widefont);\r
1280     gppfont(sesskey, "WideBoldFont", conf, CONF_wideboldfont);\r
1281     gppi(sesskey, "ShadowBoldOffset", 1, conf, CONF_shadowboldoffset);\r
1282     gpps(sesskey, "SerialLine", "", conf, CONF_serline);\r
1283     gppi(sesskey, "SerialSpeed", 9600, conf, CONF_serspeed);\r
1284     gppi(sesskey, "SerialDataBits", 8, conf, CONF_serdatabits);\r
1285     gppi(sesskey, "SerialStopHalfbits", 2, conf, CONF_serstopbits);\r
1286     gppi(sesskey, "SerialParity", SER_PAR_NONE, conf, CONF_serparity);\r
1287     gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, conf, CONF_serflow);\r
1288     gpps(sesskey, "WindowClass", "", conf, CONF_winclass);\r
1289     gppb(sesskey, "ConnectionSharing", false,\r
1290          conf, CONF_ssh_connection_sharing);\r
1291     gppb(sesskey, "ConnectionSharingUpstream", true,\r
1292          conf, CONF_ssh_connection_sharing_upstream);\r
1293     gppb(sesskey, "ConnectionSharingDownstream", true,\r
1294          conf, CONF_ssh_connection_sharing_downstream);\r
1295     gppmap(sesskey, "SSHManualHostKeys", conf, CONF_ssh_manual_hostkeys);\r
1297     /*\r
1298      * SUPDUP settings\r
1299      */\r
1300     gpps(sesskey, "SUPDUPLocation", "The Internet", conf, CONF_supdup_location);\r
1301     gppi(sesskey, "SUPDUPCharset", false, conf, CONF_supdup_ascii_set);\r
1302     gppb(sesskey, "SUPDUPMoreProcessing", false, conf, CONF_supdup_more);\r
1303     gppb(sesskey, "SUPDUPScrolling", false, conf, CONF_supdup_scroll);\r
1306 bool do_defaults(const char *session, Conf *conf)\r
1308     return load_settings(session, conf);\r
1311 static int sessioncmp(const void *av, const void *bv)\r
1313     const char *a = *(const char *const *) av;\r
1314     const char *b = *(const char *const *) bv;\r
1316     /*\r
1317      * Alphabetical order, except that "Default Settings" is a\r
1318      * special case and comes first.\r
1319      */\r
1320     if (!strcmp(a, "Default Settings"))\r
1321         return -1;                     /* a comes first */\r
1322     if (!strcmp(b, "Default Settings"))\r
1323         return +1;                     /* b comes first */\r
1324     /*\r
1325      * FIXME: perhaps we should ignore the first & in determining\r
1326      * sort order.\r
1327      */\r
1328     return strcmp(a, b);               /* otherwise, compare normally */\r
1331 bool sesslist_demo_mode = false;\r
1333 void get_sesslist(struct sesslist *list, bool allocate)\r
1335     int i;\r
1336     char *p;\r
1337     settings_e *handle;\r
1339     if (allocate) {\r
1340         strbuf *sb = strbuf_new();\r
1342         if (sesslist_demo_mode) {\r
1343             put_asciz(sb, "demo-server");\r
1344             put_asciz(sb, "demo-server-2");\r
1345         } else {\r
1346             if ((handle = enum_settings_start()) != NULL) {\r
1347                 while (enum_settings_next(handle, sb))\r
1348                     put_byte(sb, '\0');\r
1349                 enum_settings_finish(handle);\r
1350             }\r
1351             put_byte(sb, '\0');\r
1352         }\r
1354         list->buffer = strbuf_to_str(sb);\r
1356         /*\r
1357          * Now set up the list of sessions. Note that "Default\r
1358          * Settings" must always be claimed to exist, even if it\r
1359          * doesn't really.\r
1360          */\r
1362         p = list->buffer;\r
1363         list->nsessions = 1;           /* "Default Settings" counts as one */\r
1364         while (*p) {\r
1365             if (strcmp(p, "Default Settings"))\r
1366                 list->nsessions++;\r
1367             while (*p)\r
1368                 p++;\r
1369             p++;\r
1370         }\r
1372         list->sessions = snewn(list->nsessions + 1, const char *);\r
1373         list->sessions[0] = "Default Settings";\r
1374         p = list->buffer;\r
1375         i = 1;\r
1376         while (*p) {\r
1377             if (strcmp(p, "Default Settings"))\r
1378                 list->sessions[i++] = p;\r
1379             while (*p)\r
1380                 p++;\r
1381             p++;\r
1382         }\r
1384         qsort(list->sessions, i, sizeof(const char *), sessioncmp);\r
1385     } else {\r
1386         sfree(list->buffer);\r
1387         sfree(list->sessions);\r
1388         list->buffer = NULL;\r
1389         list->sessions = NULL;\r
1390     }\r