2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* config.c - the platform-independent parts of the PuTTY
|
|
|
|
* configuration box.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "putty.h"
|
|
|
|
#include "dialog.h"
|
|
|
|
#include "storage.h"
|
Initial support for host certificates.
Now we offer the OpenSSH certificate key types in our KEXINIT host key
algorithm list, so that if the server has a certificate, they can send
it to us.
There's a new storage.h abstraction for representing a list of trusted
host CAs, and which ones are trusted to certify hosts for what
domains. This is stored outside the normal saved session data, because
the whole point of host certificates is to avoid per-host faffing.
Configuring this set of trusted CAs is done via a new GUI dialog box,
separate from the main PuTTY config box (because it modifies a single
set of settings across all saved sessions), which you can launch by
clicking a button in the 'Host keys' pane. The GUI is pretty crude for
the moment, and very much at a 'just about usable' stage right now. It
will want some polishing.
If we have no CA configured that matches the hostname, we don't offer
to receive certified host keys in the first place. So for existing
users who haven't set any of this up yet, nothing will immediately
change.
Currently, if we do offer to receive certified host keys and the
server presents one signed by a CA we don't trust, PuTTY will bomb out
unconditionally with an error, instead of offering a confirmation box.
That's an unfinished part which I plan to fix before this goes into a
release.
2022-04-22 11:07:24 +00:00
|
|
|
#include "tree234.h"
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
#define PRINTER_DISABLED_STRING "None (printing disabled)"
|
|
|
|
|
2006-08-28 10:35:12 +00:00
|
|
|
#define HOST_BOX_TITLE "Host Name (or IP address)"
|
|
|
|
#define PORT_BOX_TITLE "Port"
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_radiobutton_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
|
|
|
int button;
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For a standard radio button set, the context parameter gives
|
|
|
|
* the primary key (CONF_foo), and the extra data per button
|
|
|
|
* gives the value the target field should take if that button
|
|
|
|
* is the one selected.
|
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int val = conf_get_int(conf, ctrl->context.i);
|
2019-09-08 19:29:00 +00:00
|
|
|
for (button = 0; button < ctrl->radio.nbuttons; button++)
|
|
|
|
if (val == ctrl->radio.buttondata[button].i)
|
|
|
|
break;
|
|
|
|
/* We expected that `break' to happen, in all circumstances. */
|
|
|
|
assert(button < ctrl->radio.nbuttons);
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, button);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
button = dlg_radiobutton_get(ctrl, dlg);
|
|
|
|
assert(button >= 0 && button < ctrl->radio.nbuttons);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
conf_set_int(conf, ctrl->context.i,
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl->radio.buttondata[button].i);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_radiobutton_bool_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2018-10-29 19:57:31 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
int button;
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Same as conf_radiobutton_handler, but using conf_set_bool in
|
|
|
|
* place of conf_set_int, because it's dealing with a bool-typed
|
|
|
|
* config option.
|
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int val = conf_get_bool(conf, ctrl->context.i);
|
2019-09-08 19:29:00 +00:00
|
|
|
for (button = 0; button < ctrl->radio.nbuttons; button++)
|
|
|
|
if (val == ctrl->radio.buttondata[button].i)
|
|
|
|
break;
|
|
|
|
/* We expected that `break' to happen, in all circumstances. */
|
|
|
|
assert(button < ctrl->radio.nbuttons);
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, button);
|
2018-10-29 19:57:31 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
button = dlg_radiobutton_get(ctrl, dlg);
|
|
|
|
assert(button >= 0 && button < ctrl->radio.nbuttons);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
conf_set_bool(conf, ctrl->context.i,
|
2018-10-29 19:57:31 +00:00
|
|
|
ctrl->radio.buttondata[button].i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
#define CHECKBOX_INVERT (1<<30)
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_checkbox_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
2018-10-29 19:57:31 +00:00
|
|
|
int key;
|
|
|
|
bool invert;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For a standard checkbox, the context parameter gives the
|
|
|
|
* primary key (CONF_foo), optionally ORed with CHECKBOX_INVERT.
|
|
|
|
*/
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
key = ctrl->context.i;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (key & CHECKBOX_INVERT) {
|
2019-09-08 19:29:00 +00:00
|
|
|
key &= ~CHECKBOX_INVERT;
|
|
|
|
invert = true;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
invert = false;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* C lacks a logical XOR, so the following code uses the idiom
|
|
|
|
* (!a ^ !b) to obtain the logical XOR of a and b. (That is, 1
|
|
|
|
* iff exactly one of a and b is nonzero, otherwise 0.)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
bool val = conf_get_bool(conf, key);
|
|
|
|
dlg_checkbox_set(ctrl, dlg, (!val ^ !invert));
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_bool(conf, key, !dlg_checkbox_get(ctrl,dlg) ^ !invert);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-24 06:56:45 +00:00
|
|
|
const struct conf_editbox_handler_type conf_editbox_str = {.type = EDIT_STR};
|
|
|
|
const struct conf_editbox_handler_type conf_editbox_int = {.type = EDIT_INT};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_editbox_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
|
|
|
/*
|
2022-08-24 06:56:45 +00:00
|
|
|
* The standard edit-box handler expects the main `context' field
|
|
|
|
* to contain the primary key. The secondary `context2' field is a
|
|
|
|
* pointer to the struct conf_editbox_handler_type defined in
|
|
|
|
* putty.h.
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
*/
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int key = ctrl->context.i;
|
2022-08-24 06:56:45 +00:00
|
|
|
const struct conf_editbox_handler_type *type = ctrl->context2.cp;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
2022-08-24 06:56:45 +00:00
|
|
|
if (type->type == EDIT_STR) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
char *field = conf_get_str(conf, key);
|
|
|
|
dlg_editbox_set(ctrl, dlg, field);
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
|
|
|
char *field = dlg_editbox_get(ctrl, dlg);
|
|
|
|
conf_set_str(conf, key, field);
|
|
|
|
sfree(field);
|
|
|
|
}
|
2022-08-24 06:56:45 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
char str[80];
|
|
|
|
int value = conf_get_int(conf, key);
|
2022-08-24 06:56:45 +00:00
|
|
|
if (type->type == EDIT_INT)
|
2019-09-08 19:29:00 +00:00
|
|
|
sprintf(str, "%d", value);
|
|
|
|
else
|
2022-08-24 06:56:45 +00:00
|
|
|
sprintf(str, "%g", (double)value / type->denominator);
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_editbox_set(ctrl, dlg, str);
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
|
|
|
char *str = dlg_editbox_get(ctrl, dlg);
|
2022-08-24 06:56:45 +00:00
|
|
|
if (type->type == EDIT_INT)
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int(conf, key, atoi(str));
|
|
|
|
else
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_set_int(conf, key, (int)(type->denominator * atof(str)));
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(str);
|
|
|
|
}
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_filesel_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int key = ctrl->context.i;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_filesel_set(
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
ctrl, dlg, conf_get_filename(conf, key));
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
Filename *filename = dlg_filesel_get(ctrl, dlg);
|
|
|
|
conf_set_filename(conf, key, filename);
|
2011-10-02 11:01:57 +00:00
|
|
|
filename_free(filename);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void conf_fontsel_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
{
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int key = ctrl->context.i;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_fontsel_set(
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
ctrl, dlg, conf_get_fontspec(conf, key));
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
FontSpec *fontspec = dlg_fontsel_get(ctrl, dlg);
|
|
|
|
conf_set_fontspec(conf, key, fontspec);
|
2011-10-01 17:38:59 +00:00
|
|
|
fontspec_free(fontspec);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void config_host_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2006-08-28 10:35:12 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2006-08-28 10:35:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This function works just like the standard edit box handler,
|
|
|
|
* only it has to choose the control's label and text from two
|
|
|
|
* different places depending on the protocol.
|
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL) {
|
|
|
|
/*
|
|
|
|
* This label text is carefully chosen to contain an n,
|
|
|
|
* since that's the shortcut for the host name control.
|
|
|
|
*/
|
|
|
|
dlg_label_change(ctrl, dlg, "Serial line");
|
|
|
|
dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_serline));
|
|
|
|
} else {
|
|
|
|
dlg_label_change(ctrl, dlg, HOST_BOX_TITLE);
|
|
|
|
dlg_editbox_set(ctrl, dlg, conf_get_str(conf, CONF_host));
|
|
|
|
}
|
2006-08-28 10:35:12 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *s = dlg_editbox_get(ctrl, dlg);
|
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
|
|
|
conf_set_str(conf, CONF_serline, s);
|
|
|
|
else
|
|
|
|
conf_set_str(conf, CONF_host, s);
|
|
|
|
sfree(s);
|
2006-08-28 10:35:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void config_port_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2006-08-28 10:35:12 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2006-08-28 10:35:12 +00:00
|
|
|
char buf[80];
|
|
|
|
|
|
|
|
/*
|
2011-01-14 19:57:00 +00:00
|
|
|
* This function works similarly to the standard edit box handler,
|
2006-08-28 10:35:12 +00:00
|
|
|
* only it has to choose the control's label and text from two
|
|
|
|
* different places depending on the protocol.
|
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL) {
|
|
|
|
/*
|
|
|
|
* This label text is carefully chosen to contain a p,
|
|
|
|
* since that's the shortcut for the port control.
|
|
|
|
*/
|
|
|
|
dlg_label_change(ctrl, dlg, "Speed");
|
|
|
|
sprintf(buf, "%d", conf_get_int(conf, CONF_serspeed));
|
|
|
|
} else {
|
|
|
|
dlg_label_change(ctrl, dlg, PORT_BOX_TITLE);
|
|
|
|
if (conf_get_int(conf, CONF_port) != 0)
|
|
|
|
sprintf(buf, "%d", conf_get_int(conf, CONF_port));
|
|
|
|
else
|
|
|
|
/* Display an (invalid) port of 0 as blank */
|
|
|
|
buf[0] = '\0';
|
|
|
|
}
|
|
|
|
dlg_editbox_set(ctrl, dlg, buf);
|
2006-08-28 10:35:12 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *s = dlg_editbox_get(ctrl, dlg);
|
|
|
|
int i = atoi(s);
|
|
|
|
sfree(s);
|
|
|
|
|
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
|
|
|
conf_set_int(conf, CONF_serspeed, i);
|
|
|
|
else
|
|
|
|
conf_set_int(conf, CONF_port, i);
|
2006-08-28 10:35:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct hostport {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *host, *port, *protradio, *protlist;
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
bool mid_refresh;
|
2006-08-28 10:35:12 +00:00
|
|
|
};
|
|
|
|
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
/*
|
|
|
|
* Shared handler for protocol radio-button and drop-list controls.
|
|
|
|
* Handles the interaction of those two controls, and also changes
|
|
|
|
* the setting of the port box to match the protocol if necessary,
|
|
|
|
* and refreshes both host and port boxes when switching to/from the
|
|
|
|
* serial backend.
|
|
|
|
*/
|
2022-05-01 08:48:38 +00:00
|
|
|
static void config_protocols_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
int curproto = conf_get_int(conf, CONF_protocol);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
struct hostport *hp = (struct hostport *)ctrl->context.p;
|
2006-08-28 10:35:12 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
/*
|
|
|
|
* Refresh the states of the controls from Conf.
|
|
|
|
*
|
|
|
|
* When refreshing these controls, we have to watch out for
|
|
|
|
* re-entrancy: because there are two controls involved, the
|
|
|
|
* refresh is not atomic, so the VALCHANGE and/or SELCHANGE
|
|
|
|
* callbacks resulting from our updates here might cause other
|
|
|
|
* settings here to change unwantedly. (E.g. setting the list
|
|
|
|
* selection shouldn't trigger the SELCHANGE side effect of
|
|
|
|
* selecting the Other radio button; setting the radio button
|
|
|
|
* to Other here shouldn't have the side effect of selecting
|
|
|
|
* whatever protocol is _currently_ selected in the list box,
|
|
|
|
* if we haven't selected the right one yet.)
|
|
|
|
*/
|
|
|
|
hp->mid_refresh = true;
|
|
|
|
|
|
|
|
if (ctrl == hp->protradio) {
|
|
|
|
/* Available buttons were set up when control was created.
|
|
|
|
* Just select one of them, possibly. */
|
|
|
|
for (int button = 0; button < ctrl->radio.nbuttons; button++)
|
|
|
|
/* The final button is "Other:". If we reach that one, the
|
|
|
|
* current protocol must be in the drop list, so we should
|
|
|
|
* select the "Other:" button. */
|
|
|
|
if (curproto == ctrl->radio.buttondata[button].i ||
|
|
|
|
button == ctrl->radio.nbuttons-1) {
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, button);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (ctrl == hp->protlist) {
|
|
|
|
int curentry = -1;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
assert(n_ui_backends > 0 && n_ui_backends < PROTOCOL_LIMIT);
|
|
|
|
for (size_t i = n_ui_backends;
|
|
|
|
i < PROTOCOL_LIMIT && backends[i]; i++) {
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg,
|
2021-10-23 17:26:34 +00:00
|
|
|
backends[i]->displayname_tc,
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
backends[i]->protocol);
|
|
|
|
if (backends[i]->protocol == curproto)
|
|
|
|
curentry = i - n_ui_backends;
|
|
|
|
}
|
|
|
|
if (curentry > 0) {
|
|
|
|
/*
|
|
|
|
* The currently configured protocol is one of the
|
|
|
|
* list-box ones, so select it in protlist.
|
|
|
|
*
|
|
|
|
* (The corresponding refresh event for protradio
|
|
|
|
* should have selected the "Other:" radio button, to
|
|
|
|
* keep things consistent.)
|
|
|
|
*/
|
|
|
|
dlg_listbox_select(ctrl, dlg, curentry);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If the currently configured protocol is one of the
|
|
|
|
* radio buttons, we must still ensure *something* is
|
|
|
|
* selected in the list box. The sensible default is
|
|
|
|
* the first list element, which be_*.c ought to have
|
|
|
|
* arranged to be the 'runner-up' in protocol
|
|
|
|
* popularity out of the ones relegated to the list
|
|
|
|
* box.
|
|
|
|
*
|
|
|
|
* We don't make much effort to retain the state of
|
|
|
|
* the list box when it doesn't correspond to an
|
|
|
|
* actual protocol. So it's easy for this case to be
|
|
|
|
* reached as a side effect of other actions, e.g.
|
|
|
|
* loading a saved session that has a radio-button
|
|
|
|
* protocol configured.
|
|
|
|
*/
|
|
|
|
dlg_listbox_select(ctrl, dlg, 0);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
}
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
hp->mid_refresh = false;
|
|
|
|
} else if (!hp->mid_refresh) {
|
|
|
|
/*
|
|
|
|
* Potentially update Conf from the states of the controls.
|
|
|
|
*/
|
|
|
|
int newproto = curproto;
|
|
|
|
|
|
|
|
if (event == EVENT_VALCHANGE && ctrl == hp->protradio) {
|
|
|
|
int button = dlg_radiobutton_get(ctrl, dlg);
|
|
|
|
assert(button >= 0 && button < ctrl->radio.nbuttons);
|
|
|
|
if (ctrl->radio.buttondata[button].i == -1) {
|
|
|
|
/*
|
|
|
|
* The 'Other' radio button was selected, which means we
|
|
|
|
* have to set CONF_protocol based on the currently
|
|
|
|
* selected list box entry.
|
|
|
|
*
|
|
|
|
* (We conditionalise this on there _being_ a selected
|
|
|
|
* list box entry. I hope the case where nothing is
|
|
|
|
* selected can't actually come up except during
|
|
|
|
* initialisation, and I also hope that hp->mid_session
|
|
|
|
* will prevent that case from getting here. But as a
|
|
|
|
* last-ditch fallback, this if statement should at least
|
|
|
|
* guarantee that we don't pass a nonsense value to
|
|
|
|
* dlg_listbox_getid.)
|
|
|
|
*/
|
|
|
|
int i = dlg_listbox_index(hp->protlist, dlg);
|
|
|
|
if (i >= 0)
|
|
|
|
newproto = dlg_listbox_getid(hp->protlist, dlg, i);
|
|
|
|
} else {
|
|
|
|
newproto = ctrl->radio.buttondata[button].i;
|
|
|
|
}
|
|
|
|
} else if (event == EVENT_SELCHANGE && ctrl == hp->protlist) {
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i >= 0) {
|
|
|
|
newproto = dlg_listbox_getid(ctrl, dlg, i);
|
|
|
|
/* Select the "Other" radio button, too */
|
|
|
|
dlg_radiobutton_set(hp->protradio, dlg,
|
|
|
|
hp->protradio->radio.nbuttons-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newproto != curproto) {
|
|
|
|
conf_set_int(conf, CONF_protocol, newproto);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
const struct BackendVtable *cvt = backend_vt_from_proto(curproto);
|
2018-10-05 06:03:46 +00:00
|
|
|
const struct BackendVtable *nvt = backend_vt_from_proto(newproto);
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
assert(cvt);
|
2018-09-11 15:23:38 +00:00
|
|
|
assert(nvt);
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
/*
|
|
|
|
* Iff the user hasn't changed the port from the old
|
|
|
|
* protocol's default, update it with the new protocol's
|
|
|
|
* default.
|
|
|
|
*
|
|
|
|
* (This includes a "default" of 0, implying that there is
|
|
|
|
* no sensible default for that protocol; in this case
|
|
|
|
* it's displayed as a blank.)
|
|
|
|
*
|
2019-09-08 19:29:00 +00:00
|
|
|
* This helps with the common case of tabbing through the
|
|
|
|
* controls in order and setting a non-default port before
|
|
|
|
* getting to the protocol; we want that non-default port
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
* to be preserved.
|
|
|
|
*/
|
|
|
|
int port = conf_get_int(conf, CONF_port);
|
|
|
|
if (port == cvt->default_port)
|
2018-09-11 15:23:38 +00:00
|
|
|
conf_set_int(conf, CONF_port, nvt->default_port);
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
|
|
|
|
dlg_refresh(hp->host, dlg);
|
|
|
|
dlg_refresh(hp->port, dlg);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void loggingbuttons_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2005-03-15 10:43:29 +00:00
|
|
|
{
|
|
|
|
int button;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2005-03-15 10:43:29 +00:00
|
|
|
/* This function works just like the standard radio-button handler,
|
|
|
|
* but it has to fall back to "no logging" in situations where the
|
|
|
|
* configured logging type isn't applicable.
|
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int logtype = conf_get_int(conf, CONF_logtype);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
2005-03-15 10:43:29 +00:00
|
|
|
for (button = 0; button < ctrl->radio.nbuttons; button++)
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (logtype == ctrl->radio.buttondata[button].i)
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* We fell off the end, so we lack the configured logging type */
|
|
|
|
if (button == ctrl->radio.nbuttons) {
|
|
|
|
button = 0;
|
|
|
|
conf_set_int(conf, CONF_logtype, LGTYP_NONE);
|
|
|
|
}
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, button);
|
2005-03-15 10:43:29 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
|
|
|
button = dlg_radiobutton_get(ctrl, dlg);
|
|
|
|
assert(button >= 0 && button < ctrl->radio.nbuttons);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_set_int(conf, CONF_logtype, ctrl->radio.buttondata[button].i);
|
2005-03-15 10:43:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void numeric_keypad_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
|
|
|
int button;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* This function works much like the standard radio button
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
* handler, but it has to handle two fields in Conf.
|
2003-03-05 22:07:40 +00:00
|
|
|
*/
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_bool(conf, CONF_nethack_keypad))
|
|
|
|
button = 2;
|
|
|
|
else if (conf_get_bool(conf, CONF_app_keypad))
|
|
|
|
button = 1;
|
|
|
|
else
|
|
|
|
button = 0;
|
|
|
|
assert(button < ctrl->radio.nbuttons);
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, button);
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
button = dlg_radiobutton_get(ctrl, dlg);
|
|
|
|
assert(button >= 0 && button < ctrl->radio.nbuttons);
|
|
|
|
if (button == 2) {
|
|
|
|
conf_set_bool(conf, CONF_app_keypad, false);
|
|
|
|
conf_set_bool(conf, CONF_nethack_keypad, true);
|
|
|
|
} else {
|
|
|
|
conf_set_bool(conf, CONF_app_keypad, (button != 0));
|
|
|
|
conf_set_bool(conf, CONF_nethack_keypad, false);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void cipherlist_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
static const struct { const char *s; int c; } ciphers[] = {
|
2015-06-07 11:51:51 +00:00
|
|
|
{ "ChaCha20 (SSH-2 only)", CIPHER_CHACHA20 },
|
Implement AES-GCM using the @openssh.com protocol IDs.
I only recently found out that OpenSSH defined their own protocol IDs
for AES-GCM, defined to work the same as the standard ones except that
they fixed the semantics for how you select the linked cipher+MAC pair
during key exchange.
(RFC 5647 defines protocol ids for AES-GCM in both the cipher and MAC
namespaces, and requires that you MUST select both or neither - but
this contradicts the selection policy set out in the base SSH RFCs,
and there's no discussion of how you resolve a conflict between them!
OpenSSH's answer is to do it the same way ChaCha20-Poly1305 works,
because that will ensure the two suites don't fight.)
People do occasionally ask us for this linked cipher/MAC pair, and now
I know it's actually feasible, I've implemented it, including a pair
of vector implementations for x86 and Arm using their respective
architecture extensions for multiplying polynomials over GF(2).
Unlike ChaCha20-Poly1305, I've kept the cipher and MAC implementations
in separate objects, with an arm's-length link between them that the
MAC uses when it needs to encrypt single cipher blocks to use as the
inputs to the MAC algorithm. That enables the cipher and the MAC to be
independently selected from their hardware-accelerated versions, just
in case someone runs on a system that has polynomial multiplication
instructions but not AES acceleration, or vice versa.
There's a fourth implementation of the GCM MAC, which is a pure
software implementation of the same algorithm used in the vectorised
versions. It's too slow to use live, but I've kept it in the code for
future testing needs, and because it's a convenient place to dump my
design comments.
The vectorised implementations are fairly crude as far as optimisation
goes. I'm sure serious x86 _or_ Arm optimisation engineers would look
at them and laugh. But GCM is a fast MAC compared to HMAC-SHA-256
(indeed compared to HMAC-anything-at-all), so it should at least be
good enough to use. And we've got a working version with some tests
now, so if someone else wants to improve them, they can.
2022-08-16 17:36:58 +00:00
|
|
|
{ "AES-GCM (SSH-2 only)", CIPHER_AESGCM },
|
2019-09-08 19:29:00 +00:00
|
|
|
{ "3DES", CIPHER_3DES },
|
|
|
|
{ "Blowfish", CIPHER_BLOWFISH },
|
|
|
|
{ "DES", CIPHER_DES },
|
|
|
|
{ "AES (SSH-2 only)", CIPHER_AES },
|
|
|
|
{ "Arcfour (SSH-2 only)", CIPHER_ARCFOUR },
|
|
|
|
{ "-- warn below here --", CIPHER_WARN }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Set up the "selected ciphers" box. */
|
|
|
|
/* (cipherlist assumed to contain all ciphers) */
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < CIPHER_MAX; i++) {
|
|
|
|
int c = conf_get_int_int(conf, CONF_ssh_cipherlist, i);
|
|
|
|
int j;
|
|
|
|
const char *cstr = NULL;
|
|
|
|
for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) {
|
|
|
|
if (ciphers[j].c == c) {
|
|
|
|
cstr = ciphers[j].s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, cstr, c);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Update array to match the list box. */
|
|
|
|
for (i=0; i < CIPHER_MAX; i++)
|
|
|
|
conf_set_int_int(conf, CONF_ssh_cipherlist, i,
|
|
|
|
dlg_listbox_getid(ctrl, dlg, i));
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-19 18:22:17 +00:00
|
|
|
#ifndef NO_GSSAPI
|
2022-05-01 08:48:38 +00:00
|
|
|
static void gsslist_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2010-05-19 18:22:17 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2010-05-19 18:22:17 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2010-05-19 18:22:17 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < ngsslibs; i++) {
|
|
|
|
int id = conf_get_int_int(conf, CONF_ssh_gsslist, i);
|
|
|
|
assert(id >= 0 && id < ngsslibs);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, gsslibnames[id], id);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2010-05-19 18:22:17 +00:00
|
|
|
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2010-05-19 18:22:17 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Update array to match the list box. */
|
|
|
|
for (i=0; i < ngsslibs; i++)
|
|
|
|
conf_set_int_int(conf, CONF_ssh_gsslist, i,
|
|
|
|
dlg_listbox_getid(ctrl, dlg, i));
|
2010-05-19 18:22:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void kexlist_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2004-12-23 02:24:07 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2004-12-23 02:24:07 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2004-12-23 02:24:07 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
static const struct { const char *s; int k; } kexes[] = {
|
2022-08-29 06:44:39 +00:00
|
|
|
{ "Diffie-Hellman group 1 (1024-bit)", KEX_DHGROUP1 },
|
|
|
|
{ "Diffie-Hellman group 14 (2048-bit)", KEX_DHGROUP14 },
|
|
|
|
{ "Diffie-Hellman group 15 (3072-bit)", KEX_DHGROUP15 },
|
|
|
|
{ "Diffie-Hellman group 16 (4096-bit)", KEX_DHGROUP16 },
|
|
|
|
{ "Diffie-Hellman group 17 (6144-bit)", KEX_DHGROUP17 },
|
|
|
|
{ "Diffie-Hellman group 18 (8192-bit)", KEX_DHGROUP18 },
|
|
|
|
{ "Diffie-Hellman group exchange", KEX_DHGEX },
|
|
|
|
{ "RSA-based key exchange", KEX_RSA },
|
|
|
|
{ "ECDH key exchange", KEX_ECDH },
|
2022-10-21 16:46:38 +00:00
|
|
|
{ "NTRU Prime / Curve25519 hybrid kex", KEX_NTRU_HYBRID },
|
2022-08-29 06:44:39 +00:00
|
|
|
{ "-- warn below here --", KEX_WARN }
|
2019-09-08 19:29:00 +00:00
|
|
|
};
|
2004-12-23 02:24:07 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Set up the "kex preference" box. */
|
|
|
|
/* (kexlist assumed to contain all algorithms) */
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
2018-05-01 06:41:01 +00:00
|
|
|
for (i = 0; i < KEX_MAX; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int k = conf_get_int_int(conf, CONF_ssh_kexlist, i);
|
|
|
|
int j;
|
|
|
|
const char *kstr = NULL;
|
|
|
|
for (j = 0; j < (sizeof kexes) / (sizeof kexes[0]); j++) {
|
|
|
|
if (kexes[j].k == k) {
|
|
|
|
kstr = kexes[j].s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, kstr, k);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2004-12-23 02:24:07 +00:00
|
|
|
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
2004-12-23 02:24:07 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Update array to match the list box. */
|
2018-05-01 06:41:01 +00:00
|
|
|
for (i=0; i < KEX_MAX; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int_int(conf, CONF_ssh_kexlist, i,
|
|
|
|
dlg_listbox_getid(ctrl, dlg, i));
|
2004-12-23 02:24:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void hklist_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2022-08-03 19:48:46 +00:00
|
|
|
void *data, int event)
|
2016-03-25 15:56:31 +00:00
|
|
|
{
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
static const struct { const char *s; int k; } hks[] = {
|
|
|
|
{ "Ed25519", HK_ED25519 },
|
2020-03-02 18:43:00 +00:00
|
|
|
{ "Ed448", HK_ED448 },
|
2016-03-25 15:56:31 +00:00
|
|
|
{ "ECDSA", HK_ECDSA },
|
|
|
|
{ "DSA", HK_DSA },
|
|
|
|
{ "RSA", HK_RSA },
|
|
|
|
{ "-- warn below here --", HK_WARN }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Set up the "host key preference" box. */
|
|
|
|
/* (hklist assumed to contain all algorithms) */
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < HK_MAX; i++) {
|
|
|
|
int k = conf_get_int_int(conf, CONF_ssh_hklist, i);
|
|
|
|
int j;
|
|
|
|
const char *kstr = NULL;
|
|
|
|
for (j = 0; j < lenof(hks); j++) {
|
|
|
|
if (hks[j].k == k) {
|
|
|
|
kstr = hks[j].s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, kstr, k);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
|
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Update array to match the list box. */
|
|
|
|
for (i=0; i < HK_MAX; i++)
|
|
|
|
conf_set_int_int(conf, CONF_ssh_hklist, i,
|
|
|
|
dlg_listbox_getid(ctrl, dlg, i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void printerbox_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int nprinters, i;
|
|
|
|
printer_enum *pe;
|
|
|
|
const char *printer;
|
|
|
|
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
/*
|
|
|
|
* Some backends may wish to disable the drop-down list on
|
|
|
|
* this edit box. Be prepared for this.
|
|
|
|
*/
|
|
|
|
if (ctrl->editbox.has_list) {
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
dlg_listbox_add(ctrl, dlg, PRINTER_DISABLED_STRING);
|
|
|
|
pe = printer_start_enum(&nprinters);
|
|
|
|
for (i = 0; i < nprinters; i++)
|
|
|
|
dlg_listbox_add(ctrl, dlg, printer_get_name(pe, i));
|
|
|
|
printer_finish_enum(pe);
|
|
|
|
}
|
|
|
|
printer = conf_get_str(conf, CONF_printer);
|
|
|
|
if (!printer)
|
|
|
|
printer = PRINTER_DISABLED_STRING;
|
|
|
|
dlg_editbox_set(ctrl, dlg, printer);
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *printer = dlg_editbox_get(ctrl, dlg);
|
|
|
|
if (!strcmp(printer, PRINTER_DISABLED_STRING))
|
|
|
|
printer[0] = '\0';
|
|
|
|
conf_set_str(conf, CONF_printer, printer);
|
|
|
|
sfree(printer);
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void codepage_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
|
|
|
const char *cp, *thiscp;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
thiscp = cp_name(decode_codepage(conf_get_str(conf,
|
|
|
|
CONF_line_codepage)));
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; (cp = cp_enumerate(i)) != NULL; i++)
|
|
|
|
dlg_listbox_add(ctrl, dlg, cp);
|
|
|
|
dlg_editbox_set(ctrl, dlg, thiscp);
|
|
|
|
conf_set_str(conf, CONF_line_codepage, thiscp);
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *codepage = dlg_editbox_get(ctrl, dlg);
|
|
|
|
conf_set_str(conf, CONF_line_codepage,
|
|
|
|
cp_name(decode_codepage(codepage)));
|
|
|
|
sfree(codepage);
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void sshbug_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
if (event == EVENT_REFRESH) {
|
2012-07-28 16:53:09 +00:00
|
|
|
/*
|
|
|
|
* We must fetch the previously configured value from the Conf
|
|
|
|
* before we start modifying the drop-down list, otherwise the
|
|
|
|
* spurious SELCHANGE we trigger in the process will overwrite
|
|
|
|
* the value we wanted to keep.
|
|
|
|
*/
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int oldconf = conf_get_int(conf, ctrl->context.i);
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON);
|
|
|
|
switch (oldconf) {
|
|
|
|
case AUTO: dlg_listbox_select(ctrl, dlg, 0); break;
|
|
|
|
case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 1); break;
|
|
|
|
case FORCE_ON: dlg_listbox_select(ctrl, dlg, 2); break;
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0)
|
|
|
|
i = AUTO;
|
|
|
|
else
|
|
|
|
i = dlg_listbox_getid(ctrl, dlg, i);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
conf_set_int(conf, ctrl->context.i, i);
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void sshbug_handler_manual_only(dlgcontrol *ctrl, dlgparam *dlg,
|
Bug workaround to delay sending our SSH greeting.
Ian Jackson recently tried to use the recipe in the psusan manpage for
talking to UML, and found that the connection was not successfully set
up, because at some point during startup, UML read the SSH greeting
(ok, the bare-ssh-connection greeting) from its input fd and threw it
away. So by the time psusan was run by the guest init process, the
greeting wasn't there to be read.
Ian's report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
I was also able to reproduce this locally, which makes me wonder why I
_didn't_ notice it when I originally wrote that part of the psusan man
page. It worked for me before, honest! But now it doesn't.
Anyway. The ssh verstring module already has a mode switch to decide
whether we ought to send our greeting before or after waiting for the
other side's greeting (because that decision varies between client and
server, and between SSH-1 and SSH-2). So it's easy to implement an
override that forces it to 'wait for the server greeting first'.
I've added this as yet another bug workaround flag. But unlike all the
others, it can't be autodetected from the server's version string,
because, of course, we have to act on it _before_ seeing the server's
greeting and version string! So it's a manual-only flag.
However, I've mentioned it in the UML section of the psusan man page,
since that's the place where I _know_ people are likely to need to use
this flag.
2021-08-14 09:56:20 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This is just like sshbug_handler, except that there's no 'Auto'
|
|
|
|
* option. Used for bug workaround flags that can't be
|
|
|
|
* autodetected, and have to be manually enabled if they're to be
|
|
|
|
* used at all.
|
|
|
|
*/
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
if (event == EVENT_REFRESH) {
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int oldconf = conf_get_int(conf, ctrl->context.i);
|
Bug workaround to delay sending our SSH greeting.
Ian Jackson recently tried to use the recipe in the psusan manpage for
talking to UML, and found that the connection was not successfully set
up, because at some point during startup, UML read the SSH greeting
(ok, the bare-ssh-connection greeting) from its input fd and threw it
away. So by the time psusan was run by the guest init process, the
greeting wasn't there to be read.
Ian's report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
I was also able to reproduce this locally, which makes me wonder why I
_didn't_ notice it when I originally wrote that part of the psusan man
page. It worked for me before, honest! But now it doesn't.
Anyway. The ssh verstring module already has a mode switch to decide
whether we ought to send our greeting before or after waiting for the
other side's greeting (because that decision varies between client and
server, and between SSH-1 and SSH-2). So it's easy to implement an
override that forces it to 'wait for the server greeting first'.
I've added this as yet another bug workaround flag. But unlike all the
others, it can't be autodetected from the server's version string,
because, of course, we have to act on it _before_ seeing the server's
greeting and version string! So it's a manual-only flag.
However, I've mentioned it in the UML section of the psusan man page,
since that's the place where I _know_ people are likely to need to use
this flag.
2021-08-14 09:56:20 +00:00
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF);
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON);
|
|
|
|
switch (oldconf) {
|
|
|
|
case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 0); break;
|
|
|
|
case FORCE_ON: dlg_listbox_select(ctrl, dlg, 1); break;
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0)
|
|
|
|
i = FORCE_OFF;
|
|
|
|
else
|
|
|
|
i = dlg_listbox_getid(ctrl, dlg, i);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
conf_set_int(conf, ctrl->context.i, i);
|
Bug workaround to delay sending our SSH greeting.
Ian Jackson recently tried to use the recipe in the psusan manpage for
talking to UML, and found that the connection was not successfully set
up, because at some point during startup, UML read the SSH greeting
(ok, the bare-ssh-connection greeting) from its input fd and threw it
away. So by the time psusan was run by the guest init process, the
greeting wasn't there to be read.
Ian's report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
I was also able to reproduce this locally, which makes me wonder why I
_didn't_ notice it when I originally wrote that part of the psusan man
page. It worked for me before, honest! But now it doesn't.
Anyway. The ssh verstring module already has a mode switch to decide
whether we ought to send our greeting before or after waiting for the
other side's greeting (because that decision varies between client and
server, and between SSH-1 and SSH-2). So it's easy to implement an
override that forces it to 'wait for the server greeting first'.
I've added this as yet another bug workaround flag. But unlike all the
others, it can't be autodetected from the server's version string,
because, of course, we have to act on it _before_ seeing the server's
greeting and version string! So it's a manual-only flag.
However, I've mentioned it in the UML section of the psusan man page,
since that's the place where I _know_ people are likely to need to use
this flag.
2021-08-14 09:56:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
struct sessionsaver_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *editbox, *listbox, *loadbutton, *savebutton, *delbutton;
|
|
|
|
dlgcontrol *okbutton, *cancelbutton;
|
2005-04-07 01:36:28 +00:00
|
|
|
struct sesslist sesslist;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool midsession;
|
2013-07-14 10:46:34 +00:00
|
|
|
char *savedsession; /* the current contents of ssd->editbox */
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2013-07-14 10:46:34 +00:00
|
|
|
static void sessionsaver_data_free(void *ssdv)
|
|
|
|
{
|
|
|
|
struct sessionsaver_data *ssd = (struct sessionsaver_data *)ssdv;
|
2018-10-29 19:50:29 +00:00
|
|
|
get_sesslist(&ssd->sesslist, false);
|
2013-07-14 10:46:34 +00:00
|
|
|
sfree(ssd->savedsession);
|
|
|
|
sfree(ssd);
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
2003-03-05 22:07:40 +00:00
|
|
|
* Helper function to load the session selected in the list box, if
|
|
|
|
* any, as this is done in more than one place below. Returns 0 for
|
|
|
|
* failure.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool load_selected_session(
|
|
|
|
struct sessionsaver_data *ssd,
|
|
|
|
dlgparam *dlg, Conf *conf, bool *maybe_launch)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
|
|
|
int i = dlg_listbox_index(ssd->listbox, dlg);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool isdef;
|
2003-03-05 22:07:40 +00:00
|
|
|
if (i < 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_beep(dlg);
|
|
|
|
return false;
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
2005-04-07 01:36:28 +00:00
|
|
|
isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
load_settings(ssd->sesslist.sessions[i], conf);
|
2013-07-14 10:46:34 +00:00
|
|
|
sfree(ssd->savedsession);
|
|
|
|
ssd->savedsession = dupstr(isdef ? "" : ssd->sesslist.sessions[i]);
|
|
|
|
if (maybe_launch)
|
|
|
|
*maybe_launch = !isdef;
|
2003-03-05 22:07:40 +00:00
|
|
|
dlg_refresh(NULL, dlg);
|
|
|
|
/* Restore the selection, which might have been clobbered by
|
|
|
|
* changing the value of the edit box. */
|
|
|
|
dlg_listbox_select(ssd->listbox, dlg, i);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return true;
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void sessionsaver_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct sessionsaver_data *ssd =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct sessionsaver_data *)ctrl->context.p;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ssd->editbox) {
|
|
|
|
dlg_editbox_set(ctrl, dlg, ssd->savedsession);
|
|
|
|
} else if (ctrl == ssd->listbox) {
|
|
|
|
int i;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < ssd->sesslist.nsessions; i++)
|
|
|
|
dlg_listbox_add(ctrl, dlg, ssd->sesslist.sessions[i]);
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2005-09-21 14:53:32 +00:00
|
|
|
int top, bottom, halfway, i;
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ssd->editbox) {
|
2013-07-14 10:46:34 +00:00
|
|
|
sfree(ssd->savedsession);
|
|
|
|
ssd->savedsession = dlg_editbox_get(ctrl, dlg);
|
2019-09-08 19:29:00 +00:00
|
|
|
top = ssd->sesslist.nsessions;
|
|
|
|
bottom = -1;
|
|
|
|
while (top-bottom > 1) {
|
|
|
|
halfway = (top+bottom)/2;
|
|
|
|
i = strcmp(ssd->savedsession, ssd->sesslist.sessions[halfway]);
|
|
|
|
if (i <= 0 ) {
|
|
|
|
top = halfway;
|
|
|
|
} else {
|
|
|
|
bottom = halfway;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (top == ssd->sesslist.nsessions) {
|
|
|
|
top -= 1;
|
|
|
|
}
|
|
|
|
dlg_listbox_select(ssd->listbox, dlg, top);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
bool mbl = false;
|
|
|
|
if (!ssd->midsession &&
|
|
|
|
(ctrl == ssd->listbox ||
|
|
|
|
(ssd->loadbutton && ctrl == ssd->loadbutton))) {
|
|
|
|
/*
|
|
|
|
* The user has double-clicked a session, or hit Load.
|
|
|
|
* We must load the selected session, and then
|
|
|
|
* terminate the configuration dialog _if_ there was a
|
|
|
|
* double-click on the list box _and_ that session
|
|
|
|
* contains a hostname.
|
|
|
|
*/
|
|
|
|
if (load_selected_session(ssd, dlg, conf, &mbl) &&
|
|
|
|
(mbl && ctrl == ssd->listbox && conf_launchable(conf))) {
|
|
|
|
dlg_end(dlg, 1); /* it's all over, and succeeded */
|
|
|
|
}
|
|
|
|
} else if (ctrl == ssd->savebutton) {
|
|
|
|
bool isdef = !strcmp(ssd->savedsession, "Default Settings");
|
|
|
|
if (!ssd->savedsession[0]) {
|
|
|
|
int i = dlg_listbox_index(ssd->listbox, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
isdef = !strcmp(ssd->sesslist.sessions[i], "Default Settings");
|
2013-07-14 10:46:34 +00:00
|
|
|
sfree(ssd->savedsession);
|
|
|
|
ssd->savedsession = dupstr(isdef ? "" :
|
|
|
|
ssd->sesslist.sessions[i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2003-04-01 18:10:25 +00:00
|
|
|
{
|
2013-07-14 10:46:34 +00:00
|
|
|
char *errmsg = save_settings(ssd->savedsession, conf);
|
2003-04-01 18:10:25 +00:00
|
|
|
if (errmsg) {
|
|
|
|
dlg_error_msg(dlg, errmsg);
|
|
|
|
sfree(errmsg);
|
|
|
|
}
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
get_sesslist(&ssd->sesslist, false);
|
|
|
|
get_sesslist(&ssd->sesslist, true);
|
|
|
|
dlg_refresh(ssd->editbox, dlg);
|
|
|
|
dlg_refresh(ssd->listbox, dlg);
|
|
|
|
} else if (!ssd->midsession &&
|
|
|
|
ssd->delbutton && ctrl == ssd->delbutton) {
|
|
|
|
int i = dlg_listbox_index(ssd->listbox, dlg);
|
|
|
|
if (i <= 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
} else {
|
|
|
|
del_settings(ssd->sesslist.sessions[i]);
|
|
|
|
get_sesslist(&ssd->sesslist, false);
|
|
|
|
get_sesslist(&ssd->sesslist, true);
|
|
|
|
dlg_refresh(ssd->listbox, dlg);
|
|
|
|
}
|
|
|
|
} else if (ctrl == ssd->okbutton) {
|
2004-12-30 10:58:28 +00:00
|
|
|
if (ssd->midsession) {
|
2003-04-10 18:00:50 +00:00
|
|
|
/* In a mid-session Change Settings, Apply is always OK. */
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_end(dlg, 1);
|
2003-04-10 18:00:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Annoying special case. If the `Open' button is
|
|
|
|
* pressed while no host name is currently set, _and_
|
|
|
|
* the session list previously had the focus, _and_
|
|
|
|
* there was a session selected in that which had a
|
|
|
|
* valid host name in it, then load it and go.
|
|
|
|
*/
|
|
|
|
if (dlg_last_focused(ctrl, dlg) == ssd->listbox &&
|
|
|
|
!conf_launchable(conf) && dlg_is_visible(ssd->listbox, dlg)) {
|
|
|
|
Conf *conf2 = conf_new();
|
|
|
|
bool mbl = false;
|
|
|
|
if (!load_selected_session(ssd, dlg, conf2, &mbl)) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
conf_free(conf2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* If at this point we have a valid session, go! */
|
|
|
|
if (mbl && conf_launchable(conf2)) {
|
|
|
|
conf_copy_into(conf, conf2);
|
|
|
|
dlg_end(dlg, 1);
|
|
|
|
} else
|
|
|
|
dlg_beep(dlg);
|
|
|
|
|
|
|
|
conf_free(conf2);
|
2004-11-15 11:10:36 +00:00
|
|
|
return;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, do the normal thing: if we have a valid
|
|
|
|
* session, get going.
|
|
|
|
*/
|
|
|
|
if (conf_launchable(conf)) {
|
|
|
|
dlg_end(dlg, 1);
|
|
|
|
} else
|
|
|
|
dlg_beep(dlg);
|
|
|
|
} else if (ctrl == ssd->cancelbutton) {
|
|
|
|
dlg_end(dlg, 0);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct charclass_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *listbox, *editbox, *button;
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void charclass_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct charclass_data *ccd =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct charclass_data *)ctrl->context.p;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ccd->listbox) {
|
|
|
|
int i;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
|
|
char str[100];
|
|
|
|
sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i,
|
|
|
|
(i >= 0x21 && i != 0x7F) ? i : ' ',
|
|
|
|
conf_get_int_int(conf, CONF_wordness, i));
|
|
|
|
dlg_listbox_add(ctrl, dlg, str);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ccd->button) {
|
|
|
|
char *str;
|
|
|
|
int i, n;
|
|
|
|
str = dlg_editbox_get(ccd->editbox, dlg);
|
|
|
|
n = atoi(str);
|
|
|
|
sfree(str);
|
|
|
|
for (i = 0; i < 128; i++) {
|
|
|
|
if (dlg_listbox_issel(ccd->listbox, dlg, i))
|
|
|
|
conf_set_int_int(conf, CONF_wordness, i, n);
|
|
|
|
}
|
|
|
|
dlg_refresh(ccd->listbox, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct colour_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *listbox, *redit, *gedit, *bedit, *button;
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2021-02-07 19:59:20 +00:00
|
|
|
/* Array of the user-visible colour names defined in the list macro in
|
|
|
|
* putty.h */
|
2003-03-05 22:07:40 +00:00
|
|
|
static const char *const colours[] = {
|
2021-02-07 19:59:20 +00:00
|
|
|
#define CONF_COLOUR_NAME_DECL(id,name) name,
|
|
|
|
CONF_COLOUR_LIST(CONF_COLOUR_NAME_DECL)
|
|
|
|
#undef CONF_COLOUR_NAME_DECL
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void colour_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct colour_data *cd =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct colour_data *)ctrl->context.p;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool update = false, clear = false;
|
|
|
|
int r, g, b;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == cd->listbox) {
|
|
|
|
int i;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < lenof(colours); i++)
|
|
|
|
dlg_listbox_add(ctrl, dlg, colours[i]);
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
clear = true;
|
|
|
|
update = true;
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == cd->listbox) {
|
|
|
|
/* The user has selected a colour. Update the RGB text. */
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
clear = true;
|
|
|
|
} else {
|
|
|
|
clear = false;
|
|
|
|
r = conf_get_int_int(conf, CONF_colours, i*3+0);
|
|
|
|
g = conf_get_int_int(conf, CONF_colours, i*3+1);
|
|
|
|
b = conf_get_int_int(conf, CONF_colours, i*3+2);
|
|
|
|
}
|
|
|
|
update = true;
|
|
|
|
}
|
2003-03-22 11:07:59 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == cd->redit || ctrl == cd->gedit || ctrl == cd->bedit) {
|
|
|
|
/* The user has changed the colour using the edit boxes. */
|
|
|
|
char *str;
|
|
|
|
int i, cval;
|
|
|
|
|
|
|
|
str = dlg_editbox_get(ctrl, dlg);
|
|
|
|
cval = atoi(str);
|
|
|
|
sfree(str);
|
|
|
|
if (cval > 255) cval = 255;
|
|
|
|
if (cval < 0) cval = 0;
|
|
|
|
|
|
|
|
i = dlg_listbox_index(cd->listbox, dlg);
|
|
|
|
if (i >= 0) {
|
|
|
|
if (ctrl == cd->redit)
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+0, cval);
|
|
|
|
else if (ctrl == cd->gedit)
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+1, cval);
|
|
|
|
else if (ctrl == cd->bedit)
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+2, cval);
|
|
|
|
}
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == cd->button) {
|
|
|
|
int i = dlg_listbox_index(cd->listbox, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Start a colour selector, which will send us an
|
|
|
|
* EVENT_CALLBACK when it's finished and allow us to
|
|
|
|
* pick up the results.
|
|
|
|
*/
|
|
|
|
dlg_coloursel_start(ctrl, dlg,
|
|
|
|
conf_get_int_int(conf, CONF_colours, i*3+0),
|
|
|
|
conf_get_int_int(conf, CONF_colours, i*3+1),
|
|
|
|
conf_get_int_int(conf, CONF_colours, i*3+2));
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_CALLBACK) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == cd->button) {
|
|
|
|
int i = dlg_listbox_index(cd->listbox, dlg);
|
|
|
|
/*
|
|
|
|
* Collect the results of the colour selector. Will
|
|
|
|
* return nonzero on success, or zero if the colour
|
|
|
|
* selector did nothing (user hit Cancel, for example).
|
|
|
|
*/
|
|
|
|
if (dlg_coloursel_results(ctrl, dlg, &r, &g, &b)) {
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+0, r);
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+1, g);
|
|
|
|
conf_set_int_int(conf, CONF_colours, i*3+2, b);
|
|
|
|
clear = false;
|
|
|
|
update = true;
|
|
|
|
}
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (update) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (clear) {
|
|
|
|
dlg_editbox_set(cd->redit, dlg, "");
|
|
|
|
dlg_editbox_set(cd->gedit, dlg, "");
|
|
|
|
dlg_editbox_set(cd->bedit, dlg, "");
|
|
|
|
} else {
|
|
|
|
char buf[40];
|
|
|
|
sprintf(buf, "%d", r); dlg_editbox_set(cd->redit, dlg, buf);
|
|
|
|
sprintf(buf, "%d", g); dlg_editbox_set(cd->gedit, dlg, buf);
|
|
|
|
sprintf(buf, "%d", b); dlg_editbox_set(cd->bedit, dlg, buf);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-21 13:57:08 +00:00
|
|
|
struct ttymodes_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *valradio, *valbox, *setbutton, *listbox;
|
2005-04-21 13:57:08 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void ttymodes_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2005-04-21 13:57:08 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2005-04-21 13:57:08 +00:00
|
|
|
struct ttymodes_data *td =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct ttymodes_data *)ctrl->context.p;
|
2005-04-21 13:57:08 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == td->listbox) {
|
|
|
|
char *key, *val;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (val = conf_get_str_strs(conf, CONF_ttymodes, NULL, &key);
|
|
|
|
val != NULL;
|
|
|
|
val = conf_get_str_strs(conf, CONF_ttymodes, key, &key)) {
|
|
|
|
char *disp = dupprintf("%s\t%s", key,
|
|
|
|
(val[0] == 'A') ? "(auto)" :
|
|
|
|
((val[0] == 'N') ? "(don't send)"
|
|
|
|
: val+1));
|
|
|
|
dlg_listbox_add(ctrl, dlg, disp);
|
|
|
|
sfree(disp);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
} else if (ctrl == td->valradio) {
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, 0);
|
|
|
|
}
|
2017-03-06 10:36:26 +00:00
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == td->listbox) {
|
|
|
|
int ind = dlg_listbox_index(td->listbox, dlg);
|
|
|
|
char *val;
|
|
|
|
if (ind < 0) {
|
|
|
|
return; /* no item selected */
|
|
|
|
}
|
|
|
|
val = conf_get_str_str(conf, CONF_ttymodes,
|
|
|
|
conf_get_str_nthstrkey(conf, CONF_ttymodes,
|
|
|
|
ind));
|
|
|
|
assert(val != NULL);
|
|
|
|
/* Do this first to defuse side-effects on radio buttons: */
|
|
|
|
dlg_editbox_set(td->valbox, dlg, val+1);
|
|
|
|
dlg_radiobutton_set(td->valradio, dlg,
|
|
|
|
val[0] == 'A' ? 0 : (val[0] == 'N' ? 1 : 2));
|
|
|
|
}
|
2017-03-06 10:36:26 +00:00
|
|
|
} else if (event == EVENT_VALCHANGE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == td->valbox) {
|
|
|
|
/* If they're editing the text box, we assume they want its
|
|
|
|
* value to be used. */
|
|
|
|
dlg_radiobutton_set(td->valradio, dlg, 2);
|
|
|
|
}
|
2005-04-21 13:57:08 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == td->setbutton) {
|
|
|
|
int ind = dlg_listbox_index(td->listbox, dlg);
|
|
|
|
const char *key;
|
|
|
|
char *str, *val;
|
|
|
|
char type;
|
2017-03-06 10:36:26 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
2017-06-20 20:17:43 +00:00
|
|
|
const char types[] = {'A', 'N', 'V'};
|
2019-09-08 19:29:00 +00:00
|
|
|
int button = dlg_radiobutton_get(td->valradio, dlg);
|
|
|
|
assert(button >= 0 && button < lenof(types));
|
|
|
|
type = types[button];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Construct new entry */
|
|
|
|
if (ind >= 0) {
|
|
|
|
key = conf_get_str_nthstrkey(conf, CONF_ttymodes, ind);
|
|
|
|
str = (type == 'V' ? dlg_editbox_get(td->valbox, dlg)
|
|
|
|
: dupstr(""));
|
|
|
|
val = dupprintf("%c%s", type, str);
|
|
|
|
sfree(str);
|
|
|
|
conf_set_str_str(conf, CONF_ttymodes, key, val);
|
|
|
|
sfree(val);
|
|
|
|
dlg_refresh(td->listbox, dlg);
|
|
|
|
dlg_listbox_select(td->listbox, dlg, ind);
|
|
|
|
} else {
|
|
|
|
/* Not a multisel listbox, so this means nothing selected */
|
|
|
|
dlg_beep(dlg);
|
|
|
|
}
|
|
|
|
}
|
2005-04-21 13:57:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
struct environ_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *varbox, *valbox, *addbutton, *rembutton, *listbox;
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void environ_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct environ_data *ed =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct environ_data *)ctrl->context.p;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ed->listbox) {
|
|
|
|
char *key, *val;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key);
|
|
|
|
val != NULL;
|
|
|
|
val = conf_get_str_strs(conf, CONF_environmt, key, &key)) {
|
|
|
|
char *p = dupprintf("%s\t%s", key, val);
|
|
|
|
dlg_listbox_add(ctrl, dlg, p);
|
|
|
|
sfree(p);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == ed->addbutton) {
|
|
|
|
char *key, *val, *str;
|
|
|
|
key = dlg_editbox_get(ed->varbox, dlg);
|
|
|
|
if (!*key) {
|
|
|
|
sfree(key);
|
|
|
|
dlg_beep(dlg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
val = dlg_editbox_get(ed->valbox, dlg);
|
|
|
|
if (!*val) {
|
|
|
|
sfree(key);
|
|
|
|
sfree(val);
|
|
|
|
dlg_beep(dlg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
conf_set_str_str(conf, CONF_environmt, key, val);
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
str = dupcat(key, "\t", val);
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_editbox_set(ed->varbox, dlg, "");
|
|
|
|
dlg_editbox_set(ed->valbox, dlg, "");
|
|
|
|
sfree(str);
|
|
|
|
sfree(key);
|
|
|
|
sfree(val);
|
|
|
|
dlg_refresh(ed->listbox, dlg);
|
|
|
|
} else if (ctrl == ed->rembutton) {
|
|
|
|
int i = dlg_listbox_index(ed->listbox, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
} else {
|
|
|
|
char *key, *val;
|
|
|
|
|
|
|
|
key = conf_get_str_nthstrkey(conf, CONF_environmt, i);
|
|
|
|
if (key) {
|
|
|
|
/* Populate controls with the entry we're about to delete
|
|
|
|
* for ease of editing */
|
|
|
|
val = conf_get_str_str(conf, CONF_environmt, key);
|
|
|
|
dlg_editbox_set(ed->varbox, dlg, key);
|
|
|
|
dlg_editbox_set(ed->valbox, dlg, val);
|
|
|
|
/* And delete it */
|
|
|
|
conf_del_str_str(conf, CONF_environmt, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_refresh(ed->listbox, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct portfwd_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *addbutton, *rembutton, *listbox;
|
|
|
|
dlgcontrol *sourcebox, *destbox, *direction;
|
2005-03-05 15:05:18 +00:00
|
|
|
#ifndef NO_IPV6
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *addressfamily;
|
2005-03-05 15:05:18 +00:00
|
|
|
#endif
|
2003-03-05 22:07:40 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void portfwd_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2019-09-08 19:29:00 +00:00
|
|
|
void *data, int event)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
Conf *conf = (Conf *)data;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct portfwd_data *pfd =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct portfwd_data *)ctrl->context.p;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == pfd->listbox) {
|
|
|
|
char *key, *val;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
|
|
|
|
val != NULL;
|
|
|
|
val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
|
|
|
|
char *p;
|
2013-08-22 17:45:26 +00:00
|
|
|
if (!strcmp(val, "D")) {
|
|
|
|
char *L;
|
|
|
|
/*
|
|
|
|
* A dynamic forwarding is stored as L12345=D or
|
|
|
|
* 6L12345=D (since it's mutually exclusive with
|
|
|
|
* L12345=anything else), but displayed as D12345
|
|
|
|
* to match the fiction that 'Local', 'Remote' and
|
|
|
|
* 'Dynamic' are three distinct modes and also to
|
|
|
|
* align with OpenSSH's command line option syntax
|
|
|
|
* that people will already be used to. So, for
|
|
|
|
* display purposes, find the L in the key string
|
|
|
|
* and turn it into a D.
|
|
|
|
*/
|
|
|
|
p = dupprintf("%s\t", key);
|
|
|
|
L = strchr(p, 'L');
|
|
|
|
if (L) *L = 'D';
|
|
|
|
} else
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
p = dupprintf("%s\t%s", key, val);
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_listbox_add(ctrl, dlg, p);
|
|
|
|
sfree(p);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
} else if (ctrl == pfd->direction) {
|
|
|
|
/*
|
|
|
|
* Default is Local.
|
|
|
|
*/
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, 0);
|
2005-03-05 15:05:18 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (ctrl == pfd->addressfamily) {
|
|
|
|
dlg_radiobutton_set(ctrl, dlg, 0);
|
2005-03-05 15:05:18 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == pfd->addbutton) {
|
|
|
|
const char *family, *type;
|
2015-05-15 10:15:42 +00:00
|
|
|
char *src, *key, *val;
|
2019-09-08 19:29:00 +00:00
|
|
|
int whichbutton;
|
2004-12-30 16:45:11 +00:00
|
|
|
|
2005-03-05 15:05:18 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
whichbutton = dlg_radiobutton_get(pfd->addressfamily, dlg);
|
|
|
|
if (whichbutton == 1)
|
|
|
|
family = "4";
|
|
|
|
else if (whichbutton == 2)
|
|
|
|
family = "6";
|
|
|
|
else
|
2005-03-05 15:05:18 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
family = "";
|
|
|
|
|
|
|
|
whichbutton = dlg_radiobutton_get(pfd->direction, dlg);
|
|
|
|
if (whichbutton == 0)
|
|
|
|
type = "L";
|
|
|
|
else if (whichbutton == 1)
|
|
|
|
type = "R";
|
|
|
|
else
|
|
|
|
type = "D";
|
|
|
|
|
|
|
|
src = dlg_editbox_get(pfd->sourcebox, dlg);
|
|
|
|
if (!*src) {
|
|
|
|
dlg_error_msg(dlg, "You need to specify a source port number");
|
|
|
|
sfree(src);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (*type != 'D') {
|
|
|
|
val = dlg_editbox_get(pfd->destbox, dlg);
|
|
|
|
if (!*val || !host_strchr(val, ':')) {
|
|
|
|
dlg_error_msg(dlg,
|
|
|
|
"You need to specify a destination address\n"
|
|
|
|
"in the form \"host.name:port\"");
|
|
|
|
sfree(src);
|
|
|
|
sfree(val);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
type = "L";
|
2019-09-08 19:29:00 +00:00
|
|
|
val = dupstr("D"); /* special case */
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
}
|
|
|
|
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
key = dupcat(family, type, src);
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(src);
|
|
|
|
|
|
|
|
if (conf_get_str_str_opt(conf, CONF_portfwd, key)) {
|
|
|
|
dlg_error_msg(dlg, "Specified forwarding already exists");
|
|
|
|
} else {
|
|
|
|
conf_set_str_str(conf, CONF_portfwd, key, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(key);
|
|
|
|
sfree(val);
|
|
|
|
dlg_refresh(pfd->listbox, dlg);
|
|
|
|
} else if (ctrl == pfd->rembutton) {
|
|
|
|
int i = dlg_listbox_index(pfd->listbox, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
} else {
|
|
|
|
char *key, *p;
|
2015-05-15 10:15:42 +00:00
|
|
|
const char *val;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
key = conf_get_str_nthstrkey(conf, CONF_portfwd, i);
|
|
|
|
if (key) {
|
|
|
|
static const char *const afs = "A46";
|
|
|
|
static const char *const dirs = "LRD";
|
|
|
|
const char *afp;
|
|
|
|
int dir;
|
2007-09-03 20:52:56 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
int idx;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
#endif
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Populate controls with the entry we're about to delete
|
|
|
|
* for ease of editing */
|
|
|
|
p = key;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
afp = strchr(afs, *p);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
idx = afp ? afp-afs : 0;
|
2007-09-03 20:52:56 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
if (afp)
|
|
|
|
p++;
|
2007-02-18 19:56:16 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_radiobutton_set(pfd->addressfamily, dlg, idx);
|
2007-02-18 19:56:16 +00:00
|
|
|
#endif
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
dir = *p;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
|
|
|
val = conf_get_str_str(conf, CONF_portfwd, key);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!strcmp(val, "D")) {
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
dir = 'D';
|
2019-09-08 19:29:00 +00:00
|
|
|
val = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
dlg_radiobutton_set(pfd->direction, dlg,
|
|
|
|
strchr(dirs, dir) - dirs);
|
|
|
|
p++;
|
|
|
|
|
|
|
|
dlg_editbox_set(pfd->sourcebox, dlg, p);
|
|
|
|
dlg_editbox_set(pfd->destbox, dlg, val);
|
|
|
|
/* And delete it */
|
|
|
|
conf_del_str_str(conf, CONF_portfwd, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_refresh(pfd->listbox, dlg);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
struct manual_hostkey_data {
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *addbutton, *rembutton, *listbox, *keybox;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
};
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void manual_hostkey_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
struct manual_hostkey_data *mh =
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
(struct manual_hostkey_data *)ctrl->context.p;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == mh->listbox) {
|
|
|
|
char *key, *val;
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (val = conf_get_str_strs(conf, CONF_ssh_manual_hostkeys,
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
NULL, &key);
|
2019-09-08 19:29:00 +00:00
|
|
|
val != NULL;
|
|
|
|
val = conf_get_str_strs(conf, CONF_ssh_manual_hostkeys,
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
key, &key)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_listbox_add(ctrl, dlg, key);
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
}
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
} else if (event == EVENT_ACTION) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrl == mh->addbutton) {
|
|
|
|
char *key;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
key = dlg_editbox_get(mh->keybox, dlg);
|
|
|
|
if (!*key) {
|
|
|
|
dlg_error_msg(dlg, "You need to specify a host key or "
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
"fingerprint");
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(key);
|
|
|
|
return;
|
|
|
|
}
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
|
|
|
|
if (!validate_manual_hostkey(key)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_error_msg(dlg, "Host key is not in a valid format");
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
} else if (conf_get_str_str_opt(conf, CONF_ssh_manual_hostkeys,
|
|
|
|
key)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_error_msg(dlg, "Specified host key is already listed");
|
|
|
|
} else {
|
|
|
|
conf_set_str_str(conf, CONF_ssh_manual_hostkeys, key, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(key);
|
|
|
|
dlg_refresh(mh->listbox, dlg);
|
|
|
|
} else if (ctrl == mh->rembutton) {
|
|
|
|
int i = dlg_listbox_index(mh->listbox, dlg);
|
|
|
|
if (i < 0) {
|
|
|
|
dlg_beep(dlg);
|
|
|
|
} else {
|
|
|
|
char *key;
|
|
|
|
|
|
|
|
key = conf_get_str_nthstrkey(conf, CONF_ssh_manual_hostkeys, i);
|
|
|
|
if (key) {
|
|
|
|
dlg_editbox_set(mh->keybox, dlg, key);
|
|
|
|
/* And delete it */
|
|
|
|
conf_del_str_str(conf, CONF_ssh_manual_hostkeys, key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dlg_refresh(mh->listbox, dlg);
|
|
|
|
}
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void clipboard_selector_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2017-12-10 17:16:50 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
Conf *conf = (Conf *)data;
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int setting = ctrl->context.i;
|
2017-12-17 18:44:27 +00:00
|
|
|
#ifdef NAMED_CLIPBOARDS
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int strsetting = ctrl->context2.i;
|
2017-12-17 18:44:27 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
const char *name;
|
|
|
|
int id;
|
|
|
|
} options[] = {
|
|
|
|
{"No action", CLIPUI_NONE},
|
|
|
|
{CLIPNAME_IMPLICIT, CLIPUI_IMPLICIT},
|
|
|
|
{CLIPNAME_EXPLICIT, CLIPUI_EXPLICIT},
|
|
|
|
};
|
2017-12-10 17:16:50 +00:00
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
int i, val = conf_get_int(conf, setting);
|
|
|
|
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
2017-12-17 18:44:27 +00:00
|
|
|
|
|
|
|
#ifdef NAMED_CLIPBOARDS
|
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
dlg_listbox_add(ctrl, dlg, options[i].name);
|
|
|
|
if (val == CLIPUI_CUSTOM) {
|
|
|
|
const char *sval = conf_get_str(conf, strsetting);
|
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
if (!strcmp(sval, options[i].name))
|
|
|
|
break; /* needs escaping */
|
|
|
|
if (i < lenof(options) || sval[0] == '=') {
|
Make dupcat() into a variadic macro.
Up until now, it's been a variadic _function_, whose argument list
consists of 'const char *' ASCIZ strings to concatenate, terminated by
one containing a null pointer. Now, that function is dupcat_fn(), and
it's wrapped by a C99 variadic _macro_ called dupcat(), which
automatically suffixes the null-pointer terminating argument.
This has three benefits. Firstly, it's just less effort at every call
site. Secondly, it protects against the risk of accidentally leaving
off the NULL, causing arbitrary words of stack memory to be
dereferenced as char pointers. And thirdly, it protects against the
more subtle risk of writing a bare 'NULL' as the terminating argument,
instead of casting it explicitly to a pointer. That last one is
necessary because C permits the macro NULL to expand to an integer
constant such as 0, so NULL by itself may not have pointer type, and
worse, it may not be marshalled in a variadic argument list in the
same way as a pointer. (For example, on a 64-bit machine it might only
occupy 32 bits. And yet, on another 64-bit platform, it might work
just fine, so that you don't notice the mistake!)
I was inspired to do this by happening to notice one of those bare
NULL terminators, and thinking I'd better check if there were any
more. Turned out there were quite a few. Now there are none.
2019-10-14 18:42:37 +00:00
|
|
|
char *escaped = dupcat("=", sval);
|
2017-12-17 18:44:27 +00:00
|
|
|
dlg_editbox_set(ctrl, dlg, escaped);
|
|
|
|
sfree(escaped);
|
|
|
|
} else {
|
|
|
|
dlg_editbox_set(ctrl, dlg, sval);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dlg_editbox_set(ctrl, dlg, options[0].name); /* fallback */
|
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
if (val == options[i].id)
|
|
|
|
dlg_editbox_set(ctrl, dlg, options[i].name);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, options[i].name, options[i].id);
|
2017-12-10 17:16:50 +00:00
|
|
|
dlg_listbox_select(ctrl, dlg, 0); /* fallback */
|
2017-12-17 18:44:27 +00:00
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
if (val == options[i].id)
|
2017-12-10 17:16:50 +00:00
|
|
|
dlg_listbox_select(ctrl, dlg, i);
|
2017-12-17 18:44:27 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
dlg_update_done(ctrl, dlg);
|
2017-12-17 18:44:27 +00:00
|
|
|
} else if (event == EVENT_SELCHANGE
|
|
|
|
#ifdef NAMED_CLIPBOARDS
|
|
|
|
|| event == EVENT_VALCHANGE
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
#ifdef NAMED_CLIPBOARDS
|
2020-06-16 16:43:36 +00:00
|
|
|
char *sval = dlg_editbox_get(ctrl, dlg);
|
2017-12-17 18:44:27 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < lenof(options); i++)
|
|
|
|
if (!strcmp(sval, options[i].name)) {
|
|
|
|
conf_set_int(conf, setting, options[i].id);
|
|
|
|
conf_set_str(conf, strsetting, "");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == lenof(options)) {
|
|
|
|
conf_set_int(conf, setting, CLIPUI_CUSTOM);
|
|
|
|
if (sval[0] == '=')
|
|
|
|
sval++;
|
|
|
|
conf_set_str(conf, strsetting, sval);
|
|
|
|
}
|
2020-06-16 16:43:36 +00:00
|
|
|
|
|
|
|
sfree(sval);
|
2017-12-17 18:44:27 +00:00
|
|
|
#else
|
2017-12-10 17:16:50 +00:00
|
|
|
int index = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (index >= 0) {
|
|
|
|
int val = dlg_listbox_getid(ctrl, dlg, index);
|
|
|
|
conf_set_int(conf, setting, val);
|
|
|
|
}
|
2017-12-17 18:44:27 +00:00
|
|
|
#endif
|
2017-12-10 17:16:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-17 18:44:27 +00:00
|
|
|
static void clipboard_control(struct controlset *s, const char *label,
|
2022-07-05 17:11:54 +00:00
|
|
|
char shortcut, int percentage, HelpCtx helpctx,
|
2017-12-17 18:44:27 +00:00
|
|
|
int setting, int strsetting)
|
|
|
|
{
|
|
|
|
#ifdef NAMED_CLIPBOARDS
|
|
|
|
ctrl_combobox(s, label, shortcut, percentage, helpctx,
|
|
|
|
clipboard_selector_handler, I(setting), I(strsetting));
|
|
|
|
#else
|
|
|
|
/* strsetting isn't needed in this case */
|
|
|
|
ctrl_droplist(s, label, shortcut, percentage, helpctx,
|
|
|
|
clipboard_selector_handler, I(setting));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void serial_parity_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2020-03-10 21:18:08 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
const char *name;
|
|
|
|
int val;
|
|
|
|
} parities[] = {
|
|
|
|
{"None", SER_PAR_NONE},
|
|
|
|
{"Odd", SER_PAR_ODD},
|
|
|
|
{"Even", SER_PAR_EVEN},
|
|
|
|
{"Mark", SER_PAR_MARK},
|
|
|
|
{"Space", SER_PAR_SPACE},
|
|
|
|
};
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int mask = ctrl->context.i;
|
2020-03-10 21:18:08 +00:00
|
|
|
int i, j;
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
/* Fetching this once at the start of the function ensures we
|
|
|
|
* remember what the right value is supposed to be when
|
|
|
|
* operations below cause reentrant calls to this function. */
|
|
|
|
int oldparity = conf_get_int(conf, CONF_serparity);
|
|
|
|
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < lenof(parities); i++) {
|
|
|
|
if (mask & (1 << parities[i].val))
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, parities[i].name,
|
|
|
|
parities[i].val);
|
|
|
|
}
|
|
|
|
for (i = j = 0; i < lenof(parities); i++) {
|
|
|
|
if (mask & (1 << parities[i].val)) {
|
|
|
|
if (oldparity == parities[i].val) {
|
|
|
|
dlg_listbox_select(ctrl, dlg, j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == lenof(parities)) { /* an unsupported setting was chosen */
|
|
|
|
dlg_listbox_select(ctrl, dlg, 0);
|
|
|
|
oldparity = SER_PAR_NONE;
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
conf_set_int(conf, CONF_serparity, oldparity); /* restore */
|
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0)
|
|
|
|
i = SER_PAR_NONE;
|
|
|
|
else
|
|
|
|
i = dlg_listbox_getid(ctrl, dlg, i);
|
|
|
|
conf_set_int(conf, CONF_serparity, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void serial_flow_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2020-03-10 21:18:08 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
const char *name;
|
|
|
|
int val;
|
|
|
|
} flows[] = {
|
|
|
|
{"None", SER_FLOW_NONE},
|
|
|
|
{"XON/XOFF", SER_FLOW_XONXOFF},
|
|
|
|
{"RTS/CTS", SER_FLOW_RTSCTS},
|
|
|
|
{"DSR/DTR", SER_FLOW_DSRDTR},
|
|
|
|
};
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
int mask = ctrl->context.i;
|
2020-03-10 21:18:08 +00:00
|
|
|
int i, j;
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
|
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
/* Fetching this once at the start of the function ensures we
|
|
|
|
* remember what the right value is supposed to be when
|
|
|
|
* operations below cause reentrant calls to this function. */
|
|
|
|
int oldflow = conf_get_int(conf, CONF_serflow);
|
|
|
|
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
for (i = 0; i < lenof(flows); i++) {
|
|
|
|
if (mask & (1 << flows[i].val))
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, flows[i].name, flows[i].val);
|
|
|
|
}
|
|
|
|
for (i = j = 0; i < lenof(flows); i++) {
|
|
|
|
if (mask & (1 << flows[i].val)) {
|
|
|
|
if (oldflow == flows[i].val) {
|
|
|
|
dlg_listbox_select(ctrl, dlg, j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i == lenof(flows)) { /* an unsupported setting was chosen */
|
|
|
|
dlg_listbox_select(ctrl, dlg, 0);
|
|
|
|
oldflow = SER_FLOW_NONE;
|
|
|
|
}
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
conf_set_int(conf, CONF_serflow, oldflow);/* restore */
|
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0)
|
|
|
|
i = SER_FLOW_NONE;
|
|
|
|
else
|
|
|
|
i = dlg_listbox_getid(ctrl, dlg, i);
|
|
|
|
conf_set_int(conf, CONF_serflow, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
void proxy_type_handler(dlgcontrol *ctrl, dlgparam *dlg,
|
2022-04-22 13:55:44 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
Conf *conf = (Conf *)data;
|
|
|
|
if (event == EVENT_REFRESH) {
|
|
|
|
/*
|
|
|
|
* We must fetch the previously configured value from the Conf
|
|
|
|
* before we start modifying the drop-down list, otherwise the
|
|
|
|
* spurious SELCHANGE we trigger in the process will overwrite
|
|
|
|
* the value we wanted to keep.
|
|
|
|
*/
|
|
|
|
int proxy_type = conf_get_int(conf, CONF_proxy_type);
|
|
|
|
|
|
|
|
dlg_update_start(ctrl, dlg);
|
|
|
|
dlg_listbox_clear(ctrl, dlg);
|
|
|
|
|
|
|
|
int index_to_select = 0, current_index = 0;
|
|
|
|
|
|
|
|
#define ADD(id, title) do { \
|
|
|
|
dlg_listbox_addwithid(ctrl, dlg, title, id); \
|
|
|
|
if (id == proxy_type) \
|
|
|
|
index_to_select = current_index; \
|
|
|
|
current_index++; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
ADD(PROXY_NONE, "None");
|
|
|
|
ADD(PROXY_SOCKS5, "SOCKS 5");
|
|
|
|
ADD(PROXY_SOCKS4, "SOCKS 4");
|
|
|
|
ADD(PROXY_HTTP, "HTTP CONNECT");
|
|
|
|
if (ssh_proxy_supported) {
|
2022-04-22 13:12:15 +00:00
|
|
|
ADD(PROXY_SSH_TCPIP, "SSH to proxy and use port forwarding");
|
|
|
|
ADD(PROXY_SSH_EXEC, "SSH to proxy and execute a command");
|
|
|
|
ADD(PROXY_SSH_SUBSYSTEM, "SSH to proxy and invoke a subsystem");
|
2022-04-22 13:55:44 +00:00
|
|
|
}
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
if (ctrl->context.i & PROXY_UI_FLAG_LOCAL) {
|
2022-04-22 13:55:44 +00:00
|
|
|
ADD(PROXY_CMD, "Local (run a subprogram to connect)");
|
|
|
|
}
|
|
|
|
ADD(PROXY_TELNET, "'Telnet' (send an ad-hoc command)");
|
|
|
|
|
|
|
|
#undef ADD
|
|
|
|
|
|
|
|
dlg_listbox_select(ctrl, dlg, index_to_select);
|
|
|
|
|
|
|
|
dlg_update_done(ctrl, dlg);
|
|
|
|
} else if (event == EVENT_SELCHANGE) {
|
|
|
|
int i = dlg_listbox_index(ctrl, dlg);
|
|
|
|
if (i < 0)
|
|
|
|
i = AUTO;
|
|
|
|
else
|
|
|
|
i = dlg_listbox_getid(ctrl, dlg, i);
|
|
|
|
conf_set_int(conf, CONF_proxy_type, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 08:48:38 +00:00
|
|
|
static void host_ca_button_handler(dlgcontrol *ctrl, dlgparam *dp,
|
Initial support for host certificates.
Now we offer the OpenSSH certificate key types in our KEXINIT host key
algorithm list, so that if the server has a certificate, they can send
it to us.
There's a new storage.h abstraction for representing a list of trusted
host CAs, and which ones are trusted to certify hosts for what
domains. This is stored outside the normal saved session data, because
the whole point of host certificates is to avoid per-host faffing.
Configuring this set of trusted CAs is done via a new GUI dialog box,
separate from the main PuTTY config box (because it modifies a single
set of settings across all saved sessions), which you can launch by
clicking a button in the 'Host keys' pane. The GUI is pretty crude for
the moment, and very much at a 'just about usable' stage right now. It
will want some polishing.
If we have no CA configured that matches the hostname, we don't offer
to receive certified host keys in the first place. So for existing
users who haven't set any of this up yet, nothing will immediately
change.
Currently, if we do offer to receive certified host keys and the
server presents one signed by a CA we don't trust, PuTTY will bomb out
unconditionally with an error, instead of offering a confirmation box.
That's an unfinished part which I plan to fix before this goes into a
release.
2022-04-22 11:07:24 +00:00
|
|
|
void *data, int event)
|
|
|
|
{
|
|
|
|
if (event == EVENT_ACTION)
|
|
|
|
show_ca_config_box(dp);
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void setup_config_box(struct controlbox *b, bool midsession,
|
2019-09-08 19:29:00 +00:00
|
|
|
int protocol, int protcfginfo)
|
2003-03-05 22:07:40 +00:00
|
|
|
{
|
2020-02-14 12:49:56 +00:00
|
|
|
const struct BackendVtable *backvt;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct controlset *s;
|
|
|
|
struct sessionsaver_data *ssd;
|
|
|
|
struct charclass_data *ccd;
|
|
|
|
struct colour_data *cd;
|
2005-04-21 13:57:08 +00:00
|
|
|
struct ttymodes_data *td;
|
2003-03-05 22:07:40 +00:00
|
|
|
struct environ_data *ed;
|
|
|
|
struct portfwd_data *pfd;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
struct manual_hostkey_data *mh;
|
2022-05-01 08:48:38 +00:00
|
|
|
dlgcontrol *c;
|
2020-02-14 12:49:56 +00:00
|
|
|
bool resize_forbidden = false;
|
2003-04-06 14:11:33 +00:00
|
|
|
char *str;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
ssd = (struct sessionsaver_data *)
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_alloc_with_free(b, sizeof(struct sessionsaver_data),
|
2013-07-14 10:46:34 +00:00
|
|
|
sessionsaver_data_free);
|
2003-04-10 18:00:50 +00:00
|
|
|
memset(ssd, 0, sizeof(*ssd));
|
2013-07-14 10:46:34 +00:00
|
|
|
ssd->savedsession = dupstr("");
|
2004-12-30 10:58:28 +00:00
|
|
|
ssd->midsession = midsession;
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The standard panel that appears at the bottom of all panels:
|
|
|
|
* Open, Cancel, Apply etc.
|
|
|
|
*/
|
|
|
|
s = ctrl_getset(b, "", "", "");
|
|
|
|
ctrl_columns(s, 5, 20, 20, 20, 20, 20);
|
|
|
|
ssd->okbutton = ctrl_pushbutton(s,
|
2019-09-08 19:29:00 +00:00
|
|
|
(midsession ? "Apply" : "Open"),
|
|
|
|
(char)(midsession ? 'a' : 'o'),
|
|
|
|
HELPCTX(no_help),
|
|
|
|
sessionsaver_handler, P(ssd));
|
2018-10-29 19:50:29 +00:00
|
|
|
ssd->okbutton->button.isdefault = true;
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->okbutton->column = 3;
|
2003-03-05 22:07:40 +00:00
|
|
|
ssd->cancelbutton = ctrl_pushbutton(s, "Cancel", 'c', HELPCTX(no_help),
|
2019-09-08 19:29:00 +00:00
|
|
|
sessionsaver_handler, P(ssd));
|
2018-10-29 19:50:29 +00:00
|
|
|
ssd->cancelbutton->button.iscancel = true;
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->cancelbutton->column = 4;
|
2003-03-05 22:07:40 +00:00
|
|
|
/* We carefully don't close the 5-column part, so that platform-
|
|
|
|
* specific add-ons can put extra buttons alongside Open and Cancel. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Session panel.
|
|
|
|
*/
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("Basic options for your %s session", appname);
|
|
|
|
ctrl_settitle(b, "Session", str);
|
|
|
|
sfree(str);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
if (!midsession) {
|
2019-09-08 19:29:00 +00:00
|
|
|
struct hostport *hp = (struct hostport *)
|
|
|
|
ctrl_alloc(b, sizeof(struct hostport));
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
memset(hp, 0, sizeof(*hp));
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Session", "hostport",
|
|
|
|
"Specify the destination you want to connect to");
|
|
|
|
ctrl_columns(s, 2, 75, 25);
|
|
|
|
c = ctrl_editbox(s, HOST_BOX_TITLE, 'n', 100,
|
|
|
|
HELPCTX(session_hostname),
|
|
|
|
config_host_handler, I(0), I(0));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
hp->host = c;
|
|
|
|
c = ctrl_editbox(s, PORT_BOX_TITLE, 'p', 100,
|
|
|
|
HELPCTX(session_hostname),
|
|
|
|
config_port_handler, I(0), I(0));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
hp->port = c;
|
2006-08-28 10:35:12 +00:00
|
|
|
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
c = ctrl_text(s, "Connection type:", HELPCTX(session_hostname));
|
|
|
|
ctrl_columns(s, 2, 62, 38);
|
|
|
|
c = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(session_hostname),
|
2022-06-01 10:14:21 +00:00
|
|
|
config_protocols_handler, P(hp));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
hp->protradio = c;
|
2020-02-22 14:00:23 +00:00
|
|
|
c->radio.buttons = sresize(c->radio.buttons, PROTOCOL_LIMIT, char *);
|
|
|
|
c->radio.shortcuts = sresize(c->radio.shortcuts, PROTOCOL_LIMIT, char);
|
|
|
|
c->radio.buttondata = sresize(c->radio.buttondata, PROTOCOL_LIMIT,
|
|
|
|
intorptr);
|
|
|
|
assert(c->radio.nbuttons == 0);
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
/* UI design assumes there exists at least one 'real' radio button */
|
|
|
|
assert(n_ui_backends > 0 && n_ui_backends < PROTOCOL_LIMIT);
|
|
|
|
for (size_t i = 0; i < n_ui_backends; i++) {
|
|
|
|
assert(backends[i]);
|
|
|
|
c->radio.buttons[c->radio.nbuttons] =
|
2021-10-23 17:26:34 +00:00
|
|
|
dupstr(backends[i]->displayname_tc);
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
c->radio.shortcuts[c->radio.nbuttons] =
|
|
|
|
(backends[i]->protocol == PROT_SSH ? 's' :
|
|
|
|
backends[i]->protocol == PROT_SERIAL ? 'r' :
|
|
|
|
backends[i]->protocol == PROT_RAW ? 'w' : /* FIXME unused */
|
|
|
|
NO_SHORTCUT);
|
|
|
|
c->radio.buttondata[c->radio.nbuttons] =
|
|
|
|
I(backends[i]->protocol);
|
|
|
|
c->radio.nbuttons++;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
/* UI design assumes there exists at least one droplist entry */
|
|
|
|
assert(backends[c->radio.nbuttons]);
|
|
|
|
|
|
|
|
c->radio.buttons[c->radio.nbuttons] = dupstr("Other:");
|
|
|
|
c->radio.shortcuts[c->radio.nbuttons] = 't';
|
|
|
|
c->radio.buttondata[c->radio.nbuttons] = I(-1);
|
|
|
|
c->radio.nbuttons++;
|
|
|
|
|
|
|
|
c = ctrl_droplist(s, NULL, NO_SHORTCUT, 100,
|
|
|
|
HELPCTX(session_hostname),
|
|
|
|
config_protocols_handler, P(hp));
|
|
|
|
hp->protlist = c;
|
|
|
|
/* droplist is populated in config_protocols_handler */
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 1;
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
|
|
|
|
/* Vertically centre the two protocol controls w.r.t. each other */
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
hp->protlist->align_next_to = hp->protradio;
|
New GUI for protocol selection.
This replaces the pure radio-button setup that we've always had on the
Session config panel.
Since the last release, that set of radio buttons has been getting out
of hand. We've added two new protocols (SUPDUP, and the 'bare
ssh-connection' aka psusan protocol), neither of which is mainstream
enough to be a sensible thing to wave at all users on the front page
of the config GUI, so that they perhaps start wondering if that's the
protocol they want to use, or get sidetracked by going and looking it
up.
The replacement UI still has radio buttons, but only for the most
common protocols, which will typically be SSH and serial. Everything
else is relegated to a drop-down list sitting next to a third radio
button labelled "Other".
In every be_* module providing a backends[] list, there's also a
variable n_ui_backends which indicates how many of the backends ought
to appear as first-level radio buttons.
(Credit where due: this patch is a joint effort between Jacob and me,
and is one of those rare cases where it would be nice to be able to
put both our names into the Author field of the commit. Failing that,
I can at least mention it here.)
2021-04-10 08:51:29 +00:00
|
|
|
|
|
|
|
ctrl_columns(s, 1, 100);
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
|
2004-12-28 16:46:30 +00:00
|
|
|
/*
|
|
|
|
* The Load/Save panel is available even in mid-session.
|
|
|
|
*/
|
|
|
|
s = ctrl_getset(b, "Session", "savedsessions",
|
2019-09-08 19:29:00 +00:00
|
|
|
midsession ? "Save the current session settings" :
|
|
|
|
"Load, save or delete a stored session");
|
2004-12-28 16:46:30 +00:00
|
|
|
ctrl_columns(s, 2, 75, 25);
|
2018-10-29 19:50:29 +00:00
|
|
|
get_sesslist(&ssd->sesslist, true);
|
2004-12-28 16:46:30 +00:00
|
|
|
ssd->editbox = ctrl_editbox(s, "Saved Sessions", 'e', 100,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(session_saved),
|
|
|
|
sessionsaver_handler, P(ssd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->editbox->column = 0;
|
2004-12-28 16:46:30 +00:00
|
|
|
/* Reset columns so that the buttons are alongside the list, rather
|
|
|
|
* than alongside that edit box. */
|
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
ctrl_columns(s, 2, 75, 25);
|
|
|
|
ssd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(session_saved),
|
|
|
|
sessionsaver_handler, P(ssd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->listbox->column = 0;
|
2004-12-28 16:46:30 +00:00
|
|
|
ssd->listbox->listbox.height = 7;
|
2004-12-30 10:58:28 +00:00
|
|
|
if (!midsession) {
|
2019-09-08 19:29:00 +00:00
|
|
|
ssd->loadbutton = ctrl_pushbutton(s, "Load", 'l',
|
|
|
|
HELPCTX(session_saved),
|
|
|
|
sessionsaver_handler, P(ssd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->loadbutton->column = 1;
|
2004-12-30 10:58:28 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* We can't offer the Load button mid-session, as it would allow the
|
|
|
|
* user to load and subsequently save settings they can't see. (And
|
|
|
|
* also change otherwise immutable settings underfoot; that probably
|
|
|
|
* shouldn't be a problem, but.) */
|
|
|
|
ssd->loadbutton = NULL;
|
2004-12-30 10:58:28 +00:00
|
|
|
}
|
|
|
|
/* "Save" button is permitted mid-session. */
|
2004-12-28 16:46:30 +00:00
|
|
|
ssd->savebutton = ctrl_pushbutton(s, "Save", 'v',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(session_saved),
|
|
|
|
sessionsaver_handler, P(ssd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->savebutton->column = 1;
|
2004-12-30 10:58:28 +00:00
|
|
|
if (!midsession) {
|
2019-09-08 19:29:00 +00:00
|
|
|
ssd->delbutton = ctrl_pushbutton(s, "Delete", 'd',
|
|
|
|
HELPCTX(session_saved),
|
|
|
|
sessionsaver_handler, P(ssd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ssd->delbutton->column = 1;
|
2004-12-30 10:58:28 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Disable the Delete button mid-session too, for UI consistency. */
|
|
|
|
ssd->delbutton = NULL;
|
2004-12-30 10:58:28 +00:00
|
|
|
}
|
2004-12-28 16:46:30 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
s = ctrl_getset(b, "Session", "otheropts", NULL);
|
2013-07-14 10:46:42 +00:00
|
|
|
ctrl_radiobuttons(s, "Close window on exit:", 'x', 4,
|
|
|
|
HELPCTX(session_coe),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_close_on_exit),
|
|
|
|
"Always", I(FORCE_ON),
|
|
|
|
"Never", I(FORCE_OFF),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Only on clean exit", I(AUTO));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Session/Logging panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Session/Logging", "Options controlling session logging");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Session/Logging", "main", NULL);
|
2003-04-26 14:35:34 +00:00
|
|
|
/*
|
|
|
|
* The logging buttons change depending on whether SSH packet
|
|
|
|
* logging can sensibly be available.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
const char *sshlogname, *sshrawlogname;
|
|
|
|
if ((midsession && protocol == PROT_SSH) ||
|
2018-09-11 15:23:38 +00:00
|
|
|
(!midsession && backend_vt_from_proto(PROT_SSH))) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sshlogname = "SSH packets";
|
|
|
|
sshrawlogname = "SSH packets and raw data";
|
New logging mode, which records the exact bytes sent over the wire
in an SSH connection _in addition_ to the decrypted packets. This
will hopefully come in useful for debugging wire data corruption
issues: you can strace the server, enable this mode in the client,
and compare the sent and received data.
I'd _like_ to have this mode also log Diffie-Hellman private
exponents, session IDs, encryption and MAC keys, so that the
resulting log file could be used to independently verify the
correctness of all cryptographic operations performed by PuTTY.
However, I haven't been able to convince myself that the security
implications are acceptable. (It doesn't matter that this
information would permit an attacker to decrypt the session, because
the _already_ decrypted session is stored alongside it in the log
file. And I'm not planning, under any circumstances, to log users'
private keys. But gaining access to the log file while the session
was still running would permit an attacker to _hijack_ the session,
and that's the iffy bit.)
[originally from svn r6835]
2006-08-29 19:07:11 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
sshlogname = NULL; /* this will disable both buttons */
|
|
|
|
sshrawlogname = NULL; /* this will just placate optimisers */
|
New logging mode, which records the exact bytes sent over the wire
in an SSH connection _in addition_ to the decrypted packets. This
will hopefully come in useful for debugging wire data corruption
issues: you can strace the server, enable this mode in the client,
and compare the sent and received data.
I'd _like_ to have this mode also log Diffie-Hellman private
exponents, session IDs, encryption and MAC keys, so that the
resulting log file could be used to independently verify the
correctness of all cryptographic operations performed by PuTTY.
However, I haven't been able to convince myself that the security
implications are acceptable. (It doesn't matter that this
information would permit an attacker to decrypt the session, because
the _already_ decrypted session is stored alongside it in the log
file. And I'm not planning, under any circumstances, to log users'
private keys. But gaining access to the log file while the session
was still running would permit an attacker to _hijack_ the session,
and that's the iffy bit.)
[originally from svn r6835]
2006-08-29 19:07:11 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_radiobuttons(s, "Session logging:", NO_SHORTCUT, 2,
|
|
|
|
HELPCTX(logging_main),
|
|
|
|
loggingbuttons_handler,
|
|
|
|
I(CONF_logtype),
|
|
|
|
"None", 't', I(LGTYP_NONE),
|
|
|
|
"Printable output", 'p', I(LGTYP_ASCII),
|
|
|
|
"All session output", 'l', I(LGTYP_DEBUG),
|
|
|
|
sshlogname, 's', I(LGTYP_PACKETS),
|
2022-06-01 10:14:21 +00:00
|
|
|
sshrawlogname, 'r', I(LGTYP_SSHRAW));
|
2003-04-26 14:35:34 +00:00
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_filesel(s, "Log file name:", 'f',
|
2019-09-08 19:29:00 +00:00
|
|
|
NULL, true, "Select session log file name",
|
|
|
|
HELPCTX(logging_filename),
|
|
|
|
conf_filesel_handler, I(CONF_logfilename));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_text(s, "(Log file name can contain &Y, &M, &D for date,"
|
2019-09-08 19:29:00 +00:00
|
|
|
" &T for time, &H for host name, and &P for port number)",
|
|
|
|
HELPCTX(logging_filename));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "What to do if the log file already exists:", 'e', 1,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(logging_exists),
|
|
|
|
conf_radiobutton_handler, I(CONF_logxfovr),
|
|
|
|
"Always overwrite it", I(LGXF_OVR),
|
|
|
|
"Always append to the end of it", I(LGXF_APN),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Ask the user every time", I(LGXF_ASK));
|
2004-12-16 15:22:36 +00:00
|
|
|
ctrl_checkbox(s, "Flush log file frequently", 'u',
|
2022-08-03 19:48:46 +00:00
|
|
|
HELPCTX(logging_flush),
|
|
|
|
conf_checkbox_handler, I(CONF_logflush));
|
2018-09-26 22:38:56 +00:00
|
|
|
ctrl_checkbox(s, "Include header", 'i',
|
2022-08-03 19:48:46 +00:00
|
|
|
HELPCTX(logging_header),
|
|
|
|
conf_checkbox_handler, I(CONF_logheader));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2004-10-02 00:33:27 +00:00
|
|
|
if ((midsession && protocol == PROT_SSH) ||
|
2018-09-11 15:23:38 +00:00
|
|
|
(!midsession && backend_vt_from_proto(PROT_SSH))) {
|
2019-09-08 19:29:00 +00:00
|
|
|
s = ctrl_getset(b, "Session/Logging", "ssh",
|
|
|
|
"Options specific to SSH packet logging");
|
|
|
|
ctrl_checkbox(s, "Omit known password fields", 'k',
|
|
|
|
HELPCTX(logging_ssh_omit_password),
|
|
|
|
conf_checkbox_handler, I(CONF_logomitpass));
|
|
|
|
ctrl_checkbox(s, "Omit session data", 'd',
|
|
|
|
HELPCTX(logging_ssh_omit_data),
|
|
|
|
conf_checkbox_handler, I(CONF_logomitdata));
|
2004-10-02 00:33:27 +00:00
|
|
|
}
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
/*
|
|
|
|
* The Terminal panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Terminal", "Options controlling the terminal emulation");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal", "general", "Set various terminal options");
|
|
|
|
ctrl_checkbox(s, "Auto wrap mode initially on", 'w',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_autowrap),
|
|
|
|
conf_checkbox_handler, I(CONF_wrap_mode));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "DEC Origin Mode initially on", 'd',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_decom),
|
|
|
|
conf_checkbox_handler, I(CONF_dec_om));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Implicit CR in every LF", 'r',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_lfhascr),
|
|
|
|
conf_checkbox_handler, I(CONF_lfhascr));
|
2007-08-04 19:16:46 +00:00
|
|
|
ctrl_checkbox(s, "Implicit LF in every CR", 'f',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_crhaslf),
|
|
|
|
conf_checkbox_handler, I(CONF_crhaslf));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Use background colour to erase screen", 'e',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_bce),
|
|
|
|
conf_checkbox_handler, I(CONF_bce));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Enable blinking text", 'n',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_blink),
|
|
|
|
conf_checkbox_handler, I(CONF_blinktext));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "Answerback to ^E:", 's', 100,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_answerback),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_answerback), ED_STR);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal", "ldisc", "Line discipline options");
|
|
|
|
ctrl_radiobuttons(s, "Local echo:", 'l', 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_localecho),
|
|
|
|
conf_radiobutton_handler,I(CONF_localecho),
|
|
|
|
"Auto", I(AUTO),
|
|
|
|
"Force on", I(FORCE_ON),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Force off", I(FORCE_OFF));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "Local line editing:", 't', 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_localedit),
|
|
|
|
conf_radiobutton_handler,I(CONF_localedit),
|
|
|
|
"Auto", I(AUTO),
|
|
|
|
"Force on", I(FORCE_ON),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Force off", I(FORCE_OFF));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
|
|
|
|
ctrl_combobox(s, "Printer to send ANSI printer output to:", 'p', 100,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(terminal_printing),
|
|
|
|
printerbox_handler, P(NULL), P(NULL));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Terminal/Keyboard panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Terminal/Keyboard",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Options controlling the effects of keys");
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal/Keyboard", "mappings",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Change the sequences sent by:");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "The Backspace key", 'b', 2,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(keyboard_backspace),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_bksp_is_delete),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Control-H", I(0), "Control-? (127)", I(1));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "The Home and End keys", 'e', 2,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(keyboard_homeend),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_rxvt_homeend),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Standard", I(false), "rxvt", I(true));
|
2021-10-23 10:04:53 +00:00
|
|
|
ctrl_radiobuttons(s, "The Function keys and keypad", 'f', 4,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(keyboard_funkeys),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_funky_type),
|
2021-10-23 10:04:53 +00:00
|
|
|
"ESC[n~", I(FUNKY_TILDE),
|
|
|
|
"Linux", I(FUNKY_LINUX),
|
|
|
|
"Xterm R6", I(FUNKY_XTERM),
|
|
|
|
"VT400", I(FUNKY_VT400),
|
|
|
|
"VT100+", I(FUNKY_VT100P),
|
|
|
|
"SCO", I(FUNKY_SCO),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Xterm 216+", I(FUNKY_XTERM_216));
|
New config option for shifted arrow key handling.
This commit introduces a new config option for how to handle shifted
arrow keys.
In the default mode (SHARROW_APPLICATION), we do what we've always
done: Ctrl flips the arrow keys between sending their most usual
escape sequences (ESC [ A ... ESC [ D) and sending the 'application
cursor keys' sequences (ESC O A ... ESC O D). Whichever of those modes
is currently configured, Ctrl+arrow sends the other one.
In the new mode (SHARROW_BITMAP), application cursor key mode is
unaffected by any shift keys, but the default sequences acquire two
numeric arguments. The first argument is 1 (reflecting the fact that a
shifted arrow key still notionally moves just 1 character cell); the
second is the bitmap (1 for Shift) + (2 for Alt) + (4 for Ctrl),
offset by 1. (Except that if _none_ of those modifiers is pressed,
both numeric arguments are simply omitted.)
The new bitmap mode is what current xterm generates, and also what
Windows ConPTY seems to expect. If you start an ordinary Command
Prompt and launch into WSL, those are the sequences it will generate
for shifted arrow keys; conversely, if you run a Command Prompt within
a ConPTY, then these sequences for Ctrl+arrow will have the effect you
expect in cmd.exe command-line editing (going backward or forward a
word). For that reason, I enable this mode unconditionally when
launching Windows pterm.
2021-10-18 19:00:25 +00:00
|
|
|
ctrl_radiobuttons(s, "Shift/Ctrl/Alt with the arrow keys", 'w', 2,
|
|
|
|
HELPCTX(keyboard_sharrow),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_sharrow_type),
|
|
|
|
"Ctrl toggles app mode", I(SHARROW_APPLICATION),
|
2022-06-01 10:14:21 +00:00
|
|
|
"xterm-style bitmap", I(SHARROW_BITMAP));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal/Keyboard", "appkeypad",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Application keypad settings:");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "Initial state of cursor keys:", 'r', 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(keyboard_appcursor),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_app_cursor),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Normal", I(0), "Application", I(1));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "Initial state of numeric keypad:", 'n', 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(keyboard_appkeypad),
|
|
|
|
numeric_keypad_handler, P(NULL),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Normal", I(0), "Application", I(1), "NetHack", I(2));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Terminal/Bell panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Terminal/Bell",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Options controlling the terminal bell");
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
|
|
|
|
ctrl_radiobuttons(s, "Action to happen when a bell occurs:", 'b', 1,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_style),
|
|
|
|
conf_radiobutton_handler, I(CONF_beep),
|
|
|
|
"None (bell disabled)", I(BELL_DISABLED),
|
|
|
|
"Make default system alert sound", I(BELL_DEFAULT),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Visual bell (flash window)", I(BELL_VISUAL));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal/Bell", "overload",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Control the bell overload behaviour");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Bell is temporarily disabled when over-used", 'd',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_overload),
|
|
|
|
conf_checkbox_handler, I(CONF_bellovl));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "Over-use means this many bells...", 'm', 20,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_overload),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_bellovl_n), ED_INT);
|
|
|
|
|
|
|
|
static const struct conf_editbox_handler_type conf_editbox_tickspersec = {
|
|
|
|
.type = EDIT_FIXEDPOINT, .denominator = TICKSPERSEC};
|
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "... in this many seconds", 't', 20,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_overload),
|
|
|
|
conf_editbox_handler, I(CONF_bellovl_t),
|
2022-08-24 06:56:45 +00:00
|
|
|
CP(&conf_editbox_tickspersec));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_text(s, "The bell is re-enabled after a few seconds of silence.",
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_overload));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "Seconds of silence required", 's', 20,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(bell_overload),
|
|
|
|
conf_editbox_handler, I(CONF_bellovl_s),
|
2022-08-24 06:56:45 +00:00
|
|
|
CP(&conf_editbox_tickspersec));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Terminal/Features panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Terminal/Features",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Enabling and disabling advanced terminal features");
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Terminal/Features", "main", NULL);
|
|
|
|
ctrl_checkbox(s, "Disable application cursor keys mode", 'u',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_application),
|
|
|
|
conf_checkbox_handler, I(CONF_no_applic_c));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable application keypad mode", 'k',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_application),
|
|
|
|
conf_checkbox_handler, I(CONF_no_applic_k));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable xterm-style mouse reporting", 'x',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_mouse),
|
|
|
|
conf_checkbox_handler, I(CONF_no_mouse_rep));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable remote-controlled terminal resizing", 's',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_resize),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_no_remote_resize));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable switching to alternate terminal screen", 'w',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_altscreen),
|
|
|
|
conf_checkbox_handler, I(CONF_no_alt_screen));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable remote-controlled window title changing", 't',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_retitle),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_no_remote_wintitle));
|
2006-12-31 15:33:33 +00:00
|
|
|
ctrl_radiobuttons(s, "Response to remote title query (SECURITY):", 'q', 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_qtitle),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_remote_qtitle_action),
|
|
|
|
"None", I(TITLE_NONE),
|
|
|
|
"Empty string", I(TITLE_EMPTY),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Window title", I(TITLE_REAL));
|
2019-04-19 14:30:35 +00:00
|
|
|
ctrl_checkbox(s, "Disable remote-controlled clearing of scrollback", 'e',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_clearscroll),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_no_remote_clearscroll));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable destructive backspace on server sending ^?",'b',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(features_dbackspace),
|
|
|
|
conf_checkbox_handler, I(CONF_no_dbackspace));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Disable remote-controlled character set configuration",
|
2019-09-08 19:29:00 +00:00
|
|
|
'r', HELPCTX(features_charset), conf_checkbox_handler,
|
|
|
|
I(CONF_no_remote_charset));
|
2004-05-22 10:36:50 +00:00
|
|
|
ctrl_checkbox(s, "Disable Arabic text shaping",
|
2019-09-08 19:29:00 +00:00
|
|
|
'l', HELPCTX(features_arabicshaping), conf_checkbox_handler,
|
|
|
|
I(CONF_no_arabicshaping));
|
2004-05-22 10:36:50 +00:00
|
|
|
ctrl_checkbox(s, "Disable bidirectional text display",
|
2019-09-08 19:29:00 +00:00
|
|
|
'd', HELPCTX(features_bidi), conf_checkbox_handler,
|
|
|
|
I(CONF_no_bidi));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window panel.
|
|
|
|
*/
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("Options controlling %s's window", appname);
|
|
|
|
ctrl_settitle(b, "Window", str);
|
|
|
|
sfree(str);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2020-02-14 12:49:56 +00:00
|
|
|
backvt = backend_vt_from_proto(protocol);
|
|
|
|
if (backvt)
|
|
|
|
resize_forbidden = (backvt->flags & BACKEND_RESIZE_FORBIDDEN);
|
|
|
|
|
|
|
|
if (!resize_forbidden || !midsession) {
|
|
|
|
s = ctrl_getset(b, "Window", "size", "Set the size of the window");
|
|
|
|
ctrl_columns(s, 2, 50, 50);
|
|
|
|
c = ctrl_editbox(s, "Columns", 'm', 100,
|
|
|
|
HELPCTX(window_size),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_width), ED_INT);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
2020-02-14 12:49:56 +00:00
|
|
|
c = ctrl_editbox(s, "Rows", 'r', 100,
|
|
|
|
HELPCTX(window_size),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_height),ED_INT);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 1;
|
2020-02-14 12:49:56 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window", "scrollback",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Control the scrollback in the window");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "Lines of scrollback", 's', 50,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(window_scrollback),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_savelines), ED_INT);
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Display scrollbar", 'd',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(window_scrollback),
|
|
|
|
conf_checkbox_handler, I(CONF_scrollbar));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Reset scrollback on keypress", 'k',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(window_scrollback),
|
|
|
|
conf_checkbox_handler, I(CONF_scroll_on_key));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Reset scrollback on display activity", 'p',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(window_scrollback),
|
|
|
|
conf_checkbox_handler, I(CONF_scroll_on_disp));
|
2003-03-06 12:51:12 +00:00
|
|
|
ctrl_checkbox(s, "Push erased text into scrollback", 'e',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(window_erased),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_erase_to_scrollback));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window/Appearance panel.
|
|
|
|
*/
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("Configure the appearance of %s's window", appname);
|
|
|
|
ctrl_settitle(b, "Window/Appearance", str);
|
|
|
|
sfree(str);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Appearance", "cursor",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Adjust the use of the cursor");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s, "Cursor appearance:", NO_SHORTCUT, 3,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_cursor),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_cursor_type),
|
2023-05-29 14:51:17 +00:00
|
|
|
"Block", 'l', I(CURSOR_BLOCK),
|
|
|
|
"Underline", 'u', I(CURSOR_UNDERLINE),
|
|
|
|
"Vertical line", 'v', I(CURSOR_VERTICAL_LINE));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Cursor blinks", 'b',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_cursor),
|
|
|
|
conf_checkbox_handler, I(CONF_blink_cur));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Appearance", "font",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Font settings");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_fontsel(s, "Font used in the terminal window", 'n',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_font),
|
|
|
|
conf_fontsel_handler, I(CONF_font));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Appearance", "mouse",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Adjust the use of the mouse pointer");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Hide mouse pointer when typing in window", 'p',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_hidemouse),
|
|
|
|
conf_checkbox_handler, I(CONF_hide_mouseptr));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Appearance", "border",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Adjust the window border");
|
2005-04-07 01:42:36 +00:00
|
|
|
ctrl_editbox(s, "Gap between text and window edge:", 'e', 20,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_border),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_window_border), ED_INT);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window/Behaviour panel.
|
|
|
|
*/
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("Configure the behaviour of %s's window", appname);
|
|
|
|
ctrl_settitle(b, "Window/Behaviour", str);
|
|
|
|
sfree(str);
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Behaviour", "title",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Adjust the behaviour of the window title");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_editbox(s, "Window title:", 't', 100,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_title),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_wintitle), ED_STR);
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Separate window and icon titles", 'i',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(appearance_title),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CHECKBOX_INVERT | CONF_win_name_always));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
|
|
|
|
ctrl_checkbox(s, "Warn before closing window", 'w',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(behaviour_closewarn),
|
|
|
|
conf_checkbox_handler, I(CONF_warn_on_close));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window/Translation panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Window/Translation",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Options controlling character set translation");
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Translation", "trans",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Character set translation");
|
2008-10-13 22:34:57 +00:00
|
|
|
ctrl_combobox(s, "Remote character set:",
|
2019-09-08 19:29:00 +00:00
|
|
|
'r', 100, HELPCTX(translation_codepage),
|
|
|
|
codepage_handler, P(NULL), P(NULL));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2005-03-22 23:20:23 +00:00
|
|
|
s = ctrl_getset(b, "Window/Translation", "tweaks", NULL);
|
|
|
|
ctrl_checkbox(s, "Treat CJK ambiguous characters as wide", 'w',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(translation_cjk_ambig_wide),
|
|
|
|
conf_checkbox_handler, I(CONF_cjk_ambig_wide));
|
2005-03-22 23:20:23 +00:00
|
|
|
|
2003-11-20 18:33:22 +00:00
|
|
|
str = dupprintf("Adjust how %s handles line drawing characters", appname);
|
2003-04-06 14:11:33 +00:00
|
|
|
s = ctrl_getset(b, "Window/Translation", "linedraw", str);
|
|
|
|
sfree(str);
|
2022-06-01 10:14:21 +00:00
|
|
|
ctrl_radiobuttons(
|
|
|
|
s, "Handling of line drawing characters:", NO_SHORTCUT,1,
|
|
|
|
HELPCTX(translation_linedraw),
|
|
|
|
conf_radiobutton_handler, I(CONF_vtmode),
|
|
|
|
"Use Unicode line drawing code points",'u',I(VT_UNICODE),
|
|
|
|
"Poor man's line drawing (+, - and |)",'p',I(VT_POORMAN));
|
2003-11-20 18:33:22 +00:00
|
|
|
ctrl_checkbox(s, "Copy and paste line drawing characters as lqqqk",'d',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(selection_linedraw),
|
|
|
|
conf_checkbox_handler, I(CONF_rawcnp));
|
Option to support VT100 line drawing in UTF-8 mode.
Thanks to Jiri Kaspar for sending this patch (apart from the new docs
section, which is in my own words), which implements a feature we've
had as a wishlist item ('utf8-plus-vt100') for a long time.
I was actually surprised it was possible to implement it in so few
lines of code! I'd forgotten, or possibly never noticed in the first
place, that even in UTF-8 mode PuTTY not only accepts but still
_processes_ all the ISO 2022 control sequences and shift characters,
and keeps running track of all the same state in term->cset and
term->cset_attrs that it tracks in IS0-2022-enabled modes. It's just
that in UTF-8 mode, at the very last minute when a character+attribute
pair is about to be written into the terminal's character buffer, it
deliberately ignores the contents of those variables.
So all that was needed was a new flag checked at that last moment
which causes it not quite to ignore them after all, and bingo,
utf8-plus-vt100 is supported. And it works no matter which ISO 2022
sequences you're using; whether you're using ESC ( 0 to select the
line drawing set directly into GL and ESC ( B to get back when you're
done, or whether you send a preliminary ESC ( B ESC ) 0 to get GL/GR
to be ASCII and line drawing respectively so you can use SI and SO as
one-byte mode switches thereafter, both work just as well.
This implementation strategy has a couple of consequences, which I
don't think matter very much one way or the other but I document them
just in case they turn out to be important later:
- if an application expecting this mode has already filled your
terminal window with lqqqqqqqqk, then enabling this mode in Change
Settings won't retroactively turn them into the line drawing
characters you wanted, because no memory is preserved in the screen
buffer of what the ISO 2022 state was when they were printed. So
the application still has to do a screen refresh.
- on the other hand, if you already sent the ESC ( 0 or whatever to
put the terminal _into_ line drawing mode, and then you turn on
this mode in Change Settings, you _will_ still be in line drawing
mode, because the system _does_ remember your current ISO 2022
state at all times, whether it's currently applying it to output
printing characters or not.
2018-05-12 07:43:52 +00:00
|
|
|
ctrl_checkbox(s, "Enable VT100 line drawing even in UTF-8 mode",'8',
|
|
|
|
HELPCTX(translation_utf8linedraw),
|
|
|
|
conf_checkbox_handler, I(CONF_utf8linedraw));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window/Selection panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Window/Selection", "Options controlling copy and paste");
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2003-03-05 22:07:40 +00:00
|
|
|
s = ctrl_getset(b, "Window/Selection", "mouse",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Control use of mouse");
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_checkbox(s, "Shift overrides application's use of mouse", 'p',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(selection_shiftdrag),
|
|
|
|
conf_checkbox_handler, I(CONF_mouse_override));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_radiobuttons(s,
|
2019-09-08 19:29:00 +00:00
|
|
|
"Default selection mode (Alt+drag does the other one):",
|
|
|
|
NO_SHORTCUT, 2,
|
|
|
|
HELPCTX(selection_rect),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_rect_select),
|
|
|
|
"Normal", 'n', I(false),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Rectangular block", 'r', I(true));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2017-12-10 17:16:50 +00:00
|
|
|
s = ctrl_getset(b, "Window/Selection", "clipboards",
|
|
|
|
"Assign copy/paste actions to clipboards");
|
|
|
|
ctrl_checkbox(s, "Auto-copy selected text to "
|
|
|
|
CLIPNAME_EXPLICIT_OBJECT,
|
|
|
|
NO_SHORTCUT, HELPCTX(selection_autocopy),
|
|
|
|
conf_checkbox_handler, I(CONF_mouseautocopy));
|
2017-12-17 18:44:27 +00:00
|
|
|
clipboard_control(s, "Mouse paste action:", NO_SHORTCUT, 60,
|
|
|
|
HELPCTX(selection_clipactions),
|
|
|
|
CONF_mousepaste, CONF_mousepaste_custom);
|
|
|
|
clipboard_control(s, "{Ctrl,Shift} + Ins:", NO_SHORTCUT, 60,
|
|
|
|
HELPCTX(selection_clipactions),
|
|
|
|
CONF_ctrlshiftins, CONF_ctrlshiftins_custom);
|
|
|
|
clipboard_control(s, "Ctrl + Shift + {C,V}:", NO_SHORTCUT, 60,
|
|
|
|
HELPCTX(selection_clipactions),
|
|
|
|
CONF_ctrlshiftcv, CONF_ctrlshiftcv_custom);
|
2017-12-10 17:16:50 +00:00
|
|
|
|
2018-03-11 17:40:42 +00:00
|
|
|
s = ctrl_getset(b, "Window/Selection", "paste",
|
2018-03-11 18:57:13 +00:00
|
|
|
"Control pasting of text from clipboard to terminal");
|
2018-03-11 17:40:42 +00:00
|
|
|
ctrl_checkbox(s, "Permit control characters in pasted text",
|
2018-03-27 22:10:39 +00:00
|
|
|
NO_SHORTCUT, HELPCTX(selection_pastectrl),
|
2018-03-11 17:40:42 +00:00
|
|
|
conf_checkbox_handler, I(CONF_paste_controls));
|
|
|
|
|
2017-12-16 11:13:31 +00:00
|
|
|
/*
|
2018-03-11 18:57:13 +00:00
|
|
|
* The Window/Selection/Copy panel.
|
2017-12-16 11:13:31 +00:00
|
|
|
*/
|
2018-03-11 18:57:13 +00:00
|
|
|
ctrl_settitle(b, "Window/Selection/Copy",
|
|
|
|
"Options controlling copying from terminal to clipboard");
|
2017-12-16 11:13:31 +00:00
|
|
|
|
2018-03-11 18:57:13 +00:00
|
|
|
s = ctrl_getset(b, "Window/Selection/Copy", "charclass",
|
2019-09-08 19:29:00 +00:00
|
|
|
"Classes of character that group together");
|
2003-03-05 22:07:40 +00:00
|
|
|
ccd = (struct charclass_data *)
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_alloc(b, sizeof(struct charclass_data));
|
2003-03-05 22:07:40 +00:00
|
|
|
ccd->listbox = ctrl_listbox(s, "Character classes:", 'e',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(copy_charclasses),
|
|
|
|
charclass_handler, P(ccd));
|
2003-03-05 22:07:40 +00:00
|
|
|
ccd->listbox->listbox.multisel = 1;
|
|
|
|
ccd->listbox->listbox.ncols = 4;
|
2003-03-29 16:14:26 +00:00
|
|
|
ccd->listbox->listbox.percentages = snewn(4, int);
|
2003-03-05 22:07:40 +00:00
|
|
|
ccd->listbox->listbox.percentages[0] = 15;
|
|
|
|
ccd->listbox->listbox.percentages[1] = 25;
|
|
|
|
ccd->listbox->listbox.percentages[2] = 20;
|
|
|
|
ccd->listbox->listbox.percentages[3] = 40;
|
|
|
|
ctrl_columns(s, 2, 67, 33);
|
|
|
|
ccd->editbox = ctrl_editbox(s, "Set to class", 't', 50,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(copy_charclasses),
|
|
|
|
charclass_handler, P(ccd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ccd->editbox->column = 0;
|
2003-03-05 22:07:40 +00:00
|
|
|
ccd->button = ctrl_pushbutton(s, "Set", 's',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(copy_charclasses),
|
|
|
|
charclass_handler, P(ccd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ccd->button->column = 1;
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Window/Colours panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Window/Colours", "Options controlling use of colours");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Window/Colours", "general",
|
2019-09-08 19:29:00 +00:00
|
|
|
"General options for colour usage");
|
2004-11-09 17:57:32 +00:00
|
|
|
ctrl_checkbox(s, "Allow terminal to specify ANSI colours", 'i',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(colours_ansi),
|
|
|
|
conf_checkbox_handler, I(CONF_ansi_colour));
|
2004-11-28 15:13:34 +00:00
|
|
|
ctrl_checkbox(s, "Allow terminal to use xterm 256-colour mode", '2',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(colours_xterm256), conf_checkbox_handler,
|
|
|
|
I(CONF_xterm_256_colour));
|
2017-10-05 19:27:27 +00:00
|
|
|
ctrl_checkbox(s, "Allow terminal to use 24-bit colours", '4',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(colours_truecolour), conf_checkbox_handler,
|
|
|
|
I(CONF_true_colour));
|
2012-06-09 15:09:22 +00:00
|
|
|
ctrl_radiobuttons(s, "Indicate bolded text by changing:", 'b', 3,
|
|
|
|
HELPCTX(colours_bold),
|
|
|
|
conf_radiobutton_handler, I(CONF_bold_style),
|
2023-05-29 14:51:56 +00:00
|
|
|
"The font", I(BOLD_STYLE_FONT),
|
|
|
|
"The colour", I(BOLD_STYLE_COLOUR),
|
|
|
|
"Both", I(BOLD_STYLE_FONT | BOLD_STYLE_COLOUR));
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2003-04-06 14:11:33 +00:00
|
|
|
str = dupprintf("Adjust the precise colours %s displays", appname);
|
|
|
|
s = ctrl_getset(b, "Window/Colours", "adjust", str);
|
|
|
|
sfree(str);
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_text(s, "Select a colour from the list, and then click the"
|
2019-09-08 19:29:00 +00:00
|
|
|
" Modify button to change its appearance.",
|
|
|
|
HELPCTX(colours_config));
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_columns(s, 2, 67, 33);
|
|
|
|
cd = (struct colour_data *)ctrl_alloc(b, sizeof(struct colour_data));
|
|
|
|
cd->listbox = ctrl_listbox(s, "Select a colour to adjust:", 'u',
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(colours_config), colour_handler, P(cd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
cd->listbox->column = 0;
|
2003-03-22 11:07:59 +00:00
|
|
|
cd->listbox->listbox.height = 7;
|
2003-03-05 22:07:40 +00:00
|
|
|
c = ctrl_text(s, "RGB value:", HELPCTX(colours_config));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 1;
|
2003-03-22 11:07:59 +00:00
|
|
|
cd->redit = ctrl_editbox(s, "Red", 'r', 50, HELPCTX(colours_config),
|
2019-09-08 19:29:00 +00:00
|
|
|
colour_handler, P(cd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
cd->redit->column = 1;
|
2003-03-22 11:07:59 +00:00
|
|
|
cd->gedit = ctrl_editbox(s, "Green", 'n', 50, HELPCTX(colours_config),
|
2019-09-08 19:29:00 +00:00
|
|
|
colour_handler, P(cd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
cd->gedit->column = 1;
|
2003-03-22 11:07:59 +00:00
|
|
|
cd->bedit = ctrl_editbox(s, "Blue", 'e', 50, HELPCTX(colours_config),
|
2019-09-08 19:29:00 +00:00
|
|
|
colour_handler, P(cd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
cd->bedit->column = 1;
|
2003-03-05 22:07:40 +00:00
|
|
|
cd->button = ctrl_pushbutton(s, "Modify", 'm', HELPCTX(colours_config),
|
2019-09-08 19:29:00 +00:00
|
|
|
colour_handler, P(cd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
cd->button->column = 1;
|
2003-03-05 22:07:40 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
|
|
|
|
/*
|
2003-04-26 14:35:34 +00:00
|
|
|
* The Connection panel. This doesn't show up if we're in a
|
|
|
|
* non-network utility such as pterm. We tell this by being
|
|
|
|
* passed a protocol < 0.
|
2003-03-05 22:07:40 +00:00
|
|
|
*/
|
2003-04-26 14:35:34 +00:00
|
|
|
if (protocol >= 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_settitle(b, "Connection", "Options controlling the connection");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection", "keepalive",
|
|
|
|
"Sending of null packets to keep session active");
|
|
|
|
ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
|
|
|
|
HELPCTX(connection_keepalive),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_ping_interval), ED_INT);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
s = ctrl_getset(b, "Connection", "tcp",
|
|
|
|
"Low-level TCP connection options");
|
|
|
|
ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)",
|
|
|
|
'n', HELPCTX(connection_nodelay),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_tcp_nodelay));
|
|
|
|
ctrl_checkbox(s, "Enable TCP keepalives (SO_KEEPALIVE option)",
|
|
|
|
'p', HELPCTX(connection_tcpkeepalive),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_tcp_keepalives));
|
2005-01-09 11:44:21 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
s = ctrl_getset(b, "Connection", "ipversion",
|
2022-08-03 19:48:46 +00:00
|
|
|
"Internet protocol version");
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
|
2022-08-03 19:48:46 +00:00
|
|
|
HELPCTX(connection_ipversion),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_addressfamily),
|
|
|
|
"Auto", 'u', I(ADDRTYPE_UNSPEC),
|
|
|
|
"IPv4", '4', I(ADDRTYPE_IPV4),
|
|
|
|
"IPv6", '6', I(ADDRTYPE_IPV6));
|
2005-01-09 11:44:21 +00:00
|
|
|
#endif
|
2008-06-01 11:16:32 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
2018-09-11 15:23:38 +00:00
|
|
|
const char *label = backend_vt_from_proto(PROT_SSH) ?
|
2019-09-08 19:29:00 +00:00
|
|
|
"Logical name of remote host (e.g. for SSH key lookup):" :
|
|
|
|
"Logical name of remote host:";
|
|
|
|
s = ctrl_getset(b, "Connection", "identity",
|
|
|
|
"Logical name of remote host");
|
|
|
|
ctrl_editbox(s, label, 'm', 100,
|
|
|
|
HELPCTX(connection_loghost),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_loghost), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A sub-panel Connection/Data, containing options that
|
|
|
|
* decide on data to send to the server.
|
|
|
|
*/
|
|
|
|
if (!midsession) {
|
|
|
|
ctrl_settitle(b, "Connection/Data", "Data to send to the server");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Data", "login",
|
|
|
|
"Login details");
|
|
|
|
ctrl_editbox(s, "Auto-login username", 'u', 50,
|
|
|
|
HELPCTX(connection_username),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_username), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
/* We assume the local username is sufficiently stable
|
|
|
|
* to include on the dialog box. */
|
|
|
|
char *user = get_username();
|
|
|
|
char *userlabel = dupprintf("Use system username (%s)",
|
|
|
|
user ? user : "");
|
|
|
|
sfree(user);
|
|
|
|
ctrl_radiobuttons(s, "When username is not specified:", 'n', 4,
|
|
|
|
HELPCTX(connection_username_from_env),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_username_from_env),
|
|
|
|
"Prompt", I(false),
|
2022-06-01 10:14:21 +00:00
|
|
|
userlabel, I(true));
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(userlabel);
|
|
|
|
}
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Data", "term",
|
|
|
|
"Terminal details");
|
|
|
|
ctrl_editbox(s, "Terminal-type string", 't', 50,
|
|
|
|
HELPCTX(connection_termtype),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_termtype), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_editbox(s, "Terminal speeds", 's', 50,
|
|
|
|
HELPCTX(connection_termspeed),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_termspeed), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Data", "env",
|
|
|
|
"Environment variables");
|
|
|
|
ctrl_columns(s, 2, 80, 20);
|
|
|
|
ed = (struct environ_data *)
|
|
|
|
ctrl_alloc(b, sizeof(struct environ_data));
|
|
|
|
ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
|
|
|
|
HELPCTX(telnet_environ),
|
|
|
|
environ_handler, P(ed), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ed->varbox->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
|
|
|
|
HELPCTX(telnet_environ),
|
|
|
|
environ_handler, P(ed), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ed->valbox->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
|
|
|
|
HELPCTX(telnet_environ),
|
|
|
|
environ_handler, P(ed));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ed->addbutton->column = 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
|
|
|
|
HELPCTX(telnet_environ),
|
|
|
|
environ_handler, P(ed));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
ed->rembutton->column = 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
|
|
|
|
HELPCTX(telnet_environ),
|
|
|
|
environ_handler, P(ed));
|
|
|
|
ed->listbox->listbox.height = 3;
|
|
|
|
ed->listbox->listbox.ncols = 2;
|
|
|
|
ed->listbox->listbox.percentages = snewn(2, int);
|
|
|
|
ed->listbox->listbox.percentages[0] = 30;
|
|
|
|
ed->listbox->listbox.percentages[1] = 70;
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* The Connection/Proxy panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/Proxy",
|
|
|
|
"Options controlling proxy usage");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
|
2022-04-22 13:55:44 +00:00
|
|
|
c = ctrl_droplist(s, "Proxy type:", 't', 70,
|
|
|
|
HELPCTX(proxy_type), proxy_type_handler, I(0));
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_columns(s, 2, 80, 20);
|
|
|
|
c = ctrl_editbox(s, "Proxy hostname", 'y', 100,
|
|
|
|
HELPCTX(proxy_main),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_proxy_host), ED_STR);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
c = ctrl_editbox(s, "Port", 'p', 100,
|
|
|
|
HELPCTX(proxy_main),
|
|
|
|
conf_editbox_handler,
|
|
|
|
I(CONF_proxy_port),
|
2022-08-24 06:56:45 +00:00
|
|
|
ED_INT);
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
ctrl_editbox(s, "Exclude Hosts/IPs", 'e', 100,
|
|
|
|
HELPCTX(proxy_exclude),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_proxy_exclude_list), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_checkbox(s, "Consider proxying local host connections", 'x',
|
|
|
|
HELPCTX(proxy_exclude),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_even_proxy_localhost));
|
|
|
|
ctrl_radiobuttons(s, "Do DNS name lookup at proxy end:", 'd', 3,
|
|
|
|
HELPCTX(proxy_dns),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_proxy_dns),
|
|
|
|
"No", I(FORCE_OFF),
|
|
|
|
"Auto", I(AUTO),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Yes", I(FORCE_ON));
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_editbox(s, "Username", 'u', 60,
|
|
|
|
HELPCTX(proxy_auth),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_proxy_username), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
c = ctrl_editbox(s, "Password", 'w', 60,
|
|
|
|
HELPCTX(proxy_auth),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_proxy_password), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
c->editbox.password = true;
|
2022-04-22 13:55:44 +00:00
|
|
|
ctrl_editbox(s, "Command to send to proxy (for some types)", 'm', 100,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(proxy_command),
|
|
|
|
conf_editbox_handler,
|
2022-08-24 06:56:45 +00:00
|
|
|
I(CONF_proxy_telnet_command), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
ctrl_radiobuttons(s, "Print proxy diagnostics "
|
2015-11-22 14:33:28 +00:00
|
|
|
"in the terminal window", 'r', 5,
|
2019-09-08 19:29:00 +00:00
|
|
|
HELPCTX(proxy_logging),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_proxy_log_to_term),
|
|
|
|
"No", I(FORCE_OFF),
|
|
|
|
"Yes", I(FORCE_ON),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Only until session starts", I(AUTO));
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-03-10 21:18:08 +00:00
|
|
|
* Each per-protocol configuration GUI panel is conditionally
|
|
|
|
* displayed. We don't display it if this binary doesn't contain a
|
|
|
|
* backend for its protocol at all; we don't display it if we're
|
|
|
|
* already in mid-session with a different protocol selected; and
|
|
|
|
* even if we _do_ have this protocol selected, we don't display
|
|
|
|
* the panel if the protocol doesn't permit any mid-session
|
|
|
|
* reconfiguration anyway.
|
2003-03-05 22:07:40 +00:00
|
|
|
*/
|
|
|
|
|
2020-03-10 21:18:08 +00:00
|
|
|
#define DISPLAY_RECONFIGURABLE_PROTOCOL(which_proto) \
|
|
|
|
(backend_vt_from_proto(which_proto) && \
|
|
|
|
(!midsession || protocol == (which_proto)))
|
|
|
|
#define DISPLAY_NON_RECONFIGURABLE_PROTOCOL(which_proto) \
|
|
|
|
(backend_vt_from_proto(which_proto) && !midsession)
|
2003-03-05 22:07:40 +00:00
|
|
|
|
2020-05-01 17:08:20 +00:00
|
|
|
if (DISPLAY_RECONFIGURABLE_PROTOCOL(PROT_SSH) ||
|
|
|
|
DISPLAY_RECONFIGURABLE_PROTOCOL(PROT_SSHCONN)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* The Connection/SSH panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH",
|
|
|
|
"Options controlling SSH connections");
|
|
|
|
|
|
|
|
/* SSH-1 or connection-sharing downstream */
|
|
|
|
if (midsession && (protcfginfo == 1 || protcfginfo == -1)) {
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "disclaimer", NULL);
|
|
|
|
ctrl_text(s, "Nothing on this panel may be reconfigured in mid-"
|
|
|
|
"session; it is only here so that sub-panels of it can "
|
|
|
|
"exist without looking strange.", HELPCTX(no_help));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "data",
|
|
|
|
"Data to send to the server");
|
|
|
|
ctrl_editbox(s, "Remote command:", 'r', 100,
|
|
|
|
HELPCTX(ssh_command),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_remote_cmd), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
|
|
|
|
ctrl_checkbox(s, "Don't start a shell or command at all", 'n',
|
|
|
|
HELPCTX(ssh_noshell),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_no_shell));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession || !(protcfginfo == 1 || protcfginfo == -1)) {
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Enable compression", 'e',
|
|
|
|
HELPCTX(ssh_compress),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_compression));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "sharing", "Sharing an SSH connection between PuTTY tools");
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Share SSH connections if possible", 's',
|
|
|
|
HELPCTX(ssh_share),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_connection_sharing));
|
2013-11-17 14:05:41 +00:00
|
|
|
|
|
|
|
ctrl_text(s, "Permitted roles in a shared connection:",
|
|
|
|
HELPCTX(ssh_share));
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_checkbox(s, "Upstream (connecting to the real server)", 'u',
|
|
|
|
HELPCTX(ssh_share),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_connection_sharing_upstream));
|
|
|
|
ctrl_checkbox(s, "Downstream (connecting to the upstream PuTTY)", 'd',
|
|
|
|
HELPCTX(ssh_share),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_connection_sharing_downstream));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
s = ctrl_getset(b, "Connection/SSH", "protocol", "Protocol options");
|
|
|
|
|
|
|
|
ctrl_radiobuttons(s, "SSH protocol version:", NO_SHORTCUT, 2,
|
|
|
|
HELPCTX(ssh_protocol),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_sshprot),
|
|
|
|
"2", '2', I(3),
|
2022-06-01 10:14:21 +00:00
|
|
|
"1 (INSECURE)", '1', I(0));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/Kex panel. (Owing to repeat key
|
|
|
|
* exchange, much of this is meaningful in mid-session _if_
|
|
|
|
* we're using SSH-2 and are not a connection-sharing
|
|
|
|
* downstream, or haven't decided yet.)
|
|
|
|
*/
|
|
|
|
if (protcfginfo != 1 && protcfginfo != -1) {
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Kex",
|
|
|
|
"Options controlling SSH key exchange");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Kex", "main",
|
|
|
|
"Key exchange algorithm options");
|
|
|
|
c = ctrl_draglist(s, "Algorithm selection policy:", 's',
|
|
|
|
HELPCTX(ssh_kexlist),
|
|
|
|
kexlist_handler, P(NULL));
|
2018-05-01 06:41:01 +00:00
|
|
|
c->listbox.height = KEX_MAX;
|
2019-03-25 23:46:59 +00:00
|
|
|
#ifndef NO_GSSAPI
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_checkbox(s, "Attempt GSSAPI key exchange",
|
|
|
|
'k', HELPCTX(ssh_gssapi),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_try_gssapi_kex));
|
2019-03-25 23:46:59 +00:00
|
|
|
#endif
|
2004-12-29 12:32:25 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
s = ctrl_getset(b, "Connection/SSH/Kex", "repeat",
|
|
|
|
"Options controlling key re-exchange");
|
2004-12-29 12:32:25 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_editbox(s, "Max minutes before rekey (0 for no limit)", 't', 20,
|
|
|
|
HELPCTX(ssh_kex_repeat),
|
|
|
|
conf_editbox_handler,
|
|
|
|
I(CONF_ssh_rekey_time),
|
2022-08-24 06:56:45 +00:00
|
|
|
ED_INT);
|
2019-03-25 23:46:59 +00:00
|
|
|
#ifndef NO_GSSAPI
|
Support GSS key exchange, for Kerberos 5 only.
This is a heavily edited (by me) version of a patch originally due to
Nico Williams and Viktor Dukhovni. Their comments:
* Don't delegate credentials when rekeying unless there's a new TGT
or the old service ticket is nearly expired.
* Check for the above conditions more frequently (every two minutes
by default) and rekey when we would delegate credentials.
* Do not rekey with very short service ticket lifetimes; some GSSAPI
libraries may lose the race to use an almost expired ticket. Adjust
the timing of rekey checks to try to avoid this possibility.
My further comments:
The most interesting thing about this patch to me is that the use of
GSS key exchange causes a switch over to a completely different model
of what host keys are for. This comes from RFC 4462 section 2.1: the
basic idea is that when your session is mostly bidirectionally
authenticated by the GSSAPI exchanges happening in initial kex and
every rekey, host keys become more or less vestigial, and their
remaining purpose is to allow a rekey to happen if the requirements of
the SSH protocol demand it at an awkward moment when the GSS
credentials are not currently available (e.g. timed out and haven't
been renewed yet). As such, there's no need for host keys to be
_permanent_ or to be a reliable identifier of a particular host, and
RFC 4462 allows for the possibility that they might be purely
transient and only for this kind of emergency fallback purpose.
Therefore, once PuTTY has done a GSS key exchange, it disconnects
itself completely from the permanent host key cache functions in
storage.h, and instead switches to a _transient_ host key cache stored
in memory with the lifetime of just that SSH session. That cache is
populated with keys received from the server as a side effect of GSS
kex (via the optional SSH2_MSG_KEXGSS_HOSTKEY message), and used if
later in the session we have to fall back to a non-GSS key exchange.
However, in practice servers we've tested against do not send a host
key in that way, so we also have a fallback method of populating the
transient cache by triggering an immediate non-GSS rekey straight
after userauth (reusing the code path we also use to turn on OpenSSH
delayed encryption without the race condition).
2018-04-26 06:18:59 +00:00
|
|
|
ctrl_editbox(s, "Minutes between GSS checks (0 for never)", NO_SHORTCUT, 20,
|
|
|
|
HELPCTX(ssh_kex_repeat),
|
|
|
|
conf_editbox_handler,
|
|
|
|
I(CONF_gssapirekey),
|
2022-08-24 06:56:45 +00:00
|
|
|
ED_INT);
|
2019-03-25 23:46:59 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_editbox(s, "Max data before rekey (0 for no limit)", 'x', 20,
|
|
|
|
HELPCTX(ssh_kex_repeat),
|
|
|
|
conf_editbox_handler,
|
|
|
|
I(CONF_ssh_rekey_data),
|
2022-08-24 06:56:45 +00:00
|
|
|
ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_text(s, "(Use 1M for 1 megabyte, 1G for 1 gigabyte etc)",
|
|
|
|
HELPCTX(ssh_kex_repeat));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The 'Connection/SSH/Host keys' panel.
|
|
|
|
*/
|
|
|
|
if (protcfginfo != 1 && protcfginfo != -1) {
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Host keys",
|
|
|
|
"Options controlling SSH host keys");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Host keys", "main",
|
|
|
|
"Host key algorithm preference");
|
|
|
|
c = ctrl_draglist(s, "Algorithm selection policy:", 's',
|
|
|
|
HELPCTX(ssh_hklist),
|
|
|
|
hklist_handler, P(NULL));
|
|
|
|
c->listbox.height = 5;
|
2020-06-11 14:57:18 +00:00
|
|
|
|
|
|
|
ctrl_checkbox(s, "Prefer algorithms for which a host key is known",
|
|
|
|
'p', HELPCTX(ssh_hk_known), conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_prefer_known_hostkeys));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Manual host key configuration is irrelevant mid-session,
|
|
|
|
* as we enforce that the host key for rekeys is the
|
|
|
|
* same as that used at the start of the session.
|
|
|
|
*/
|
|
|
|
if (!midsession) {
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Host keys", "hostkeys",
|
|
|
|
"Manually configure host keys for this connection");
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
|
|
|
|
ctrl_columns(s, 2, 75, 25);
|
|
|
|
c = ctrl_text(s, "Host keys or fingerprints to accept:",
|
|
|
|
HELPCTX(ssh_kex_manual_hostkeys));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
/* You want to select from the list, _then_ hit Remove. So
|
|
|
|
* tab order should be that way round. */
|
|
|
|
mh = (struct manual_hostkey_data *)
|
|
|
|
ctrl_alloc(b,sizeof(struct manual_hostkey_data));
|
|
|
|
mh->rembutton = ctrl_pushbutton(s, "Remove", 'r',
|
|
|
|
HELPCTX(ssh_kex_manual_hostkeys),
|
|
|
|
manual_hostkey_handler, P(mh));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
mh->rembutton->column = 1;
|
|
|
|
mh->rembutton->delay_taborder = true;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
mh->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
|
|
|
|
HELPCTX(ssh_kex_manual_hostkeys),
|
|
|
|
manual_hostkey_handler, P(mh));
|
|
|
|
/* This list box can't be very tall, because there's not
|
|
|
|
* much room in the pane on Windows at least. This makes
|
|
|
|
* it become really unhelpful if a horizontal scrollbar
|
|
|
|
* appears, so we suppress that. */
|
|
|
|
mh->listbox->listbox.height = 2;
|
2018-10-29 19:50:29 +00:00
|
|
|
mh->listbox->listbox.hscroll = false;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
ctrl_tabdelay(s, mh->rembutton);
|
2019-09-08 19:29:00 +00:00
|
|
|
mh->keybox = ctrl_editbox(s, "Key", 'k', 80,
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
HELPCTX(ssh_kex_manual_hostkeys),
|
|
|
|
manual_hostkey_handler, P(mh), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
mh->keybox->column = 0;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
mh->addbutton = ctrl_pushbutton(s, "Add key", 'y',
|
|
|
|
HELPCTX(ssh_kex_manual_hostkeys),
|
|
|
|
manual_hostkey_handler, P(mh));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
mh->addbutton->column = 1;
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
ctrl_columns(s, 1, 100);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2004-12-28 14:10:32 +00:00
|
|
|
|
Initial support for host certificates.
Now we offer the OpenSSH certificate key types in our KEXINIT host key
algorithm list, so that if the server has a certificate, they can send
it to us.
There's a new storage.h abstraction for representing a list of trusted
host CAs, and which ones are trusted to certify hosts for what
domains. This is stored outside the normal saved session data, because
the whole point of host certificates is to avoid per-host faffing.
Configuring this set of trusted CAs is done via a new GUI dialog box,
separate from the main PuTTY config box (because it modifies a single
set of settings across all saved sessions), which you can launch by
clicking a button in the 'Host keys' pane. The GUI is pretty crude for
the moment, and very much at a 'just about usable' stage right now. It
will want some polishing.
If we have no CA configured that matches the hostname, we don't offer
to receive certified host keys in the first place. So for existing
users who haven't set any of this up yet, nothing will immediately
change.
Currently, if we do offer to receive certified host keys and the
server presents one signed by a CA we don't trust, PuTTY will bomb out
unconditionally with an error, instead of offering a confirmation box.
That's an unfinished part which I plan to fix before this goes into a
release.
2022-04-22 11:07:24 +00:00
|
|
|
/*
|
|
|
|
* But there's no reason not to forbid access to the host CA
|
|
|
|
* configuration box, which is common across sessions in any
|
|
|
|
* case.
|
|
|
|
*/
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Host keys", "ca",
|
|
|
|
"Configure trusted certification authorities");
|
|
|
|
c = ctrl_pushbutton(s, "Configure host CAs", NO_SHORTCUT,
|
2022-08-07 11:06:36 +00:00
|
|
|
HELPCTX(ssh_kex_cert),
|
|
|
|
host_ca_button_handler, I(0));
|
Initial support for host certificates.
Now we offer the OpenSSH certificate key types in our KEXINIT host key
algorithm list, so that if the server has a certificate, they can send
it to us.
There's a new storage.h abstraction for representing a list of trusted
host CAs, and which ones are trusted to certify hosts for what
domains. This is stored outside the normal saved session data, because
the whole point of host certificates is to avoid per-host faffing.
Configuring this set of trusted CAs is done via a new GUI dialog box,
separate from the main PuTTY config box (because it modifies a single
set of settings across all saved sessions), which you can launch by
clicking a button in the 'Host keys' pane. The GUI is pretty crude for
the moment, and very much at a 'just about usable' stage right now. It
will want some polishing.
If we have no CA configured that matches the hostname, we don't offer
to receive certified host keys in the first place. So for existing
users who haven't set any of this up yet, nothing will immediately
change.
Currently, if we do offer to receive certified host keys and the
server presents one signed by a CA we don't trust, PuTTY will bomb out
unconditionally with an error, instead of offering a confirmation box.
That's an unfinished part which I plan to fix before this goes into a
release.
2022-04-22 11:07:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!midsession || !(protcfginfo == 1 || protcfginfo == -1)) {
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/Cipher panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Cipher",
|
|
|
|
"Options controlling SSH encryption");
|
2013-11-17 14:03:25 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
s = ctrl_getset(b, "Connection/SSH/Cipher",
|
2013-11-17 14:03:25 +00:00
|
|
|
"encryption", "Encryption options");
|
2019-09-08 19:29:00 +00:00
|
|
|
c = ctrl_draglist(s, "Encryption cipher selection policy:", 's',
|
|
|
|
HELPCTX(ssh_ciphers),
|
|
|
|
cipherlist_handler, P(NULL));
|
|
|
|
c->listbox.height = 6;
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Enable legacy use of single-DES in SSH-2", 'i',
|
|
|
|
HELPCTX(ssh_ciphers),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh2_des_cbc));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/Auth panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Auth",
|
|
|
|
"Options controlling SSH authentication");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth", "main", NULL);
|
|
|
|
ctrl_checkbox(s, "Display pre-authentication banner (SSH-2 only)",
|
|
|
|
'd', HELPCTX(ssh_auth_banner),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_show_banner));
|
|
|
|
ctrl_checkbox(s, "Bypass authentication entirely (SSH-2 only)", 'b',
|
|
|
|
HELPCTX(ssh_auth_bypass),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_no_userauth));
|
New option to reject 'trivial' success of userauth.
Suggested by Manfred Kaiser, who also wrote most of this patch
(although outlying parts, like documentation and SSH-1 support, are by
me).
This is a second line of defence against the kind of spoofing attacks
in which a malicious or compromised SSH server rushes the client
through the userauth phase of SSH without actually requiring any auth
inputs (passwords or signatures or whatever), and then at the start of
the connection phase it presents something like a spoof prompt,
intended to be taken for part of userauth by the user but in fact with
some more sinister purpose.
Our existing line of defence against this is the trust sigil system,
and as far as I know, that's still working. This option allows a bit of
extra defence in depth: if you don't expect your SSH server to
trivially accept authentication in the first place, then enabling this
option will cause PuTTY to disconnect if it unexpectedly does so,
without the user having to spot the presence or absence of a fiddly
little sigil anywhere.
Several types of authentication count as 'trivial'. The obvious one is
the SSH-2 "none" method, which clients always try first so that the
failure message will tell them what else they can try, and which a
server can instead accept in order to authenticate you unconditionally.
But there are two other ways to do it that we know of: one is to run
keyboard-interactive authentication and send an empty INFO_REQUEST
packet containing no actual prompts for the user, and another even
weirder one is to send USERAUTH_SUCCESS in response to the user's
preliminary *offer* of a public key (instead of sending the usual PK_OK
to request an actual signature from the key).
This new option detects all of those, by clearing the 'is_trivial_auth'
flag only when we send some kind of substantive authentication response
(be it a password, a k-i prompt response, a signature, or a GSSAPI
token). So even if there's a further path through the userauth maze we
haven't spotted, that somehow avoids sending anything substantive, this
strategy should still pick it up.
2021-06-19 14:39:15 +00:00
|
|
|
ctrl_checkbox(s, "Disconnect if authentication succeeds trivially",
|
|
|
|
'n', HELPCTX(ssh_no_trivial_userauth),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_ssh_no_trivial_userauth));
|
2019-09-08 19:29:00 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth", "methods",
|
|
|
|
"Authentication methods");
|
|
|
|
ctrl_checkbox(s, "Attempt authentication using Pageant", 'p',
|
|
|
|
HELPCTX(ssh_auth_pageant),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_tryagent));
|
|
|
|
ctrl_checkbox(s, "Attempt TIS or CryptoCard auth (SSH-1)", 'm',
|
|
|
|
HELPCTX(ssh_auth_tis),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_try_tis_auth));
|
|
|
|
ctrl_checkbox(s, "Attempt \"keyboard-interactive\" auth (SSH-2)",
|
|
|
|
'i', HELPCTX(ssh_auth_ki),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_try_ki_auth));
|
|
|
|
|
New feature: k-i authentication helper plugins.
In recent months I've had two requests from different people to build
support into PuTTY for automatically handling complicated third-party
auth protocols layered on top of keyboard-interactive - the kind of
thing where you're asked to enter some auth response, and you have to
refer to some external source like a web server to find out what the
right response _is_, which is a pain to do by hand, so you'd prefer it
to be automated in the SSH client.
That seems like a reasonable thing for an end user to want, but I
didn't think it was a good idea to build support for specific
protocols of that kind directly into PuTTY, where there would no doubt
be an ever-lengthening list, and maintenance needed on all of them.
So instead, in collaboration with one of my correspondents, I've
designed and implemented a protocol to be spoken between PuTTY and a
plugin running as a subprocess. The plugin can opt to handle the
keyboard-interactive authentication loop on behalf of the user, in
which case PuTTY passes on all the INFO_REQUEST packets to it, and
lets it make up responses. It can also ask questions of the user if
necessary.
The protocol spec is provided in a documentation appendix. The entire
configuration for the end user consists of providing a full command
line to use as the subprocess.
In the contrib directory I've provided an example plugin written in
Python. It gives a set of fixed responses suitable for getting through
Uppity's made-up k-i system, because that was a reasonable thing I
already had lying around to test against. But it also provides example
code that someone else could pick up and insert their own live
response-provider into the middle of, assuming they were happy with it
being in Python.
2022-09-01 18:38:46 +00:00
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth", "aux",
|
|
|
|
"Other authentication-related options");
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_checkbox(s, "Allow agent forwarding", 'f',
|
|
|
|
HELPCTX(ssh_auth_agentfwd),
|
|
|
|
conf_checkbox_handler, I(CONF_agentfwd));
|
|
|
|
ctrl_checkbox(s, "Allow attempted changes of username in SSH-2", NO_SHORTCUT,
|
|
|
|
HELPCTX(ssh_auth_changeuser),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_change_username));
|
New feature: k-i authentication helper plugins.
In recent months I've had two requests from different people to build
support into PuTTY for automatically handling complicated third-party
auth protocols layered on top of keyboard-interactive - the kind of
thing where you're asked to enter some auth response, and you have to
refer to some external source like a web server to find out what the
right response _is_, which is a pain to do by hand, so you'd prefer it
to be automated in the SSH client.
That seems like a reasonable thing for an end user to want, but I
didn't think it was a good idea to build support for specific
protocols of that kind directly into PuTTY, where there would no doubt
be an ever-lengthening list, and maintenance needed on all of them.
So instead, in collaboration with one of my correspondents, I've
designed and implemented a protocol to be spoken between PuTTY and a
plugin running as a subprocess. The plugin can opt to handle the
keyboard-interactive authentication loop on behalf of the user, in
which case PuTTY passes on all the INFO_REQUEST packets to it, and
lets it make up responses. It can also ask questions of the user if
necessary.
The protocol spec is provided in a documentation appendix. The entire
configuration for the end user consists of providing a full command
line to use as the subprocess.
In the contrib directory I've provided an example plugin written in
Python. It gives a set of fixed responses suitable for getting through
Uppity's made-up k-i system, because that was a reasonable thing I
already had lying around to test against. But it also provides example
code that someone else could pick up and insert their own live
response-provider into the middle of, assuming they were happy with it
being in Python.
2022-09-01 18:38:46 +00:00
|
|
|
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Auth/Credentials",
|
|
|
|
"Credentials to authenticate with");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth/Credentials", "publickey",
|
|
|
|
"Public-key authentication");
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_filesel(s, "Private key file for authentication:", 'k',
|
|
|
|
FILTER_KEY_FILES, false, "Select private key file",
|
|
|
|
HELPCTX(ssh_auth_privkey),
|
|
|
|
conf_filesel_handler, I(CONF_keyfile));
|
2023-07-19 16:15:23 +00:00
|
|
|
ctrl_filesel(s, "Certificate to use with the private key "
|
|
|
|
"(optional):", 'e',
|
Support for detached certificates in userauth.
This is triggered by a new config option, or alternatively a -cert
command-line option. You provide a certificate file (i.e. a public key
containing one of the cert key formats), and then, whenever you
authenticate with a private key that matches the public key inside
that certificate, the certificate will be sent to the server in place
of whatever public key it would have used before.
I expect this to be more convenient for some users than the approach
of baking the certificate into a modified version of the PPK file -
especially users who want to use different certificates on the same
key, either in sequence (if a CA continually reissues certificates
with short lifetimes) or in parallel (if different hosts trust
different CAs).
In particular, this substitution is applied consistently, even when
doing authentication via an agent. So if your bare private key is held
in Pageant, you can _still_ specify a detached certificate, and PuTTY
will spot that the key it's picked from Pageant matches that
certificate, and do the same substitution.
The detached certificate also overrides an existing certificate, if
there was one on the public key already.
2022-04-21 09:55:44 +00:00
|
|
|
NULL, false, "Select certificate file",
|
2022-08-07 11:06:36 +00:00
|
|
|
HELPCTX(ssh_auth_cert),
|
Support for detached certificates in userauth.
This is triggered by a new config option, or alternatively a -cert
command-line option. You provide a certificate file (i.e. a public key
containing one of the cert key formats), and then, whenever you
authenticate with a private key that matches the public key inside
that certificate, the certificate will be sent to the server in place
of whatever public key it would have used before.
I expect this to be more convenient for some users than the approach
of baking the certificate into a modified version of the PPK file -
especially users who want to use different certificates on the same
key, either in sequence (if a CA continually reissues certificates
with short lifetimes) or in parallel (if different hosts trust
different CAs).
In particular, this substitution is applied consistently, even when
doing authentication via an agent. So if your bare private key is held
in Pageant, you can _still_ specify a detached certificate, and PuTTY
will spot that the key it's picked from Pageant matches that
certificate, and do the same substitution.
The detached certificate also overrides an existing certificate, if
there was one on the public key already.
2022-04-21 09:55:44 +00:00
|
|
|
conf_filesel_handler, I(CONF_detached_cert));
|
2010-05-19 18:22:17 +00:00
|
|
|
|
New feature: k-i authentication helper plugins.
In recent months I've had two requests from different people to build
support into PuTTY for automatically handling complicated third-party
auth protocols layered on top of keyboard-interactive - the kind of
thing where you're asked to enter some auth response, and you have to
refer to some external source like a web server to find out what the
right response _is_, which is a pain to do by hand, so you'd prefer it
to be automated in the SSH client.
That seems like a reasonable thing for an end user to want, but I
didn't think it was a good idea to build support for specific
protocols of that kind directly into PuTTY, where there would no doubt
be an ever-lengthening list, and maintenance needed on all of them.
So instead, in collaboration with one of my correspondents, I've
designed and implemented a protocol to be spoken between PuTTY and a
plugin running as a subprocess. The plugin can opt to handle the
keyboard-interactive authentication loop on behalf of the user, in
which case PuTTY passes on all the INFO_REQUEST packets to it, and
lets it make up responses. It can also ask questions of the user if
necessary.
The protocol spec is provided in a documentation appendix. The entire
configuration for the end user consists of providing a full command
line to use as the subprocess.
In the contrib directory I've provided an example plugin written in
Python. It gives a set of fixed responses suitable for getting through
Uppity's made-up k-i system, because that was a reasonable thing I
already had lying around to test against. But it also provides example
code that someone else could pick up and insert their own live
response-provider into the middle of, assuming they were happy with it
being in Python.
2022-09-01 18:38:46 +00:00
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth/Credentials", "plugin",
|
|
|
|
"Plugin to provide authentication responses");
|
|
|
|
ctrl_editbox(s, "Plugin command to run", NO_SHORTCUT, 100,
|
|
|
|
HELPCTX(ssh_auth_plugin),
|
|
|
|
conf_editbox_handler, I(CONF_auth_plugin), ED_STR);
|
2010-05-19 18:22:17 +00:00
|
|
|
#ifndef NO_GSSAPI
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Connection/SSH/Auth/GSSAPI, which sadly won't fit on
|
|
|
|
* the main Auth panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Auth/GSSAPI",
|
|
|
|
"Options controlling GSSAPI authentication");
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Auth/GSSAPI", "gssapi", NULL);
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Attempt GSSAPI authentication (SSH-2 only)",
|
|
|
|
't', HELPCTX(ssh_gssapi),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_try_gssapi_auth));
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Attempt GSSAPI key exchange (SSH-2 only)",
|
|
|
|
'k', HELPCTX(ssh_gssapi),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_try_gssapi_kex));
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Allow GSSAPI credential delegation", 'l',
|
|
|
|
HELPCTX(ssh_gssapi_delegation),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_gssapifwd));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GSSAPI library selection.
|
|
|
|
*/
|
|
|
|
if (ngsslibs > 1) {
|
|
|
|
c = ctrl_draglist(s, "Preference order for GSSAPI libraries:",
|
|
|
|
'p', HELPCTX(ssh_gssapi_libraries),
|
|
|
|
gsslist_handler, P(NULL));
|
|
|
|
c->listbox.height = ngsslibs;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* I currently assume that if more than one GSS
|
|
|
|
* library option is available, then one of them is
|
|
|
|
* 'user-supplied' and so we should present the
|
|
|
|
* following file selector. This is at least half-
|
|
|
|
* reasonable, because if we're using statically
|
|
|
|
* linked GSSAPI then there will only be one option
|
|
|
|
* and no way to load from a user-supplied library,
|
|
|
|
* whereas if we're using dynamic libraries then
|
|
|
|
* there will almost certainly be some default
|
|
|
|
* option in addition to a user-supplied path. If
|
|
|
|
* anyone ever ports PuTTY to a system on which
|
|
|
|
* dynamic-library GSSAPI is available but there is
|
|
|
|
* absolutely no consensus on where to keep the
|
|
|
|
* libraries, there'll need to be a flag alongside
|
|
|
|
* ngsslibs to control whether the file selector is
|
|
|
|
* displayed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ctrl_filesel(s, "User-supplied GSSAPI library path:", 's',
|
|
|
|
FILTER_DYNLIB_FILES, false, "Select library file",
|
|
|
|
HELPCTX(ssh_gssapi_libraries),
|
|
|
|
conf_filesel_handler,
|
|
|
|
I(CONF_ssh_gss_custom));
|
|
|
|
}
|
2010-05-19 18:22:17 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/TTY panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/TTY", "Remote terminal settings");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/TTY", "sshtty", NULL);
|
|
|
|
ctrl_checkbox(s, "Don't allocate a pseudo-terminal", 'p',
|
|
|
|
HELPCTX(ssh_nopty),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_nopty));
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/TTY", "ttymodes",
|
|
|
|
"Terminal modes");
|
|
|
|
td = (struct ttymodes_data *)
|
|
|
|
ctrl_alloc(b, sizeof(struct ttymodes_data));
|
|
|
|
ctrl_text(s, "Terminal modes to send:", HELPCTX(ssh_ttymodes));
|
|
|
|
td->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
|
|
|
|
HELPCTX(ssh_ttymodes),
|
|
|
|
ttymodes_handler, P(td));
|
|
|
|
td->listbox->listbox.height = 8;
|
|
|
|
td->listbox->listbox.ncols = 2;
|
|
|
|
td->listbox->listbox.percentages = snewn(2, int);
|
|
|
|
td->listbox->listbox.percentages[0] = 40;
|
|
|
|
td->listbox->listbox.percentages[1] = 60;
|
|
|
|
ctrl_columns(s, 2, 75, 25);
|
|
|
|
c = ctrl_text(s, "For selected mode, send:", HELPCTX(ssh_ttymodes));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
td->setbutton = ctrl_pushbutton(s, "Set", 's',
|
|
|
|
HELPCTX(ssh_ttymodes),
|
|
|
|
ttymodes_handler, P(td));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
td->setbutton->column = 1;
|
|
|
|
td->setbutton->delay_taborder = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_columns(s, 1, 100); /* column break */
|
|
|
|
/* Bit of a hack to get the value radio buttons and
|
|
|
|
* edit-box on the same row. */
|
|
|
|
ctrl_columns(s, 2, 75, 25);
|
|
|
|
td->valradio = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
|
|
|
|
HELPCTX(ssh_ttymodes),
|
|
|
|
ttymodes_handler, P(td),
|
|
|
|
"Auto", NO_SHORTCUT, P(NULL),
|
|
|
|
"Nothing", NO_SHORTCUT, P(NULL),
|
2022-06-01 10:14:21 +00:00
|
|
|
"This:", NO_SHORTCUT, P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
td->valradio->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
td->valbox = ctrl_editbox(s, NULL, NO_SHORTCUT, 100,
|
|
|
|
HELPCTX(ssh_ttymodes),
|
|
|
|
ttymodes_handler, P(td), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
td->valbox->column = 1;
|
|
|
|
td->valbox->align_next_to = td->valradio;
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_tabdelay(s, td->setbutton);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/X11 panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/X11",
|
|
|
|
"Options controlling SSH X11 forwarding");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
|
|
|
|
ctrl_checkbox(s, "Enable X11 forwarding", 'e',
|
|
|
|
HELPCTX(ssh_tunnels_x11),
|
|
|
|
conf_checkbox_handler,I(CONF_x11_forward));
|
|
|
|
ctrl_editbox(s, "X display location", 'x', 50,
|
|
|
|
HELPCTX(ssh_tunnels_x11),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_x11_display), ED_STR);
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_radiobuttons(s, "Remote X11 authentication protocol", 'u', 2,
|
|
|
|
HELPCTX(ssh_tunnels_x11auth),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_x11_auth),
|
|
|
|
"MIT-Magic-Cookie-1", I(X11_MIT),
|
2022-06-01 10:14:21 +00:00
|
|
|
"XDM-Authorization-1", I(X11_XDM));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Tunnels panel _is_ still available in mid-session.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Tunnels",
|
|
|
|
"Options controlling SSH port forwarding");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
|
|
|
|
"Port forwarding");
|
|
|
|
ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
|
|
|
|
HELPCTX(ssh_tunnels_portfwd_localhost),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_lport_acceptall));
|
|
|
|
ctrl_checkbox(s, "Remote ports do the same (SSH-2 only)", 'p',
|
|
|
|
HELPCTX(ssh_tunnels_portfwd_localhost),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_rport_acceptall));
|
|
|
|
|
|
|
|
ctrl_columns(s, 3, 55, 20, 25);
|
|
|
|
c = ctrl_text(s, "Forwarded ports:", HELPCTX(ssh_tunnels_portfwd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
c->column = COLUMN_FIELD(0,2);
|
2019-09-08 19:29:00 +00:00
|
|
|
/* You want to select from the list, _then_ hit Remove. So tab order
|
|
|
|
* should be that way round. */
|
|
|
|
pfd = (struct portfwd_data *)ctrl_alloc(b,sizeof(struct portfwd_data));
|
|
|
|
pfd->rembutton = ctrl_pushbutton(s, "Remove", 'r',
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
pfd->rembutton->column = 2;
|
|
|
|
pfd->rembutton->delay_taborder = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
pfd->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd));
|
|
|
|
pfd->listbox->listbox.height = 3;
|
|
|
|
pfd->listbox->listbox.ncols = 2;
|
|
|
|
pfd->listbox->listbox.percentages = snewn(2, int);
|
|
|
|
pfd->listbox->listbox.percentages[0] = 20;
|
|
|
|
pfd->listbox->listbox.percentages[1] = 80;
|
|
|
|
ctrl_tabdelay(s, pfd->rembutton);
|
|
|
|
ctrl_text(s, "Add new forwarded port:", HELPCTX(ssh_tunnels_portfwd));
|
|
|
|
/* You want to enter source, destination and type, _then_ hit Add.
|
|
|
|
* Again, we adjust the tab order to reflect this. */
|
|
|
|
pfd->addbutton = ctrl_pushbutton(s, "Add", 'd',
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
pfd->addbutton->column = 2;
|
|
|
|
pfd->addbutton->delay_taborder = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
pfd->sourcebox = ctrl_editbox(s, "Source port", 's', 40,
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd), P(NULL));
|
Restructure dlgcontrol as a struct with an anon union.
This gets rid of that awkward STANDARD_PREFIX system in which every
branch of the old 'union control' had to repeat all the generic
fields, and then call sites had to make an arbitrary decision about
which branch to access them through.
That was the best we could do before accepting C99 features in this
code base. But now we have anonymous unions, so we don't need to put
up with that nonsense any more!
'dlgcontrol' is now a struct rather than a union, and the generic
fields common to all control types are ordinary members of the struct,
so you don't have to refer to them as ctrl->generic.foo at all, just
ctrl->foo, which saves verbiage at the point of use.
The extra per-control fields are still held in structures named after
the control type, so you'll still say ctrl->listbox.height or
whatever. But now those structures are themselves members of an
anonymous union field following the generic fields, so those
sub-structures don't have to reiterate all the standard stuff too.
While I'm here, I've promoted 'context2' from an editbox-specific
field to a generic one (it just seems silly _not_ to allow any control
to have two context fields if it needs it). Also, I had to rename the
boolean field 'tabdelay' to avoid it clashing with the subsidiary
structure field 'tabdelay', now that the former isn't generic.tabdelay
any more.
2022-05-01 08:55:52 +00:00
|
|
|
pfd->sourcebox->column = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
pfd->destbox = ctrl_editbox(s, "Destination", 'i', 67,
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd), P(NULL));
|
|
|
|
pfd->direction = ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
|
|
|
|
HELPCTX(ssh_tunnels_portfwd),
|
|
|
|
portfwd_handler, P(pfd),
|
|
|
|
"Local", 'l', P(NULL),
|
|
|
|
"Remote", 'm', P(NULL),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Dynamic", 'y', P(NULL));
|
2004-12-30 16:45:11 +00:00
|
|
|
#ifndef NO_IPV6
|
2019-09-08 19:29:00 +00:00
|
|
|
pfd->addressfamily =
|
|
|
|
ctrl_radiobuttons(s, NULL, NO_SHORTCUT, 3,
|
|
|
|
HELPCTX(ssh_tunnels_portfwd_ipversion),
|
|
|
|
portfwd_handler, P(pfd),
|
|
|
|
"Auto", 'u', I(ADDRTYPE_UNSPEC),
|
|
|
|
"IPv4", '4', I(ADDRTYPE_IPV4),
|
2022-06-01 10:14:21 +00:00
|
|
|
"IPv6", '6', I(ADDRTYPE_IPV6));
|
2005-01-09 11:44:21 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_tabdelay(s, pfd->addbutton);
|
|
|
|
ctrl_columns(s, 1, 100);
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
/*
|
|
|
|
* The Connection/SSH/Bugs panels.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SSH/Bugs",
|
|
|
|
"Workarounds for SSH server bugs");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/Bugs", "main",
|
|
|
|
"Detection of known bugs in SSH servers");
|
|
|
|
ctrl_droplist(s, "Chokes on SSH-2 ignore messages", '2', 20,
|
|
|
|
HELPCTX(ssh_bugs_ignore2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_ignore2));
|
|
|
|
ctrl_droplist(s, "Handles SSH-2 key re-exchange badly", 'k', 20,
|
|
|
|
HELPCTX(ssh_bugs_rekey2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_rekey2));
|
|
|
|
ctrl_droplist(s, "Chokes on PuTTY's SSH-2 'winadj' requests", 'j',
|
2012-07-28 19:30:12 +00:00
|
|
|
20, HELPCTX(ssh_bugs_winadj),
|
2019-09-08 19:29:00 +00:00
|
|
|
sshbug_handler, I(CONF_sshbug_winadj));
|
|
|
|
ctrl_droplist(s, "Replies to requests on closed channels", 'q', 20,
|
|
|
|
HELPCTX(ssh_bugs_chanreq),
|
|
|
|
sshbug_handler, I(CONF_sshbug_chanreq));
|
|
|
|
ctrl_droplist(s, "Ignores SSH-2 maximum packet size", 'x', 20,
|
|
|
|
HELPCTX(ssh_bugs_maxpkt2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_maxpkt2));
|
|
|
|
|
Bug workaround to delay sending our SSH greeting.
Ian Jackson recently tried to use the recipe in the psusan manpage for
talking to UML, and found that the connection was not successfully set
up, because at some point during startup, UML read the SSH greeting
(ok, the bare-ssh-connection greeting) from its input fd and threw it
away. So by the time psusan was run by the guest init process, the
greeting wasn't there to be read.
Ian's report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
I was also able to reproduce this locally, which makes me wonder why I
_didn't_ notice it when I originally wrote that part of the psusan man
page. It worked for me before, honest! But now it doesn't.
Anyway. The ssh verstring module already has a mode switch to decide
whether we ought to send our greeting before or after waiting for the
other side's greeting (because that decision varies between client and
server, and between SSH-1 and SSH-2). So it's easy to implement an
override that forces it to 'wait for the server greeting first'.
I've added this as yet another bug workaround flag. But unlike all the
others, it can't be autodetected from the server's version string,
because, of course, we have to act on it _before_ seeing the server's
greeting and version string! So it's a manual-only flag.
However, I've mentioned it in the UML section of the psusan man page,
since that's the place where I _know_ people are likely to need to use
this flag.
2021-08-14 09:56:20 +00:00
|
|
|
s = ctrl_getset(b, "Connection/SSH/Bugs", "manual",
|
|
|
|
"Manually enabled workarounds");
|
|
|
|
ctrl_droplist(s, "Discards data sent before its greeting", 'd', 20,
|
|
|
|
HELPCTX(ssh_bugs_dropstart),
|
|
|
|
sshbug_handler_manual_only,
|
|
|
|
I(CONF_sshbug_dropstart));
|
New bug workaround: KEXINIT filtering.
We've occasionally had reports of SSH servers disconnecting as soon as
they receive PuTTY's KEXINIT. I think all such reports have involved
the kind of simple ROM-based SSH server software you find in small
embedded devices.
I've never been able to prove it, but I've always suspected that one
possible cause of this is simply that PuTTY's KEXINIT is _too long_,
either in number of algorithms listed or in total length (especially
given all the ones that end in @very.long.domain.name suffixes).
If I'm right about either of those being the cause, then it's just
become even more likely to happen, because of all the extra
Diffie-Hellman groups and GSSAPI algorithms we just threw into our
already-long list in the previous few commits.
A workaround I've had in mind for ages is to wait for the server's
KEXINIT, and then filter our own down to just the algorithms the
server also mentioned. Then our KEXINIT is no longer than that of the
server, and hence, presumably fits in whatever buffer it has. So I've
implemented that workaround, in anticipation of it being needed in the
near future.
(Well ... it's not _quite_ true that our KEXINIT is at most the same
length as the server. In fact I had to leave in one KEXINIT item that
won't match anything in the server's list, namely "ext-info-c" which
gates access to SHA-2 based RSA. So if we turn out to support
absolutely everything on all the server's lists, then our KEXINIT
would be a few bytes longer than the server's, even with this
workaround. But that would only cause trouble if the server's outgoing
KEXINIT was skating very close to whatever buffer size it has for the
incoming one, and I'm guessing that's not very likely.)
((Another possible cause of this kind of disconnection would be a
server that simply objects to seeing any KEXINIT string it doesn't
know how to speak. But _surely_ no such server would have survived
initial testing against any full-featured client at all!))
2022-08-30 17:51:33 +00:00
|
|
|
ctrl_droplist(s, "Chokes on PuTTY's full KEXINIT", 'p', 20,
|
|
|
|
HELPCTX(ssh_bugs_filter_kexinit),
|
|
|
|
sshbug_handler_manual_only,
|
|
|
|
I(CONF_sshbug_filter_kexinit));
|
Bug workaround to delay sending our SSH greeting.
Ian Jackson recently tried to use the recipe in the psusan manpage for
talking to UML, and found that the connection was not successfully set
up, because at some point during startup, UML read the SSH greeting
(ok, the bare-ssh-connection greeting) from its input fd and threw it
away. So by the time psusan was run by the guest init process, the
greeting wasn't there to be read.
Ian's report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=991958
I was also able to reproduce this locally, which makes me wonder why I
_didn't_ notice it when I originally wrote that part of the psusan man
page. It worked for me before, honest! But now it doesn't.
Anyway. The ssh verstring module already has a mode switch to decide
whether we ought to send our greeting before or after waiting for the
other side's greeting (because that decision varies between client and
server, and between SSH-1 and SSH-2). So it's easy to implement an
override that forces it to 'wait for the server greeting first'.
I've added this as yet another bug workaround flag. But unlike all the
others, it can't be autodetected from the server's version string,
because, of course, we have to act on it _before_ seeing the server's
greeting and version string! So it's a manual-only flag.
However, I've mentioned it in the UML section of the psusan man page,
since that's the place where I _know_ people are likely to need to use
this flag.
2021-08-14 09:56:20 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_settitle(b, "Connection/SSH/More bugs",
|
|
|
|
"Further workarounds for SSH server bugs");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SSH/More bugs", "main",
|
|
|
|
"Detection of known bugs in SSH servers");
|
2023-05-05 22:19:22 +00:00
|
|
|
ctrl_droplist(s, "Old RSA/SHA2 cert algorithm naming", 'l', 20,
|
2023-05-04 17:24:18 +00:00
|
|
|
HELPCTX(ssh_bugs_rsa_sha2_cert_userauth),
|
|
|
|
sshbug_handler,
|
|
|
|
I(CONF_sshbug_rsa_sha2_cert_userauth));
|
2019-09-08 19:29:00 +00:00
|
|
|
ctrl_droplist(s, "Requires padding on SSH-2 RSA signatures", 'p', 20,
|
|
|
|
HELPCTX(ssh_bugs_rsapad2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_rsapad2));
|
|
|
|
ctrl_droplist(s, "Only supports pre-RFC4419 SSH-2 DH GEX", 'd', 20,
|
|
|
|
HELPCTX(ssh_bugs_oldgex2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_oldgex2));
|
|
|
|
ctrl_droplist(s, "Miscomputes SSH-2 HMAC keys", 'm', 20,
|
|
|
|
HELPCTX(ssh_bugs_hmac2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_hmac2));
|
|
|
|
ctrl_droplist(s, "Misuses the session ID in SSH-2 PK auth", 'n', 20,
|
|
|
|
HELPCTX(ssh_bugs_pksessid2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_pksessid2));
|
|
|
|
ctrl_droplist(s, "Miscomputes SSH-2 encryption keys", 'e', 20,
|
|
|
|
HELPCTX(ssh_bugs_derivekey2),
|
|
|
|
sshbug_handler, I(CONF_sshbug_derivekey2));
|
|
|
|
ctrl_droplist(s, "Chokes on SSH-1 ignore messages", 'i', 20,
|
|
|
|
HELPCTX(ssh_bugs_ignore1),
|
|
|
|
sshbug_handler, I(CONF_sshbug_ignore1));
|
|
|
|
ctrl_droplist(s, "Refuses all SSH-1 password camouflage", 's', 20,
|
|
|
|
HELPCTX(ssh_bugs_plainpw1),
|
|
|
|
sshbug_handler, I(CONF_sshbug_plainpw1));
|
|
|
|
ctrl_droplist(s, "Chokes on SSH-1 RSA authentication", 'r', 20,
|
|
|
|
HELPCTX(ssh_bugs_rsa1),
|
|
|
|
sshbug_handler, I(CONF_sshbug_rsa1));
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|
2020-03-10 07:06:44 +00:00
|
|
|
|
2020-03-10 21:18:08 +00:00
|
|
|
if (DISPLAY_RECONFIGURABLE_PROTOCOL(PROT_SERIAL)) {
|
|
|
|
const BackendVtable *ser_vt = backend_vt_from_proto(PROT_SERIAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Connection/Serial panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/Serial",
|
|
|
|
"Options controlling local serial lines");
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
/*
|
|
|
|
* We don't permit switching to a different serial port in
|
|
|
|
* midflight, although we do allow all other
|
|
|
|
* reconfiguration.
|
|
|
|
*/
|
|
|
|
s = ctrl_getset(b, "Connection/Serial", "serline",
|
|
|
|
"Select a serial line");
|
|
|
|
ctrl_editbox(s, "Serial line to connect to", 'l', 40,
|
|
|
|
HELPCTX(serial_line),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_serline), ED_STR);
|
2020-03-10 21:18:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
|
|
|
|
ctrl_editbox(s, "Speed (baud)", 's', 40,
|
|
|
|
HELPCTX(serial_speed),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_serspeed), ED_INT);
|
2020-03-10 21:18:08 +00:00
|
|
|
ctrl_editbox(s, "Data bits", 'b', 40,
|
|
|
|
HELPCTX(serial_databits),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_serdatabits), ED_INT);
|
2020-03-10 21:18:08 +00:00
|
|
|
/*
|
|
|
|
* Stop bits come in units of one half.
|
|
|
|
*/
|
2022-08-24 06:56:45 +00:00
|
|
|
static const struct conf_editbox_handler_type conf_editbox_stopbits = {
|
|
|
|
.type = EDIT_FIXEDPOINT, .denominator = 2};
|
|
|
|
|
2020-03-10 21:18:08 +00:00
|
|
|
ctrl_editbox(s, "Stop bits", 't', 40,
|
|
|
|
HELPCTX(serial_stopbits),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_serstopbits),
|
|
|
|
CP(&conf_editbox_stopbits));
|
2020-03-10 21:18:08 +00:00
|
|
|
ctrl_droplist(s, "Parity", 'p', 40,
|
|
|
|
HELPCTX(serial_parity), serial_parity_handler,
|
|
|
|
I(ser_vt->serial_parity_mask));
|
|
|
|
ctrl_droplist(s, "Flow control", 'f', 40,
|
|
|
|
HELPCTX(serial_flow), serial_flow_handler,
|
|
|
|
I(ser_vt->serial_flow_mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DISPLAY_RECONFIGURABLE_PROTOCOL(PROT_TELNET)) {
|
2020-03-10 07:06:44 +00:00
|
|
|
/*
|
|
|
|
* The Connection/Telnet panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/Telnet",
|
|
|
|
"Options controlling Telnet connections");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Telnet", "protocol",
|
|
|
|
"Telnet protocol adjustments");
|
|
|
|
|
|
|
|
if (!midsession) {
|
|
|
|
ctrl_radiobuttons(s, "Handling of OLD_ENVIRON ambiguity:",
|
|
|
|
NO_SHORTCUT, 2,
|
|
|
|
HELPCTX(telnet_oldenviron),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_rfc_environ),
|
|
|
|
"BSD (commonplace)", 'b', I(false),
|
2022-06-01 10:14:21 +00:00
|
|
|
"RFC 1408 (unusual)", 'f', I(true));
|
2020-03-10 07:06:44 +00:00
|
|
|
ctrl_radiobuttons(s, "Telnet negotiation mode:", 't', 2,
|
|
|
|
HELPCTX(telnet_passive),
|
|
|
|
conf_radiobutton_bool_handler,
|
|
|
|
I(CONF_passive_telnet),
|
2022-06-01 10:14:21 +00:00
|
|
|
"Passive", I(true), "Active", I(false));
|
2020-03-10 07:06:44 +00:00
|
|
|
}
|
|
|
|
ctrl_checkbox(s, "Keyboard sends Telnet special commands", 'k',
|
|
|
|
HELPCTX(telnet_specialkeys),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_telnet_keyboard));
|
|
|
|
ctrl_checkbox(s, "Return key sends Telnet New Line instead of ^M",
|
|
|
|
'm', HELPCTX(telnet_newline),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_telnet_newline));
|
|
|
|
}
|
|
|
|
|
2020-03-10 21:18:08 +00:00
|
|
|
if (DISPLAY_NON_RECONFIGURABLE_PROTOCOL(PROT_RLOGIN)) {
|
2020-03-10 07:06:44 +00:00
|
|
|
/*
|
|
|
|
* The Connection/Rlogin panel.
|
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/Rlogin",
|
|
|
|
"Options controlling Rlogin connections");
|
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/Rlogin", "data",
|
|
|
|
"Data to send to the server");
|
|
|
|
ctrl_editbox(s, "Local username:", 'l', 50,
|
|
|
|
HELPCTX(rlogin_localuser),
|
2022-08-24 06:56:45 +00:00
|
|
|
conf_editbox_handler, I(CONF_localusername), ED_STR);
|
2020-03-10 07:06:44 +00:00
|
|
|
|
2020-03-10 21:18:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (DISPLAY_NON_RECONFIGURABLE_PROTOCOL(PROT_SUPDUP)) {
|
2020-03-10 07:06:44 +00:00
|
|
|
/*
|
2020-03-10 21:18:08 +00:00
|
|
|
* The Connection/SUPDUP panel.
|
2020-03-10 07:06:44 +00:00
|
|
|
*/
|
|
|
|
ctrl_settitle(b, "Connection/SUPDUP",
|
2021-04-10 14:30:19 +00:00
|
|
|
"Options controlling SUPDUP connections");
|
2020-03-10 07:06:44 +00:00
|
|
|
|
|
|
|
s = ctrl_getset(b, "Connection/SUPDUP", "main", NULL);
|
|
|
|
|
|
|
|
ctrl_editbox(s, "Location string", 'l', 70,
|
|
|
|
HELPCTX(supdup_location),
|
|
|
|
conf_editbox_handler, I(CONF_supdup_location),
|
2022-08-24 06:56:45 +00:00
|
|
|
ED_STR);
|
2020-03-10 07:06:44 +00:00
|
|
|
|
2021-04-10 14:30:19 +00:00
|
|
|
ctrl_radiobuttons(s, "Extended ASCII Character set:", 'e', 4,
|
2020-03-10 07:06:44 +00:00
|
|
|
HELPCTX(supdup_ascii),
|
|
|
|
conf_radiobutton_handler,
|
|
|
|
I(CONF_supdup_ascii_set),
|
|
|
|
"None", I(SUPDUP_CHARSET_ASCII),
|
|
|
|
"ITS", I(SUPDUP_CHARSET_ITS),
|
2022-06-01 10:14:21 +00:00
|
|
|
"WAITS", I(SUPDUP_CHARSET_WAITS));
|
2020-03-10 07:06:44 +00:00
|
|
|
|
|
|
|
ctrl_checkbox(s, "**MORE** processing", 'm',
|
|
|
|
HELPCTX(supdup_more),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_supdup_more));
|
|
|
|
|
|
|
|
ctrl_checkbox(s, "Terminal scrolling", 's',
|
|
|
|
HELPCTX(supdup_scroll),
|
|
|
|
conf_checkbox_handler,
|
|
|
|
I(CONF_supdup_scroll));
|
|
|
|
}
|
2003-03-05 22:07:40 +00:00
|
|
|
}
|