AmendHub

Download:

jcs

/

wallops

/

amendments

/

13

irc: Support IRC server passwords for automatic NickServ identification

This was much harder than it needed to be because there is no
way to have password fields in a dialog box. We are now faking it by
intercepting keystrokes on such fields and manipulating a char array
behind the scenes while just passing • characters to the TextEdit
control.

jcs made amendment 13 over 2 years ago
--- chatter.c Sun Feb 6 19:30:43 2022 +++ chatter.c Mon Feb 7 16:51:10 2022 @@ -35,8 +35,8 @@ void chatter_atexit(struct focusable *focusable); void chatter_init(const char *server, const unsigned short port, - const char *nick, const char *ident, const char *realname, - const char *channel) + const char *password, const char *nick, const char *ident, + const char *realname, const char *channel) { struct focusable *focusable; struct chatter *chatter; @@ -51,10 +51,13 @@ chatter_init(const char *server, const unsigned short chatter->irc_state = IRC_STATE_UNINITED; chatter->irc_hostname = xstrdup(server); chatter->irc_port = port; + if (password && password[0]) + chatter->irc_password = xstrdup(password); chatter->irc_nick = xstrdup(nick); chatter->irc_ident = xstrdup(ident); chatter->irc_realname = xstrdup(realname); - chatter->irc_channel_autojoin = xstrdup(channel); + if (channel && channel[0]) + chatter->irc_channel_autojoin = xstrdup(channel); bounds.left = padding; bounds.top = screenBits.bounds.top + padding + --- chatter.h Sun Feb 6 19:37:55 2022 +++ chatter.h Mon Feb 7 12:57:14 2022 @@ -47,10 +47,11 @@ #define CONNECT_DLOG_ID 129 #define CONNECT_SERVER_ID 2 #define CONNECT_PORT_ID 3 -#define CONNECT_NICK_ID 4 -#define CONNECT_IDENT_ID 5 -#define CONNECT_REALNAME_ID 6 -#define CONNECT_CHANNEL_ID 7 +#define CONNECT_PASSWORD_ID 4 +#define CONNECT_NICK_ID 5 +#define CONNECT_IDENT_ID 6 +#define CONNECT_REALNAME_ID 7 +#define CONNECT_CHANNEL_ID 8 #define STR_SERVER_ID 1000 #define STR_PORT_ID 1001 @@ -58,6 +59,7 @@ #define STR_IDENT_ID 1003 #define STR_REALNAME_ID 1004 #define STR_CHANNEL_ID 1005 +#define STR_PASSWORD_ID 1006 #define DEFAULT_SERVER_NAME "irc.libera.chat" #define DEFAULT_PORT "6667" @@ -93,6 +95,7 @@ struct chatter { short irc_state; char *irc_hostname; short irc_port; + char *irc_password; char *irc_nick; char *irc_ident; char *irc_realname; @@ -121,8 +124,8 @@ void close_focusable(struct focusable *focusable); void hide_focusable(struct focusable *focusable); void chatter_init(const char *server, const unsigned short port, - const char *nick, const char *ident, const char *realname, - const char *channel); + const char *nick, const char *password, const char *ident, + const char *realname, const char *channel); void chatter_update_titlebar(struct chatter *chatter); size_t chatter_printf(struct chatter *chatter, const char *format, ...); void chatter_sync_nick_list(struct chatter *chatter, bool initial_sync); --- irc.c Sun Feb 6 20:17:09 2022 +++ irc.c Mon Feb 7 16:52:11 2022 @@ -276,6 +276,12 @@ irc_login(struct chatter *chatter) if (!irc_can_send(chatter)) return; + if (chatter->irc_password && chatter->irc_password[0]) { + len = snprintf(chatter->irc_line, sizeof(chatter->irc_line), + "PASS %s\r\n", chatter->irc_password); + irc_send(chatter, chatter->irc_line, len); + } + len = snprintf(chatter->irc_line, sizeof(chatter->irc_line), "NICK %s\r\n", chatter->irc_nick); irc_send(chatter, chatter->irc_line, len); @@ -284,7 +290,7 @@ irc_login(struct chatter *chatter) "USER %s 8 * :%s\r\n", chatter->irc_ident, chatter->irc_realname); irc_send(chatter, chatter->irc_line, len); - if (chatter->irc_channel_autojoin) { + if (chatter->irc_channel_autojoin && chatter->irc_channel_autojoin[0]) { len = snprintf(chatter->irc_line, sizeof(chatter->irc_line), "JOIN %s\r\n", chatter->irc_channel_autojoin); irc_send(chatter, chatter->irc_line, len); --- main.c Sun Feb 6 20:21:15 2022 +++ main.c Mon Feb 7 16:49:02 2022 @@ -27,7 +27,8 @@ NMRec notification = { 0 }; enum { CONFIG_TYPE_STRING, - CONFIG_TYPE_SHORT + CONFIG_TYPE_SHORT, + CONFIG_TYPE_PASSWORD }; struct config_field { @@ -38,11 +39,14 @@ struct config_field { short ditl_id; short res_id; char sdefault[32]; + char password_storage[256]; } config_fields[] = { { "Server Name", CONFIG_TYPE_STRING, 1, 0, CONNECT_SERVER_ID, STR_SERVER_ID, DEFAULT_SERVER_NAME }, { "Server Port", CONFIG_TYPE_SHORT, 1, 65535, CONNECT_PORT_ID, STR_PORT_ID, DEFAULT_PORT }, + { "Server Password", CONFIG_TYPE_PASSWORD, 0, 0, + CONNECT_PASSWORD_ID, STR_PASSWORD_ID, "" }, { "Nickname", CONFIG_TYPE_STRING, 1, 0, CONNECT_NICK_ID, STR_NICK_ID, "" }, { "Ident", CONFIG_TYPE_STRING, 1, 0, @@ -202,12 +206,12 @@ main(void) short show_connect_dialog(void) { - Str255 txt, server, ports, nick, ident, realname, channel; + Str255 txt, server, ports, nick, ident, realname, channel, password; StringHandle h; DialogPtr dlg; Handle ihandle; Rect irect; - size_t size, n; + size_t size, n, m; long port; short hit, itype, ret; @@ -220,9 +224,25 @@ show_connect_dialog(void) GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect); + if (cf->type == CONFIG_TYPE_PASSWORD) { + PasswordDialogFieldFilterSetup(cf->ditl_id, + cf->password_storage, sizeof(cf->password_storage)); + } + if (cf->res_id && (h = GetString(cf->res_id))) { HLock(h); - SetIText(ihandle, *h); + if (cf->type == CONFIG_TYPE_PASSWORD) { + size = (*h)[0]; + for (m = 0; m < size; m++) + cf->password_storage[m] = '•'; + cf->password_storage[m] = '\0'; + CtoPstr(cf->password_storage); + SetIText(ihandle, cf->password_storage); + strlcpy(cf->password_storage, PtoCstr(*h), + sizeof(cf->password_storage)); + } else { + SetIText(ihandle, *h); + } HUnlock(h); ReleaseResource(h); } else if (cf->sdefault[0] != '\0') { @@ -235,7 +255,7 @@ show_connect_dialog(void) ShowWindow(dlg); get_input: - ModalDialog(ModalDialogFilter, &hit); + ModalDialog(PasswordDialogFieldFilter, &hit); switch (hit) { case -1: DisposeDialog(dlg); @@ -252,12 +272,17 @@ verify: long lval; short sval; - GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect); - GetIText(ihandle, txt); - PtoCstr(txt); - + if (cf->type == CONFIG_TYPE_PASSWORD) { + memcpy((char *)&txt, cf->password_storage, sizeof(txt)); + } else { + GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect); + GetIText(ihandle, txt); + PtoCstr(txt); + } + switch (cf->type) { case CONFIG_TYPE_STRING: + case CONFIG_TYPE_PASSWORD: if (cf->min && strlen((char *)txt) < cf->min) { warn("%s is too short (minimum %d)", cf->name, cf->min); goto get_input; @@ -287,6 +312,9 @@ verify: case CONNECT_PORT_ID: port = atol((char *)txt); break; + case CONNECT_PASSWORD_ID: + strlcpy((char *)&password, (char *)txt, sizeof(password)); + break; case CONNECT_NICK_ID: strlcpy((char *)&nick, (char *)txt, sizeof(nick)); break; @@ -315,10 +343,11 @@ verify: ReleaseResource(h); } + PasswordDialogFieldFinish(); DisposeDialog(dlg); - - chatter_init((char *)&server, port, (char *)&nick, (char *)&ident, - (char *)&realname, (char *)&channel); + + chatter_init((char *)&server, port, (char *)&password, (char *)&nick, + (char *)&ident, (char *)&realname, (char *)&channel); } bool @@ -450,7 +479,12 @@ close_focusable(struct focusable *focusable) } nfocusables--; - focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables); + if (nfocusables) + focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables); + else { + free(focusables); + focusables = NULL; + } if (nfocusables && focusables[0]->visible) SelectWindow(focusables[0]->win); --- util.c Thu Feb 3 16:34:58 2022 +++ util.c Mon Feb 7 16:06:20 2022 @@ -19,6 +19,8 @@ #include <stdlib.h> #include <string.h> #include <GestaltEqu.h> +#include <Script.h> +#include <SetUpA4.h> #include "util.h" /* ALRT resources */ @@ -1157,6 +1159,85 @@ ModalDialogFilter(DialogPtr dlg, EventRecord *event, s } return false; +} + +static short _password_dialog_ditl_id = -1; +static char *_password_dialog_storage = NULL; +static size_t _password_dialog_storage_len = 0; + +void +PasswordDialogFieldFilterSetup(short ditl_id, char *storage, size_t len) +{ + _password_dialog_ditl_id = ditl_id; + _password_dialog_storage = storage; + _password_dialog_storage_len = len; + + memset(_password_dialog_storage, 0, len); +} + +pascal bool +PasswordDialogFieldFilter(DialogPtr dlg, EventRecord *event, short *hit) +{ + DialogPeek dlgp; + WindowPtr event_win; + short event_in, sel_start, sel_end; + char key; + + dlgp = (DialogPeek)dlg; + if (dlgp->editField == _password_dialog_ditl_id - 1) { + sel_start = (*(dlgp->textH))->selStart; + sel_end = (*(dlgp->textH))->selEnd; + + switch (event->what) { + case keyDown: + case autoKey: + key = event->message & charCodeMask; + if (event->modifiers & cmdKey) { + /* TODO: implement DlgPaste for cmd+v? */ + event->what = nullEvent; + return false; + } + + if (key == 8) { + /* backspace */ + if (sel_start == sel_end && sel_start > 0) + memmove(_password_dialog_storage + sel_start - 1, + _password_dialog_storage + sel_start, + _password_dialog_storage_len - sel_start - 1); + else if (sel_start != sel_end) + memmove(_password_dialog_storage + sel_start, + _password_dialog_storage + sel_end, + _password_dialog_storage_len - sel_end - 1); + } else if (sel_start >= _password_dialog_storage_len) { + event->what = nullEvent; + return false; + } else if (key >= ' ' && key <= '~') { + if (sel_start != sel_end) + /* delete selection before making space for new char */ + memmove(_password_dialog_storage + sel_start, + _password_dialog_storage + sel_end, + _password_dialog_storage_len - sel_end - 1); + memmove(_password_dialog_storage + sel_start + 1, + _password_dialog_storage + sel_start, + _password_dialog_storage_len - sel_start - 1); + _password_dialog_storage[sel_start] = key; + event->message = '•'; + } + _password_dialog_storage[(*(dlgp->textH))->teLength + 1] = '\0'; + sel_start = 0; + break; + } + } + + return ModalDialogFilter(dlg, event, hit); +} + +void +PasswordDialogFieldFinish(void) +{ + _password_dialog_ditl_id = -1; + _password_dialog_storage = NULL; + _password_dialog_storage_len = 0; } /* (*(some_te))->caretHook = NullCaretHook; */ --- util.h Thu Feb 3 16:26:22 2022 +++ util.h Mon Feb 7 16:05:45 2022 @@ -122,6 +122,11 @@ void SetTrackControlTE(TEHandle te); pascal void TrackMouseDownInControl(ControlHandle control, short part); pascal bool ModalDialogFilter(DialogPtr dlg, EventRecord *event, short *hit); +void PasswordDialogFieldFilterSetup(short ditl_id, char *storage, + size_t len); +pascal bool PasswordDialogFieldFilter(DialogPtr dlg, EventRecord *event, + short *hit); +void PasswordDialogFieldFinish(void); pascal void NullCaretHook(void); #endif --- wallops.π.r Sun Feb 6 20:34:55 2022 +++ wallops.π.r Mon Feb 7 17:04:12 2022 @@ -32,34 +32,29 @@ data 'DITL' (128) { }; data 'DITL' (129, "CONNECT_DITL") { - $"000C 0000 0000 00BE 006E 00D2 00B8 0407" /* .......æ.n.“.∏.. */ - $"436F 6E6E 6563 7400 0000 0000 000A 006E" /* Connect........n */ - $"001A 011B 1000 0000 0000 0028 006E 0038" /* ...........(.n.8 */ - $"00A2 1004 3636 3637 0000 0000 0046 006E" /* .¢..6667.....F.n */ - $"0056 00CC 1000 0000 0000 0064 006E 0074" /* .V.Ã.......d.n.t */ - $"00CC 1000 0000 0000 0082 006E 0093 011C" /* .Ã.......Ç.n.ì.. */ - $"1000 0000 0000 00A0 006E 00B1 00CC 1000" /* .......†.n.±.Ã.. */ - $"0000 0000 000A 000A 001A 0055 8807 5365" /* ...........Uà.Se */ - $"7276 6572 3A0C 0000 0000 0028 000A 0038" /* rver:......(...8 */ - $"005E 880C 5365 7276 6572 2050 6F72 743A" /* .^à.Server Port: */ - $"0000 0000 0046 000A 0056 0055 8805 4E69" /* .....F...V.Uà.Ni */ - $"636B 3A06 0000 0000 0064 000A 0074 0055" /* ck:......d...t.U */ - $"8806 4964 656E 743A 0000 0000 0082 000A" /* à.Ident:.....Ç.. */ - $"0092 0055 880A 5265 616C 204E 616D 653A" /* .í.Uà.Real Name: */ - $"0000 0000 00A0 000A 00B0 0055 8808 4368" /* .....†...∞.Uà.Ch */ - $"616E 6E65 6C3A" /* annel: */ + $"000E 0000 0000 00DC 0096 00F0 00E0 0407" /* .........ñ...... */ + $"436F 6E6E 6563 7400 0000 0000 000A 0096" /* Connect........ñ */ + $"001A 0144 1000 0000 0000 0028 0096 0038" /* ...D.......(.ñ.8 */ + $"00CA 1004 3636 3637 0000 0000 0046 0096" /* . ..6667.....F.ñ */ + $"0056 00F4 1000 0000 0000 0064 0096 0074" /* .V.........d.ñ.t */ + $"00F4 1000 0000 0000 0082 0096 0092 00F4" /* .........Ç.ñ.í.. */ + $"1000 0000 0000 00A0 0096 00B0 0144 1000" /* .......†.ñ.∞.D.. */ + $"0000 0000 00BE 0096 00CE 00F4 1000 0000" /* .....æ.ñ.Œ...... */ + $"0000 000A 000A 001A 0055 8807 5365 7276" /* .........Uà.Serv */ + $"6572 3A0C 0000 0000 0028 000A 0038 005E" /* er:......(...8.^ */ + $"880C 5365 7276 6572 2050 6F72 743A 0000" /* à.Server Port:.. */ + $"0000 0046 000A 0056 0089 8810 5365 7276" /* ...F...V.âà.Serv */ + $"6572 2050 6173 7377 6F72 643A 0000 0000" /* er Password:.... */ + $"0064 000A 0074 0055 8805 4E69 636B 3A3A" /* .d...t.Uà.Nick:: */ + $"0000 0000 0082 000A 0092 0055 8806 4964" /* .....Ç...í.Uà.Id */ + $"656E 743A 0000 0000 00A0 000A 00B0 0055" /* ent:.....†...∞.U */ + $"880A 5265 616C 204E 616D 653A 0000 0000" /* à.Real Name:.... */ + $"00BE 000A 00CF 0072 880D 4A6F 696E 2043" /* .æ...œ.rà¬Join C */ + $"6861 6E6E 656C 3A00" /* hannel:. */ }; -data 'LDEF' (128, "mailbox list", purgeable) { - $"2F3A 0004 4E75 0000 0000" /* /:..Nu.... */ -}; - -data 'LDEF' (129, "message list") { - $"2F3A 0004 4E75 0000 0000" /* /:..Nu.... */ -}; - data 'DLOG' (129, "CONNECT_DLOG") { - $"0048 0066 0122 018E 0004 0000 0100 0000" /* .H.f.".é........ */ + $"003C 0056 0137 01A7 0004 0000 0100 0000" /* .<.V.7.ß........ */ $"0000 0081 1143 6F6E 6E65 6374 2074 6F20" /* ...Å.Connect to */ $"5365 7276 6572" /* Server */ };