pidgin/pidgin

Remove the Zephyr protocol plugin

20 months ago, Gary Kramlich
a6a511564c1b
Parents 63f39d354a73
Children 017e9a61a5ef
Remove the Zephyr protocol plugin

A lot of work has gone into trying to keep this protocol plugin alive, but after
much deliberation it's time to remove it.

I reached out on Twitter awhile ago to see if anyone used it and no one
responded.

As such, it's time to let it go.

Testing Done:
ran `meson --wipe` then did a full build and `ninja pidgin-pot`

Reviewed at https://reviews.imfreedom.org/r/1971/
  • +0 -1
    libpurple/protocols/meson.build
  • +0 -169
    libpurple/protocols/zephyr/ZAsyncLocate.c
  • +0 -53
    libpurple/protocols/zephyr/ZCkAuth.c
  • +0 -50
    libpurple/protocols/zephyr/ZCkIfNot.c
  • +0 -20
    libpurple/protocols/zephyr/ZClosePort.c
  • +0 -17
    libpurple/protocols/zephyr/ZCmpUID.c
  • +0 -23
    libpurple/protocols/zephyr/ZCmpUIDP.c
  • +0 -33
    libpurple/protocols/zephyr/ZFlsLocs.c
  • +0 -34
    libpurple/protocols/zephyr/ZFlsSubs.c
  • +0 -55
    libpurple/protocols/zephyr/ZFmtAuth.c
  • +0 -48
    libpurple/protocols/zephyr/ZFmtList.c
  • +0 -35
    libpurple/protocols/zephyr/ZFmtNotice.c
  • +0 -34
    libpurple/protocols/zephyr/ZFmtRaw.c
  • +0 -46
    libpurple/protocols/zephyr/ZFmtRawLst.c
  • +0 -31
    libpurple/protocols/zephyr/ZFmtSmRaw.c
  • +0 -18
    libpurple/protocols/zephyr/ZFreeNot.c
  • +0 -36
    libpurple/protocols/zephyr/ZGetLocs.c
  • +0 -54
    libpurple/protocols/zephyr/ZGetSender.c
  • +0 -37
    libpurple/protocols/zephyr/ZGetSubs.c
  • +0 -43
    libpurple/protocols/zephyr/ZGetWGPort.c
  • +0 -55
    libpurple/protocols/zephyr/ZIfNotice.c
  • +0 -180
    libpurple/protocols/zephyr/ZInit.c
  • +0 -159
    libpurple/protocols/zephyr/ZLocations.c
  • +0 -78
    libpurple/protocols/zephyr/ZMakeAscii.c
  • +0 -94
    libpurple/protocols/zephyr/ZMkAuth.c
  • +0 -40
    libpurple/protocols/zephyr/ZNewLocU.c
  • +0 -67
    libpurple/protocols/zephyr/ZOpenPort.c
  • +0 -285
    libpurple/protocols/zephyr/ZParseNot.c
  • +0 -24
    libpurple/protocols/zephyr/ZPeekNot.c
  • +0 -36
    libpurple/protocols/zephyr/ZPeekPkt.c
  • +0 -29
    libpurple/protocols/zephyr/ZPending.c
  • +0 -82
    libpurple/protocols/zephyr/ZReadAscii.c
  • +0 -47
    libpurple/protocols/zephyr/ZRecvNot.c
  • +0 -37
    libpurple/protocols/zephyr/ZRecvPkt.c
  • +0 -170
    libpurple/protocols/zephyr/ZRetSubs.c
  • +0 -41
    libpurple/protocols/zephyr/ZSendList.c
  • +0 -41
    libpurple/protocols/zephyr/ZSendNot.c
  • +0 -74
    libpurple/protocols/zephyr/ZSendPkt.c
  • +0 -19
    libpurple/protocols/zephyr/ZSetDest.c
  • +0 -180
    libpurple/protocols/zephyr/ZSubs.c
  • +0 -224
    libpurple/protocols/zephyr/ZVariables.c
  • +0 -62
    libpurple/protocols/zephyr/ZWait4Not.c
  • +0 -72
    libpurple/protocols/zephyr/ZhmStat.c
  • +0 -810
    libpurple/protocols/zephyr/Zinternal.c
  • +0 -40
    libpurple/protocols/zephyr/internal.h
  • +0 -85
    libpurple/protocols/zephyr/meson.build
  • +0 -24
    libpurple/protocols/zephyr/mit-copyright.h
  • +0 -19
    libpurple/protocols/zephyr/mit-sipb-copyright.h
  • +0 -0
    libpurple/protocols/zephyr/resources/icons/16x16/apps/im-zephyr.png
  • +0 -189
    libpurple/protocols/zephyr/resources/icons/16x16/apps/scalable/im-zephyr.svg
  • +0 -0
    libpurple/protocols/zephyr/resources/icons/22x22/apps/im-zephyr.png
  • +0 -212
    libpurple/protocols/zephyr/resources/icons/22x22/apps/scalable/im-zephyr.svg
  • +0 -0
    libpurple/protocols/zephyr/resources/icons/48x48/apps/im-zephyr.png
  • +0 -141
    libpurple/protocols/zephyr/resources/icons/scalable/apps/im-zephyr.svg
  • +0 -11
    libpurple/protocols/zephyr/resources/zephyr.gresource.xml
  • +0 -91
    libpurple/protocols/zephyr/sysdep.h
  • +0 -1876
    libpurple/protocols/zephyr/zephyr.c
  • +0 -32
    libpurple/protocols/zephyr/zephyr.h
  • +0 -87
    libpurple/protocols/zephyr/zephyr_account.h
  • +0 -28
    libpurple/protocols/zephyr/zephyr_err.h
  • +0 -406
    libpurple/protocols/zephyr/zephyr_html.c
  • +0 -43
    libpurple/protocols/zephyr/zephyr_html.h
  • +0 -370
    libpurple/protocols/zephyr/zephyr_internal.h
  • +0 -619
    libpurple/protocols/zephyr/zephyr_tzc.c
  • +0 -38
    libpurple/protocols/zephyr/zephyr_tzc.h
  • +0 -241
    libpurple/protocols/zephyr/zephyr_zeph02.c
  • +0 -38
    libpurple/protocols/zephyr/zephyr_zeph02.h
  • +1 -1
    libpurple/purpleprotocol.h
  • +1 -49
    meson.build
  • +0 -6
    meson_options.txt
  • +1 -1
    pidgin/data/im.pidgin.Pidgin3.desktop.in.in
  • +0 -47
    po/POTFILES.in
  • --- a/libpurple/protocols/meson.build Wed Oct 26 01:22:53 2022 -0500
    +++ b/libpurple/protocols/meson.build Wed Oct 26 01:39:49 2022 -0500
    @@ -7,4 +7,3 @@
    subdir('jabber')
    subdir('novell')
    subdir('sametime')
    -subdir('zephyr')
    --- a/libpurple/protocols/zephyr/ZAsyncLocate.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,169 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for asynchronous location functions.
    - *
    - * Created by: Marc Horowitz
    - *
    - * Copyright (c) 1990,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#include <purple.h>
    -
    -Code_t
    -ZRequestLocations(const char *user, ZAsyncLocateData_t *zald,
    - ZNotice_Kind_t kind, /* UNSAFE, UNACKED, or ACKED */
    - Z_AuthProc auth)
    -{
    - int retval;
    - ZNotice_t notice;
    - size_t userlen, versionlen;
    -
    - if (ZGetSocket() == NULL) {
    - retval = ZOpenPort(NULL);
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - }
    -
    - (void) memset((char *)&notice, 0, sizeof(notice));
    - notice.z_kind = kind;
    - notice.z_port = __Zephyr_port;
    - notice.z_class = LOCATE_CLASS;
    - notice.z_class_inst = user;
    - notice.z_opcode = LOCATE_LOCATE;
    - notice.z_sender = 0;
    - notice.z_recipient = "";
    - notice.z_default_format = "";
    - notice.z_message_len = 0;
    -
    - if ((retval = ZSendNotice(&notice, auth)) != ZERR_NONE)
    - return(retval);
    -
    - userlen = strlen(user) + 1;
    - versionlen = strlen(notice.z_version) + 1;
    - if ((zald->user = (char *) malloc(userlen)) == NULL) {
    - return(ENOMEM);
    - }
    - if ((zald->version = (char *) malloc(versionlen)) == NULL) {
    - free(zald->user);
    - return(ENOMEM);
    - }
    - zald->uid = notice.z_multiuid;
    - g_strlcpy(zald->user,user,userlen);
    - g_strlcpy(zald->version,notice.z_version,versionlen);
    -
    - return(ZERR_NONE);
    -}
    -
    -Code_t
    -ZParseLocations(ZNotice_t *notice, ZAsyncLocateData_t *zald, int *nlocs,
    - char **user)
    -{
    - char *ptr, *end;
    - int i;
    -
    - ZFlushLocations(); /* This never fails (this function is part of the
    - library, so it is allowed to know this). */
    -
    - /* non-matching protocol version numbers means the
    - server is probably an older version--must punt */
    -
    - if (zald && !purple_strequal(notice->z_version, zald->version))
    - return(ZERR_VERS);
    -
    - if (notice->z_kind == SERVNAK)
    - return (ZERR_SERVNAK);
    -
    - /* flag ACKs as special */
    - if (notice->z_kind == SERVACK &&
    - purple_strequal(notice->z_opcode, LOCATE_LOCATE)) {
    - *nlocs = -1;
    - return(ZERR_NONE);
    - }
    -
    - if (notice->z_kind != ACKED)
    - return (ZERR_INTERNAL);
    -
    - end = notice->z_message+notice->z_message_len;
    -
    - __locate_num = 0;
    -
    - for (ptr=notice->z_message;ptr<end;ptr++)
    - if (!*ptr)
    - __locate_num++;
    -
    - __locate_num /= 3;
    -
    - if (__locate_num)
    - {
    - __locate_list = (ZLocations_t *)malloc((unsigned)__locate_num*
    - sizeof(ZLocations_t));
    - if (!__locate_list)
    - return (ENOMEM);
    - } else {
    - __locate_list = NULL;
    - }
    -
    - for (ptr=notice->z_message, i=0; i<__locate_num; i++) {
    - unsigned int len;
    -
    - len = strlen (ptr) + 1;
    - __locate_list[i].host = (char *) malloc(len);
    - if (!__locate_list[i].host)
    - return (ENOMEM);
    - g_strlcpy(__locate_list[i].host, ptr,len);
    - ptr += len;
    -
    - len = strlen (ptr) + 1;
    - __locate_list[i].time = (char *) malloc(len);
    - if (!__locate_list[i].time)
    - return (ENOMEM);
    - g_strlcpy(__locate_list[i].time, ptr,len);
    - ptr += len;
    -
    - len = strlen (ptr) + 1;
    - __locate_list[i].tty = (char *) malloc(len);
    - if (!__locate_list[i].tty)
    - return (ENOMEM);
    - g_strlcpy(__locate_list[i].tty, ptr,len);
    - ptr += len;
    - }
    -
    - __locate_next = 0;
    - *nlocs = __locate_num;
    - if (user) {
    - size_t len;
    - if (zald) {
    - len = strlen(zald->user) + 1;
    - if ((*user = (char *) malloc(len)) == NULL)
    - return(ENOMEM);
    - g_strlcpy(*user,zald->user,len);
    - } else {
    - len = strlen(notice->z_class_inst) + 1;
    - if ((*user = (char *) malloc(len)) == NULL)
    - return(ENOMEM);
    - g_strlcpy(*user,notice->z_class_inst,len);
    - }
    - }
    - return (ZERR_NONE);
    -}
    -
    -int
    -ZCompareALDPred(ZNotice_t *notice, void *zald)
    -{
    - return(ZCompareUID(&(notice->z_multiuid),
    - &(((ZAsyncLocateData_t *) zald)->uid)));
    -}
    -
    -void
    -ZFreeALD(ZAsyncLocateData_t *zald)
    -{
    - if (!zald) return;
    -
    - free(zald->user);
    - free(zald->version);
    - (void) memset(zald, 0, sizeof(*zald));
    -}
    --- a/libpurple/protocols/zephyr/ZCkAuth.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,53 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZCheckAuthentication function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -/* Check authentication of the notice.
    - If it looks authentic but fails the Kerberos check, return -1.
    - If it looks authentic and passes the Kerberos check, return 1.
    - If it doesn't look authentic, return 0
    -
    - When not using Kerberos, return true if the notice claims to be authentic.
    - */
    -Code_t
    -ZCheckAuthentication(ZNotice_t *notice)
    -{
    -#ifdef ZEPHYR_USES_KERBEROS
    - int result;
    - ZChecksum_t our_checksum;
    - CREDENTIALS cred;
    -
    - /* If the value is already known, return it. */
    - if (notice->z_checked_auth != ZAUTH_UNSET)
    - return (notice->z_checked_auth);
    -
    - if (!notice->z_auth)
    - return (ZAUTH_NO);
    -
    - if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
    - __Zephyr_realm, &cred)) != 0)
    - return (ZAUTH_NO);
    -
    -#ifdef NOENCRYPTION
    - our_checksum = 0;
    -#else
    - our_checksum = des_quad_cksum(notice->z_packet, NULL,
    - notice->z_default_format+
    - strlen(notice->z_default_format)+1-
    - notice->z_packet, 0, (C_Block *)cred.session);
    -#endif
    - /* if mismatched checksum, then the packet was corrupted */
    - return ((our_checksum == notice->z_checksum) ? ZAUTH_YES : ZAUTH_FAILED);
    -
    -#else
    - return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
    -#endif
    -}
    --- a/libpurple/protocols/zephyr/ZCkIfNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,50 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZCheckIfNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZCheckIfNotice(ZNotice_t *notice, GSocketAddress **from,
    - register int (*predicate)(ZNotice_t *, void *), void *args)
    -{
    - ZNotice_t tmpnotice;
    - Code_t retval;
    - register char *buffer;
    - register Z_InputQ *qptr;
    -
    - if ((retval = Z_ReadEnqueue()) != ZERR_NONE)
    - return (retval);
    -
    - qptr = Z_GetFirstComplete();
    -
    - while (qptr) {
    - if ((retval = ZParseNotice(qptr->packet, qptr->packet_len,
    - &tmpnotice)) != ZERR_NONE)
    - return (retval);
    - if ((*predicate)(&tmpnotice, args)) {
    - if (!(buffer = (char *) malloc((unsigned) qptr->packet_len)))
    - return (ENOMEM);
    - (void) memcpy(buffer, qptr->packet, qptr->packet_len);
    - if (from) {
    - *from = g_object_ref(qptr->from);
    - }
    - if ((retval = ZParseNotice(buffer, qptr->packet_len,
    - notice)) != ZERR_NONE) {
    - free(buffer);
    - return (retval);
    - }
    - Z_RemQueue(qptr);
    - return (ZERR_NONE);
    - }
    - qptr = Z_GetNextComplete(qptr);
    - }
    -
    - return (ZERR_NONOTICE);
    -}
    --- a/libpurple/protocols/zephyr/ZClosePort.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,20 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZClosePort function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZClosePort(void)
    -{
    - g_clear_object(&__Zephyr_socket);
    - ZSetDestAddr(NULL);
    -
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZCmpUID.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,17 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZCompareUID function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -int
    -ZCompareUID(ZUnique_Id_t *uid1, ZUnique_Id_t *uid2)
    -{
    - return (!memcmp((char *)uid1, (char *)uid2, sizeof (*uid1)));
    -}
    --- a/libpurple/protocols/zephyr/ZCmpUIDP.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,23 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZCompareUIDPred function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -int
    -ZCompareUIDPred(ZNotice_t *notice, void *uid)
    -{
    - return (ZCompareUID(&notice->z_uid, (ZUnique_Id_t *) uid));
    -}
    -
    -int
    -ZCompareMultiUIDPred(ZNotice_t *notice, void *uid)
    -{
    - return (ZCompareUID(&notice->z_multiuid, (ZUnique_Id_t *) uid));
    -}
    --- a/libpurple/protocols/zephyr/ZFlsLocs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,33 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFlushLocations function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFlushLocations(void)
    -{
    - int i;
    -
    - if (!__locate_list)
    - return (ZERR_NONE);
    -
    - for (i=0;i<__locate_num;i++) {
    - free(__locate_list[i].host);
    - free(__locate_list[i].time);
    - free(__locate_list[i].tty);
    - }
    -
    - free((char *)__locate_list);
    -
    - __locate_list = NULL;
    - __locate_num = 0;
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFlsSubs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,34 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFlushSubscriptions function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFlushSubscriptions(void)
    -{
    - register int i;
    -
    - if (!__subscriptions_list)
    - return (ZERR_NONE);
    -
    - for (i=0;i<__subscriptions_num;i++) {
    - free(__subscriptions_list[i].zsub_class);
    - free(__subscriptions_list[i].zsub_classinst);
    - free(__subscriptions_list[i].zsub_recipient);
    - }
    -
    - free((char *)__subscriptions_list);
    -
    - __subscriptions_list = NULL;
    - __subscriptions_num = 0;
    -
    - return (ZERR_NONE);
    -}
    -
    --- a/libpurple/protocols/zephyr/ZFmtAuth.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,55 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatAuthenticNotice function.
    - *
    - * Created by: Robert French
    -
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    -Code_t
    -ZFormatAuthenticNotice(ZNotice_t *notice, register char *buffer,
    - register int buffer_len, int *len, C_Block session)
    -{
    - ZNotice_t newnotice;
    - char *ptr;
    - int retval, hdrlen;
    -
    - newnotice = *notice;
    - newnotice.z_auth = 1;
    - newnotice.z_authent_len = 0;
    - newnotice.z_ascii_authent = "";
    -
    - if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
    - &hdrlen, &ptr, NULL)) != ZERR_NONE)
    - return (retval);
    -
    -#ifdef NOENCRYPTION
    - newnotice.z_checksum = 0;
    -#else
    - newnotice.z_checksum =
    - (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, (C_Block*)session);
    -#endif
    - if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
    - &hdrlen, NULL, NULL)) != ZERR_NONE)
    - return (retval);
    -
    - ptr = buffer+hdrlen;
    -
    - if (newnotice.z_message_len+hdrlen > buffer_len)
    - return (ZERR_PKTLEN);
    -
    - (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
    -
    - *len = hdrlen+newnotice.z_message_len;
    -
    - if (*len > Z_MAXPKTLEN)
    - return (ZERR_PKTLEN);
    -
    - return (ZERR_NONE);
    -}
    -#endif
    --- a/libpurple/protocols/zephyr/ZFmtList.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,48 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatNoticeList function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFormatNoticeList(ZNotice_t *notice, register char **list, int nitems,
    - char **buffer, int *ret_len, Z_AuthProc cert_routine)
    -{
    - char header[Z_MAXHEADERLEN];
    - register int i;
    - int hdrlen, size;
    - char *ptr;
    - Code_t retval;
    -
    - if ((retval = Z_FormatHeader(notice, header, sizeof(header), &hdrlen,
    - cert_routine)) != ZERR_NONE)
    - return (retval);
    -
    - size = 0;
    - for (i=0;i<nitems;i++)
    - size += strlen(list[i])+1;
    -
    - *ret_len = hdrlen+size;
    -
    - /* *ret_len can never be zero here, no need to worry about malloc(0). */
    - if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
    - return (ENOMEM);
    -
    - (void) memcpy(*buffer, header, hdrlen);
    -
    - ptr = *buffer+hdrlen;
    -
    - for (;nitems;nitems--, list++) {
    - i = strlen(*list)+1;
    - (void) memcpy(ptr, *list, i);
    - ptr += i;
    - }
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFmtNotice.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,35 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFormatNotice(register ZNotice_t *notice, char **buffer, int *ret_len,
    - Z_AuthProc cert_routine)
    -{
    - char header[Z_MAXHEADERLEN];
    - int hdrlen;
    - Code_t retval;
    -
    - if ((retval = Z_FormatHeader(notice, header, sizeof(header), &hdrlen,
    - cert_routine)) != ZERR_NONE)
    - return (retval);
    -
    - *ret_len = hdrlen+notice->z_message_len;
    -
    - /* Length can never be zero, don't have to worry about malloc(0). */
    - if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
    - return (ENOMEM);
    -
    - (void) memcpy(*buffer, header, hdrlen);
    - (void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFmtRaw.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,34 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatRawNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFormatRawNotice(register ZNotice_t *notice, char **buffer, int *ret_len)
    -{
    - char header[Z_MAXHEADERLEN];
    - int hdrlen;
    - Code_t retval;
    -
    - if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
    - &hdrlen, NULL, NULL)) != ZERR_NONE)
    - return (retval);
    -
    - *ret_len = hdrlen+notice->z_message_len;
    -
    - /* *ret_len is never 0, don't have to worry about malloc(0) */
    - if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
    - return (ENOMEM);
    -
    - (void) memcpy(*buffer, header, hdrlen);
    - (void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFmtRawLst.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,46 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatRawNoticeList function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFormatRawNoticeList(ZNotice_t *notice, char *list[], int nitems, char **buffer,
    - int *ret_len)
    -{
    - char header[Z_MAXHEADERLEN];
    - int hdrlen, i, size;
    - char *ptr;
    - Code_t retval;
    -
    - if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
    - &hdrlen, NULL, NULL)) != ZERR_NONE)
    - return (retval);
    -
    - size = 0;
    - for (i=0;i<nitems;i++)
    - size += strlen(list[i])+1;
    -
    - *ret_len = hdrlen+size;
    -
    - if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
    - return (ENOMEM);
    -
    - (void) memcpy(*buffer, header, hdrlen);
    -
    - ptr = *buffer+hdrlen;
    -
    - for (;nitems;nitems--, list++) {
    - i = strlen(*list)+1;
    - (void) memcpy(ptr, *list, i);
    - ptr += i;
    - }
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFmtSmRaw.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,31 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFormatSmallRawNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFormatSmallRawNotice(ZNotice_t *notice, ZPacket_t buffer, int *ret_len)
    -{
    - Code_t retval;
    - int hdrlen;
    -
    - if ((retval = Z_FormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
    - &hdrlen, NULL, NULL)) != ZERR_NONE)
    - return (retval);
    -
    - *ret_len = hdrlen+notice->z_message_len;
    -
    - if (*ret_len > Z_MAXPKTLEN)
    - return (ZERR_PKTLEN);
    -
    - (void) memcpy(buffer+hdrlen, notice->z_message, notice->z_message_len);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZFreeNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,18 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZFreeNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZFreeNotice(ZNotice_t *notice)
    -{
    - free(notice->z_packet);
    - return 0;
    -}
    --- a/libpurple/protocols/zephyr/ZGetLocs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,36 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZGetLocations function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t ZGetLocations(ZLocations_t *location, int *numlocs)
    -{
    - int i;
    -
    - if (!__locate_list) {
    - return (ZERR_NOLOCATIONS);
    - }
    -
    - if (__locate_next == __locate_num) {
    - return (ZERR_NOMORELOCS);
    - }
    -
    - for (i = 0; i < MIN(*numlocs, __locate_num - __locate_next); i++) {
    - location[i] = __locate_list[i + __locate_next];
    - }
    -
    - if (__locate_num - __locate_next < *numlocs) {
    - *numlocs = __locate_num - __locate_next;
    - }
    -
    - __locate_next += *numlocs;
    -
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZGetSender.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,54 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZGetSender.c function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#ifndef WIN32
    -#include <pwd.h>
    -#endif
    -
    -char *
    -ZGetSender(void)
    -{
    - struct passwd *pw;
    -#ifdef ZEPHYR_USES_KERBEROS
    - char pname[ANAME_SZ];
    - char pinst[INST_SZ];
    - char prealm[REALM_SZ];
    - static char sender[ANAME_SZ+INST_SZ+REALM_SZ+3] = "";
    - long int kerror;
    -#else
    - static char sender[128] = "";
    -#endif
    -
    -#ifdef WIN32
    - unsigned long sender_size = sizeof(sender) - 1;
    -#endif
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    - if ((kerror = krb_get_tf_fullname((char *)TKT_FILE, pname, pinst, prealm)) == KSUCCESS)
    - {
    - sprintf(sender, "%s%s%s@%s", pname, (pinst[0] ? "." : ""), pinst, prealm);
    - return sender;
    - }
    -#endif
    -
    -#ifdef WIN32
    - GetUserName(sender, &sender_size);
    -#else
    - /* XXX a uid_t is a u_short (now), but getpwuid
    - * wants an int. AARGH! */
    - pw = getpwuid((int) getuid());
    - if (!pw)
    - return ("unknown");
    - sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
    -#endif
    - return sender;
    -}
    --- a/libpurple/protocols/zephyr/ZGetSubs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,37 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZGetSubscriptions function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t ZGetSubscriptions(ZSubscription_t *subscription, int *numsubs)
    -{
    - int i;
    -
    - if (!__subscriptions_list) {
    - return (ZERR_NOSUBSCRIPTIONS);
    - }
    -
    - if (__subscriptions_next == __subscriptions_num) {
    - return (ZERR_NOMORESUBSCRIPTIONS);
    - }
    -
    - for (i = 0; i < MIN(*numsubs, __subscriptions_num - __subscriptions_next);
    - i++) {
    - subscription[i] = __subscriptions_list[i + __subscriptions_next];
    - }
    -
    - if (__subscriptions_num - __subscriptions_next < *numsubs) {
    - *numsubs = __subscriptions_num - __subscriptions_next;
    - }
    -
    - __subscriptions_next += *numsubs;
    -
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZGetWGPort.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,43 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZGetWGPort function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -int
    -ZGetWGPort(void)
    -{
    - char *envptr, name[128];
    - FILE *fp;
    - int wgport;
    -#ifdef WIN32
    - long int buffsize= 128;
    - char tempdir[buffsize];
    -#endif
    - envptr = getenv("WGFILE");
    - if (!envptr) {
    -#ifdef WIN32
    - GetTempPath(buffsize,tempdir);
    - GetTempFileName(tempdir,"wg.",0,name);
    -#else
    - (void) sprintf(name, "/tmp/wg.%d", getuid());
    -#endif
    - envptr = name;
    - }
    - if (!(fp = fopen(envptr, "r")))
    - return (-1);
    -
    - /* if fscanf fails, return -1 via wgport */
    - if (fscanf(fp, "%d", &wgport) != 1)
    - wgport = -1;
    -
    - (void) fclose(fp);
    -
    - return (wgport);
    -}
    --- a/libpurple/protocols/zephyr/ZIfNotice.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,55 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZIfNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZIfNotice(ZNotice_t *notice, GSocketAddress **from,
    - int (*predicate)(ZNotice_t *, void *), void *args)
    -{
    - ZNotice_t tmpnotice;
    - Code_t retval;
    - char *buffer;
    - Z_InputQ *qptr;
    -
    - if ((retval = Z_WaitForComplete()) != ZERR_NONE)
    - return (retval);
    -
    - qptr = Z_GetFirstComplete();
    -
    - for (;;) {
    - while (qptr) {
    - if ((retval = ZParseNotice(qptr->packet, qptr->packet_len,
    - &tmpnotice)) != ZERR_NONE)
    - return (retval);
    - if ((*predicate)(&tmpnotice, args)) {
    - if (!(buffer = (char *) malloc((unsigned) qptr->packet_len)))
    - return (ENOMEM);
    - (void) memcpy(buffer, qptr->packet, qptr->packet_len);
    - if (from) {
    - *from = g_object_ref(qptr->from);
    - }
    - if ((retval = ZParseNotice(buffer, qptr->packet_len,
    - notice)) != ZERR_NONE) {
    - free(buffer);
    - return (retval);
    - }
    - Z_RemQueue(qptr);
    - return (ZERR_NONE);
    - }
    - qptr = Z_GetNextComplete(qptr);
    - }
    - if ((retval = Z_ReadWait()) != ZERR_NONE)
    - return (retval);
    - qptr = Z_GetFirstComplete(); /* need to look over all of
    - the queued messages, in case
    - a fragment has been reassembled */
    - }
    -}
    --- a/libpurple/protocols/zephyr/ZInit.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,180 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZInitialize function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    -#ifdef WIN32
    -
    -#else
    -#include <krb_err.h>
    -#endif
    -#endif
    -
    -#include "internal.h"
    -
    -#ifdef WIN32
    -#include <winsock2.h>
    -#else
    -#include <sys/socket.h>
    -#endif
    -
    -
    -#ifndef INADDR_NONE
    -#define INADDR_NONE 0xffffffff
    -#endif
    -
    -Code_t
    -ZInitialize(void)
    -{
    - struct servent *hmserv;
    - GResolver *resolver = NULL;
    - GList *hosts = NULL;
    - guint32 servaddr;
    - guint16 port;
    - Code_t code;
    - ZNotice_t notice;
    -#ifdef ZEPHYR_USES_KERBEROS
    - gchar *krealm = NULL;
    - gint krbval;
    - gchar d1[ANAME_SZ], d2[INST_SZ];
    -#endif
    -
    - g_clear_object(&__HM_addr);
    -
    - hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp");
    - port = hmserv ? hmserv->s_port : HM_SVC_FALLBACK;
    -
    - /* Set up local loopback address for HostManager */
    - __HM_addr = g_inet_socket_address_new_from_string("127.0.0.1", port);
    -
    - /* Initialize the input queue */
    - g_queue_init(&Z_input_queue);
    -
    - /* If there is no zhm, the code will fall back to something which might
    - * not be "right", but this is is ok, since none of the servers call
    - * krb_rd_req. */
    -
    - servaddr = INADDR_NONE;
    - if ((code = ZOpenPort(NULL)) != ZERR_NONE) {
    - return code;
    - }
    -
    - if ((code = ZhmStat(&notice)) != ZERR_NONE) {
    - return code;
    - }
    -
    - ZClosePort();
    -
    - /* the first field, which is NUL-terminated, is the server name.
    - If this code ever support a multiplexing zhm, this will have to
    - be made smarter, and probably per-message */
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    - krealm = krb_realmofhost(notice.z_message);
    -#endif
    - resolver = g_resolver_get_default();
    - hosts = g_resolver_lookup_by_name(resolver, notice.z_message, NULL, NULL);
    - while (hosts) {
    - GInetAddress *host_addr = hosts->data;
    - if (g_inet_address_get_family(host_addr) == G_SOCKET_FAMILY_IPV4) {
    - memcpy(&servaddr, g_inet_address_to_bytes(host_addr),
    - sizeof(servaddr));
    - g_list_free_full(hosts, g_object_unref);
    - hosts = NULL;
    - break;
    - }
    - g_object_unref(host_addr);
    - hosts = g_list_delete_link(hosts, hosts);
    - }
    -
    - ZFreeNotice(&notice);
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    - if (krealm) {
    - g_strlcpy(__Zephyr_realm, krealm, REALM_SZ);
    - } else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm) !=
    - KSUCCESS) &&
    - ((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
    - g_object_unref(resolver);
    - return krbval;
    - }
    -#else
    - g_strlcpy(__Zephyr_realm, "local-realm", REALM_SZ);
    -#endif
    -
    - __My_addr = INADDR_NONE;
    - if (servaddr != INADDR_NONE) {
    - /* Try to get the local interface address by connecting a UDP
    - * socket to the server address and getting the local address.
    - * Some broken operating systems (e.g. Solaris 2.0-2.5) yield
    - * INADDR_ANY (zero), so we have to check for that. */
    - GSocket *s = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
    - G_SOCKET_PROTOCOL_DEFAULT, NULL);
    - if (s != NULL) {
    - GSocketAddress *remote_addr = NULL;
    - GInetAddress *inet_addr = NULL;
    -
    - inet_addr = g_inet_address_new_from_bytes((const guint8 *)&servaddr,
    - G_SOCKET_FAMILY_IPV4);
    - remote_addr =
    - g_inet_socket_address_new(inet_addr, HM_SRV_SVC_FALLBACK);
    - g_object_unref(inet_addr);
    -
    - if (g_socket_connect(s, remote_addr, NULL, NULL)) {
    - GSocketAddress *local_addr =
    - g_socket_get_local_address(s, NULL);
    - if (local_addr) {
    - inet_addr = g_inet_socket_address_get_address(
    - G_INET_SOCKET_ADDRESS(local_addr));
    - if (inet_addr) {
    - memcpy(&__My_addr, g_inet_address_to_bytes(inet_addr),
    - sizeof(__My_addr));
    - g_object_unref(inet_addr);
    - }
    - g_object_unref(local_addr);
    - }
    - }
    - g_object_unref(remote_addr);
    - g_object_unref(s);
    - }
    - }
    - if (__My_addr == INADDR_NONE) {
    - /* We couldn't figure out the local interface address by the
    - * above method. Try by resolving the local hostname. (This
    - * is a pretty broken thing to do, and unfortunately what we
    - * always do on server machines.) */
    - const gchar *hostname = g_get_host_name();
    - hosts = g_resolver_lookup_by_name(resolver, hostname, NULL, NULL);
    - while (hosts) {
    - GInetAddress *host_addr = hosts->data;
    - if (g_inet_address_get_family(host_addr) == G_SOCKET_FAMILY_IPV4) {
    - memcpy(&servaddr, g_inet_address_to_bytes(host_addr),
    - sizeof(servaddr));
    - g_list_free_full(hosts, g_object_unref);
    - hosts = NULL;
    - break;
    - }
    - g_object_unref(host_addr);
    - hosts = g_list_delete_link(hosts, hosts);
    - }
    - }
    - /* If the above methods failed, zero out __My_addr so things will sort
    - * of kind of work. */
    - if (__My_addr == INADDR_NONE) {
    - __My_addr = 0;
    - }
    -
    - g_object_unref(resolver);
    -
    - /* Get the sender so we can cache it */
    - ZGetSender();
    -
    - return ZERR_NONE;
    -}
    -
    --- a/libpurple/protocols/zephyr/ZLocations.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,159 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSetLocation, ZUnsetLocation, and
    - * ZFlushMyLocations functions.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#include <purple.h>
    -
    -#ifndef WIN32
    -#include <pwd.h>
    -#endif
    -
    -#include <stdlib.h>
    -#include <errno.h>
    -
    -Code_t
    -ZSetLocation(char *exposure)
    -{
    - return (Z_SendLocation(LOGIN_CLASS, exposure, ZAUTH,
    - "$sender logged in to $1 on $3 at $2"));
    -}
    -
    -Code_t
    -ZUnsetLocation(void)
    -{
    - return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_LOGOUT, ZNOAUTH,
    - "$sender logged out of $1 on $3 at $2"));
    -}
    -
    -Code_t
    -ZFlushMyLocations(void)
    -{
    - return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, ""));
    -}
    -
    -static char host[MAXHOSTNAMELEN];
    -static char *mytty = NULL;
    -static int reenter = 0;
    -
    -Code_t
    -Z_SendLocation(char *class, char *opcode, Z_AuthProc auth, char *format)
    -{
    - int retval;
    - time_t ourtime;
    - ZNotice_t notice, retnotice;
    - char *bptr[3];
    -#ifndef X_DISPLAY_MISSING
    - char *display;
    -#endif
    -#ifndef WIN32
    - char *ttyp;
    - char *p;
    -#endif
    - struct hostent *hent;
    - short wg_port = ZGetWGPort();
    -
    - (void) memset((char *)&notice, 0, sizeof(notice));
    - notice.z_kind = ACKED;
    - notice.z_port = (unsigned short) ((wg_port == -1) ? 0 : wg_port);
    - notice.z_class = class;
    - notice.z_class_inst = ZGetSender();
    - notice.z_opcode = opcode;
    - notice.z_sender = 0;
    - notice.z_recipient = "";
    - notice.z_num_other_fields = 0;
    - notice.z_default_format = format;
    -
    - /*
    - keep track of what we said before so that we can be consistent
    - when changing location information.
    - This is done mainly for the sake of the WindowGram client.
    - */
    -
    - if (!reenter) {
    - hent = gethostbyname(g_get_host_name());
    - if (hent) {
    - (void) strncpy(host, hent->h_name, sizeof(host));
    - host[sizeof(host) - 1] = '\0';
    - }
    -#ifndef X_DISPLAY_MISSING
    - if ((display = getenv("DISPLAY")) && *display) {
    - mytty = g_strdup(display);
    - } else {
    -#endif
    -#ifdef WIN32
    - mytty = g_strdup("WinPurple");
    -#else
    - ttyp = ttyname(0);
    - if (ttyp && *ttyp) {
    - p = strchr(ttyp + 1, '/');
    - mytty = g_strdup((p) ? p + 1 : ttyp);
    - } else {
    - mytty = g_strdup("unknown");
    - }
    -#endif
    -#ifndef X_DISPLAY_MISSING
    - }
    -#endif
    - reenter = 1;
    - }
    -
    - ourtime = time((time_t *)0);
    - bptr[0] = host;
    - bptr[1] = ctime(&ourtime);
    - bptr[1][strlen(bptr[1])-1] = '\0';
    - bptr[2] = mytty;
    -
    - if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
    - return (retval);
    -
    - retval = Z_WaitForNotice (&retnotice, ZCompareUIDPred, &notice.z_uid,
    - SRV_TIMEOUT);
    - if (retval != ZERR_NONE)
    - return retval;
    -
    - if (retnotice.z_kind == SERVNAK) {
    - if (!retnotice.z_message_len) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_SERVNAK);
    - }
    - if (purple_strequal(retnotice.z_message, ZSRVACK_NOTSENT)) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_AUTHFAIL);
    - }
    - if (purple_strequal(retnotice.z_message, ZSRVACK_FAIL)) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_LOGINFAIL);
    - }
    - ZFreeNotice(&retnotice);
    - return (ZERR_SERVNAK);
    - }
    -
    - if (retnotice.z_kind != SERVACK) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_INTERNAL);
    - }
    -
    - if (!retnotice.z_message_len) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_INTERNAL);
    - }
    -
    - if (!purple_strequal(retnotice.z_message, ZSRVACK_SENT) &&
    - !purple_strequal(retnotice.z_message, ZSRVACK_NOTSENT)) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_INTERNAL);
    - }
    -
    - ZFreeNotice(&retnotice);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZMakeAscii.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,78 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZMakeAscii function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -static char *itox_chars = "0123456789ABCDEF";
    -
    -Code_t
    -ZMakeAscii(register char *ptr, int len, unsigned char *field, int num)
    -{
    - int i;
    -
    - for (i=0;i<num;i++) {
    - /* we need to add "0x" if we are between 4 byte pieces */
    - if ((i & 3) == 0) {
    - if (len < (i?4:3))
    - return ZERR_FIELDLEN;
    - /* except at the beginning, put a space in before the "0x" */
    - if (i) {
    - *ptr++ = ' ';
    - len--;
    - }
    - *ptr++ = '0';
    - *ptr++ = 'x';
    - len -= 2;
    - }
    - if (len < 3)
    - return ZERR_FIELDLEN;
    - *ptr++ = itox_chars[(int) (field[i] >> 4)];
    - *ptr++ = itox_chars[(int) (field[i] & 0xf)];
    - len -= 2;
    - }
    -
    - *ptr = '\0';
    - return ZERR_NONE;
    -}
    -
    -Code_t
    -ZMakeAscii32(register char *ptr, int len, unsigned long value)
    -{
    - if (len < 11)
    - return ZERR_FIELDLEN;
    - *ptr++ = '0';
    - *ptr++ = 'x';
    - *ptr++ = itox_chars[(value >> 28) & 0xf];
    - *ptr++ = itox_chars[(value >> 24) & 0xf];
    - *ptr++ = itox_chars[(value >> 20) & 0xf];
    - *ptr++ = itox_chars[(value >> 16) & 0xf];
    - *ptr++ = itox_chars[(value >> 12) & 0xf];
    - *ptr++ = itox_chars[(value >> 8) & 0xf];
    - *ptr++ = itox_chars[(value >> 4) & 0xf];
    - *ptr++ = itox_chars[(value >> 0) & 0xf];
    - *ptr = 0;
    - return ZERR_NONE;
    -}
    -
    -Code_t
    -ZMakeAscii16(register char *ptr, int len, unsigned int value)
    -{
    - if (len < 7)
    - return ZERR_FIELDLEN;
    - *ptr++ = '0';
    - *ptr++ = 'x';
    - *ptr++ = itox_chars[(value >> 12) & 0xf];
    - *ptr++ = itox_chars[(value >> 8) & 0xf];
    - *ptr++ = itox_chars[(value >> 4) & 0xf];
    - *ptr++ = itox_chars[(value >> 0) & 0xf];
    - *ptr = 0;
    - return ZERR_NONE;
    -}
    -
    --- a/libpurple/protocols/zephyr/ZMkAuth.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,94 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZMakeAuthentication function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#ifndef ERROR_TABLE_BASE_krb
    -#define ERROR_TABLE_BASE_krb (39525376L)
    -#endif
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    -#ifdef WIN32
    -
    -#else
    -#include <krb_err.h>
    -#endif
    -static long last_authent_time = 0L;
    -static KTEXT_ST last_authent;
    -#endif
    -
    -Code_t
    -ZMakeAuthentication(register ZNotice_t *notice, char *buffer, int buffer_len,
    - int *len)
    -{
    -#ifdef ZEPHYR_USES_KERBEROS
    - int result;
    - time_t now;
    - KTEXT_ST authent;
    - char *cstart, *cend;
    - ZChecksum_t checksum;
    - CREDENTIALS cred;
    - extern unsigned long des_quad_cksum();
    -
    - now = time(0);
    - if (last_authent_time == 0 || (now - last_authent_time > 120)) {
    - result = krb_mk_req(&authent, SERVER_SERVICE,
    - SERVER_INSTANCE, __Zephyr_realm, 0);
    - if (result != MK_AP_OK) {
    - last_authent_time = 0;
    - return (result+ERROR_TABLE_BASE_krb);
    - }
    - last_authent_time = now;
    - last_authent = authent;
    - }
    - else {
    - authent = last_authent;
    - }
    - notice->z_auth = 1;
    - notice->z_authent_len = authent.length;
    - notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
    - /* zero length authent is an error, so malloc(0) is not a problem */
    - if (!notice->z_ascii_authent)
    - return (ENOMEM);
    - if ((result = ZMakeAscii(notice->z_ascii_authent,
    - authent.length*3,
    - authent.dat,
    - authent.length)) != ZERR_NONE) {
    - free(notice->z_ascii_authent);
    - return (result);
    - }
    - result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
    - &cend);
    - free(notice->z_ascii_authent);
    - notice->z_authent_len = 0;
    - if (result)
    - return(result);
    -
    - /* Compute a checksum over the header and message. */
    - if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
    - __Zephyr_realm, &cred)) != 0)
    - return result;
    - checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, (C_Block *)cred.session);
    - checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
    - (C_Block *)cred.session);
    - checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
    - 0, (C_Block *)cred.session);
    - notice->z_checksum = checksum;
    - ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
    -
    - return (ZERR_NONE);
    -#else
    - notice->z_checksum = 0;
    - notice->z_auth = 1;
    - notice->z_authent_len = 0;
    - notice->z_ascii_authent = "";
    - return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
    -#endif
    -}
    --- a/libpurple/protocols/zephyr/ZNewLocU.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,40 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZLocateUser function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZLocateUser(char *user, int *nlocs, Z_AuthProc auth)
    -{
    - Code_t retval;
    - ZNotice_t notice;
    - ZAsyncLocateData_t zald;
    -
    - (void) ZFlushLocations(); /* ZFlushLocations never fails (the library
    - is allowed to know this). */
    -
    - if ((retval = ZRequestLocations(user, &zald, UNACKED, auth)) != ZERR_NONE)
    - return(retval);
    -
    - retval = Z_WaitForNotice (&notice, ZCompareALDPred, &zald, SRV_TIMEOUT);
    - if (retval == ZERR_NONOTICE)
    - return ETIMEDOUT;
    - if (retval != ZERR_NONE)
    - return retval;
    -
    - if ((retval = ZParseLocations(&notice, &zald, nlocs, NULL)) != ZERR_NONE) {
    - ZFreeNotice(&notice);
    - return(retval);
    - }
    -
    - ZFreeNotice(&notice);
    - ZFreeALD(&zald);
    - return(ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZOpenPort.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,67 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZOpenPort function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -#include <purple.h>
    -#ifdef WIN32
    -#include <winsock2.h>
    -#else
    -#include <sys/socket.h>
    -#endif
    -
    -Code_t
    -ZOpenPort(unsigned short *port)
    -{
    - GSocketAddress *bindin = NULL;
    - GError *error = NULL;
    -
    - ZClosePort();
    -
    - __Zephyr_socket = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
    - G_SOCKET_PROTOCOL_DEFAULT, &error);
    - if (__Zephyr_socket == NULL) {
    - purple_debug_error("zephyr", "Failed to open socket: %s",
    - error->message);
    - g_error_free(error);
    - return ZERR_INTERNAL;
    - }
    -
    - bindin = g_inet_socket_address_new_from_string("0.0.0.0", port ? *port : 0);
    - if (!g_socket_bind(__Zephyr_socket, bindin, FALSE, &error)) {
    - gint err = ZERR_INTERNAL;
    - if (error->code == G_IO_ERROR_ADDRESS_IN_USE && port && *port) {
    - err = ZERR_PORTINUSE;
    - }
    - purple_debug_error("zephyr", "Failed to bind socket to port %d: %s",
    - port ? *port : 0, error->message);
    - g_error_free(error);
    - g_object_unref(bindin);
    - g_clear_object(&__Zephyr_socket);
    - return err;
    - }
    - g_object_unref(bindin);
    -
    - bindin = g_socket_get_local_address(__Zephyr_socket, &error);
    - if (bindin == NULL) {
    - purple_debug_error("zephyr", "Failed to get bound socket port: %s",
    - error->message);
    - g_error_free(error);
    - g_clear_object(&__Zephyr_socket);
    - return ZERR_INTERNAL;
    - }
    - __Zephyr_port =
    - g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(bindin));
    - if (port) {
    - *port = __Zephyr_port;
    - }
    - g_object_unref(bindin);
    -
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZParseNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,285 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZParseNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#include <gio/gio.h>
    -
    -#include <purple.h>
    -
    -/* Assume that strlen is efficient on this machine... */
    -#define next_field(ptr) ptr += strlen (ptr) + 1
    -
    -#if defined (__GNUC__) && defined (__vax__)
    -#undef next_field
    -static __inline__ char * Istrend (char *str) {
    - /*
    - * This should be faster on VAX models outside the 2 series. Don't
    - * use it if you are using MicroVAX 2 servers. If you are using a
    - * VS2 server, use something like
    - * #define next_field(ptr) while(*ptr++)
    - * instead of this code.
    - *
    - * This requires use of GCC to get the optimized code, but
    - * everybody uses GCC, don't they? :-)
    - */
    - register char *str2 asm ("r1");
    - /* Assumes that no field is longer than 64K.... */
    - asm ("locc $0,$65535,(%1)" : "=r" (str2) : "r" (str) : "r0");
    - return str2;
    -}
    -#define next_field(ptr) ptr = Istrend (ptr) + 1
    -#endif
    -
    -#ifdef mips
    -#undef next_field
    -/*
    - * The compiler doesn't optimize this macro as well as it does the
    - * following function.
    - */
    -#define next_fieldXXX(ptr) do{register unsigned c1,c2;c1= *ptr; \
    - while((ptr++,c2= *ptr,c1)&&(ptr++,c1= *ptr,c2));}while(0)
    -static char *next_field_1 (s) char *s; {
    - /*
    - * Calling overhead is still present, but this routine is faster
    - * than strlen, and doesn't bother with some of the other math
    - * that we'd just have to undo later anyways.
    - */
    - register unsigned c1 = *s, c2;
    - while (1) {
    - s++; c2 = *s; if (c1 == 0) break;
    - s++; c1 = *s; if (c2 == 0) break;
    - s++; c2 = *s; if (c1 == 0) break;
    - s++; c1 = *s; if (c2 == 0) break;
    - }
    - return s;
    -}
    -#define next_field(ptr) ptr=next_field_1(ptr)
    -#endif
    -
    -Code_t
    -ZParseNotice(char *buffer, int len, ZNotice_t *notice)
    -{
    - char *ptr, *end;
    - unsigned long temp;
    - int maj, numfields, i;
    -
    -#ifdef __LINE__
    - int lineno;
    - /* Note: This definition of BAD eliminates lint and compiler
    - * complains about the "while (0)", but require that the macro not
    - * be used as the "then" part of an "if" statement that also has
    - * an "else" clause.
    - */
    -#define BAD_PACKET {lineno=__LINE__;goto badpkt;}
    - /* This one gets lint/compiler complaints. */
    -/*#define BAD do{lineno=__LINE__;goto badpkt;}while(0)*/
    -#else
    -#define BAD_PACKET goto badpkt
    -#endif
    -
    - (void) memset((char *)notice, 0, sizeof(ZNotice_t));
    -
    - ptr = buffer;
    - end = buffer+len;
    -
    - notice->z_packet = buffer;
    -
    - notice->z_version = ptr;
    - if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1))
    - return (ZERR_VERS);
    - ptr += sizeof(ZVERSIONHDR) - 1;
    - if (!*ptr) {
    - purple_debug_error("zephyr", "ZParseNotice: null version string");
    - return ZERR_BADPKT;
    - }
    - maj = atoi(ptr);
    - if (maj != ZVERSIONMAJOR)
    - return (ZERR_VERS);
    - next_field (ptr);
    -
    - if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
    - BAD_PACKET;
    - numfields = temp;
    - next_field (ptr);
    -
    - /*XXX 3 */
    - numfields -= 2; /* numfields, version, and checksum */
    - if (numfields < 0) {
    - GInetAddress *inet_addr = NULL;
    - gchar *inet_addr_str = NULL;
    - badpkt:
    - inet_addr = g_inet_address_new_from_bytes(
    - (const guint8 *)&notice->z_uid.zuid_addr,
    - G_SOCKET_FAMILY_IPV4);
    - inet_addr_str = g_inet_address_to_string(inet_addr);
    -#ifdef __LINE__
    - lineno = __LINE__;
    - purple_debug_error("zephyr", "ZParseNotice: bad packet from %s/%d (line %d)",
    - inet_addr_str, notice->z_port, lineno);
    -#else
    - purple_debug_error("zephyr", "ZParseNotice: bad packet from %s/%d",
    - inet_addr_str, notice->z_port);
    -#endif
    - g_free(inet_addr_str);
    - g_object_unref(inet_addr);
    - return ZERR_BADPKT;
    - }
    -
    - if (numfields) {
    - if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_kind = temp;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    -
    - if (numfields) {
    - if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
    - sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_time.tv_sec = GUINT64_FROM_BE((guint64)notice->z_uid.tv.tv_sec);
    - notice->z_time.tv_usec = GUINT64_FROM_BE((guint64)notice->z_uid.tv.tv_usec);
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    -
    - if (numfields) {
    - if (ZReadAscii16(ptr, end-ptr, &notice->z_port) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_port = g_htons(notice->z_port);
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    -
    - if (numfields) {
    - if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_auth = temp;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    - notice->z_checked_auth = ZAUTH_UNSET;
    -
    - if (numfields) {
    - if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_authent_len = temp;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    -
    - if (numfields) {
    - notice->z_ascii_authent = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - BAD_PACKET;
    -
    - if (numfields) {
    - notice->z_class = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_class = "";
    -
    - if (numfields) {
    - notice->z_class_inst = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_class_inst = "";
    -
    - if (numfields) {
    - notice->z_opcode = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_opcode = "";
    -
    - if (numfields) {
    - notice->z_sender = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_sender = "";
    -
    - if (numfields) {
    - notice->z_recipient = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_recipient = "";
    -
    - if (numfields) {
    - notice->z_default_format = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_default_format = "";
    -
    -/*XXX*/
    - if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_checksum = temp;
    - numfields--;
    - next_field (ptr);
    -
    - if (numfields) {
    - notice->z_multinotice = ptr;
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_multinotice = "";
    -
    - if (numfields) {
    - if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
    - sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
    - BAD_PACKET;
    - notice->z_time.tv_sec = GUINT64_FROM_BE((guint64)notice->z_multiuid.tv.tv_sec);
    - notice->z_time.tv_usec = GUINT64_FROM_BE((guint64)notice->z_multiuid.tv.tv_usec);
    - numfields--;
    - next_field (ptr);
    - }
    - else
    - notice->z_multiuid = notice->z_uid;
    -
    - for (i=0;i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) {
    - notice->z_other_fields[i] = ptr;
    - next_field (ptr);
    - }
    - notice->z_num_other_fields = i;
    -
    - for (i=0;i<numfields;i++)
    - next_field (ptr);
    -
    - notice->z_message = (void *)ptr;
    - notice->z_message_len = len-(ptr-buffer);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZPeekNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,24 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for ZPeekNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZPeekNotice(ZNotice_t *notice, GSocketAddress **from)
    -{
    - char *buffer;
    - int len;
    - Code_t retval;
    -
    - if ((retval = ZPeekPacket(&buffer, &len, from)) != ZERR_NONE)
    - return (retval);
    -
    - return (ZParseNotice(buffer, len, notice));
    -}
    --- a/libpurple/protocols/zephyr/ZPeekPkt.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,36 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for ZPeekPacket function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZPeekPacket(char **buffer, int *ret_len, GSocketAddress **from)
    -{
    - Code_t retval;
    - Z_InputQ *nextq;
    -
    - if ((retval = Z_WaitForComplete()) != ZERR_NONE)
    - return (retval);
    -
    - nextq =Z_GetFirstComplete();
    -
    - *ret_len = nextq->packet_len;
    -
    - if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
    - return (ENOMEM);
    -
    - (void) memcpy(*buffer, nextq->packet, *ret_len);
    -
    - if (from) {
    - *from = g_object_ref(nextq->from);
    - }
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZPending.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,29 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZPending function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -int
    -ZPending(void)
    -{
    - int retval;
    -
    - if (ZGetSocket() == NULL) {
    - errno = ZERR_NOPORT;
    - return (-1);
    - }
    -
    - if ((retval = Z_ReadEnqueue()) != ZERR_NONE) {
    - errno = retval;
    - return (-1);
    - }
    -
    - return(ZQLength());
    -}
    --- a/libpurple/protocols/zephyr/ZReadAscii.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,82 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZReadAscii function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987, 1990 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#define Z_cnvt_xtoi(c) ((temp=(c)-'0'),(temp<10)?(int)temp:((temp-='A'-'9'-1),(temp<16)?(int)temp:-1))
    -
    -Code_t
    -ZReadAscii(char *ptr, int len, unsigned char *field, int num)
    -{
    - int i;
    - unsigned int hexbyte;
    - register int c1, c2;
    - register unsigned int temp;
    -
    - for (i=0;i<num;i++) {
    - if (*ptr == ' ') {
    - ptr++;
    - if (--len < 0)
    - return ZERR_BADFIELD;
    - }
    - if (ptr[0] == '0' && ptr[1] == 'x') {
    - ptr += 2;
    - len -= 2;
    - if (len < 0)
    - return ZERR_BADFIELD;
    - }
    - c1 = Z_cnvt_xtoi(ptr[0]);
    - if (c1 < 0)
    - return ZERR_BADFIELD;
    - c2 = Z_cnvt_xtoi(ptr[1]);
    - if (c2 < 0)
    - return ZERR_BADFIELD;
    - hexbyte = (c1 << 4) | c2;
    - field[i] = hexbyte;
    - ptr += 2;
    - len -= 2;
    - if (len < 0)
    - return ZERR_BADFIELD;
    - }
    -
    - return *ptr ? ZERR_BADFIELD : ZERR_NONE;
    -}
    -
    -Code_t
    -ZReadAscii32(char *ptr, int len, unsigned long *value_ptr)
    -{
    - unsigned char buf[4];
    - unsigned long value = 0;
    - Code_t retval;
    -
    - retval = ZReadAscii(ptr, len, buf, 4);
    - if (retval != ZERR_NONE)
    - return retval;
    - value |= (unsigned long)buf[0] << 24;
    - value |= buf[1] << 16;
    - value |= buf[2] << 8;
    - value |= buf[3];
    - *value_ptr = value;
    - return ZERR_NONE;
    -}
    -
    -Code_t
    -ZReadAscii16(char *ptr, int len, unsigned short *value_ptr)
    -{
    - unsigned char buf[2];
    - Code_t retval;
    -
    - retval = ZReadAscii(ptr, len, buf, 2);
    - if (retval != ZERR_NONE)
    - return retval;
    - *value_ptr = (buf[0] << 8) | buf[1];
    - return ZERR_NONE;
    -}
    -
    --- a/libpurple/protocols/zephyr/ZRecvNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,47 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for ZReceiveNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZReceiveNotice(ZNotice_t *notice, GSocketAddress **from)
    -{
    - char *buffer;
    - Z_InputQ *nextq;
    - int len, auth;
    - Code_t retval;
    -
    - if ((retval = Z_WaitForComplete()) != ZERR_NONE)
    - return (retval);
    -
    - nextq = Z_GetFirstComplete();
    -
    - if (!nextq)
    - return (ENOMEM);
    -
    - len = nextq->packet_len;
    -
    - if (!(buffer = (char *) malloc((unsigned) len)))
    - return (ENOMEM);
    -
    - if (from) {
    - *from = g_object_ref(nextq->from);
    - }
    -
    - (void) memcpy(buffer, nextq->packet, len);
    -
    - auth = nextq->auth;
    - Z_RemQueue(nextq);
    -
    - if ((retval = ZParseNotice(buffer, len, notice)) != ZERR_NONE)
    - return (retval);
    - notice->z_checked_auth = auth;
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZRecvPkt.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,37 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for ZReceivePacket function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZReceivePacket(ZPacket_t buffer, int *ret_len, GSocketAddress **from)
    -{
    - Code_t retval;
    - Z_InputQ *nextq;
    -
    - if ((retval = Z_WaitForComplete()) != ZERR_NONE)
    - return (retval);
    -
    - nextq = Z_GetFirstComplete();
    -
    - *ret_len = nextq->packet_len;
    - if (*ret_len > Z_MAXPKTLEN)
    - return (ZERR_PKTLEN);
    -
    - (void) memcpy(buffer, nextq->packet, *ret_len);
    -
    - if (from) {
    - *from = g_object_ref(nextq->from);
    - }
    -
    - Z_RemQueue(nextq);
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZRetSubs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,170 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZRetrieveSubscriptions and
    - * ZRetrieveDefaultSubscriptions functions.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#include <purple.h>
    -
    -static Code_t Z_RetSubs(ZNotice_t *notice, int *nsubs, Z_AuthProc auth_routine);
    -
    -Code_t ZRetrieveSubscriptions(unsigned short port, int *nsubs)
    -{
    - int retval;
    - ZNotice_t notice;
    - char asciiport[50];
    -
    - if (!port) /* use default port */
    - port = __Zephyr_port;
    -
    - retval = ZMakeAscii16(asciiport, sizeof(asciiport), g_ntohs(port));
    - if (retval != ZERR_NONE)
    - return (retval);
    -
    - (void) memset((char *)&notice, 0, sizeof(notice));
    - notice.z_message = asciiport;
    - notice.z_message_len = strlen(asciiport)+1;
    - notice.z_opcode = CLIENT_GIMMESUBS;
    -
    - return(Z_RetSubs(&notice, nsubs, ZAUTH));
    -}
    -
    -static Code_t
    -Z_RetSubs(register ZNotice_t *notice, int *nsubs, Z_AuthProc auth_routine)
    -{
    - register int i;
    - int retval,nrecv,gimmeack;
    - ZNotice_t retnotice;
    - char *ptr,*end,*ptr2;
    -
    - retval = ZFlushSubscriptions();
    -
    - if (retval != ZERR_NONE && retval != ZERR_NOSUBSCRIPTIONS)
    - return (retval);
    -
    - if (ZGetSocket() == NULL) {
    - retval = ZOpenPort(NULL);
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - }
    -
    - notice->z_kind = ACKED;
    - notice->z_port = __Zephyr_port;
    - notice->z_class = ZEPHYR_CTL_CLASS;
    - notice->z_class_inst = ZEPHYR_CTL_CLIENT;
    - notice->z_sender = 0;
    - notice->z_recipient = "";
    - notice->z_default_format = "";
    -
    - if ((retval = ZSendNotice(notice,auth_routine)) != ZERR_NONE)
    - return (retval);
    -
    - nrecv = 0;
    - gimmeack = 0;
    - __subscriptions_list = (ZSubscription_t *) 0;
    -
    - while (!nrecv || !gimmeack) {
    - retval = Z_WaitForNotice (&retnotice, ZCompareMultiUIDPred,
    - &notice->z_multiuid, SRV_TIMEOUT);
    - if (retval == ZERR_NONOTICE)
    - return ETIMEDOUT;
    - else if (retval != ZERR_NONE)
    - return retval;
    -
    - if (retnotice.z_kind == SERVNAK) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_SERVNAK);
    - }
    - /* non-matching protocol version numbers means the
    - server is probably an older version--must punt */
    - if (!purple_strequal(notice->z_version,retnotice.z_version)) {
    - ZFreeNotice(&retnotice);
    - return(ZERR_VERS);
    - }
    - if (retnotice.z_kind == SERVACK &&
    - purple_strequal(retnotice.z_opcode,notice->z_opcode)) {
    - ZFreeNotice(&retnotice);
    - gimmeack = 1;
    - continue;
    - }
    -
    - if (retnotice.z_kind != ACKED) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_INTERNAL);
    - }
    -
    - nrecv++;
    -
    - end = retnotice.z_message+retnotice.z_message_len;
    -
    - __subscriptions_num = 0;
    - for (ptr=retnotice.z_message;ptr<end;ptr++)
    - if (!*ptr)
    - __subscriptions_num++;
    -
    - __subscriptions_num = __subscriptions_num / 3;
    -
    - if (!__subscriptions_num) {
    - ZFreeNotice(&retnotice);
    - continue;
    - }
    -
    - free(__subscriptions_list);
    - __subscriptions_list = (ZSubscription_t *)
    - malloc((unsigned)(__subscriptions_num*
    - sizeof(ZSubscription_t)));
    - if (!__subscriptions_list) {
    - ZFreeNotice(&retnotice);
    - return (ENOMEM);
    - }
    -
    - for (ptr=retnotice.z_message,i = 0; i< __subscriptions_num; i++) {
    - size_t len;
    -
    - len = strlen(ptr) + 1;
    - __subscriptions_list[i].zsub_class = (char *)
    - malloc(len);
    - if (!__subscriptions_list[i].zsub_class) {
    - ZFreeNotice(&retnotice);
    - return (ENOMEM);
    - }
    - g_strlcpy(__subscriptions_list[i].zsub_class,ptr,len);
    - ptr += len;
    - len = strlen(ptr) + 1;
    - __subscriptions_list[i].zsub_classinst = (char *)
    - malloc(len);
    - if (!__subscriptions_list[i].zsub_classinst) {
    - ZFreeNotice(&retnotice);
    - return (ENOMEM);
    - }
    - g_strlcpy(__subscriptions_list[i].zsub_classinst,ptr,len);
    - ptr += len;
    - ptr2 = ptr;
    - if (!*ptr2)
    - ptr2 = "*";
    - len = strlen(ptr2) + 1;
    - __subscriptions_list[i].zsub_recipient = (char *)
    - malloc(len);
    - if (!__subscriptions_list[i].zsub_recipient) {
    - ZFreeNotice(&retnotice);
    - return (ENOMEM);
    - }
    - g_strlcpy(__subscriptions_list[i].zsub_recipient,ptr2,len);
    - ptr += strlen(ptr)+1;
    - }
    - ZFreeNotice(&retnotice);
    - }
    -
    - __subscriptions_next = 0;
    - *nsubs = __subscriptions_num;
    -
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZSendList.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,41 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSendList function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZSendList(ZNotice_t *notice, char *list[], int nitems, Z_AuthProc cert_routine)
    -{
    - return(ZSrvSendList(notice, list, nitems, cert_routine, Z_XmitFragment));
    -}
    -
    -Code_t
    -ZSrvSendList(ZNotice_t *notice, char *list[], int nitems,
    - Z_AuthProc cert_routine, Code_t (*send_routine)())
    -{
    - Code_t retval;
    - ZNotice_t newnotice;
    - char *buffer;
    - int len;
    -
    - if ((retval = ZFormatNoticeList(notice, list, nitems, &buffer,
    - &len, cert_routine)) != ZERR_NONE)
    - return (retval);
    -
    - if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
    - return (retval);
    -
    - retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
    - send_routine);
    -
    - free(buffer);
    -
    - return (retval);
    -}
    --- a/libpurple/protocols/zephyr/ZSendNot.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,41 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSendNotice function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZSendNotice(ZNotice_t *notice, Z_AuthProc cert_routine)
    -{
    - return(ZSrvSendNotice(notice, cert_routine, Z_XmitFragment));
    -}
    -
    -Code_t
    -ZSrvSendNotice(ZNotice_t *notice, Z_AuthProc cert_routine,
    - Code_t (*send_routine)())
    -{
    - Code_t retval;
    - ZNotice_t newnotice;
    - char *buffer;
    - int len;
    -
    - if ((retval = ZFormatNotice(notice, &buffer, &len,
    - cert_routine)) != ZERR_NONE)
    - return (retval);
    -
    - if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
    - return (retval);
    -
    - retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
    - send_routine);
    -
    - free(buffer);
    -
    - return (retval);
    -}
    --- a/libpurple/protocols/zephyr/ZSendPkt.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,74 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSendPacket function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include <purple.h>
    -
    -#include "internal.h"
    -#ifdef WIN32
    -#include <winsock.h>
    -#else
    -#include <sys/socket.h>
    -#endif
    -
    -static int wait_for_hmack(ZNotice_t *notice, void *uid);
    -
    -Code_t
    -ZSendPacket(char *packet, int len, int waitforack)
    -{
    - GError *error = NULL;
    - Code_t retval;
    - ZNotice_t notice, acknotice;
    -
    - if (packet == NULL || len < 0) {
    - return ZERR_ILLVAL;
    - }
    -
    - if (len > Z_MAXPKTLEN) {
    - return ZERR_PKTLEN;
    - }
    -
    - if (ZGetSocket() == NULL) {
    - retval = ZOpenPort(NULL);
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - }
    -
    - if (g_socket_send_to(ZGetSocket(), ZGetDestAddr(), packet, len, NULL,
    - &error) < 0) {
    - purple_debug_error("zephyr", "Failed to send packet of size %d: %s",
    - len, error->message);
    - g_error_free(error);
    - return ZERR_INTERNAL;
    - }
    -
    - if (!waitforack) {
    - return ZERR_NONE;
    - }
    -
    - if ((retval = ZParseNotice(packet, len, &notice)) != ZERR_NONE) {
    - return retval;
    - }
    -
    - retval = Z_WaitForNotice(&acknotice, wait_for_hmack, &notice.z_uid,
    - HM_TIMEOUT);
    - if (retval == ETIMEDOUT) {
    - return ZERR_HMDEAD;
    - }
    - if (retval == ZERR_NONE) {
    - ZFreeNotice(&acknotice);
    - }
    - return retval;
    -}
    -
    -static int wait_for_hmack(ZNotice_t *notice, void *uid)
    -{
    - return (notice->z_kind == HMACK && ZCompareUID(&notice->z_uid, (ZUnique_Id_t *)uid));
    -}
    --- a/libpurple/protocols/zephyr/ZSetDest.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,19 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSetDestAddr function.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -Code_t
    -ZSetDestAddr(GSocketAddress *addr)
    -{
    - g_set_object(&__HM_addr, addr);
    -
    - return ZERR_NONE;
    -}
    --- a/libpurple/protocols/zephyr/ZSubs.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,180 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZSubscribeTo, ZUnsubscribeTo, and
    - * ZCancelSubscriptions functions.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -static Code_t Z_Subscriptions(register ZSubscription_t *sublist, int nitems,
    - unsigned int port, char *opcode, int authit);
    -static Code_t subscr_sendoff(ZNotice_t *notice, char **lyst, int num,
    - int authit);
    -
    -Code_t
    -ZSubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port)
    -{
    - return (Z_Subscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE, 1));
    -}
    -
    -Code_t
    -ZSubscribeToSansDefaults(ZSubscription_t *sublist, int nitems,
    - unsigned int port)
    -{
    - return (Z_Subscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE_NODEFS,
    - 1));
    -}
    -
    -Code_t
    -ZUnsubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port)
    -{
    - return (Z_Subscriptions(sublist, nitems, port, CLIENT_UNSUBSCRIBE, 1));
    -}
    -
    -Code_t
    -ZCancelSubscriptions(unsigned int port)
    -{
    - return (Z_Subscriptions((ZSubscription_t *)0, 0, port,
    - CLIENT_CANCELSUB, 0));
    -}
    -
    -/*
    - * This routine must do its own fragmentation. Subscriptions must
    - * not be broken across packet boundaries, or else the server will
    - * mis-interpret them.
    - */
    -
    -static Code_t
    -Z_Subscriptions(register ZSubscription_t *sublist, int nitems,
    - unsigned int port, char *opcode, int authit)
    -{
    - register int i, j;
    - int retval;
    - ZNotice_t notice;
    - char header[Z_MAXHEADERLEN];
    - char **list;
    - char *recip;
    - int hdrlen;
    - int size_avail = Z_MAXPKTLEN-Z_FRAGFUDGE; /* space avail for data,
    - adjusted below */
    - int size, start, numok;
    -
    - /* nitems = 0 means cancel all subscriptions; still need to allocate a */
    - /* array for one item so we can cancel, however. */
    -
    - list = (char **)malloc((unsigned)((nitems==0)?1:nitems)*3*sizeof(char *));
    - if (!list)
    - return (ENOMEM);
    -
    - (void) memset((char *)&notice, 0, sizeof(notice));
    - notice.z_kind = ACKED;
    - notice.z_port = port;
    - notice.z_class = ZEPHYR_CTL_CLASS;
    - notice.z_class_inst = ZEPHYR_CTL_CLIENT;
    - notice.z_opcode = opcode;
    - notice.z_sender = 0;
    - notice.z_recipient = "";
    - notice.z_default_format = "";
    - notice.z_message_len = 0;
    -
    - /* format the header to figure out how long it is */
    - retval = Z_FormatHeader(&notice, header, sizeof(header), &hdrlen, ZAUTH);
    - if (retval != ZERR_NONE && !authit)
    - retval = Z_FormatHeader(&notice, header, sizeof(header),
    - &hdrlen, ZNOAUTH);
    - if (retval != ZERR_NONE) {
    - free((char *)list);
    - return(retval);
    - }
    -
    - /* compute amount of room left */
    - size_avail -= hdrlen;
    - size = size_avail;
    -
    - /* assemble subs into an array of pointers */
    - for (i=0;i<nitems;i++) {
    - list[i*3] = sublist[i].zsub_class;
    - list[i*3+1] = sublist[i].zsub_classinst;
    - recip = sublist[i].zsub_recipient;
    - if (recip && *recip == '*')
    - recip++;
    - if (!recip || (*recip != 0 && *recip != '@'))
    - recip = ZGetSender();
    - list[i*3+2] = recip;
    - }
    -
    - start = -1;
    - i = 0;
    - numok = 0;
    - if (!nitems) {
    - /* there aren't really any, but we need to xmit anyway */
    - retval = subscr_sendoff(&notice, list, 0, authit);
    - free((char *)list);
    - return(retval);
    - }
    - while(i < nitems) {
    - if (start == -1) {
    - size = size_avail;
    - start = i;
    - numok = 0;
    - }
    - if ((j = strlen(list[i*3])
    - + strlen(list[i*3+1])
    - + strlen(list[i*3+2]) + 3) <= size) {
    - /* it will fit in this packet */
    - size -= j;
    - numok++;
    - i++;
    - continue;
    - }
    - if (!numok) { /* a single subscription won't
    - fit into one packet */
    - free((char *)list);
    - return(ZERR_FIELDLEN);
    - }
    - retval = subscr_sendoff(&notice, &list[start*3], numok, authit);
    - if (retval) {
    - free((char *)list);
    - return(retval);
    - }
    - start = -1;
    - }
    - if (numok)
    - retval = subscr_sendoff(&notice, &list[start*3], numok, authit);
    - free((char *)list);
    - return(retval);
    -}
    -
    -static Code_t
    -subscr_sendoff(ZNotice_t *notice, char **lyst, int num, int authit)
    -{
    - register Code_t retval;
    - ZNotice_t retnotice;
    -
    - retval = ZSendList(notice, lyst, num*3, ZAUTH);
    - if (retval != ZERR_NONE && !authit)
    - retval = ZSendList(notice, lyst, num*3, ZNOAUTH);
    -
    - if (retval != ZERR_NONE)
    - return (retval);
    - retval = ZIfNotice(&retnotice, NULL, ZCompareUIDPred,
    - (char *)&notice->z_uid);
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - if (retnotice.z_kind == SERVNAK) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_SERVNAK);
    - }
    - if (retnotice.z_kind != SERVACK) {
    - ZFreeNotice(&retnotice);
    - return (ZERR_INTERNAL);
    - }
    - ZFreeNotice(&retnotice);
    - return (ZERR_NONE);
    -}
    --- a/libpurple/protocols/zephyr/ZVariables.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,224 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the ZGetVariable, ZSetVariable, and ZUnsetVariable
    - * functions.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include <glib.h>
    -#include <glib/gstdio.h>
    -
    -#include "internal.h"
    -
    -#include <purple.h>
    -
    -#include <ctype.h>
    -#ifndef WIN32
    -#include <pwd.h>
    -#endif
    -
    -static char *get_localvarfile(void);
    -static const gchar *get_varval(const gchar *fn, const gchar *val);
    -static int varline(const gchar *bfr, const gchar *var);
    -
    -const gchar *
    -ZGetVariable(const gchar *var)
    -{
    - gchar *varfile;
    - const gchar *ret;
    -
    - if ((varfile = get_localvarfile()) == NULL)
    - return ((char *)0);
    -
    - ret = get_varval(varfile, var);
    - g_free(varfile);
    - if (ret != ZERR_NONE)
    - return ret;
    -
    -#ifdef _WIN32
    - varfile = g_strdup("C:\\zephyr\\zephyr.var");
    -#else
    - varfile = g_build_filename(PURPLE_SYSCONFDIR, "zephyr.vars", NULL);
    -#endif
    - ret = get_varval(varfile, var);
    - g_free(varfile);
    -
    - return ret;
    -}
    -
    -Code_t
    -ZSetVariable(char *var, char *value)
    -{
    - int written;
    - FILE *fpin, *fpout;
    - char *varfile, *varfilebackup, varbfr[512];
    -
    - written = 0;
    -
    - if ((varfile = get_localvarfile()) == NULL)
    - return (ZERR_INTERNAL);
    -
    - varfilebackup = g_strconcat(varfile, ".backup", NULL);
    -
    - if (!(fpout = fopen(varfilebackup, "w"))) {
    - g_free(varfile);
    - g_free(varfilebackup);
    - return (errno);
    - }
    - if ((fpin = fopen(varfile, "r")) != NULL) {
    - while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
    - if (varbfr[strlen(varbfr)-1] < ' ')
    - varbfr[strlen(varbfr)-1] = '\0';
    - if (varline(varbfr, var)) {
    - fprintf(fpout, "%s = %s\n", var, value);
    - written = 1;
    - }
    - else
    - fprintf(fpout, "%s\n", varbfr);
    - }
    - (void) fclose(fpin); /* don't care about errs on input */
    - }
    - if (!written)
    - fprintf(fpout, "%s = %s\n", var, value);
    - if (fclose(fpout) == EOF) {
    - g_free(varfilebackup);
    - g_free(varfile);
    - return(EIO); /* can't rely on errno */
    - }
    - if (g_rename(varfilebackup, varfile)) {
    - g_free(varfilebackup);
    - g_free(varfile);
    - return (errno);
    - }
    - g_free(varfilebackup);
    - g_free(varfile);
    - return (ZERR_NONE);
    -}
    -
    -Code_t
    -ZUnsetVariable(char *var)
    -{
    - FILE *fpin, *fpout;
    - char *varfile, *varfilebackup, varbfr[512];
    -
    - if ((varfile = get_localvarfile()) == NULL)
    - return (ZERR_INTERNAL);
    -
    - varfilebackup = g_strconcat(varfile, ".backup", NULL);
    -
    - if (!(fpout = fopen(varfilebackup, "w"))) {
    - g_free(varfile);
    - g_free(varfilebackup);
    - return (errno);
    - }
    - if ((fpin = fopen(varfile, "r")) != NULL) {
    - while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
    - if (varbfr[strlen(varbfr)-1] < ' ')
    - varbfr[strlen(varbfr)-1] = '\0';
    - if (!varline(varbfr, var))
    - fprintf(fpout, "%s\n", varbfr);
    - }
    - (void) fclose(fpin); /* don't care about read close errs */
    - }
    - if (fclose(fpout) == EOF) {
    - g_free(varfilebackup);
    - g_free(varfile);
    - return(EIO); /* errno isn't reliable */
    - }
    - if (g_rename(varfilebackup, varfile)) {
    - g_free(varfilebackup);
    - g_free(varfile);
    - return (errno);
    - }
    - g_free(varfilebackup);
    - g_free(varfile);
    - return (ZERR_NONE);
    -}
    -
    -static char *get_localvarfile(void)
    -{
    - const char *base;
    -#ifndef WIN32
    - struct passwd *pwd;
    - base = purple_home_dir();
    -#else
    - base = getenv("HOME");
    - if (!base)
    - base = getenv("HOMEPATH");
    - if (!base)
    - base = "C:\\";
    -#endif
    - if (!base) {
    -#ifndef WIN32
    - if (!(pwd = getpwuid((int) getuid()))) {
    - fprintf(stderr, "Zephyr internal failure: Can't find your entry in /etc/passwd\n");
    - return NULL;
    - }
    - base = pwd->pw_dir;
    -#endif
    - }
    -
    - return g_strconcat(base, "/.zephyr.vars", NULL);
    -}
    -
    -static const gchar *
    -get_varval(const gchar *fn, const gchar *var)
    -{
    - FILE *fp;
    - static gchar varbfr[512];
    - int i;
    -
    - fp = fopen(fn, "r");
    - if (!fp)
    - return ((char *)0);
    -
    - while (fgets(varbfr, sizeof varbfr, fp) != (char *) 0) {
    - if (varbfr[strlen(varbfr)-1] < ' ')
    - varbfr[strlen(varbfr)-1] = '\0';
    - if (!(i = varline(varbfr, var)))
    - continue;
    - (void) fclose(fp); /* open read-only, don't care */
    - return (varbfr+i);
    - }
    - (void) fclose(fp); /* open read-only, don't care */
    - return ((char *)0);
    -}
    -
    -/* If the variable in the line bfr[] is the same as var, return index to
    - the variable value, else return 0. */
    -static int
    -varline(const gchar *bfr, const gchar *var)
    -{
    - register const gchar *cp;
    -
    - if (!bfr[0] || bfr[0] == '#') {
    - /* comment or null line */
    - return (0);
    - }
    -
    - cp = bfr;
    - while (*cp && !isspace(*cp) && (*cp != '=')) {
    - cp++;
    - }
    -
    - if (g_ascii_strncasecmp(bfr, var, MAX(strlen(var), (gsize)(cp - bfr)))) {
    - /* var is not the var in bfr ==> no match */
    - return 0;
    - }
    -
    - cp = strchr(bfr, '=');
    - if (!cp) {
    - return (0);
    - }
    - cp++;
    - while (*cp && isspace(*cp)) {
    - /* space up to variable value */
    - cp++;
    - }
    -
    - return (cp - bfr); /* return index */
    -}
    --- a/libpurple/protocols/zephyr/ZWait4Not.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,62 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains the ZCheckIfNotice/select loop used for waiting for
    - * a notice, with a timeout.
    - *
    - * Copyright (c) 1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#ifdef WIN32
    -#include <winsock2.h>
    -#else
    -#include <sys/socket.h>
    -#endif
    -
    -Code_t
    -Z_WaitForNotice(ZNotice_t *notice, int (*pred)(ZNotice_t *, void *), void *arg,
    - int timeout)
    -{
    - Code_t retval;
    - gint64 t0, tdiff, timeout_us;
    - GError *error = NULL;
    -
    - retval = ZCheckIfNotice(notice, NULL, pred, (char *)arg);
    - if (retval == ZERR_NONE) {
    - return ZERR_NONE;
    - }
    - if (retval != ZERR_NONOTICE) {
    - return retval;
    - }
    -
    - timeout_us = timeout * G_USEC_PER_SEC;
    - t0 = g_get_monotonic_time() + timeout_us;
    - while (TRUE) {
    - if (!g_socket_condition_timed_wait(ZGetSocket(), G_IO_IN, timeout_us,
    - NULL, &error)) {
    - gint ret = ZERR_INTERNAL;
    - if (error->code == G_IO_ERROR_TIMED_OUT) {
    - ret = ETIMEDOUT;
    - }
    - g_error_free(error);
    - return ret;
    - }
    -
    - retval = ZCheckIfNotice(notice, NULL, pred, (char *)arg);
    - if (retval != ZERR_NONOTICE) {
    - /* includes ZERR_NONE */
    - return retval;
    - }
    -
    - tdiff = t0 - g_get_monotonic_time();
    - if (tdiff < 0) {
    - return ETIMEDOUT;
    - }
    - /* g_socket_condition_timed_wait requires timeout to be an integral
    - * number of milliseconds. */
    - timeout_us = (tdiff / 1000 + 1) * 1000;
    - }
    - /* NOTREACHED */
    -}
    --- a/libpurple/protocols/zephyr/ZhmStat.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,72 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains the ZhmStat() function.
    - *
    - * Created by: Marc Horowitz
    - *
    - * Copyright (c) 1996 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include "internal.h"
    -
    -#ifdef WIN32
    -#include <winsock2.h>
    -#else
    -#include <sys/socket.h>
    -#endif
    -
    -Code_t
    -ZhmStat(ZNotice_t *notice)
    -{
    - struct servent *sp;
    - GInetAddress *inet_addr = NULL;
    - GSocketAddress *addr = NULL;
    - ZNotice_t req;
    - Code_t code;
    - GError *error = NULL;
    -
    - sp = getservbyname(HM_SVCNAME, "udp");
    -
    - memset(&req, 0, sizeof(req));
    - req.z_kind = STAT;
    - req.z_port = 0;
    - req.z_class = HM_STAT_CLASS;
    - req.z_class_inst = HM_STAT_CLIENT;
    - req.z_opcode = HM_GIMMESTATS;
    - req.z_sender = "";
    - req.z_recipient = "";
    - req.z_default_format = "";
    - req.z_message_len = 0;
    -
    - inet_addr = g_inet_address_new_loopback(G_SOCKET_FAMILY_IPV4);
    - addr = g_inet_socket_address_new(inet_addr,
    - sp ? sp->s_port : HM_SVC_FALLBACK);
    - code = ZSetDestAddr(addr);
    - g_object_unref(inet_addr);
    - g_object_unref(addr);
    - if (code != ZERR_NONE) {
    - return code;
    - }
    -
    - if ((code = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE) {
    - return code;
    - }
    -
    - /* Wait up to ten seconds for a response. */
    - if (!g_socket_condition_timed_wait(ZGetSocket(), G_IO_IN,
    - 10 * G_USEC_PER_SEC, NULL, &error)) {
    - gint ret = ZERR_INTERNAL;
    - if (error->code == G_IO_ERROR_TIMED_OUT) {
    - ret = ETIMEDOUT;
    - }
    - g_error_free(error);
    - return ret;
    - }
    -
    - if (ZPending() == 0) {
    - return ZERR_HMDEAD;
    - }
    -
    - return ZReceiveNotice(notice, NULL);
    -}
    --- a/libpurple/protocols/zephyr/Zinternal.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,810 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains source for the internal Zephyr routines.
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of
    - * Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#include <purple.h>
    -#include "libpurple/glibcompat.h"
    -
    -#include "internal.h"
    -#ifdef WIN32
    -#include <winsock2.h>
    -#else
    -#include <arpa/inet.h>
    -#include <sys/socket.h>
    -#endif
    -
    -GSocket *__Zephyr_socket = NULL;
    -gint __Zephyr_port = -1;
    -guint32 __My_addr;
    -int __Q_CompleteLength;
    -int __Q_Size;
    -GQueue Z_input_queue = G_QUEUE_INIT;
    -GSocketAddress *__HM_addr;
    -ZLocations_t *__locate_list;
    -int __locate_num;
    -int __locate_next;
    -ZSubscription_t *__subscriptions_list;
    -int __subscriptions_num;
    -int __subscriptions_next;
    -int Z_discarded_packets = 0;
    -
    -#ifdef ZEPHYR_USES_KERBEROS
    -C_Block __Zephyr_session;
    -#endif
    -char __Zephyr_realm[REALM_SZ];
    -
    -static int Z_AddField(char **ptr, const char *field, char *end);
    -static int find_or_insert_uid(ZUnique_Id_t *uid, ZNotice_Kind_t kind);
    -
    -/* Find or insert uid in the old uids buffer. The buffer is a sorted
    - * circular queue. We make the assumption that most packets arrive in
    - * order, so we can usually search for a uid or insert it into the buffer
    - * by looking back just a few entries from the end. Since this code is
    - * only executed by the client, the implementation isn't microoptimized. */
    -static int
    -find_or_insert_uid(ZUnique_Id_t *uid, ZNotice_Kind_t kind)
    -{
    - static struct _filter {
    - ZUnique_Id_t uid;
    - ZNotice_Kind_t kind;
    - time_t t;
    - } *buffer;
    - static long size;
    - static long start;
    - static long num;
    -
    - time_t now;
    - struct _filter *new;
    - long i, j, new_size;
    - int result;
    -
    - /* Initialize the uid buffer if it hasn't been done already. */
    - if (!buffer) {
    - size = Z_INITFILTERSIZE;
    - buffer = (struct _filter *) malloc(size * sizeof(*buffer));
    - if (!buffer)
    - return 0;
    - }
    -
    - /* Age the uid buffer, discarding any uids older than the clock skew. */
    - time(&now);
    - while (num && (now - buffer[start % size].t) > CLOCK_SKEW)
    - start++, num--;
    - start %= size;
    -
    - /* Make room for a new uid, since we'll probably have to insert one. */
    - if (num == size) {
    - new_size = size * 2 + 2;
    - new = (struct _filter *) malloc(new_size * sizeof(*new));
    - if (!new)
    - return 0;
    - for (i = 0; i < num; i++)
    - new[i] = buffer[(start + i) % size];
    - free(buffer);
    - buffer = new;
    - size = new_size;
    - start = 0;
    - }
    -
    - /* Search for this uid in the buffer, starting from the end. */
    - for (i = start + num - 1; i >= start; i--) {
    - result = memcmp(uid, &buffer[i % size].uid, sizeof(*uid));
    - if (result == 0 && buffer[i % size].kind == kind)
    - return 1;
    - if (result > 0)
    - break;
    - }
    -
    - /* We didn't find it; insert the uid into the buffer after i. */
    - i++;
    - for (j = start + num; j > i; j--)
    - buffer[j % size] = buffer[(j - 1) % size];
    - buffer[i % size].uid = *uid;
    - buffer[i % size].kind = kind;
    - buffer[i % size].t = now;
    - num++;
    -
    - return 0;
    -}
    -
    -/* Wait for a complete notice to become available */
    -
    -Code_t Z_WaitForComplete(void)
    -{
    - Code_t retval;
    -
    - if (__Q_CompleteLength)
    - return (Z_ReadEnqueue());
    -
    - while (!__Q_CompleteLength)
    - if ((retval = Z_ReadWait()) != ZERR_NONE)
    - return (retval);
    -
    - return (ZERR_NONE);
    -}
    -
    -
    -/* Read any available packets and enqueue them */
    -
    -Code_t
    -Z_ReadEnqueue(void)
    -{
    - if (ZGetSocket() == NULL) {
    - return ZERR_NOPORT;
    - }
    -
    - while (g_socket_condition_check(ZGetSocket(), G_IO_IN)) {
    - Code_t retval = Z_ReadWait();
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - }
    -
    - return ZERR_NONE;
    -}
    -
    -
    -/*
    - * Search the queue for a notice with the proper multiuid - remove any
    - * notices that haven't been touched in a while
    - */
    -
    -static Z_InputQ *
    -Z_SearchQueue(ZUnique_Id_t *uid, ZNotice_Kind_t kind)
    -{
    - register GList *list;
    - GList *next;
    - gint64 now;
    -
    - now = g_get_monotonic_time();
    -
    - list = Z_input_queue.head;
    -
    - while (list) {
    - Z_InputQ *qptr = (Z_InputQ *)list->data;
    - if (ZCompareUID(uid, &qptr->uid) && qptr->kind == kind) {
    - return qptr;
    - }
    - next = list->next;
    - if (qptr->time && qptr->time + Z_NOTICETIMELIMIT < now) {
    - Z_RemQueue(qptr);
    - }
    - list = next;
    - }
    - return NULL;
    -}
    -
    -/*
    - * Now we delve into really convoluted queue handling and
    - * fragmentation reassembly algorithms and other stuff you probably
    - * don't want to look at...
    - *
    - * This routine does NOT guarantee a complete packet will be ready when it
    - * returns.
    - */
    -
    -Code_t
    -Z_ReadWait(void)
    -{
    - register Z_InputQ *qptr;
    - Z_Hole *hole = NULL;
    - ZNotice_t notice;
    - ZPacket_t packet;
    - GSocketAddress *from = NULL;
    - int packet_len, zvlen, part, partof;
    - char *slash;
    - Code_t retval;
    - GError *error = NULL;
    -
    - if (ZGetSocket() == NULL) {
    - return ZERR_NOPORT;
    - }
    -
    - if (!g_socket_condition_timed_wait(ZGetSocket(), G_IO_IN,
    - 60 * G_USEC_PER_SEC, NULL, &error)) {
    - gint ret = ZERR_INTERNAL;
    - if (error->code == G_IO_ERROR_TIMED_OUT) {
    - ret = ETIMEDOUT;
    - }
    - g_error_free(error);
    - return ret;
    - }
    -
    - packet_len = g_socket_receive_from(ZGetSocket(), &from, packet,
    - sizeof(packet) - 1, NULL, &error);
    - if (packet_len < 0) {
    - purple_debug_error("zephyr", "Unable to receive from socket: %s",
    - error->message);
    - g_error_free(error);
    - return ZERR_INTERNAL;
    - }
    -
    - if (packet_len == 0) {
    - return ZERR_EOF;
    - }
    -
    - packet[packet_len] = '\0';
    -
    - /* Ignore obviously non-Zephyr packets. */
    - zvlen = sizeof(ZVERSIONHDR) - 1;
    - if (packet_len < zvlen || memcmp(packet, ZVERSIONHDR, zvlen) != 0) {
    - Z_discarded_packets++;
    - g_object_unref(from);
    - return ZERR_NONE;
    - }
    -
    - /* Parse the notice */
    - if ((retval = ZParseNotice(packet, packet_len, &notice)) != ZERR_NONE) {
    - g_object_unref(from);
    - return retval;
    - }
    -
    - /* If the notice is of an appropriate kind, send back a CLIENTACK to
    - * whoever sent it to say we got it. */
    - if (notice.z_kind != HMACK && notice.z_kind != SERVACK &&
    - notice.z_kind != SERVNAK && notice.z_kind != CLIENTACK) {
    - GSocketAddress *olddest = NULL;
    - ZNotice_t tmpnotice;
    - ZPacket_t pkt;
    - int len;
    -
    - tmpnotice = notice;
    - tmpnotice.z_kind = CLIENTACK;
    - tmpnotice.z_message_len = 0;
    - olddest = __HM_addr;
    - __HM_addr = from;
    - if ((retval = ZFormatSmallRawNotice(&tmpnotice, pkt, &len)) != ZERR_NONE) {
    - __HM_addr = olddest;
    - g_object_unref(from);
    - return retval;
    - }
    - if ((retval = ZSendPacket(pkt, len, 0)) != ZERR_NONE) {
    - __HM_addr = olddest;
    - g_object_unref(from);
    - return retval;
    - }
    - __HM_addr = olddest;
    - }
    - if (find_or_insert_uid(&notice.z_uid, notice.z_kind)) {
    - g_object_unref(from);
    - return ZERR_NONE;
    - }
    -
    - /* Check authentication on the notice. */
    - notice.z_checked_auth = ZCheckAuthentication(&notice);
    -
    - /*
    - * Parse apart the z_multinotice field - if the field is blank for
    - * some reason, assume this packet stands by itself.
    - */
    - slash = strchr(notice.z_multinotice, '/');
    - if (slash) {
    - part = atoi(notice.z_multinotice);
    - partof = atoi(slash+1);
    - if (part > partof || partof == 0) {
    - part = 0;
    - partof = notice.z_message_len;
    - }
    - }
    - else {
    - part = 0;
    - partof = notice.z_message_len;
    - }
    -
    - /* Too big a packet...just ignore it! */
    - if (partof > Z_MAXNOTICESIZE) {
    - g_object_unref(from);
    - return ZERR_NONE;
    - }
    -
    - /* If we can find a notice in the queue with the same multiuid field,
    - * insert the current fragment as appropriate. */
    - switch (notice.z_kind) {
    - case SERVACK:
    - case SERVNAK:
    - /* The SERVACK and SERVNAK replies shouldn't be reassembled
    - (they have no parts). Instead, we should hold on to the reply
    - ONLY if it's the first part of a fragmented message, i.e.
    - multi_uid == uid. This allows programs to wait for the uid
    - of the first packet, and get a response when that notice
    - arrives. Acknowledgements of the other fragments are discarded
    - (XXX we assume here that they all carry the same information
    - regarding failure/success)
    - */
    - if (!ZCompareUID(&notice.z_multiuid, &notice.z_uid)) {
    - /* they're not the same... throw away this packet. */
    - g_object_unref(from);
    - return ZERR_NONE;
    - }
    - /* fall thru & process it */
    - default:
    - /* for HMACK types, we assume no packet loss (local loopback
    - connections). The other types can be fragmented and MUST
    - run through this code. */
    - if ((qptr = Z_SearchQueue(&notice.z_multiuid, notice.z_kind)) != NULL) {
    - /* If this is the first fragment, and we haven't already gotten
    - * a first fragment, grab the header from it. */
    - if (part == 0 && qptr->header == NULL) {
    - qptr->header_len = packet_len - notice.z_message_len;
    - qptr->header = g_memdup2(packet, qptr->header_len);
    - }
    - g_object_unref(from);
    - return Z_AddNoticeToEntry(qptr, &notice, part);
    - }
    - }
    -
    - /* We'll have to create a new entry...make sure the queue isn't going
    - * to get too big. */
    - if (__Q_Size + partof > Z_MAXQUEUESIZE) {
    - g_object_unref(from);
    - return ZERR_NONE;
    - }
    -
    - /* This is a notice we haven't heard of, so create a new queue entry
    - * for it and zero it out. */
    - qptr = g_new0(Z_InputQ, 1);
    -
    - /* Insert the entry at the end of the queue */
    - g_queue_push_tail(&Z_input_queue, qptr);
    -
    - /* Copy the from field, multiuid, kind, and checked authentication. */
    - qptr->from = from;
    - qptr->uid = notice.z_multiuid;
    - qptr->kind = notice.z_kind;
    - qptr->auth = notice.z_checked_auth;
    -
    - /* If this is the first part of the notice, we take the header from it.
    - * We only take it if this is the first fragment so that the Unique
    - * ID's will be predictable. */
    - if (part == 0) {
    - qptr->header_len = packet_len - notice.z_message_len;
    - qptr->header = g_memdup2(packet, qptr->header_len);
    - }
    -
    - /* If this is not a fragmented notice, then don't bother with a hole
    - * list. */
    - if (part == 0 && notice.z_message_len == partof) {
    - __Q_CompleteLength++;
    - qptr->holelist = NULL;
    - qptr->complete = TRUE;
    - /* allocate a msg buf for this piece */
    - if (notice.z_message_len == 0) {
    - qptr->msg = NULL;
    - } else {
    - qptr->msg = g_memdup2(notice.z_message, notice.z_message_len);
    - }
    - qptr->msg_len = notice.z_message_len;
    - __Q_Size += notice.z_message_len;
    - qptr->packet_len = qptr->header_len + qptr->msg_len;
    - qptr->packet = g_new(gchar, qptr->packet_len);
    - memcpy(qptr->packet, qptr->header, qptr->header_len);
    - if (qptr->msg) {
    - memcpy(qptr->packet + qptr->header_len, qptr->msg, qptr->msg_len);
    - }
    - return ZERR_NONE;
    - }
    -
    - /* We know how long the message is going to be (this is better than IP
    - * fragmentation...), so go ahead and allocate it all. */
    - qptr->msg = g_new0(gchar, partof);
    - qptr->msg_len = partof;
    - __Q_Size += partof;
    -
    - /*
    - * Well, it's a fragmented notice...allocate a hole list and
    - * initialize it to the full packet size. Then insert the
    - * current fragment.
    - */
    - hole = g_new0(Z_Hole, 1);
    - if (hole == NULL) {
    - return ENOMEM;
    - }
    - hole->first = 0;
    - hole->last = partof - 1;
    - qptr->holelist = g_slist_prepend(qptr->holelist, hole);
    - return Z_AddNoticeToEntry(qptr, &notice, part);
    -}
    -
    -
    -/* Fragment management routines - compliments, more or less, of RFC815 */
    -
    -static gint
    -find_hole(gconstpointer element, gconstpointer data)
    -{
    - Z_Hole *thishole = (Z_Hole *)element;
    - Z_Hole *tofind = (Z_Hole *)data;
    -
    - if (tofind->first <= thishole->last && tofind->last >= thishole->first) {
    - return 0;
    - }
    -
    - return 1;
    -}
    -
    -Code_t
    -Z_AddNoticeToEntry(Z_InputQ *qptr, ZNotice_t *notice, int part)
    -{
    - GSList *thishole;
    - Z_Hole *hole;
    - gint last;
    -
    - /* Incorporate this notice's checked authentication. */
    - if (notice->z_checked_auth == ZAUTH_FAILED) {
    - qptr->auth = ZAUTH_FAILED;
    - } else if (notice->z_checked_auth == ZAUTH_NO && qptr->auth != ZAUTH_FAILED) {
    - qptr->auth = ZAUTH_NO;
    - }
    -
    - qptr->time = g_get_monotonic_time();
    -
    - last = part + notice->z_message_len - 1;
    -
    - /* copy in the message body */
    - memcpy(qptr->msg + part, notice->z_message, notice->z_message_len);
    -
    - /* Search for a hole that overlaps with the current fragment */
    - hole = g_new(Z_Hole, 1);
    - hole->first = part;
    - hole->last = last;
    - thishole = g_slist_find_custom(qptr->holelist, hole, find_hole);
    - g_free(hole);
    -
    - /* If we found one, delete it and reconstruct a new hole */
    - if (thishole) {
    - gint oldfirst, oldlast;
    -
    - hole = (Z_Hole *)thishole->data;
    - oldfirst = hole->first;
    - oldlast = hole->last;
    - qptr->holelist = g_slist_delete_link(qptr->holelist, thishole);
    - g_free(hole);
    -
    - /*
    - * Now create a new hole that is the original hole without the
    - * current fragment.
    - */
    - if (part > oldfirst) {
    - hole = g_new0(Z_Hole, 1);
    - qptr->holelist = g_slist_prepend(qptr->holelist, hole);
    - hole->first = oldfirst;
    - hole->last = part - 1;
    - }
    - if (last < oldlast) {
    - hole = g_new0(Z_Hole, 1);
    - qptr->holelist = g_slist_prepend(qptr->holelist, hole);
    - hole->first = last + 1;
    - hole->last = oldlast;
    - }
    - }
    -
    - /* If there are no more holes, the packet is complete. */
    - if (qptr->holelist == NULL) {
    - if (!qptr->complete) {
    - __Q_CompleteLength++;
    - }
    - qptr->complete = TRUE;
    - qptr->time = 0; /* don't time out anymore */
    - qptr->packet_len = qptr->header_len + qptr->msg_len;
    - qptr->packet = g_new(gchar, qptr->packet_len);
    - memcpy(qptr->packet, qptr->header, qptr->header_len);
    - memcpy(qptr->packet + qptr->header_len, qptr->msg, qptr->msg_len);
    - }
    -
    - return ZERR_NONE;
    -}
    -
    -Code_t
    -Z_FormatHeader(ZNotice_t *notice, char *buffer, int buffer_len, int *len,
    - Z_AuthProc cert_routine)
    -{
    - static char version[BUFSIZ]; /* default init should be all \0 */
    - gint64 realtime;
    -
    - if (!notice->z_sender) {
    - notice->z_sender = ZGetSender();
    - }
    -
    - if (notice->z_port == 0) {
    - GSocketAddress *addr = NULL;
    - GError *error = NULL;
    -
    - if (ZGetSocket() == NULL) {
    - Code_t retval = ZOpenPort(NULL);
    - if (retval != ZERR_NONE) {
    - return retval;
    - }
    - }
    -
    - addr = g_socket_get_local_address(ZGetSocket(), &error);
    - if (addr == NULL) {
    - purple_debug_error("zephyr",
    - "Unable to determine socket local address: %s",
    - error->message);
    - g_error_free(error);
    - return ZERR_INTERNAL;
    - }
    - notice->z_port =
    - g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(addr));
    - g_object_unref(addr);
    - }
    -
    - notice->z_multinotice = "";
    -
    - realtime = g_get_real_time();
    - notice->z_uid.tv.tv_sec = realtime / G_USEC_PER_SEC;
    - notice->z_uid.tv.tv_usec =
    - realtime - notice->z_uid.tv.tv_sec * G_USEC_PER_SEC;
    - notice->z_uid.tv.tv_sec = GUINT64_TO_BE((guint64)notice->z_uid.tv.tv_sec);
    - notice->z_uid.tv.tv_usec = GUINT64_TO_BE((guint64)notice->z_uid.tv.tv_usec);
    -
    - memcpy(&notice->z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
    -
    - notice->z_multiuid = notice->z_uid;
    -
    - if (!version[0]) {
    - sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR, ZVERSIONMINOR);
    - }
    - notice->z_version = version;
    -
    - return Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
    -}
    -
    -Code_t
    -Z_FormatAuthHeader(ZNotice_t *notice, char *buffer, int buffer_len, int *len,
    - Z_AuthProc cert_routine)
    -{
    - if (!cert_routine) {
    - notice->z_auth = 0;
    - notice->z_authent_len = 0;
    - notice->z_ascii_authent = "";
    - notice->z_checksum = 0;
    - return (Z_FormatRawHeader(notice, buffer, buffer_len,
    - len, NULL, NULL));
    - }
    -
    - return ((*cert_routine)(notice, buffer, buffer_len, len));
    -}
    -
    -Code_t
    -Z_FormatRawHeader(ZNotice_t *notice, char *buffer, gsize buffer_len, int *len,
    - char **cstart, char **cend)
    -{
    - char newrecip[BUFSIZ];
    - char *ptr, *end;
    - int i;
    -
    - if (!notice->z_class)
    - notice->z_class = "";
    -
    - if (!notice->z_class_inst)
    - notice->z_class_inst = "";
    -
    - if (!notice->z_opcode)
    - notice->z_opcode = "";
    -
    - if (!notice->z_recipient)
    - notice->z_recipient = "";
    -
    - if (!notice->z_default_format)
    - notice->z_default_format = "";
    -
    - ptr = buffer;
    - end = buffer+buffer_len;
    -
    - if (buffer_len < strlen(notice->z_version)+1)
    - return (ZERR_HEADERLEN);
    -
    - g_strlcpy(ptr, notice->z_version, buffer_len);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii32(ptr, end-ptr, Z_NUMFIELDS + notice->z_num_other_fields)
    - == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii32(ptr, end-ptr, notice->z_kind) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
    - sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii16(ptr, end-ptr, g_ntohs(notice->z_port)) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii32(ptr, end-ptr, notice->z_auth) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (ZMakeAscii32(ptr, end-ptr, notice->z_authent_len) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - if (Z_AddField(&ptr, notice->z_ascii_authent, end))
    - return (ZERR_HEADERLEN);
    - if (Z_AddField(&ptr, notice->z_class, end))
    - return (ZERR_HEADERLEN);
    - if (Z_AddField(&ptr, notice->z_class_inst, end))
    - return (ZERR_HEADERLEN);
    - if (Z_AddField(&ptr, notice->z_opcode, end))
    - return (ZERR_HEADERLEN);
    - if (Z_AddField(&ptr, notice->z_sender, end))
    - return (ZERR_HEADERLEN);
    - if (strchr(notice->z_recipient, '@') || !*notice->z_recipient) {
    - if (Z_AddField(&ptr, notice->z_recipient, end))
    - return (ZERR_HEADERLEN);
    - }
    - else {
    - if (strlen(notice->z_recipient) + strlen(__Zephyr_realm) + 2 >
    - sizeof(newrecip))
    - return (ZERR_HEADERLEN);
    - (void) sprintf(newrecip, "%s@%s", notice->z_recipient, __Zephyr_realm);
    - if (Z_AddField(&ptr, newrecip, end))
    - return (ZERR_HEADERLEN);
    - }
    - if (Z_AddField(&ptr, notice->z_default_format, end))
    - return (ZERR_HEADERLEN);
    -
    - /* copy back the end pointer location for crypto checksum */
    - if (cstart)
    - *cstart = ptr;
    - if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    - if (cend)
    - *cend = ptr;
    -
    - if (Z_AddField(&ptr, notice->z_multinotice, end))
    - return (ZERR_HEADERLEN);
    -
    - if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
    - sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
    - return (ZERR_HEADERLEN);
    - ptr += strlen(ptr)+1;
    -
    - for (i=0;i<notice->z_num_other_fields;i++)
    - if (Z_AddField(&ptr, notice->z_other_fields[i], end))
    - return (ZERR_HEADERLEN);
    -
    - *len = ptr-buffer;
    -
    - return (ZERR_NONE);
    -}
    -
    -static int
    -Z_AddField(char **ptr, const char *field, char *end)
    -{
    - register int len;
    -
    - len = field ? strlen (field) + 1 : 1;
    -
    - if (*ptr+len > end)
    - return 1;
    - if (field)
    - strcpy(*ptr, field);
    - else
    - **ptr = '\0';
    - *ptr += len;
    -
    - return 0;
    -}
    -
    -static gint
    -find_complete_input(gconstpointer a, G_GNUC_UNUSED gconstpointer b)
    -{
    - Z_InputQ *qptr = (Z_InputQ *)a;
    - return qptr->complete ? 0 : 1;
    -}
    -
    -Z_InputQ *
    -Z_GetFirstComplete(void)
    -{
    - GList *list;
    -
    - list = g_queue_find_custom(&Z_input_queue, NULL, find_complete_input);
    - return list ? (Z_InputQ *)list->data : NULL;
    -}
    -
    -Z_InputQ *
    -Z_GetNextComplete(Z_InputQ *qptr)
    -{
    - GList *list = g_queue_find(&Z_input_queue, qptr);
    -
    - if (list) {
    - list = list->next;
    - list = g_list_find_custom(list, NULL, find_complete_input);
    - }
    -
    - return list ? (Z_InputQ *)list->data : NULL;
    -}
    -
    -void
    -Z_RemQueue(Z_InputQ *qptr)
    -{
    - if (qptr->complete) {
    - __Q_CompleteLength--;
    - }
    -
    - __Q_Size -= qptr->msg_len;
    -
    - g_free(qptr->header);
    - g_free(qptr->msg);
    - g_free(qptr->packet);
    -
    - g_clear_object(&qptr->from);
    -
    - g_slist_free_full(qptr->holelist, g_free);
    -
    - g_queue_remove(&Z_input_queue, qptr);
    - g_free(qptr);
    -}
    -
    -Code_t
    -Z_SendFragmentedNotice(ZNotice_t *notice, int len, Z_AuthProc cert_func,
    - Z_SendProc send_func)
    -{
    - ZNotice_t partnotice;
    - ZPacket_t buffer;
    - char multi[64];
    - int offset, hdrsize, fragsize, ret_len, message_len, waitforack;
    - Code_t retval;
    -
    - hdrsize = len-notice->z_message_len;
    - fragsize = Z_MAXPKTLEN-hdrsize-Z_FRAGFUDGE;
    -
    - offset = 0;
    -
    - waitforack = (notice->z_kind == UNACKED || notice->z_kind == ACKED);
    -
    - partnotice = *notice;
    -
    - while (offset < notice->z_message_len || !notice->z_message_len) {
    - (void) sprintf(multi, "%d/%d", offset, notice->z_message_len);
    - partnotice.z_multinotice = multi;
    - if (offset > 0) {
    - gint64 realtime = g_get_real_time();
    - partnotice.z_uid.tv.tv_sec = realtime / G_USEC_PER_SEC;
    - partnotice.z_uid.tv.tv_usec =
    - realtime - partnotice.z_uid.tv.tv_sec * G_USEC_PER_SEC;
    - partnotice.z_uid.tv.tv_sec =
    - GUINT64_TO_BE((guint64)partnotice.z_uid.tv.tv_sec);
    - partnotice.z_uid.tv.tv_usec =
    - GUINT64_TO_BE((guint64)partnotice.z_uid.tv.tv_usec);
    - memcpy(&partnotice.z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
    - }
    - message_len = MIN(notice->z_message_len - offset, fragsize);
    - partnotice.z_message = (char*)notice->z_message+offset;
    - partnotice.z_message_len = message_len;
    - if ((retval = Z_FormatAuthHeader(&partnotice, buffer, Z_MAXHEADERLEN,
    - &ret_len, cert_func)) != ZERR_NONE) {
    - return (retval);
    - }
    - memcpy(buffer + ret_len, partnotice.z_message, message_len);
    - if ((retval = (*send_func)(&partnotice, buffer, ret_len+message_len,
    - waitforack)) != ZERR_NONE) {
    - return (retval);
    - }
    - offset += fragsize;
    - if (!notice->z_message_len)
    - break;
    - }
    -
    - return (ZERR_NONE);
    -}
    -
    -/*ARGSUSED*/
    -Code_t
    -Z_XmitFragment(ZNotice_t *notice, char *buf, int len, int wait)
    -{
    - return(ZSendPacket(buf, len, wait));
    -}
    --- a/libpurple/protocols/zephyr/internal.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,40 +0,0 @@
    -#ifndef PURPLE_ZEPHYR_INTERNAL_H
    -#define PURPLE_ZEPHYR_INTERNAL_H
    -
    -#include <sysdep.h>
    -
    -#ifdef LIBZEPHYR_EXT
    -#include <zephyr/zephyr.h>
    -#else
    -#include <zephyr_internal.h>
    -#endif
    -
    -#ifdef WIN32
    -
    -#ifndef MAXHOSTNAMELEN
    -#define MAXHOSTNAMELEN 512
    -#endif
    -
    -#define ETIMEDOUT WSAETIMEDOUT
    -#define EADDRINUSE WSAEADDRINUSE
    -#else /* !WIN32 */
    -#include <netdb.h>
    -
    -#ifndef MAXHOSTNAMELEN
    -#define MAXHOSTNAMELEN 4096
    -#endif
    -
    -#endif
    -
    -#ifdef ZEPHYR_USES_HESIOD
    -#include <hesiod.h>
    -#endif
    -
    -#ifndef ZEPHYR_USES_KERBEROS
    -#define REALM_SZ MAXHOSTNAMELEN
    -#define INST_SZ 0 /* no instances w/o Kerberos */
    -#define ANAME_SZ 9 /* size of a username + null */
    -#define CLOCK_SKEW 300 /* max time to cache packet ids */
    -#endif
    -
    -#endif /* PURPLE_ZEPHYR_INTERNAL_H */
    --- a/libpurple/protocols/zephyr/meson.build Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,85 +0,0 @@
    -ZEPHYR_INTERNAL_SOURCES = [
    - 'ZAsyncLocate.c',
    - 'ZCkAuth.c',
    - 'ZCkIfNot.c',
    - 'ZClosePort.c',
    - 'ZCmpUID.c',
    - 'ZCmpUIDP.c',
    - 'ZFlsLocs.c',
    - 'ZFlsSubs.c',
    - 'ZFmtAuth.c',
    - 'ZFmtList.c',
    - 'ZFmtNotice.c',
    - 'ZFmtRaw.c',
    - 'ZFmtRawLst.c',
    - 'ZFmtSmRaw.c',
    - 'ZFreeNot.c',
    - 'ZGetLocs.c',
    - 'ZGetSender.c',
    - 'ZGetSubs.c',
    - 'ZGetWGPort.c',
    - 'ZIfNotice.c',
    - 'ZInit.c',
    - 'ZLocations.c',
    - 'ZMakeAscii.c',
    - 'ZMkAuth.c',
    - 'ZNewLocU.c',
    - 'ZOpenPort.c',
    - 'ZParseNot.c',
    - 'ZPeekNot.c',
    - 'ZPeekPkt.c',
    - 'ZPending.c',
    - 'ZReadAscii.c',
    - 'ZRecvNot.c',
    - 'ZRecvPkt.c',
    - 'ZRetSubs.c',
    - 'ZSendList.c',
    - 'ZSendNot.c',
    - 'ZSendPkt.c',
    - 'ZSetDest.c',
    - 'ZSubs.c',
    - 'ZVariables.c',
    - 'ZWait4Not.c',
    - 'ZhmStat.c',
    - 'Zinternal.c',
    - 'mit-copyright.h',
    - 'mit-sipb-copyright.h',
    - 'zephyr_err.h',
    - 'zephyr_internal.h'
    -]
    -
    -ZEPHYR_SOURCES = [
    - 'internal.h',
    - 'sysdep.h',
    - 'zephyr.c',
    - 'zephyr.h',
    - 'zephyr_account.h',
    - 'zephyr_html.c',
    - 'zephyr_html.h',
    - 'zephyr_tzc.c',
    - 'zephyr_tzc.h',
    - 'zephyr_zeph02.c',
    - 'zephyr_zeph02.h',
    -]
    -
    -extdep = krb4
    -if ext_zephyr.found()
    - extdep = ext_zephyr
    -else
    - ZEPHYR_SOURCES += ZEPHYR_INTERNAL_SOURCES
    -endif
    -
    -if DYNAMIC_ZEPHYR
    - zephyr_resources = gnome.compile_resources('zephyrresource',
    - 'resources/zephyr.gresource.xml',
    - source_dir : 'resources',
    - c_name : 'zephyr')
    - ZEPHYR_SOURCES += zephyr_resources
    -
    - zephyr_prpl = shared_library('zephyr', ZEPHYR_SOURCES,
    - c_args : ['-Dlint', '-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-Zephyr"'],
    - dependencies : [extdep, libpurple_dep, glib],
    - install : true, install_dir : PURPLE_PLUGINDIR)
    -
    - devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
    -endif
    --- a/libpurple/protocols/zephyr/mit-copyright.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,24 +0,0 @@
    -/*
    -
    -Copyright 1987,1988 by the Massachusetts Institute of Technology
    -
    -All rights reserved.
    -
    -Permission to use, copy, modify, and distribute this software and its
    -documentation for any purpose and without fee is hereby granted,
    -provided that the above copyright notice appear in all copies and that
    -both that copyright notice and this permission notice appear in
    -supporting documentation, and that the name of the Massachusetts
    -Institute of Technology (M.I.T.) not be used in advertising or publicity
    -pertaining to distribution of the software without specific, written
    -prior permission.
    -
    -M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
    -M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
    -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
    -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
    -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
    -SOFTWARE.
    -
    -*/
    --- a/libpurple/protocols/zephyr/mit-sipb-copyright.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,19 +0,0 @@
    -/*
    -
    -Copyright 1987, 1989 by the Student Information Processing Board
    - of the Massachusetts Institute of Technology
    -
    -Permission to use, copy, modify, and distribute this software
    -and its documentation for any purpose and without fee is
    -hereby granted, provided that the above copyright notice
    -appear in all copies and that both that copyright notice and
    -this permission notice appear in supporting documentation,
    -and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
    -used in advertising or publicity pertaining to distribution
    -of the software without specific, written prior permission.
    -M.I.T. and the M.I.T. S.I.P.B. make no representations about
    -the suitability of this software for any purpose. It is
    -provided "as is" without express or implied warranty.
    -
    -*/
    -
    Binary file libpurple/protocols/zephyr/resources/icons/16x16/apps/im-zephyr.png has changed
    --- a/libpurple/protocols/zephyr/resources/icons/16x16/apps/scalable/im-zephyr.svg Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,189 +0,0 @@
    -<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    -<!-- Created with Inkscape (http://www.inkscape.org/) -->
    -<svg
    - xmlns:dc="http://purl.org/dc/elements/1.1/"
    - xmlns:cc="http://creativecommons.org/ns#"
    - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    - xmlns:svg="http://www.w3.org/2000/svg"
    - xmlns="http://www.w3.org/2000/svg"
    - xmlns:xlink="http://www.w3.org/1999/xlink"
    - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    - width="16px"
    - height="16px"
    - id="svg4248"
    - sodipodi:version="0.32"
    - inkscape:version="0.46"
    - sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
    - sodipodi:docname="zephyr.svg"
    - inkscape:export-filename="/home/hbons/Bureaublad/zephyr.png"
    - inkscape:export-xdpi="90"
    - inkscape:export-ydpi="90"
    - inkscape:output_extension="org.inkscape.output.svg.inkscape">
    - <defs
    - id="defs4250">
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient8662">
    - <stop
    - style="stop-color:#729fcf;stop-opacity:1;"
    - offset="0"
    - id="stop8664" />
    - <stop
    - style="stop-color:#3465a4;stop-opacity:1"
    - offset="1"
    - id="stop8666" />
    - </linearGradient>
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient8654">
    - <stop
    - style="stop-color:#ffffff;stop-opacity:1;"
    - offset="0"
    - id="stop8656" />
    - <stop
    - style="stop-color:#ffffff;stop-opacity:0;"
    - offset="1"
    - id="stop8658" />
    - </linearGradient>
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient8638">
    - <stop
    - style="stop-color:#24579e;stop-opacity:1"
    - offset="0"
    - id="stop8640" />
    - <stop
    - style="stop-color:#1a3d70;stop-opacity:1"
    - offset="1"
    - id="stop8642" />
    - </linearGradient>
    - <inkscape:perspective
    - sodipodi:type="inkscape:persp3d"
    - inkscape:vp_x="0 : 8 : 1"
    - inkscape:vp_y="0 : 1000 : 0"
    - inkscape:vp_z="16 : 8 : 1"
    - inkscape:persp3d-origin="8 : 5.3333333 : 1"
    - id="perspective14" />
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient5549">
    - <stop
    - style="stop-color:#eeeeec;stop-opacity:1;"
    - offset="0"
    - id="stop5551" />
    - <stop
    - style="stop-color:#eeeeec;stop-opacity:0;"
    - offset="1"
    - id="stop5553" />
    - </linearGradient>
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient5549"
    - id="linearGradient5555"
    - x1="7.5"
    - y1="-9.7224264"
    - x2="7.5"
    - y2="13.121667"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient8638"
    - id="linearGradient8644"
    - x1="5.2488923"
    - y1="4.1856537"
    - x2="12.599797"
    - y2="14.421621"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient8638"
    - id="linearGradient8648"
    - gradientUnits="userSpaceOnUse"
    - x1="5.2488923"
    - y1="4.1856537"
    - x2="12.599797"
    - y2="14.421621" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient8654"
    - id="linearGradient8660"
    - x1="-9.5397053"
    - y1="-8.7974415"
    - x2="20.511051"
    - y2="15.852463"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient8662"
    - id="linearGradient8668"
    - x1="0.52202404"
    - y1="1.7180301"
    - x2="11.883249"
    - y2="16.740131"
    - gradientUnits="userSpaceOnUse" />
    - </defs>
    - <sodipodi:namedview
    - id="base"
    - pagecolor="#ffffff"
    - bordercolor="#666666"
    - borderopacity="1.0"
    - inkscape:pageopacity="0.0"
    - inkscape:pageshadow="2"
    - inkscape:zoom="10.355641"
    - inkscape:cx="34.179106"
    - inkscape:cy="17.513083"
    - inkscape:current-layer="layer1"
    - showgrid="true"
    - inkscape:grid-bbox="true"
    - inkscape:document-units="px"
    - inkscape:window-width="1440"
    - inkscape:window-height="847"
    - inkscape:window-x="0"
    - inkscape:window-y="0"
    - inkscape:snap-bbox="true"
    - inkscape:snap-nodes="false"
    - objecttolerance="10"
    - gridtolerance="10">
    - <inkscape:grid
    - type="xygrid"
    - id="grid7853"
    - visible="true"
    - enabled="true" />
    - </sodipodi:namedview>
    - <metadata
    - id="metadata4253">
    - <rdf:RDF>
    - <cc:Work
    - rdf:about="">
    - <dc:format>image/svg+xml</dc:format>
    - <dc:type
    - rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    - </cc:Work>
    - </rdf:RDF>
    - </metadata>
    - <g
    - id="layer1"
    - inkscape:label="Layer 1"
    - inkscape:groupmode="layer">
    - <rect
    - style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1.13196862;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect3203"
    - width="0"
    - height="2.5118096"
    - x="6"
    - y="6.4881902"
    - transform="matrix(0.883816,0,0,0.883018,-2.999998,-1.426403)" />
    - <path
    - style="opacity:1;fill:url(#linearGradient8668);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8644);stroke-width:0.99999994000000003;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
    - d="M 2.40625,0.50000003 C 1.9048,0.50000003 1.5,0.9048 1.5,1.40625 L 1.5,3.59375 C 1.5,4.0952 1.9048,4.5 2.40625,4.5 L 10.5,4.5 L 10.5,4.59375 C 10.5,5.09762 10.90238,5.5 11.40625,5.5 L 12.59375,5.5 C 13.09762,5.5 13.5,5.097621 13.5,4.59375 L 13.5,1.40625 C 13.5,1.280887 13.483182,1.170863 13.4375,1.0625 C 13.346137,0.845774 13.154226,0.65386303 12.9375,0.56250003 C 12.829137,0.51681806 12.719113,0.50000003 12.59375,0.50000003 L 11.40625,0.50000003 L 2.40625,0.50000003 z M 6.1875,6.5 C 5.8138457,6.5 5.5,6.8138458 5.5,7.1875 L 5.5,8.8125 C 5.5,9.1861543 5.8138458,9.4999998 6.1875,9.5 L 8.875,9.5 C 9.2486543,9.5 9.5625,9.1861539 9.5625,8.8125 L 9.5625,7.1875 C 9.5625,6.8138457 9.2486542,6.5 8.875,6.5 L 6.1875,6.5 z M 2.40625,10.5 C 1.9023796,10.5 1.5,10.902379 1.5,11.40625 L 1.5,14.59375 C 1.5,14.719113 1.5168185,14.829137 1.5625,14.9375 C 1.653863,15.154226 1.8457744,15.346137 2.0625,15.4375 C 2.1708628,15.483182 2.2808874,15.5 2.40625,15.5 L 3.59375,15.5 L 12.59375,15.5 C 13.0952,15.5 13.5,15.0952 13.5,14.59375 L 13.5,12.40625 C 13.5,11.9048 13.0952,11.5 12.59375,11.5 L 4.5,11.5 L 4.5,11.40625 C 4.5,10.90238 4.0976203,10.5 3.59375,10.5 L 2.40625,10.5 z"
    - id="rect8625" />
    - <path
    - sodipodi:type="inkscape:offset"
    - inkscape:radius="-1.0018694"
    - inkscape:original="M 2.40625 0.5 C 1.9048 0.49999997 1.5 0.9048 1.5 1.40625 L 1.5 3.59375 C 1.5 4.0952 1.9048 4.5 2.40625 4.5 L 10.5 4.5 L 10.5 4.59375 C 10.5 5.09762 10.90238 5.5 11.40625 5.5 L 12.59375 5.5 C 13.09762 5.5 13.5 5.097621 13.5 4.59375 L 13.5 1.40625 C 13.5 1.280887 13.483182 1.170863 13.4375 1.0625 C 13.346137 0.845774 13.154226 0.653863 12.9375 0.5625 C 12.829137 0.516818 12.719113 0.5 12.59375 0.5 L 11.40625 0.5 L 2.40625 0.5 z M 6.1875 6.5 C 5.8138457 6.5 5.5 6.8138458 5.5 7.1875 L 5.5 8.8125 C 5.5 9.1861543 5.8138458 9.4999998 6.1875 9.5 L 8.875 9.5 C 9.2486543 9.5 9.5625 9.1861539 9.5625 8.8125 L 9.5625 7.1875 C 9.5625 6.8138457 9.2486542 6.5 8.875 6.5 L 6.1875 6.5 z M 2.40625 10.5 C 1.9023796 10.5 1.5 10.902379 1.5 11.40625 L 1.5 14.59375 C 1.5 14.719113 1.5168185 14.829137 1.5625 14.9375 C 1.653863 15.154226 1.8457744 15.346137 2.0625 15.4375 C 2.1708628 15.483182 2.2808874 15.5 2.40625 15.5 L 3.59375 15.5 L 12.59375 15.5 C 13.0952 15.5 13.5 15.0952 13.5 14.59375 L 13.5 12.40625 C 13.5 11.9048 13.0952 11.5 12.59375 11.5 L 4.5 11.5 L 4.5 11.40625 C 4.5 10.90238 4.0976203 10.5 3.59375 10.5 L 2.40625 10.5 z "
    - style="opacity:0.62037037;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8660);stroke-width:0.99999994000000003;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
    - id="path8650"
    - d="M 2.5,1.5 L 2.5,3.5 L 10.5,3.5 C 11.051835,3.5010837 11.498916,3.9481648 11.5,4.5 L 12.5,4.5 L 12.5,1.5 L 11.40625,1.5 L 2.5,1.5 z M 6.5,7.5 L 6.5,8.5 L 8.5625,8.5 L 8.5625,7.5 L 6.5,7.5 z M 2.5,11.5 L 2.5,14.5 L 3.59375,14.5 L 12.5,14.5 L 12.5,12.5 L 4.5,12.5 C 3.9481648,12.498916 3.5010837,12.051835 3.5,11.5 L 2.5,11.5 z" />
    - </g>
    -</svg>
    Binary file libpurple/protocols/zephyr/resources/icons/22x22/apps/im-zephyr.png has changed
    --- a/libpurple/protocols/zephyr/resources/icons/22x22/apps/scalable/im-zephyr.svg Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,212 +0,0 @@
    -<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    -<!-- Created with Inkscape (http://www.inkscape.org/) -->
    -<svg
    - xmlns:dc="http://purl.org/dc/elements/1.1/"
    - xmlns:cc="http://creativecommons.org/ns#"
    - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    - xmlns:svg="http://www.w3.org/2000/svg"
    - xmlns="http://www.w3.org/2000/svg"
    - xmlns:xlink="http://www.w3.org/1999/xlink"
    - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    - width="24"
    - height="24"
    - id="svg1307"
    - sodipodi:version="0.32"
    - inkscape:version="0.46"
    - version="1.0"
    - sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
    - sodipodi:docname="zephyr.svg"
    - inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/zephyr.png"
    - inkscape:export-xdpi="90"
    - inkscape:export-ydpi="90"
    - inkscape:output_extension="org.inkscape.output.svg.inkscape">
    - <defs
    - id="defs1309">
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient4280">
    - <stop
    - style="stop-color:#204a87"
    - offset="0"
    - id="stop4282" />
    - <stop
    - style="stop-color:#3465a4;stop-opacity:0;"
    - offset="1"
    - id="stop4284" />
    - </linearGradient>
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient3150">
    - <stop
    - style="stop-color:#2e3436;stop-opacity:1;"
    - offset="0"
    - id="stop3152" />
    - <stop
    - style="stop-color:#2e3436;stop-opacity:0;"
    - offset="1"
    - id="stop3154" />
    - </linearGradient>
    - <radialGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3150"
    - id="radialGradient3156"
    - cx="10.748654"
    - cy="10.457643"
    - fx="10.748654"
    - fy="10.457643"
    - r="6.6449099"
    - gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
    - gradientUnits="userSpaceOnUse" />
    - <linearGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient4280"
    - id="linearGradient4290"
    - x1="12"
    - y1="15.853726"
    - x2="12"
    - y2="-46.21241"
    - gradientUnits="userSpaceOnUse" />
    - </defs>
    - <sodipodi:namedview
    - id="base"
    - pagecolor="#ffffff"
    - bordercolor="#666666"
    - borderopacity="1.0"
    - inkscape:pageopacity="0.0"
    - inkscape:pageshadow="2"
    - inkscape:zoom="23.791015"
    - inkscape:cx="14.739163"
    - inkscape:cy="14.326547"
    - inkscape:current-layer="layer1"
    - showgrid="true"
    - inkscape:grid-bbox="true"
    - inkscape:document-units="px"
    - fill="#204a87"
    - showguides="true"
    - inkscape:guide-bbox="true"
    - inkscape:window-width="1268"
    - inkscape:window-height="971"
    - inkscape:window-x="6"
    - inkscape:window-y="21" />
    - <metadata
    - id="metadata1312">
    - <rdf:RDF>
    - <cc:Work
    - rdf:about="">
    - <dc:format>image/svg+xml</dc:format>
    - <dc:type
    - rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    - </cc:Work>
    - </rdf:RDF>
    - </metadata>
    - <g
    - id="layer1"
    - inkscape:label="Layer 1"
    - inkscape:groupmode="layer">
    - <rect
    - style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect3203"
    - width="0"
    - height="2.5118096"
    - x="6"
    - y="6.4881902" />
    - <path
    - style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - d="M 5.5,2.5 L 5.5,6.5 L 15.5,6.5 L 15.5,8.5 L 18.5,8.5 L 18.5,6.5 L 18.5,5.5 L 18.5,2.5 L 5.5,2.5 z M 9.5,9.5625 L 9.5,12.5 L 14.5,12.5 L 14.5,9.5625 L 9.5,9.5625 z M 5.5,13.5 L 5.5,16.5 L 5.5,19.5 L 18.5,19.5 L 18.5,15.5 L 8.5,15.5 L 8.5,13.5 L 5.5,13.5 z "
    - id="path1331" />
    - <path
    - sodipodi:type="arc"
    - style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="path3140"
    - sodipodi:cx="10.748654"
    - sodipodi:cy="10.457643"
    - sodipodi:rx="6.6449099"
    - sodipodi:ry="2.3675451"
    - d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
    - transform="matrix(1.730648,0,0,1.300982,-7.102138,5.314662)" />
    - <path
    - style="opacity:1;fill:url(#linearGradient4290);fill-opacity:1.0;stroke:#204a87;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - d="M 5.5,2.5 L 5.5,6.5 L 15.5,6.5 L 15.5,8.5 L 18.5,8.5 L 18.5,6.5 L 18.5,5.5 L 18.5,2.5 L 5.5,2.5 z M 9.5,9.5625 L 9.5,12.5 L 14.5,12.5 L 14.5,9.5625 L 9.5,9.5625 z M 5.5,13.5 L 5.5,16.5 L 5.5,19.5 L 18.5,19.5 L 18.5,15.5 L 8.5,15.5 L 8.5,13.5 L 5.5,13.5 z "
    - id="rect4229" />
    - <path
    - sodipodi:type="inkscape:offset"
    - inkscape:radius="-0.9828251"
    - inkscape:original="M 5.5 2.5 L 5.5 6.5 L 15.5 6.5 L 15.5 8.5 L 18.5 8.5 L 18.5 6.5 L 18.5 5.5 L 18.5 2.5 L 5.5 2.5 z M 9.5 9.5625 L 9.5 12.5 L 14.5 12.5 L 14.5 9.5625 L 9.5 9.5625 z M 5.5 13.5 L 5.5 16.5 L 5.5 19.5 L 18.5 19.5 L 18.5 15.5 L 8.5 15.5 L 8.5 13.5 L 5.5 13.5 z "
    - xlink:href="#rect4229"
    - style="opacity:0.15;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="path4266"
    - inkscape:href="#rect4229"
    - d="M 6.46875,3.46875 L 6.46875,5.53125 L 15.5,5.53125 C 16.03184,5.5388652 16.461135,5.9681604 16.46875,6.5 L 16.46875,7.53125 L 17.53125,7.53125 L 17.53125,6.5 L 17.53125,5.5 L 17.53125,3.46875 L 6.46875,3.46875 z M 10.46875,10.53125 L 10.46875,11.53125 L 13.53125,11.53125 L 13.53125,10.53125 L 10.46875,10.53125 z M 6.46875,14.46875 L 6.46875,16.5 L 6.46875,18.53125 L 17.53125,18.53125 L 17.53125,16.46875 L 8.5,16.46875 C 7.9681604,16.461135 7.5388652,16.03184 7.53125,15.5 L 7.53125,14.46875 L 6.46875,14.46875 z " />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4248"
    - width="1"
    - height="1"
    - x="5"
    - y="2" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4252"
    - width="1"
    - height="1"
    - x="18"
    - y="2" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4254"
    - width="1"
    - height="1"
    - x="18"
    - y="19" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4256"
    - width="1"
    - height="1"
    - x="5"
    - y="19" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4258"
    - width="1"
    - height="1"
    - x="18"
    - y="8" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4260"
    - width="1"
    - height="1"
    - x="5"
    - y="13" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4262"
    - width="1"
    - height="1"
    - x="18"
    - y="15" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4264"
    - width="1"
    - height="1"
    - x="5"
    - y="6" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4268"
    - width="1"
    - height="1"
    - x="14"
    - y="12" />
    - <rect
    - style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999881;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect4270"
    - width="1"
    - height="1"
    - x="9"
    - y="9" />
    - </g>
    -</svg>
    Binary file libpurple/protocols/zephyr/resources/icons/48x48/apps/im-zephyr.png has changed
    --- a/libpurple/protocols/zephyr/resources/icons/scalable/apps/im-zephyr.svg Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,141 +0,0 @@
    -<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    -<!-- Created with Inkscape (http://www.inkscape.org/) -->
    -<svg
    - xmlns:dc="http://purl.org/dc/elements/1.1/"
    - xmlns:cc="http://creativecommons.org/ns#"
    - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    - xmlns:svg="http://www.w3.org/2000/svg"
    - xmlns="http://www.w3.org/2000/svg"
    - xmlns:xlink="http://www.w3.org/1999/xlink"
    - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    - width="48"
    - height="48"
    - id="svg1307"
    - sodipodi:version="0.32"
    - inkscape:version="0.46"
    - version="1.0"
    - sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
    - sodipodi:docname="zephyr.svg"
    - inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/zephyr.png"
    - inkscape:export-xdpi="90"
    - inkscape:export-ydpi="90"
    - inkscape:output_extension="org.inkscape.output.svg.inkscape">
    - <defs
    - id="defs1309">
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient2236">
    - <stop
    - style="stop-color:#ffffff;stop-opacity:1;"
    - offset="0"
    - id="stop2238" />
    - <stop
    - style="stop-color:#ffffff;stop-opacity:0;"
    - offset="1"
    - id="stop2240" />
    - </linearGradient>
    - <linearGradient
    - inkscape:collect="always"
    - id="linearGradient3150">
    - <stop
    - style="stop-color:#2e3436;stop-opacity:1;"
    - offset="0"
    - id="stop3152" />
    - <stop
    - style="stop-color:#2e3436;stop-opacity:0;"
    - offset="1"
    - id="stop3154" />
    - </linearGradient>
    - <radialGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient3150"
    - id="radialGradient3156"
    - cx="10.748654"
    - cy="10.457643"
    - fx="10.748654"
    - fy="10.457643"
    - r="6.6449099"
    - gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
    - gradientUnits="userSpaceOnUse" />
    - <radialGradient
    - inkscape:collect="always"
    - xlink:href="#linearGradient2236"
    - id="radialGradient2244"
    - cx="25"
    - cy="15.052035"
    - fx="25"
    - fy="15.052035"
    - r="13.03125"
    - gradientTransform="matrix(1.918832,-3.053611e-32,3.873765e-32,2.434201,-22.9708,-29.40113)"
    - gradientUnits="userSpaceOnUse" />
    - </defs>
    - <sodipodi:namedview
    - id="base"
    - pagecolor="#ffffff"
    - bordercolor="#666666"
    - borderopacity="1.0"
    - inkscape:pageopacity="0.0"
    - inkscape:pageshadow="2"
    - inkscape:zoom="12.749289"
    - inkscape:cx="42.013094"
    - inkscape:cy="29.955991"
    - inkscape:current-layer="layer1"
    - showgrid="true"
    - inkscape:grid-bbox="true"
    - inkscape:document-units="px"
    - fill="#3465a4"
    - showguides="true"
    - inkscape:guide-bbox="true"
    - inkscape:window-width="1268"
    - inkscape:window-height="971"
    - inkscape:window-x="6"
    - inkscape:window-y="21" />
    - <metadata
    - id="metadata1312">
    - <rdf:RDF>
    - <cc:Work
    - rdf:about="">
    - <dc:format>image/svg+xml</dc:format>
    - <dc:type
    - rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    - </cc:Work>
    - </rdf:RDF>
    - </metadata>
    - <g
    - id="layer1"
    - inkscape:label="Layer 1"
    - inkscape:groupmode="layer">
    - <rect
    - style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1.00000012;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="rect3203"
    - width="0"
    - height="5.2291808"
    - x="12.491029"
    - y="11.343686" />
    - <path
    - sodipodi:type="arc"
    - style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="path3140"
    - sodipodi:cx="10.748654"
    - sodipodi:cy="10.457643"
    - sodipodi:rx="6.6449099"
    - sodipodi:ry="2.3675451"
    - d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
    - transform="matrix(3.23556,0,0,2.111892,-10.27791,16.9144)" />
    - <path
    - style="opacity:1;fill:#3465a4;fill-opacity:1;stroke:#204a87;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - d="M 11.5,6.4993337 L 11.5,14.499492 L 32.553687,14.499492 L 32.553687,18.499569 L 38.479829,18.499569 L 38.479829,7.5185793 L 38.479829,6.4993337 L 11.5,6.4993337 z M 19.552827,20.546173 L 19.552827,26.499725 L 30.471849,26.499725 L 30.471849,20.546173 L 19.552827,20.546173 z M 11.5,28.499765 L 11.5,40.5 L 38.485458,40.5 L 38.485458,32.499843 L 17.510207,32.499843 L 17.510207,28.499765 L 11.5,28.499765 z "
    - id="rect4229"
    - sodipodi:nodetypes="cccccccccccccccccccc" />
    - <path
    - sodipodi:type="inkscape:offset"
    - inkscape:radius="-0.9828251"
    - inkscape:original="M 11.5 6.5 L 11.5 14.5 L 32.5625 14.5 L 32.5625 18.5 L 38.46875 18.5 L 38.46875 7.53125 L 38.46875 6.5 L 11.5 6.5 z M 19.5625 20.53125 L 19.5625 26.5 L 30.46875 26.5 L 30.46875 20.53125 L 19.5625 20.53125 z M 11.5 28.5 L 11.5 40.5 L 38.5 40.5 L 38.5 32.5 L 17.5 32.5 L 17.5 28.5 L 11.5 28.5 z "
    - xlink:href="#rect4229"
    - style="opacity:0.3;fill:url(#radialGradient2244);fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
    - id="path4266"
    - inkscape:href="#rect4229"
    - d="M 12.46875,4.46875 L 12.46875,10.53125 L 32.5625,10.53125 C 33.09434,10.538865 33.523635,10.96816 33.53125,11.5 L 33.53125,14.53125 L 37.5,14.53125 L 37.5,4.53125 L 37.5,4.46875 L 12.46875,4.46875 z M 20.53125,18.5 L 20.53125,22.53125 L 29.5,22.53125 L 29.5,18.5 L 20.53125,18.5 z M 12.46875,26.46875 L 12.46875,36.53125 L 37.53125,36.53125 L 37.53125,30.46875 L 17.5,30.46875 C 16.96816,30.461135 16.538865,30.03184 16.53125,29.5 L 16.53125,26.46875 L 12.46875,26.46875 z " />
    - </g>
    -</svg>
    --- a/libpurple/protocols/zephyr/resources/zephyr.gresource.xml Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,11 +0,0 @@
    -<?xml version="1.0" encoding="UTF-8"?>
    -<gresources>
    - <gresource prefix="/im/pidgin/libpurple/zephyr">
    - <file>icons/16x16/apps/im-zephyr.png</file>
    - <file>icons/16x16/apps/scalable/im-zephyr.svg</file>
    - <file>icons/22x22/apps/im-zephyr.png</file>
    - <file>icons/22x22/apps/scalable/im-zephyr.svg</file>
    - <file>icons/48x48/apps/im-zephyr.png</file>
    - <file>icons/scalable/apps/im-zephyr.svg</file>
    - </gresource>
    -</gresources>
    --- a/libpurple/protocols/zephyr/sysdep.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,91 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains system-dependent header code.
    - *
    - * Created by: Greg Hudson
    - *
    - * Copyright (c) 1988,1991 by the Massachusetts Institute of Technology.
    - * For copying and distribution information, see the file
    - * "mit-copyright.h".
    - */
    -
    -#ifndef PURPLE_ZEPHYR_SYSDEP_H
    -#define PURPLE_ZEPHYR_SYSDEP_H
    -
    -#ifdef HAVE_CONFIG_H
    -# include <config.h>
    -#endif
    -
    -#include <stdio.h>
    -#include <errno.h>
    -#include <ctype.h>
    -#include <time.h>
    -#include <signal.h>
    -#ifndef WIN32
    -#include <syslog.h>
    -#endif
    -
    -#include <sys/types.h>
    -#include <sys/stat.h>
    -#include <sys/param.h>
    -#include <sys/time.h>
    -
    -#include <stdlib.h>
    -
    -/* Strings. */
    -#include <string.h>
    -
    -/* Exit status handling and wait(). */
    -#ifdef HAVE_SYS_WAIT_H
    -# include <sys/wait.h>
    -#endif
    -
    -#ifdef HAVE_SYS_CDEFS_H
    -#include <sys/cdefs.h>
    -#endif
    -
    -#include <stdarg.h>
    -
    -#ifdef HAVE_FCNTL_H
    -# include <fcntl.h>
    -#endif
    -
    -#ifdef HAVE_UNISTD_H
    -# include <unistd.h>
    -#else
    -# ifdef HAVE_SYS_FILE_H
    -# include <sys/file.h>
    -# endif
    -uid_t getuid(void);
    -char *ttyname(void);
    -#endif
    -
    -#ifdef HAVE_TERMIOS_H
    -# include <termios.h>
    -#else
    -# ifdef HAVE_SYS_FILIO_H
    -# include <sys/filio.h>
    -# else
    -# ifdef HAVE_SGTTY_H
    -# include <sgtty.h>
    -# endif
    -# endif
    -#endif
    -
    -/* Kerberos compatibility. */
    -#ifdef ZEPHYR_USES_KERBEROS
    -# include <krb.h>
    -# ifndef WIN32
    -# include <krb_err.h>
    -# endif /* WIN32 */
    -# include <des.h>
    -#endif /* ZEPHYR_USES_KERBEROS */
    -
    -#ifdef HAVE_SYS_SELECT_H
    -# include <sys/select.h>
    -#endif
    -
    -#ifdef HAVE_SYS_MSGBUF_H
    -#include <sys/msgbuf.h>
    -#endif
    -
    -#endif /* PURPLE_ZEPHYR_SYSDEP_H */
    --- a/libpurple/protocols/zephyr/zephyr.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,1876 +0,0 @@
    -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
    -/*
    - * purple
    - *
    - * Copyright (C) 1998-2001, Mark Spencer <markster@marko.net>
    - * Some code borrowed from GtkZephyr, by
    - * Jag/Sean Dilda <agrajag@linuxpower.org>/<smdilda@unity.ncsu.edu>
    - * http://gtkzephyr.linuxpower.org/
    - *
    - * Some code borrowed from kzephyr, by
    - * Chris Colohan <colohan+@cs.cmu.edu>
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - *
    -
    -*/
    -
    -#include <glib/gi18n-lib.h>
    -
    -#include <glib.h>
    -#include <glib/gstdio.h>
    -
    -#include <gplugin.h>
    -#include <gplugin-native.h>
    -
    -#include <purple.h>
    -
    -#include "internal.h"
    -#include "zephyr.h"
    -#include "zephyr_account.h"
    -#include "zephyr_html.h"
    -#include "zephyr_tzc.h"
    -#include "zephyr_zeph02.h"
    -
    -#define ZEPHYR_FALLBACK_CHARSET "ISO-8859-1"
    -
    -#define BUF_LEN (2048)
    -
    -/* these are deliberately high, since most people don't send multiple "PING"s */
    -#define ZEPHYR_TYPING_SEND_TIMEOUT 15
    -#define ZEPHYR_TYPING_RECV_TIMEOUT 10
    -
    -static PurpleProtocol *my_protocol = NULL;
    -static GSList *cmds = NULL;
    -
    -#ifdef LIBZEPHYR_EXT
    -extern char __Zephyr_realm[];
    -#endif
    -
    -typedef struct _zephyr_triple zephyr_triple;
    -
    -typedef gboolean (*ZephyrLoginFunc)(zephyr_account *zephyr);
    -
    -struct _ZephyrProtocol {
    - PurpleProtocol parent;
    -};
    -
    -struct _zephyr_triple {
    - ZSubscription_t sub;
    - char *name;
    - gboolean open;
    - int id;
    -};
    -
    -#ifdef WIN32
    -extern const char *username;
    -#endif
    -
    -static void zephyr_chat_set_topic(PurpleConnection *gc, int id, const char *topic);
    -
    -static char *
    -zephyr_strip_local_realm(const zephyr_account *zephyr, const char *user)
    -{
    - /*
    - Takes in a username of the form username or username@realm
    - and returns:
    - username, if there is no realm, or the realm is the local realm
    - or:
    - username@realm if there is a realm and it is foreign
    - */
    - char *at = strchr(user, '@');
    - if (at && !g_ascii_strcasecmp(at+1,zephyr->realm)) {
    - /* We're passed in a username of the form user@users-realm */
    - return g_strndup(user, at - user);
    - }
    - else {
    - /* We're passed in a username of the form user or user@foreign-realm */
    - return g_strdup(user);
    - }
    -}
    -
    -static zephyr_triple *
    -zephyr_triple_new(zephyr_account *zephyr, const ZSubscription_t *sub)
    -{
    - zephyr_triple *zt;
    -
    - zt = g_new0(zephyr_triple, 1);
    - zt->sub.zsub_class = g_strdup(sub->zsub_class);
    - zt->sub.zsub_classinst = g_strdup(sub->zsub_classinst);
    - zt->sub.zsub_recipient = g_strdup(sub->zsub_recipient);
    - zt->name = g_strdup_printf("%s,%s,%s", sub->zsub_class,
    - sub->zsub_classinst ? sub->zsub_classinst : "",
    - sub->zsub_recipient ? sub->zsub_recipient : "");
    - zt->id = ++(zephyr->last_id);
    - zt->open = FALSE;
    - return zt;
    -}
    -
    -static void
    -zephyr_triple_free(zephyr_triple *zt)
    -{
    - g_free(zt->sub.zsub_class);
    - g_free(zt->sub.zsub_classinst);
    - g_free(zt->sub.zsub_recipient);
    - g_free(zt->name);
    - g_free(zt);
    -}
    -
    -/* returns 0 if sub is a subset of zt.sub. This function is used to
    - determine whether a zephyr sent to sub should be placed in the chat
    - with triple zt.sub
    -
    - sub is a subset of zt.sub
    - iff. the classnames are identical ignoring case
    - AND. the instance names are identical (ignoring case), or zt.sub->instance is *.
    - AND. the recipient names are identical
    -*/
    -static gint
    -zephyr_triple_subset(const zephyr_triple *zt, const ZSubscription_t *sub)
    -{
    - if (!sub->zsub_class) {
    - purple_debug_error("zephyr", "sub1c doesn't exist\n");
    - return 1;
    - }
    - if (!sub->zsub_classinst) {
    - purple_debug_error("zephyr", "sub1i doesn't exist\n");
    - return 1;
    - }
    - if (!sub->zsub_recipient) {
    - purple_debug_error("zephyr", "sub1r doesn't exist\n");
    - return 1;
    - }
    - if (!zt->sub.zsub_class) {
    - purple_debug_error("zephyr", "sub2c doesn't exist\n");
    - return 1;
    - }
    - if (!zt->sub.zsub_classinst) {
    - purple_debug_error("zephyr", "sub2i doesn't exist\n");
    - return 1;
    - }
    - if (!zt->sub.zsub_recipient) {
    - purple_debug_error("zephyr", "sub2r doesn't exist\n");
    - return 1;
    - }
    -
    - if (g_ascii_strcasecmp(zt->sub.zsub_class, sub->zsub_class)) {
    - return 1;
    - }
    - if (g_ascii_strcasecmp(zt->sub.zsub_classinst, sub->zsub_classinst) && g_ascii_strcasecmp(zt->sub.zsub_classinst, "*")) {
    - return 1;
    - }
    - if (g_ascii_strcasecmp(zt->sub.zsub_recipient, sub->zsub_recipient)) {
    - return 1;
    - }
    - purple_debug_info("zephyr", "<%s,%s,%s> is in <%s,%s,%s>\n",
    - sub->zsub_class, sub->zsub_classinst, sub->zsub_recipient,
    - zt->sub.zsub_class, zt->sub.zsub_classinst, zt->sub.zsub_recipient);
    - return 0;
    -}
    -
    -/*
    - Converts strings to utf-8 if necessary using user specified encoding
    -*/
    -
    -static gchar *
    -convert_to_utf8(const gchar *string, const gchar *from_encoding)
    -{
    - gchar *utf8;
    - GError *err = NULL;
    -
    - if (g_utf8_validate(string, -1, NULL)) {
    - return g_strdup(string);
    - }
    -
    - utf8 = g_convert(string, -1, "UTF-8", from_encoding, NULL, NULL, &err);
    - if (err) {
    - purple_debug_error("zephyr", "recv conversion error: %s\n", err->message);
    - utf8 = g_strdup(_("(There was an error converting this message. Check the 'Encoding' option in the Account Editor)"));
    - g_error_free(err);
    - }
    -
    - return utf8;
    -}
    -
    -static gboolean
    -pending_zloc(zephyr_account *zephyr, const char *who)
    -{
    - GList *curr;
    - char* normalized_who = zephyr_normalize_local_realm(zephyr, who);
    -
    - curr = g_list_find_custom(zephyr->pending_zloc_names, normalized_who, (GCompareFunc)g_ascii_strcasecmp);
    - g_free(normalized_who);
    - if (curr == NULL)
    - return FALSE;
    -
    - g_free((char *)curr->data);
    - zephyr->pending_zloc_names = g_list_delete_link(zephyr->pending_zloc_names, curr);
    - return TRUE;
    -}
    -
    -static PurpleBuddy *
    -find_buddy(const zephyr_account *zephyr, const char *user)
    -{
    - PurpleBuddy *buddy = purple_blist_find_buddy(zephyr->account, user);
    -
    - if (buddy == NULL) {
    - char *stripped_user = zephyr_strip_local_realm(zephyr, user);
    - buddy = purple_blist_find_buddy(zephyr->account, stripped_user);
    - g_free(stripped_user);
    - }
    -
    - return buddy;
    -}
    -
    -static void
    -zephyr_triple_open(zephyr_triple *zt, PurpleConnection *gc, const char *instance)
    -{
    - zt->open = TRUE;
    - purple_serv_got_joined_chat(gc, zt->id, zt->name);
    - zephyr_chat_set_topic(gc, zt->id, instance);
    -}
    -
    -void
    -handle_message(PurpleConnection *gc, ZNotice_t *notice)
    -{
    - zephyr_account* zephyr = purple_connection_get_protocol_data(gc);
    -
    - if (!g_ascii_strcasecmp(notice->z_class, LOGIN_CLASS)) {
    - /* well, we'll be updating in 20 seconds anyway, might as well ignore this. */
    - } else if (!g_ascii_strcasecmp(notice->z_class, LOCATE_CLASS)) {
    - if (!g_ascii_strcasecmp(notice->z_opcode, LOCATE_LOCATE)) {
    - int nlocs;
    - char *user;
    -
    - /* XXX add real error reporting */
    - if (ZParseLocations(notice, NULL, &nlocs, &user) != ZERR_NONE)
    - return;
    -
    - handle_locations(gc, user, nlocs, NULL);
    - g_free(user);
    - }
    - } else {
    - char *buf;
    - int len;
    - char *stripped_sender;
    - int signature_length = strlen(notice->z_message);
    -
    - /* Need to deal with 0 length messages to handle typing notification (OPCODE) ping messages */
    - /* One field zephyrs would have caused purple to crash */
    - if ((notice->z_message_len == 0) || (notice->z_message_len <= (signature_length + 1))) {
    - len = 0;
    - buf = g_strdup("");
    - } else {
    - char *tmpbuf;
    - char *ptr = (char *) notice->z_message + (signature_length + 1);
    - gchar *tmpescape;
    -
    - len = notice->z_message_len - (signature_length + 1);
    - tmpbuf = g_malloc(len + 1);
    - g_snprintf(tmpbuf, len + 1, "%s", ptr);
    - g_strchomp(tmpbuf);
    - tmpescape = g_markup_escape_text(tmpbuf, -1);
    - g_free(tmpbuf);
    - tmpbuf = zephyr_to_html(tmpescape);
    - buf = convert_to_utf8(tmpbuf, zephyr->encoding);
    - g_free(tmpbuf);
    - g_free(tmpescape);
    - }
    - purple_debug_info("zephyr", "message_size %d %d %d", len, notice->z_message_len, signature_length);
    -
    - stripped_sender = zephyr_strip_local_realm(zephyr, notice->z_sender);
    -
    - if (!g_ascii_strcasecmp(notice->z_class, "MESSAGE") &&
    - !g_ascii_strcasecmp(notice->z_class_inst, "PERSONAL") &&
    - !g_ascii_strcasecmp(notice->z_recipient, zephyr->username)) {
    - PurpleMessageFlags flags = 0;
    -
    - if (!g_ascii_strcasecmp(notice->z_message, "Automated reply:"))
    - flags |= PURPLE_MESSAGE_AUTO_RESP;
    -
    - if (!g_ascii_strcasecmp(notice->z_opcode, "PING"))
    - purple_serv_got_typing(gc,stripped_sender,ZEPHYR_TYPING_RECV_TIMEOUT, PURPLE_IM_TYPING);
    - else
    - purple_serv_got_im(gc, stripped_sender, buf, flags, time(NULL));
    -
    - } else {
    - ZSubscription_t sub = {
    - .zsub_class = notice->z_class,
    - .zsub_classinst = (gchar *)notice->z_class_inst,
    - .zsub_recipient = (gchar *)notice->z_recipient
    - };
    - zephyr_triple *zt;
    - gchar *send_inst_utf8;
    - GSList *l = g_slist_find_custom(zephyr->subscrips, &sub, (GCompareFunc)zephyr_triple_subset);
    - PurpleConversation *gcc;
    - PurpleConversationManager *manager;
    -
    - if (!l) {
    - /* This is a server supplied subscription */
    - zt = zephyr_triple_new(zephyr, &sub);
    - zephyr->subscrips = g_slist_append(zephyr->subscrips, zt);
    - } else {
    - zt = l->data;
    - }
    -
    - if (!zt->open) {
    - zephyr_triple_open(zt, gc, notice->z_class_inst);
    - }
    -
    - if (!g_ascii_strcasecmp(notice->z_class_inst, "PERSONAL"))
    - send_inst_utf8 = g_strdup(stripped_sender);
    - else {
    - char *send_inst = g_strdup_printf("[%s] %s", notice->z_class_inst, stripped_sender);
    - send_inst_utf8 = convert_to_utf8(send_inst, zephyr->encoding);
    - g_free(send_inst);
    - if (!send_inst_utf8) {
    - purple_debug_error("zephyr","Failed to convert instance for sender %s.\n", stripped_sender);
    - send_inst_utf8 = g_strdup(stripped_sender);
    - }
    - }
    -
    - manager = purple_conversation_manager_get_default();
    - gcc = purple_conversation_manager_find_chat(manager,
    - purple_connection_get_account(gc),
    - zt->name);
    - if (!purple_chat_conversation_has_user(PURPLE_CHAT_CONVERSATION(gcc), stripped_sender)) {
    - GInetAddress *inet_addr = NULL;
    - gchar *ipaddr = NULL;
    -
    - inet_addr = g_inet_address_new_from_bytes(
    - (const guint8 *)&notice->z_sender_addr,
    - G_SOCKET_FAMILY_IPV4);
    - ipaddr = g_inet_address_to_string(inet_addr);
    - purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(gcc),
    - stripped_sender, ipaddr,
    - PURPLE_CHAT_USER_NONE, TRUE);
    - g_free(ipaddr);
    - g_object_unref(inet_addr);
    - }
    - purple_serv_got_chat_in(gc, zt->id, send_inst_utf8,
    - PURPLE_MESSAGE_RECV, buf, time(NULL));
    - g_free(send_inst_utf8);
    - }
    - g_free(stripped_sender);
    - g_free(buf);
    - }
    -}
    -
    -void
    -handle_locations(PurpleConnection *gc, const gchar *user, int nlocs, const ZLocations_t *zloc)
    -{
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - PurpleBuddy *b;
    - const char *bname;
    - const gchar *name;
    -
    - b = find_buddy(zephyr, user);
    - bname = b ? purple_buddy_get_name(b) : NULL;
    - name = b ? bname : user;
    - if ((b && pending_zloc(zephyr, bname)) || pending_zloc(zephyr, user)) {
    - PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
    - const char *balias;
    -
    - /* TODO: Check whether it's correct to call add_pair_html,
    - or if we should be using add_pair_plaintext */
    - purple_notify_user_info_add_pair_html(user_info, _("User"), name);
    -
    - balias = b ? purple_buddy_get_local_alias(b) : NULL;
    - if (balias)
    - purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
    -
    - if (!nlocs) {
    - purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in"));
    - }
    - for (; nlocs > 0; nlocs--) {
    - ZLocations_t locs;
    - char *tmp;
    -
    - if (!zloc) {
    - /* XXX add real error reporting */
    - int one = 1;
    -
    - ZGetLocations(&locs, &one);
    - } else {
    - locs = *zloc;
    - }
    -
    - /* TODO: Need to escape locs.host and locs.time? */
    - tmp = g_strdup_printf(_("<br>At %s since %s"), locs.host, locs.time);
    - purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp);
    - g_free(tmp);
    - }
    - purple_notify_userinfo(gc, name, user_info, NULL, NULL);
    - purple_notify_user_info_destroy(user_info);
    - } else {
    - purple_protocol_got_user_status(zephyr->account, name, (nlocs > 0) ? "available" : "offline", NULL);
    - }
    -}
    -
    -static void
    -check_loc_buddy(PurpleBuddy *buddy, zephyr_account *zephyr)
    -{
    - const char *bname = purple_buddy_get_name(buddy);
    - char *chk = zephyr_normalize_local_realm(zephyr, bname);
    -#ifdef WIN32
    - int numlocs;
    -
    - ZLocateUser(chk, &numlocs, ZAUTH);
    - for (int i = 0; i < numlocs; i++) {
    - ZLocations_t locations;
    - int one = 1;
    -
    - ZGetLocations(&locations, &one);
    - purple_protocol_got_user_status(zephyr->account, bname, "available",
    - NULL);
    - purple_protocol_got_user_idle(zephyr->account, bname, FALSE, 0);
    - }
    -#else
    -
    - purple_debug_info("zephyr", "chk: %s, bname: %s", chk, bname);
    - /* XXX add real error reporting */
    - /* doesn't matter if this fails or not; we'll just move on to the next one */
    - zephyr->request_locations(zephyr, chk);
    -#endif /* WIN32 */
    -
    - g_free(chk);
    -}
    -
    -static gboolean
    -check_loc(gpointer data)
    -{
    - zephyr_account *zephyr = (zephyr_account *)data;
    - GSList *buddies = purple_blist_find_buddies(zephyr->account, NULL);
    -
    - g_slist_foreach(buddies, (GFunc)check_loc_buddy, zephyr);
    - g_slist_free(buddies);
    -
    - return G_SOURCE_CONTINUE;
    -}
    -
    -static const gchar *
    -get_exposure_level(void)
    -{
    - /* XXX add real error reporting */
    - const gchar *exposure = ZGetVariable("exposure");
    -
    - if (exposure) {
    - if (!g_ascii_strcasecmp(exposure, EXPOSE_NONE)) {
    - return EXPOSE_NONE;
    - }
    - if (!g_ascii_strcasecmp(exposure, EXPOSE_OPSTAFF)) {
    - return EXPOSE_OPSTAFF;
    - }
    - if (!g_ascii_strcasecmp(exposure, EXPOSE_REALMANN)) {
    - return EXPOSE_REALMANN;
    - }
    - if (!g_ascii_strcasecmp(exposure, EXPOSE_NETVIS)) {
    - return EXPOSE_NETVIS;
    - }
    - if (!g_ascii_strcasecmp(exposure, EXPOSE_NETANN)) {
    - return EXPOSE_NETANN;
    - }
    - }
    - return EXPOSE_REALMVIS;
    -}
    -
    -static void strip_comments(char *str)
    -{
    - char *tmp = strchr(str, '#');
    -
    - if (tmp)
    - *tmp = '\0';
    - g_strchug(str);
    - g_strchomp(str);
    -}
    -
    -static void zephyr_inithosts(zephyr_account *zephyr)
    -{
    - /* XXX This code may not be Win32 clean */
    - struct hostent *hent;
    -
    - zephyr->ourhost = g_strdup(g_get_host_name());
    - if (!(hent = gethostbyname(zephyr->ourhost))) {
    - purple_debug_error("zephyr",
    - "unable to resolve hostname, %%canon%% will be "
    - "wrong in subscriptions and has been set to the "
    - "value of %%host%%, %s",
    - zephyr->ourhost);
    - zephyr->ourhostcanon = g_strdup(zephyr->ourhost);
    - return;
    - }
    -
    - zephyr->ourhostcanon = g_strdup(hent->h_name);
    -}
    -
    -static void process_zsubs(zephyr_account *zephyr)
    -{
    - /* Loads zephyr chats "(subscriptions) from ~/.zephyr.subs, and
    - registers (subscribes to) them on the server */
    -
    - /* XXX deal with unsubscriptions */
    - /* XXX deal with punts */
    -
    - FILE *f;
    - gchar *fname;
    - gchar buff[BUFSIZ];
    -
    - fname = g_strdup_printf("%s/.zephyr.subs", purple_home_dir());
    - f = g_fopen(fname, "r");
    - if (f) {
    - char **triple;
    - ZSubscription_t sub;
    -
    - while (fgets(buff, BUFSIZ, f)) {
    - strip_comments(buff);
    - if (buff[0]) {
    - triple = g_strsplit(buff, ",", 3);
    - if (triple[0] && triple[1]) {
    - char *tmp = g_strdup(zephyr->username);
    - char *atptr;
    -
    - if (triple[2] == NULL) {
    - sub.zsub_recipient = g_malloc0(1);
    - } else if (!g_ascii_strcasecmp(triple[2], "%me%")) {
    - sub.zsub_recipient = g_strdup(zephyr->username);
    - } else if (!g_ascii_strcasecmp(triple[2], "*")) {
    - /* wildcard
    - * form of class,instance,* */
    - sub.zsub_recipient = g_malloc0(1);
    - } else if (!g_ascii_strcasecmp(triple[2], tmp)) {
    - /* form of class,instance,aatharuv@ATHENA.MIT.EDU */
    - sub.zsub_recipient = g_strdup(triple[2]);
    - } else if ((atptr = strchr(triple[2], '@')) != NULL) {
    - /* form of class,instance,*@ANDREW.CMU.EDU
    - * class,instance,@ANDREW.CMU.EDU
    - * If realm is local realm, blank recipient, else
    - * @REALM-NAME
    - */
    - char *realmat = g_strdup_printf("@%s",zephyr->realm);
    -
    - if (!g_ascii_strcasecmp(atptr, realmat)) {
    - sub.zsub_recipient = g_malloc0(1);
    - } else {
    - sub.zsub_recipient = g_strdup(atptr);
    - }
    - g_free(realmat);
    - } else {
    - sub.zsub_recipient = g_strdup(triple[2]);
    - }
    - g_free(tmp);
    -
    - if (!g_ascii_strcasecmp(triple[0], "%host%")) {
    - sub.zsub_class = g_strdup(zephyr->ourhost);
    - } else if (!g_ascii_strcasecmp(triple[0], "%canon%")) {
    - sub.zsub_class = g_strdup(zephyr->ourhostcanon);
    - } else {
    - sub.zsub_class = g_strdup(triple[0]);
    - }
    -
    - if (!g_ascii_strcasecmp(triple[1], "%host%")) {
    - sub.zsub_classinst = g_strdup(zephyr->ourhost);
    - } else if (!g_ascii_strcasecmp(triple[1], "%canon%")) {
    - sub.zsub_classinst = g_strdup(zephyr->ourhostcanon);
    - } else {
    - sub.zsub_classinst = g_strdup(triple[1]);
    - }
    -
    - /* There should be some sort of error report listing classes that couldn't be subbed to.
    - Not important right now though */
    -
    - if (!zephyr->subscribe_to(zephyr, &sub)) {
    - purple_debug_error("zephyr", "Couldn't subscribe to %s, %s, %s\n",
    - sub.zsub_class, sub.zsub_classinst, sub.zsub_recipient);
    - }
    -
    - zephyr->subscrips = g_slist_append(zephyr->subscrips, zephyr_triple_new(zephyr, &sub));
    - g_free(sub.zsub_class);
    - g_free(sub.zsub_classinst);
    - g_free(sub.zsub_recipient);
    - }
    - g_strfreev(triple);
    - }
    - }
    - fclose(f);
    - }
    - g_free(fname);
    -}
    -
    -static void
    -process_anyone(const zephyr_account *zephyr)
    -{
    - FILE *fd;
    - gchar buff[BUFSIZ], *filename;
    - PurpleGroup *g;
    - PurpleBuddy *b;
    -
    - if (!(g = purple_blist_find_group(_("Anyone")))) {
    - g = purple_group_new(_("Anyone"));
    - purple_blist_add_group(g, NULL);
    - }
    -
    - filename = g_strconcat(purple_home_dir(), "/.anyone", NULL);
    - if ((fd = g_fopen(filename, "r")) != NULL) {
    - while (fgets(buff, BUFSIZ, fd)) {
    - strip_comments(buff);
    - if (*buff && !find_buddy(zephyr, buff)) {
    - char *stripped_user = zephyr_strip_local_realm(zephyr, buff);
    - purple_debug_info("zephyr", "stripped_user %s\n", stripped_user);
    - b = purple_buddy_new(zephyr->account, stripped_user, NULL);
    - purple_blist_add_buddy(b, NULL, g, NULL);
    - g_free(stripped_user);
    - }
    - }
    - fclose(fd);
    - }
    - g_free(filename);
    -}
    -
    -static gchar *
    -get_zephyr_exposure(PurpleAccount *account)
    -{
    - const gchar *exposure;
    - gchar *exp2;
    -
    - exposure = purple_account_get_string(account, "exposure_level", EXPOSE_REALMVIS);
    -
    - /* Make sure that the exposure (visibility) is set to a sane value */
    - exp2 = g_strstrip(g_ascii_strup(exposure, -1));
    - if (exp2) {
    - if (purple_strequal(exp2, EXPOSE_NONE) ||
    - purple_strequal(exp2, EXPOSE_OPSTAFF) ||
    - purple_strequal(exp2, EXPOSE_REALMANN) ||
    - purple_strequal(exp2, EXPOSE_NETVIS) ||
    - purple_strequal(exp2, EXPOSE_NETANN)) {
    - return exp2;
    - }
    - g_free(exp2);
    - }
    - return g_strdup(EXPOSE_REALMVIS);
    -}
    -
    -gchar *
    -get_zephyr_realm(PurpleAccount *account, const gchar *local_realm)
    -{
    - const char *realm = purple_account_get_string(account, "realm", "");
    - if (!*realm) {
    - realm = local_realm;
    - }
    - g_strlcpy(__Zephyr_realm, realm, REALM_SZ - 1);
    - return g_strdup(realm);
    -}
    -
    -static void
    -zephyr_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
    - PurpleConnection *gc;
    - zephyr_account *zephyr;
    - ZephyrLoginFunc login;
    - GSourceFunc check_notify;
    - ZSubscription_t sub;
    -
    - gc = purple_account_get_connection(account);
    -
    -#ifdef WIN32
    - username = purple_account_get_username(account);
    -#endif
    - purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_AUTO_RESP |
    - PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_NO_BGCOLOR |
    - PURPLE_CONNECTION_FLAG_NO_URLDESC | PURPLE_CONNECTION_FLAG_NO_IMAGES);
    - zephyr = g_new0(zephyr_account, 1);
    - purple_connection_set_protocol_data(gc, zephyr);
    -
    - zephyr->account = account;
    - zephyr->exposure = get_zephyr_exposure(account);
    -
    - if (purple_account_get_bool(account, "use_tzc", FALSE)) {
    - zephyr->connection_type = PURPLE_ZEPHYR_TZC;
    - login = tzc_login;
    - check_notify = tzc_check_notify;
    - zephyr->subscribe_to = tzc_subscribe_to;
    - zephyr->request_locations = tzc_request_locations;
    - zephyr->send_message = tzc_send_message;
    - zephyr->set_location = tzc_set_location;
    - zephyr->get_subs_from_server = tzc_get_subs_from_server;
    - zephyr->close = tzc_close;
    - } else {
    - zephyr->connection_type = PURPLE_ZEPHYR_KRB4;
    - login = zeph02_login;
    - check_notify = zeph02_check_notify;
    - zephyr->subscribe_to = zeph02_subscribe_to;
    - zephyr->request_locations = zeph02_request_locations;
    - zephyr->send_message = zeph02_send_message;
    - zephyr->set_location = zeph02_set_location;
    - zephyr->get_subs_from_server = zeph02_get_subs_from_server;
    - zephyr->close = zeph02_close;
    - }
    -
    - zephyr->encoding = (char *)purple_account_get_string(account, "encoding", ZEPHYR_FALLBACK_CHARSET);
    -
    - if (!login(zephyr)) {
    - return;
    - }
    - purple_debug_info("zephyr","does it get here\n");
    - purple_debug_info("zephyr"," realm: %s username:%s\n", zephyr->realm, zephyr->username);
    -
    - /* For now */
    - zephyr->galaxy = NULL;
    - zephyr->krbtkfile = NULL;
    - zephyr_inithosts(zephyr);
    -
    - sub.zsub_class = "MESSAGE";
    - sub.zsub_classinst = "PERSONAL";
    - sub.zsub_recipient = zephyr->username;
    -
    - if (!zephyr->subscribe_to(zephyr, &sub)) {
    - /* XXX don't translate this yet. It could be written better */
    - /* XXX error messages could be handled with more detail */
    - purple_notify_error(gc, NULL,
    - "Unable to subscribe to messages", "Unable to subscribe to initial messages",
    - purple_request_cpar_from_connection(gc));
    - return;
    - }
    -
    - purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
    -
    - if (purple_account_get_bool(account, "read_anyone", TRUE)) {
    - process_anyone(zephyr);
    - }
    - if (purple_account_get_bool(account, "read_zsubs", TRUE)) {
    - process_zsubs(zephyr);
    - }
    -
    - zephyr->nottimer = g_timeout_add(100, check_notify, gc);
    - zephyr->loctimer = g_timeout_add_seconds(20, check_loc, zephyr);
    -}
    -
    -static void write_zsubs(zephyr_account *zephyr)
    -{
    - /* Exports subscription (chat) list back to
    - * .zephyr.subs
    - * XXX deal with %host%, %canon%, unsubscriptions, and negative subscriptions (punts?)
    - */
    -
    - GSList *s = zephyr->subscrips;
    - zephyr_triple *zt;
    - FILE *fd;
    - char *fname;
    -
    - char **triple;
    -
    - fname = g_strdup_printf("%s/.zephyr.subs", purple_home_dir());
    - fd = g_fopen(fname, "w");
    -
    - if (!fd) {
    - g_free(fname);
    - return;
    - }
    -
    - while (s) {
    - char *zclass, *zinst, *zrecip;
    - zt = s->data;
    - triple = g_strsplit(zt->name, ",", 3);
    -
    - /* deal with classes */
    - if (!g_ascii_strcasecmp(triple[0],zephyr->ourhost)) {
    - zclass = g_strdup("%host%");
    - } else if (!g_ascii_strcasecmp(triple[0],zephyr->ourhostcanon)) {
    - zclass = g_strdup("%canon%");
    - } else {
    - zclass = g_strdup(triple[0]);
    - }
    -
    - /* deal with instances */
    -
    - if (!g_ascii_strcasecmp(triple[1],zephyr->ourhost)) {
    - zinst = g_strdup("%host%");
    - } else if (!g_ascii_strcasecmp(triple[1],zephyr->ourhostcanon)) {
    - zinst = g_strdup("%canon%");;
    - } else {
    - zinst = g_strdup(triple[1]);
    - }
    -
    - /* deal with recipients */
    - if (triple[2] == NULL) {
    - zrecip = g_strdup("*");
    - } else if (!g_ascii_strcasecmp(triple[2],"")){
    - zrecip = g_strdup("*");
    - } else if (!g_ascii_strcasecmp(triple[2], zephyr->username)) {
    - zrecip = g_strdup("%me%");
    - } else {
    - zrecip = g_strdup(triple[2]);
    - }
    -
    - fprintf(fd, "%s,%s,%s\n",zclass,zinst,zrecip);
    -
    - g_free(zclass);
    - g_free(zinst);
    - g_free(zrecip);
    - g_strfreev(triple);
    - s = s->next;
    - }
    - g_free(fname);
    - fclose(fd);
    -}
    -
    -static void write_anyone(zephyr_account *zephyr)
    -{
    - GSList *buddies;
    - char *fname;
    - FILE *fd;
    - PurpleAccount *account;
    - fname = g_strdup_printf("%s/.anyone", purple_home_dir());
    - fd = g_fopen(fname, "w");
    - if (!fd) {
    - g_free(fname);
    - return;
    - }
    -
    - account = zephyr->account;
    - for (buddies = purple_blist_find_buddies(account, NULL); buddies;
    - buddies = g_slist_delete_link(buddies, buddies)) {
    - PurpleBuddy *b = buddies->data;
    - gchar *stripped_user = zephyr_strip_local_realm(zephyr, purple_buddy_get_name(b));
    - fprintf(fd, "%s\n", stripped_user);
    - g_free(stripped_user);
    - }
    -
    - fclose(fd);
    - g_free(fname);
    -}
    -
    -static void
    -zephyr_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection * gc) {
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    -
    - g_list_free_full(zephyr->pending_zloc_names, g_free);
    -
    - if (purple_account_get_bool(purple_connection_get_account(gc), "write_anyone", FALSE))
    - write_anyone(zephyr);
    -
    - if (purple_account_get_bool(purple_connection_get_account(gc), "write_zsubs", FALSE))
    - write_zsubs(zephyr);
    -
    - g_slist_free_full(zephyr->subscrips, (GDestroyNotify)zephyr_triple_free);
    -
    - if (zephyr->nottimer)
    - g_source_remove(zephyr->nottimer);
    - zephyr->nottimer = 0;
    - if (zephyr->loctimer)
    - g_source_remove(zephyr->loctimer);
    - zephyr->loctimer = 0;
    - zephyr->close(zephyr);
    -
    - g_clear_pointer(&zephyr->ourhost, g_free);
    - g_clear_pointer(&zephyr->ourhostcanon, g_free);
    -}
    -
    -static gboolean
    -zephyr_send_message(zephyr_account *zephyr, gchar *zclass, gchar *instance,
    - gchar *recipient, const gchar *im, const gchar *sig,
    - gchar *opcode)
    -{
    - /* (From the tzc source)
    - * emacs sends something of the form:
    - * ((class . "MESSAGE")
    - * (auth . t)
    - * (recipients ("PERSONAL" . "bovik") ("test" . ""))
    - * (sender . "bovik")
    - * (message . ("Harry Bovik" "my zgram"))
    - * )
    - */
    - char *tmp_buf;
    - char *html_buf;
    - gboolean result;
    -
    - tmp_buf = html_to_zephyr(im);
    - html_buf = purple_unescape_html(tmp_buf);
    - g_free(tmp_buf);
    -
    - result = zephyr->send_message(zephyr, zclass, instance, recipient, html_buf, sig, opcode);
    - g_free(html_buf);
    - return result;
    -}
    -
    -static gint
    -zephyr_triple_cmp_id(gconstpointer data, gconstpointer user_data)
    -{
    - const zephyr_triple *zt = data;
    - int id = GPOINTER_TO_INT(user_data);
    - return zt->id - id;
    -}
    -
    -static const char * zephyr_get_signature(void)
    -{
    - /* XXX add zephyr error reporting */
    - const char * sig =ZGetVariable("zwrite-signature");
    - if (!sig) {
    - sig = g_get_real_name();
    - }
    - return sig;
    -}
    -
    -static int
    -zephyr_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc,
    - int id, PurpleMessage *msg)
    -{
    - GSList *l;
    - zephyr_triple *zt;
    - const char *sig;
    - PurpleConversation *gcc;
    - PurpleConversationManager *manager;
    - char *inst;
    - char *recipient;
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    -
    - l = g_slist_find_custom(zephyr->subscrips, GINT_TO_POINTER(id), zephyr_triple_cmp_id);
    - if (!l) {
    - /* this should never happen. */
    - return -EINVAL;
    - }
    -
    - zt = l->data;
    - sig = zephyr_get_signature();
    -
    - manager = purple_conversation_manager_get_default();
    - gcc = purple_conversation_manager_find_chat(manager,
    - purple_connection_get_account(gc),
    - zt->name);
    -
    - if (!(inst = (char *)purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(gcc))))
    - inst = g_strdup("PERSONAL");
    -
    - if (!g_ascii_strcasecmp(zt->sub.zsub_recipient, "*")) {
    - recipient = zephyr_normalize_local_realm(zephyr, "");
    - } else {
    - recipient = zephyr_normalize_local_realm(zephyr, zt->sub.zsub_recipient);
    - }
    - zephyr_send_message(zephyr, zt->sub.zsub_class, inst, recipient,
    - purple_message_get_contents(msg), sig, "");
    - return 0;
    -}
    -
    -
    -static int zephyr_send_im(PurpleProtocolIM *im, PurpleConnection *gc, PurpleMessage *msg)
    -{
    - const char *sig;
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    -
    - if (purple_message_get_flags(msg) & PURPLE_MESSAGE_AUTO_RESP) {
    - sig = "Automated reply:";
    - } else {
    - sig = zephyr_get_signature();
    - }
    - zephyr_send_message(zephyr, "MESSAGE", "PERSONAL",
    - zephyr_normalize_local_realm(zephyr, purple_message_get_recipient(msg)),
    - purple_message_get_contents(msg), sig, "");
    -
    - return 1;
    -}
    -
    -
    -/* Basically the inverse of zephyr_strip_local_realm */
    -char *
    -zephyr_normalize_local_realm(const zephyr_account *zephyr, const char *orig)
    -{
    - if (*orig == '\0' || strchr(orig, '@')) {
    - return g_strdup(orig);
    - }
    -
    - return g_strdup_printf("%s@%s", orig, zephyr->realm);
    -}
    -
    -static const char *
    -zephyr_normalize(PurpleProtocolClient *client, PurpleAccount *account,
    - const char *who)
    -{
    - static char buf[BUF_LEN];
    - PurpleConnection *gc;
    - char *tmp;
    -
    - if (account == NULL) {
    - if (strlen(who) >= sizeof(buf))
    - return NULL;
    - return who;
    - }
    -
    - gc = purple_account_get_connection((PurpleAccount *)account);
    - if (gc == NULL)
    - return NULL;
    -
    - tmp = zephyr_normalize_local_realm(purple_connection_get_protocol_data(gc), who);
    -
    - if (strlen(tmp) >= sizeof(buf)) {
    - g_free(tmp);
    - return NULL;
    - }
    -
    - g_strlcpy(buf, tmp, sizeof(buf));
    - g_free(tmp);
    -
    - return buf;
    -}
    -
    -static void
    -zephyr_zloc(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    - const gchar *who)
    -{
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - gchar *normalized_who = zephyr_normalize_local_realm(zephyr, who);
    -
    - if (zephyr->request_locations(zephyr, normalized_who)) {
    - zephyr->pending_zloc_names = g_list_append(zephyr->pending_zloc_names, normalized_who);
    - } else {
    - /* XXX deal with errors somehow */
    - g_free(normalized_who);
    - }
    -}
    -
    -static void
    -zephyr_set_status(PurpleProtocolServer *protocol_server,
    - PurpleAccount *account, PurpleStatus *status)
    -{
    - PurpleConnection *gc = purple_account_get_connection(account);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status));
    -
    - g_free(zephyr->away);
    - zephyr->away = NULL;
    -
    - if (primitive == PURPLE_STATUS_AWAY) {
    - zephyr->away = g_strdup(purple_status_get_attr_string(status,"message"));
    - }
    - else if (primitive == PURPLE_STATUS_AVAILABLE) {
    - zephyr->set_location(zephyr, zephyr->exposure);
    - }
    - else if (primitive == PURPLE_STATUS_INVISIBLE) {
    - /* XXX handle errors */
    - zephyr->set_location(zephyr, EXPOSE_OPSTAFF);
    - }
    -}
    -
    -static GList *
    -zephyr_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
    - PurpleAccount *account)
    -{
    - PurpleStatusType *type;
    - GList *types = NULL;
    -
    - /* zephyr has several exposures
    - NONE (where you are hidden, and zephyrs to you are in practice silently dropped -- yes this is wrong)
    - OPSTAFF "hidden"
    - REALM-VISIBLE visible to people in local realm
    - REALM-ANNOUNCED REALM-VISIBLE+ plus your logins/logouts are announced to <login,username,*>
    - NET-VISIBLE REALM-ANNOUNCED, plus visible to people in foreign realm
    - NET-ANNOUNCED NET-VISIBLE, plus logins/logouts are announced to <login,username,*>
    -
    - Online will set the user to the exposure they have in their options (defaulting to REALM-VISIBLE),
    - Hidden, will set the user's exposure to OPSTAFF
    -
    - Away won't change their exposure but will set an auto away message (for IMs only)
    - */
    -
    - type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE);
    - types = g_list_append(types,type);
    -
    - type = purple_status_type_new(PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE);
    - types = g_list_append(types,type);
    -
    - type = purple_status_type_new_with_attrs(
    - PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
    - "message", _("Message"), purple_value_new(G_TYPE_STRING),
    - NULL);
    - types = g_list_append(types, type);
    -
    - type = purple_status_type_new(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE);
    - types = g_list_append(types,type);
    -
    - return types;
    -}
    -
    -static GList *
    -zephyr_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection * gc) {
    - GList *m = NULL;
    - PurpleProtocolChatEntry *pce;
    -
    - pce = g_new0(PurpleProtocolChatEntry, 1);
    -
    - pce->label = _("_Class:");
    - pce->identifier = "class";
    - m = g_list_append(m, pce);
    -
    - pce = g_new0(PurpleProtocolChatEntry, 1);
    -
    - pce->label = _("_Instance:");
    - pce->identifier = "instance";
    - m = g_list_append(m, pce);
    -
    - pce = g_new0(PurpleProtocolChatEntry, 1);
    -
    - pce->label = _("_Recipient:");
    - pce->identifier = "recipient";
    - m = g_list_append(m, pce);
    -
    - return m;
    -}
    -
    -static char *
    -zephyr_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data) {
    - gchar* zclass = g_hash_table_lookup(data,"class");
    - gchar* inst = g_hash_table_lookup(data,"instance");
    - gchar* recipient = g_hash_table_lookup(data, "recipient");
    - if (!zclass) /* This should never happen */
    - zclass = "";
    - if (!inst)
    - inst = "*";
    - if (!recipient)
    - recipient = "";
    - return g_strdup_printf("%s,%s,%s",zclass,inst,recipient);
    -}
    -
    -
    -static void
    -zephyr_triple_open_personal(zephyr_triple *zt, PurpleConnection *gc, char *instance)
    -{
    - if (!g_ascii_strcasecmp(instance, "*")) {
    - instance = "PERSONAL";
    - }
    - zephyr_triple_open(zt, gc, instance);
    -}
    -
    -static void
    -zephyr_join_chat(PurpleConnection *gc, ZSubscription_t *sub)
    -{
    - GSList *l;
    - zephyr_triple *zt;
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    -
    - g_return_if_fail(zephyr != NULL);
    -
    - if (!sub->zsub_class) {
    - return;
    - }
    - if (!g_ascii_strcasecmp(sub->zsub_class, "%host%")) {
    - sub->zsub_class = zephyr->ourhost;
    - } else if (!g_ascii_strcasecmp(sub->zsub_class, "%canon%")) {
    - sub->zsub_class = zephyr->ourhostcanon;
    - }
    -
    - if (!sub->zsub_classinst || *sub->zsub_classinst == '\0') {
    - sub->zsub_classinst = "*";
    - } else if (!g_ascii_strcasecmp(sub->zsub_classinst, "%host%")) {
    - sub->zsub_classinst = zephyr->ourhost;
    - } else if (!g_ascii_strcasecmp(sub->zsub_classinst, "%canon%")) {
    - sub->zsub_classinst = zephyr->ourhostcanon;
    - }
    -
    - if (!sub->zsub_recipient || *sub->zsub_recipient == '*') {
    - sub->zsub_recipient = "";
    - } else if (!g_ascii_strcasecmp(sub->zsub_recipient, "%me%")) {
    - sub->zsub_recipient = zephyr->username;
    - }
    -
    - l = g_slist_find_custom(zephyr->subscrips, &sub, (GCompareFunc)zephyr_triple_subset);
    - if (l) {
    - zt = l->data;
    - if (!zt->open) {
    - zephyr_triple_open_personal(zt, gc, sub->zsub_classinst);
    - }
    - return;
    - }
    -
    - if (!zephyr->subscribe_to(zephyr, sub)) {
    - /* Called when the server notifies us a message couldn't get sent */
    - /* XXX output better subscription information */
    - gchar *subscribe_failed = g_strdup_printf(_("Attempt to subscribe to %s,%s,%s failed"),
    - sub->zsub_class, sub->zsub_classinst, sub->zsub_recipient);
    - purple_notify_error(gc,"", subscribe_failed, NULL, purple_request_cpar_from_connection(gc));
    - g_free(subscribe_failed);
    - return;
    - }
    -
    - zt = zephyr_triple_new(zephyr, sub);
    - zephyr->subscrips = g_slist_append(zephyr->subscrips, zt);
    - zephyr_triple_open_personal(zt, gc, sub->zsub_classinst);
    -}
    -
    -static void
    -zephyr_protocol_chat_join(PurpleProtocolChat *protocol_chat,
    - PurpleConnection *gc, GHashTable * data)
    -{
    - ZSubscription_t sub = {
    - .zsub_class = g_hash_table_lookup(data, "class"),
    - .zsub_classinst = g_hash_table_lookup(data, "instance"),
    - .zsub_recipient = g_hash_table_lookup(data, "recipient")
    - };
    - zephyr_join_chat(gc, &sub);
    -}
    -
    -static void
    -zephyr_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection * gc,
    - int id)
    -{
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - GSList *l;
    -
    - l = g_slist_find_custom(zephyr->subscrips, GINT_TO_POINTER(id), zephyr_triple_cmp_id);
    - if (l) {
    - zephyr_triple *zt = l->data;
    - zt->open = FALSE;
    - zt->id = ++(zephyr->last_id);
    - }
    -}
    -
    -static PurpleChat *
    -zephyr_find_blist_chat(PurpleProtocolClient *client, PurpleAccount *account,
    - const char *name)
    -{
    - PurpleBlistNode *gnode, *cnode;
    -
    - /* XXX needs to be %host%,%canon%, and %me% clean */
    - for (gnode = purple_blist_get_default_root(); gnode;
    - gnode = purple_blist_node_get_sibling_next(gnode)) {
    - for(cnode = purple_blist_node_get_first_child(gnode);
    - cnode;
    - cnode = purple_blist_node_get_sibling_next(cnode)) {
    - PurpleChat *chat = (PurpleChat*)cnode;
    - const gchar *zclass, *inst, *recip;
    - char** triple;
    - GHashTable *components;
    - if(!PURPLE_IS_CHAT(cnode))
    - continue;
    - if(purple_chat_get_account(chat) != account)
    - continue;
    - components = purple_chat_get_components(chat);
    - if(!(zclass = g_hash_table_lookup(components, "class")))
    - continue;
    - if(!(inst = g_hash_table_lookup(components, "instance")))
    - inst = "";
    - if(!(recip = g_hash_table_lookup(components, "recipient")))
    - recip = "";
    - /* purple_debug_info("zephyr","in zephyr_find_blist_chat name: %s\n",name?name:""); */
    - triple = g_strsplit(name,",",3);
    - if (!g_ascii_strcasecmp(triple[0], zclass) &&
    - !g_ascii_strcasecmp(triple[1], inst) &&
    - !g_ascii_strcasecmp(triple[2], recip)) {
    - g_strfreev(triple);
    - return chat;
    - }
    - g_strfreev(triple);
    - }
    - }
    - return NULL;
    -}
    -
    -static GList *
    -zephyr_protocol_get_account_options(PurpleProtocol *protocol) {
    - PurpleAccountOption *option;
    - GList *opts = NULL;
    - const gchar *tmp = get_exposure_level();
    -
    - option = purple_account_option_bool_new(_("Use tzc"), "use_tzc", FALSE);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_string_new(_("tzc command"), "tzc_command",
    - "/usr/bin/tzc -e %s");
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_bool_new(_("Export to .anyone"),
    - "write_anyone", FALSE);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_bool_new(_("Export to .zephyr.subs"),
    - "write_zsubs", FALSE);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_bool_new(_("Import from .anyone"),
    - "read_anyone", TRUE);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_bool_new(_("Import from .zephyr.subs"),
    - "read_zsubs", TRUE);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_string_new(_("Realm"), "realm", "");
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_string_new(_("Exposure"), "exposure_level",
    - tmp);
    - opts = g_list_append(opts, option);
    -
    - option = purple_account_option_string_new(_("Encoding"), "encoding",
    - ZEPHYR_FALLBACK_CHARSET);
    - opts = g_list_append(opts, option);
    -
    - return opts;
    -}
    -
    -static unsigned int
    -zephyr_send_typing(G_GNUC_UNUSED PurpleProtocolIM *im, PurpleConnection *gc, const char *who, PurpleIMTypingState state)
    -{
    - zephyr_account *zephyr;
    - gchar *recipient;
    -
    - if (state == PURPLE_IM_NOT_TYPING) {
    - return 0;
    - }
    -
    - zephyr = purple_connection_get_protocol_data(gc);
    - /* XXX We probably should care if this fails. Or maybe we don't want to */
    - if (!who) {
    - purple_debug_info("zephyr", "who is null\n");
    - recipient = zephyr_normalize_local_realm(zephyr, "");
    - } else {
    - char *comma = strrchr(who, ',');
    - /* Don't ping broadcast (chat) recipients */
    - /* The strrchr case finds a realm-stripped broadcast subscription
    - e.g. comma is the last character in the string */
    - if (comma && ((*(comma+1) == '\0') || (*(comma+1) == '@'))) {
    - return 0;
    - }
    -
    - recipient = zephyr_normalize_local_realm(zephyr, who);
    - }
    -
    - purple_debug_info("zephyr", "about to send typing notification to %s", recipient);
    - zephyr_send_message(zephyr, "MESSAGE", "PERSONAL", recipient, "", "", "PING");
    - purple_debug_info("zephyr", "sent typing notification\n");
    -
    - /*
    - * TODO: Is this correct? It means we will call
    - * purple_serv_send_typing(gc, who, PURPLE_IM_TYPING) once every 15 seconds
    - * until the Purple user stops typing.
    - */
    - return ZEPHYR_TYPING_SEND_TIMEOUT;
    -}
    -
    -
    -
    -static void zephyr_chat_set_topic(PurpleConnection * gc, int id, const char *topic)
    -{
    - zephyr_triple *zt;
    - PurpleConversation *gcc;
    - PurpleConversationManager *manager;
    - gchar *topic_utf8;
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - GSList *l;
    -
    - l = g_slist_find_custom(zephyr->subscrips, GINT_TO_POINTER(id), zephyr_triple_cmp_id);
    - if (!l) {
    - return;
    - }
    - zt = l->data;
    -
    - manager = purple_conversation_manager_get_default();
    - gcc = purple_conversation_manager_find_chat(manager,
    - purple_connection_get_account(gc),
    - zt->name);
    -
    - topic_utf8 = convert_to_utf8(topic, zephyr->encoding);
    - purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(gcc), zephyr->username, topic_utf8);
    - g_free(topic_utf8);
    -}
    -
    -static void
    -zephyr_protocol_chat_set_topic(PurpleProtocolChat *protocol_chat,
    - PurpleConnection *gc, int id, const char *topic)
    -{
    - zephyr_chat_set_topic(gc, id, topic);
    -}
    -
    -/* commands */
    -
    -static PurpleCmdRet zephyr_purple_cmd_msg(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - char *recipient;
    - PurpleCmdRet ret;
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);;
    - if (!g_ascii_strcasecmp(args[0],"*"))
    - return PURPLE_CMD_RET_FAILED; /* "*" is not a valid argument */
    - else
    - recipient = zephyr_normalize_local_realm(zephyr, args[0]);
    -
    - if (strlen(recipient) < 1) {
    - g_free(recipient);
    - return PURPLE_CMD_RET_FAILED; /* a null recipient is a chat message, not an IM */
    - }
    -
    - if (zephyr_send_message(zephyr,"MESSAGE","PERSONAL",recipient,args[1],zephyr_get_signature(),""))
    - ret = PURPLE_CMD_RET_OK;
    - else
    - ret = PURPLE_CMD_RET_FAILED;
    - g_free(recipient);
    - return ret;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zlocate(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - zephyr_zloc(NULL, purple_conversation_get_connection(conv),args[0]);
    - return PURPLE_CMD_RET_OK;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_instance(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* Currently it sets the instance with leading spaces and
    - * all. This might not be the best thing to do, though having
    - * one word isn't ideal either. */
    -
    - const char* instance = args[0];
    - zephyr_chat_set_topic(purple_conversation_get_connection(conv),
    - purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)),instance);
    - return PURPLE_CMD_RET_OK;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_joinchat_cir(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* Join a new zephyr chat */
    - ZSubscription_t sub = {
    - .zsub_class = args[0],
    - .zsub_classinst = args[1],
    - .zsub_recipient = args[2]
    - };
    - zephyr_join_chat(purple_conversation_get_connection(conv), &sub);
    - return PURPLE_CMD_RET_OK;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zi(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* args = instance, message */
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - if ( zephyr_send_message(zephyr,"message",args[0],"",args[1],zephyr_get_signature(),""))
    - return PURPLE_CMD_RET_OK;
    - else
    - return PURPLE_CMD_RET_FAILED;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zci(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* args = class, instance, message */
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - if ( zephyr_send_message(zephyr,args[0],args[1],"",args[2],zephyr_get_signature(),""))
    - return PURPLE_CMD_RET_OK;
    - else
    - return PURPLE_CMD_RET_FAILED;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zcir(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* args = class, instance, recipient, message */
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - if ( zephyr_send_message(zephyr,args[0],args[1],args[2],args[3],zephyr_get_signature(),""))
    - return PURPLE_CMD_RET_OK;
    - else
    - return PURPLE_CMD_RET_FAILED;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zir(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* args = instance, recipient, message */
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - if ( zephyr_send_message(zephyr,"message",args[0],args[1],args[2],zephyr_get_signature(),""))
    - return PURPLE_CMD_RET_OK;
    - else
    - return PURPLE_CMD_RET_FAILED;
    -}
    -
    -static PurpleCmdRet zephyr_purple_cmd_zc(PurpleConversation *conv,
    - const char *cmd, char **args, char **error, void *data)
    -{
    - /* args = class, message */
    - PurpleConnection *gc = purple_conversation_get_connection(conv);
    - zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    - if ( zephyr_send_message(zephyr,args[0],"PERSONAL","",args[1],zephyr_get_signature(),""))
    - return PURPLE_CMD_RET_OK;
    - else
    - return PURPLE_CMD_RET_FAILED;
    -}
    -
    -static void zephyr_register_slash_commands(void)
    -{
    - PurpleCmdId id;
    -
    - id = purple_cmd_register("msg","ws", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_msg, _("msg &lt;nick&gt; &lt;message&gt;: Send a private message to a user"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zlocate","w", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zlocate, _("zlocate &lt;nick&gt;: Locate user"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zl","w", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zlocate, _("zl &lt;nick&gt;: Locate user"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("instance","s", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_instance, _("instance &lt;instance&gt;: Set the instance to be used on this class"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("inst","s", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_instance, _("inst &lt;instance&gt;: Set the instance to be used on this class"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("topic","s", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_instance, _("topic &lt;instance&gt;: Set the instance to be used on this class"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("sub", "www", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_joinchat_cir,
    - _("sub &lt;class&gt; &lt;instance&gt; &lt;recipient&gt;: Join a new chat"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zi","ws", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zi, _("zi &lt;instance&gt;: Send a message to &lt;message,<i>instance</i>,*&gt;"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zci","wws",PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zci,
    - _("zci &lt;class&gt; &lt;instance&gt;: Send a message to &lt;<i>class</i>,<i>instance</i>,*&gt;"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zcir","wwws",PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zcir,
    - _("zcir &lt;class&gt; &lt;instance&gt; &lt;recipient&gt;: Send a message to &lt;<i>class</i>,<i>instance</i>,<i>recipient</i>&gt;"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zir","wws",PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zir,
    - _("zir &lt;instance&gt; &lt;recipient&gt;: Send a message to &lt;MESSAGE,<i>instance</i>,<i>recipient</i>&gt;"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -
    - id = purple_cmd_register("zc","ws", PURPLE_CMD_P_PROTOCOL,
    - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
    - "prpl-zephyr",
    - zephyr_purple_cmd_zc, _("zc &lt;class&gt;: Send a message to &lt;<i>class</i>,PERSONAL,*&gt;"), NULL);
    - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
    -}
    -
    -
    -static void zephyr_unregister_slash_commands(void)
    -{
    - g_slist_free_full(cmds, (GDestroyNotify)purple_cmd_unregister);
    -}
    -
    -
    -/* Resubscribe to the in-memory list of subscriptions and also unsubscriptions */
    -static void
    -zephyr_action_resubscribe(G_GNUC_UNUSED GSimpleAction *action,
    - GVariant *parameter,
    - G_GNUC_UNUSED gpointer data)
    -{
    - const gchar *account_id = NULL;
    - PurpleAccountManager *manager = NULL;
    - PurpleAccount *account = NULL;
    - PurpleConnection *connection = NULL;
    - zephyr_account *zephyr = NULL;
    -
    - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
    - g_critical("Zephyr resubscribe action parameter is of incorrect type %s",
    - g_variant_get_type_string(parameter));
    - return;
    - }
    -
    - account_id = g_variant_get_string(parameter, NULL);
    - manager = purple_account_manager_get_default();
    - account = purple_account_manager_find_by_id(manager, account_id);
    - connection = purple_account_get_connection(account);
    - zephyr = purple_connection_get_protocol_data(connection);
    -
    - for (GSList *s = zephyr->subscrips; s; s = s->next) {
    - zephyr_triple *zt = s->data;
    - /* XXX We really should care if this fails */
    - zephyr->subscribe_to(zephyr, &zt->sub);
    - }
    - /* XXX handle unsubscriptions */
    -}
    -
    -
    -static void
    -zephyr_action_get_subs_from_server(G_GNUC_UNUSED GSimpleAction *action,
    - GVariant *parameter,
    - G_GNUC_UNUSED gpointer data)
    -{
    - const gchar *account_id = NULL;
    - PurpleAccountManager *manager = NULL;
    - PurpleAccount *account = NULL;
    - PurpleConnection *connection = NULL;
    - zephyr_account *zephyr = NULL;
    -
    - if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
    - g_critical("Zephyr get subscriptions action parameter is of incorrect type %s",
    - g_variant_get_type_string(parameter));
    - return;
    - }
    -
    - account_id = g_variant_get_string(parameter, NULL);
    - manager = purple_account_manager_get_default();
    - account = purple_account_manager_find_by_id(manager, account_id);
    - connection = purple_account_get_connection(account);
    - zephyr = purple_connection_get_protocol_data(connection);
    -
    - zephyr->get_subs_from_server(zephyr, connection);
    -}
    -
    -
    -static const gchar *
    -zephyr_protocol_actions_get_prefix(PurpleProtocolActions *actions) {
    - return "prpl-zephyr";
    -}
    -
    -static GActionGroup *
    -zephyr_protocol_actions_get_action_group(PurpleProtocolActions *actions,
    - G_GNUC_UNUSED PurpleConnection *connection)
    -{
    - GSimpleActionGroup *group = NULL;
    - GActionEntry entries[] = {
    - {
    - .name = "resubscribe",
    - .activate = zephyr_action_resubscribe,
    - .parameter_type = "s",
    - },
    - {
    - .name = "get-subcriptions",
    - .activate = zephyr_action_get_subs_from_server,
    - .parameter_type = "s",
    - },
    - };
    - gsize nentries = G_N_ELEMENTS(entries);
    -
    - group = g_simple_action_group_new();
    - g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries,
    - NULL);
    -
    - return G_ACTION_GROUP(group);
    -}
    -
    -
    -static GMenu *
    -zephyr_protocol_actions_get_menu(PurpleProtocolActions *actions) {
    - GMenu *menu = NULL;
    - GMenuItem *item = NULL;
    -
    - menu = g_menu_new();
    -
    - item = g_menu_item_new(_("Resubscribe"), "prpl-zephyr.resubscribe");
    - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
    - "account");
    - g_menu_append_item(menu, item);
    - g_object_unref(item);
    -
    - item = g_menu_item_new(_("Retrieve subscriptions from server"),
    - "prpl-zephyr.get-subscriptions");
    - g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
    - "account");
    - g_menu_append_item(menu, item);
    - g_object_unref(item);
    -
    - return menu;
    -}
    -
    -
    -static void
    -zephyr_protocol_init(ZephyrProtocol *self)
    -{
    -}
    -
    -
    -static void
    -zephyr_protocol_class_init(ZephyrProtocolClass *klass)
    -{
    - PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
    -
    - protocol_class->login = zephyr_login;
    - protocol_class->close = zephyr_close;
    - protocol_class->status_types = zephyr_status_types;
    -
    - protocol_class->get_account_options = zephyr_protocol_get_account_options;
    -}
    -
    -
    -static void
    -zephyr_protocol_class_finalize(G_GNUC_UNUSED ZephyrProtocolClass *klass)
    -{
    -}
    -
    -
    -static void
    -zephyr_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface)
    -{
    - iface->get_prefix = zephyr_protocol_actions_get_prefix;
    - iface->get_action_group = zephyr_protocol_actions_get_action_group;
    - iface->get_menu = zephyr_protocol_actions_get_menu;
    -}
    -
    -static void
    -zephyr_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface)
    -{
    - client_iface->normalize = zephyr_normalize;
    - client_iface->find_blist_chat = zephyr_find_blist_chat;
    -}
    -
    -
    -static void
    -zephyr_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
    -{
    - server_iface->get_info = zephyr_zloc;
    - server_iface->set_status = zephyr_set_status;
    -
    - server_iface->set_info = NULL; /* XXX Location? */
    - server_iface->set_buddy_icon = NULL; /* XXX */
    -}
    -
    -
    -static void
    -zephyr_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface)
    -{
    - im_iface->send = zephyr_send_im;
    - im_iface->send_typing = zephyr_send_typing;
    -}
    -
    -
    -static void
    -zephyr_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface)
    -{
    - chat_iface->info = zephyr_chat_info;
    - chat_iface->join = zephyr_protocol_chat_join;
    - chat_iface->get_name = zephyr_get_chat_name;
    - chat_iface->leave = zephyr_chat_leave;
    - chat_iface->send = zephyr_chat_send;
    - chat_iface->set_topic = zephyr_protocol_chat_set_topic;
    -
    - chat_iface->get_user_real_name = NULL; /* XXX */
    -}
    -
    -
    -G_DEFINE_DYNAMIC_TYPE_EXTENDED(
    - ZephyrProtocol, zephyr_protocol, PURPLE_TYPE_PROTOCOL, 0,
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS,
    - zephyr_protocol_actions_iface_init)
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
    - zephyr_protocol_client_iface_init)
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
    - zephyr_protocol_server_iface_init)
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
    - zephyr_protocol_im_iface_init)
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
    - zephyr_protocol_chat_iface_init));
    -
    -static PurpleProtocol *
    -zephyr_protocol_new(void) {
    - return PURPLE_PROTOCOL(g_object_new(
    - ZEPHYR_TYPE_PROTOCOL,
    - "id", "prpl-zephyr",
    - "name", "Zephyr",
    - "description", _("The chat component of Project Athena."),
    - "icon-name", "im-zephyr",
    - "icon-resource-path", "/im/pidgin/libpurple/zephyr/icons",
    - "options", OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD,
    - NULL));
    -}
    -
    -static GPluginPluginInfo *
    -zephyr_query(GError **error)
    -{
    - return purple_plugin_info_new(
    - "id", "prpl-zephyr",
    - "name", "Zephyr Protocol",
    - "version", DISPLAY_VERSION,
    - "category", N_("Protocol"),
    - "summary", N_("Zephyr Protocol Plugin"),
    - "description", N_("Zephyr Protocol Plugin"),
    - "website", PURPLE_WEBSITE,
    - "abi-version", PURPLE_ABI_VERSION,
    - "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
    - PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
    - NULL
    - );
    -}
    -
    -
    -static gboolean
    -zephyr_load(GPluginPlugin *plugin, GError **error)
    -{
    - PurpleProtocolManager *manager = purple_protocol_manager_get_default();
    -
    - zephyr_protocol_register_type(G_TYPE_MODULE(plugin));
    -
    - my_protocol = zephyr_protocol_new();
    - if(!purple_protocol_manager_register(manager, my_protocol, error)) {
    - g_clear_object(&my_protocol);
    -
    - return FALSE;
    - }
    -
    - zephyr_register_slash_commands();
    -
    - return TRUE;
    -}
    -
    -
    -static gboolean
    -zephyr_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
    -{
    - PurpleProtocolManager *manager = purple_protocol_manager_get_default();
    -
    - if(!purple_protocol_manager_unregister(manager, my_protocol, error)) {
    - return FALSE;
    - }
    -
    - zephyr_unregister_slash_commands();
    -
    - g_clear_object(&my_protocol);
    -
    - return TRUE;
    -}
    -
    -GPLUGIN_NATIVE_PLUGIN_DECLARE(zephyr)
    --- a/libpurple/protocols/zephyr/zephyr.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,32 +0,0 @@
    -/* purple
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, write to the Free Software
    - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
    - *
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_H
    -#define PURPLE_ZEPHYR_ZEPHYR_H
    -
    -#include <purple.h>
    -
    -#define ZEPHYR_TYPE_PROTOCOL (zephyr_protocol_get_type())
    -G_DECLARE_FINAL_TYPE(ZephyrProtocol, zephyr_protocol, ZEPHYR, PROTOCOL,
    - PurpleProtocol)
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_H */
    --- a/libpurple/protocols/zephyr/zephyr_account.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,87 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_ACCOUNT_H
    -#define PURPLE_ZEPHYR_ZEPHYR_ACCOUNT_H
    -
    -#include <glib.h>
    -
    -#include <purple.h>
    -
    -#include "internal.h"
    -
    -#ifndef HOST_NAME_MAX
    -# define HOST_NAME_MAX 255
    -#endif
    -
    -typedef struct _zephyr_account zephyr_account;
    -
    -typedef enum {
    - PURPLE_ZEPHYR_NONE, /* Non-kerberized ZEPH0.2 */
    - PURPLE_ZEPHYR_KRB4, /* ZEPH0.2 w/ KRB4 support */
    - PURPLE_ZEPHYR_TZC, /* tzc executable proxy */
    - PURPLE_ZEPHYR_INTERGALACTIC_KRB4 /* Kerberized ZEPH0.3 */
    -} zephyr_connection_type;
    -
    -typedef gboolean (*ZephyrSubscribeToFunc)(zephyr_account *zephyr, ZSubscription_t *sub);
    -typedef gboolean (*ZephyrRequestLocationsFunc)(zephyr_account *zephyr, gchar *who);
    -typedef gboolean (*ZephyrSendMessageFunc)(zephyr_account *zephyr, gchar *zclass, gchar *instance, gchar *recipient,
    - const gchar *html_buf, const gchar *sig, const gchar *opcode);
    -typedef void (*ZephyrSetLocationFunc)(zephyr_account *zephyr, char *exposure);
    -typedef void (*ZephyrGetSubsFromServerFunc)(zephyr_account *zephyr, PurpleConnection *gc);
    -typedef void (*ZephyrCloseFunc)(zephyr_account *zephyr);
    -
    -struct _zephyr_account {
    - PurpleAccount* account;
    - char *username;
    - char *realm;
    - char *encoding;
    - char* galaxy; /* not yet useful */
    - char* krbtkfile; /* not yet useful */
    - guint32 nottimer;
    - guint32 loctimer;
    - GList *pending_zloc_names;
    - GSList *subscrips;
    - int last_id;
    - unsigned short port;
    - gchar *ourhost;
    - gchar *ourhostcanon;
    - zephyr_connection_type connection_type;
    - char *exposure;
    - GSubprocess *tzc_proc;
    - GOutputStream *tzc_stdin;
    - GInputStream *tzc_stdout;
    - gchar *away;
    - ZephyrSubscribeToFunc subscribe_to;
    - ZephyrRequestLocationsFunc request_locations;
    - ZephyrSendMessageFunc send_message;
    - ZephyrSetLocationFunc set_location;
    - ZephyrGetSubsFromServerFunc get_subs_from_server;
    - ZephyrCloseFunc close;
    -};
    -
    -gchar *get_zephyr_realm(PurpleAccount *account, const gchar *local_realm);
    -void handle_message(PurpleConnection *gc, ZNotice_t *notice);
    -void handle_locations(PurpleConnection *gc, const gchar *user, int nlocs, const ZLocations_t *zloc);
    -char *zephyr_normalize_local_realm(const zephyr_account *zephyr, const char *orig);
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_ACCOUNT_H */
    --- a/libpurple/protocols/zephyr/zephyr_err.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,28 +0,0 @@
    -/*
    - * zephyr_err.h:
    - * This file is automatically generated; please do not edit it.
    - */
    -#define ZERR_PKTLEN (-772103680L)
    -#define ZERR_HEADERLEN (-772103679L)
    -#define ZERR_ILLVAL (-772103678L)
    -#define ZERR_HMPORT (-772103677L)
    -#define ZERR_PORTINUSE (-772103676L)
    -#define ZERR_BADPKT (-772103675L)
    -#define ZERR_VERS (-772103674L)
    -#define ZERR_NOPORT (-772103673L)
    -#define ZERR_NONOTICE (-772103672L)
    -#define ZERR_QLEN (-772103671L)
    -#define ZERR_HMDEAD (-772103670L)
    -#define ZERR_INTERNAL (-772103669L)
    -#define ZERR_NOLOCATIONS (-772103668L)
    -#define ZERR_NOMORELOCS (-772103667L)
    -#define ZERR_FIELDLEN (-772103666L)
    -#define ZERR_BADFIELD (-772103665L)
    -#define ZERR_SERVNAK (-772103664L)
    -#define ZERR_AUTHFAIL (-772103663L)
    -#define ZERR_LOGINFAIL (-772103662L)
    -#define ZERR_NOSUBSCRIPTIONS (-772103661L)
    -#define ZERR_NOMORESUBSCRIPTIONS (-772103660L)
    -#define ZERR_TOOMANYSUBS (-772103659L)
    -#define ZERR_EOF (-772103658L)
    -#define ERROR_TABLE_BASE_zeph (-772103680L)
    --- a/libpurple/protocols/zephyr/zephyr_html.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,406 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#include <ctype.h>
    -
    -#include <purple.h>
    -
    -#include "zephyr_html.h"
    -
    -typedef struct _zframe zframe;
    -
    -struct _zframe {
    - /* common part */
    - /* true for everything but @color, since inside the parens of that one is
    - * the color. */
    - gboolean has_closer;
    - /* </i>, </font>, </b>, etc. */
    - const char *closing;
    - /* text including the opening html thingie. */
    - GString *text;
    -
    - /* html_to_zephyr */
    - /* @i, @b, etc. */
    - const char *env;
    - /* }=1, ]=2, )=4, >=8 */
    - int closer_mask;
    - /* href for links */
    - gboolean is_href;
    - GString *href;
    -
    - /* zephyr_to_html */
    - /* }, ], ), > */
    - char *closer;
    -};
    -
    -static zframe *
    -zframe_new_with_text(const gchar *text, const gchar *closing, gboolean has_closer)
    -{
    - zframe *frame = g_new(zframe, 1);
    -
    - frame->text = g_string_new(text);
    - frame->closing = closing;
    - frame->has_closer = has_closer;
    -
    - return frame;
    -}
    -
    -static inline zframe *
    -zframe_new(const gchar *closing, gboolean has_closer)
    -{
    - return zframe_new_with_text("", closing, has_closer);
    -}
    -
    -static gboolean
    -zframe_href_has_prefix(const zframe *frame, const gchar *prefix)
    -{
    - gsize prefix_len = strlen(prefix);
    -
    - return (frame->href->len == (prefix_len + frame->text->len)) &&
    - !strncmp(frame->href->str, prefix, prefix_len) &&
    - purple_strequal(frame->href->str + prefix_len, frame->text->str);
    -}
    -
    -static gsize
    -html_to_zephyr_pop(GQueue *frames)
    -{
    - zframe *popped = (zframe *)g_queue_pop_head(frames);
    - zframe *head = (zframe *)g_queue_peek_head(frames);
    - gsize result = strlen(popped->closing);
    -
    - if (popped->is_href) {
    - head->href = popped->text;
    - } else {
    - g_string_append(head->text, popped->env);
    - if (popped->has_closer) {
    - g_string_append_c(head->text,
    - (popped->closer_mask & 1) ? '{' :
    - (popped->closer_mask & 2) ? '[' :
    - (popped->closer_mask & 4) ? '(' :
    - '<');
    - }
    - g_string_append(head->text, popped->text->str);
    - if (popped->href) {
    - if (!purple_strequal(popped->href->str, popped->text->str) &&
    - !zframe_href_has_prefix(popped, "http://") &&
    - !zframe_href_has_prefix(popped, "mailto:")) {
    - g_string_append(head->text, " <");
    - g_string_append(head->text, popped->href->str);
    - if (popped->closer_mask & ~8) {
    - g_string_append_c(head->text, '>');
    - popped->closer_mask &= ~8;
    - } else {
    - g_string_append(head->text, "@{>}");
    - }
    - }
    - g_string_free(popped->href, TRUE);
    - }
    - if (popped->has_closer) {
    - g_string_append_c(head->text,
    - (popped->closer_mask & 1) ? '}' :
    - (popped->closer_mask & 2) ? ']' :
    - (popped->closer_mask & 4) ? ')' :
    - '>');
    - }
    - if (!popped->has_closer) {
    - head->closer_mask = popped->closer_mask;
    - }
    - g_string_free(popped->text, TRUE);
    - }
    - g_free(popped);
    - return result;
    -}
    -
    -char *
    -html_to_zephyr(const char *message)
    -{
    - GQueue frames = G_QUEUE_INIT;
    - zframe *frame, *new_f;
    - char *ret;
    -
    - if (*message == '\0')
    - return g_strdup("");
    -
    - frame = zframe_new(NULL, FALSE);
    - frame->href = NULL;
    - frame->is_href = FALSE;
    - frame->env = "";
    - frame->closer_mask = 15;
    -
    - g_queue_push_head(&frames, frame);
    -
    - purple_debug_info("zephyr", "html received %s\n", message);
    - while (*message) {
    - frame = (zframe *)g_queue_peek_head(&frames);
    - if (frame->closing && purple_str_has_caseprefix(message, frame->closing)) {
    - message += html_to_zephyr_pop(&frames);
    - } else if (*message == '<') {
    - if (!g_ascii_strncasecmp(message + 1, "i>", 2)) {
    - new_f = zframe_new("</i>", TRUE);
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->env = "@i";
    - new_f->closer_mask = 15;
    - g_queue_push_head(&frames, new_f);
    - message += 3;
    - } else if (!g_ascii_strncasecmp(message + 1, "b>", 2)) {
    - new_f = zframe_new("</b>", TRUE);
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->env = "@b";
    - new_f->closer_mask = 15;
    - g_queue_push_head(&frames, new_f);
    - message += 3;
    - } else if (!g_ascii_strncasecmp(message + 1, "br>", 3)) {
    - g_string_append_c(frame->text, '\n');
    - message += 4;
    - } else if (!g_ascii_strncasecmp(message + 1, "a href=\"", 8)) {
    - message += 9;
    - new_f = zframe_new("</a>", FALSE);
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->env = "";
    - new_f->closer_mask = frame->closer_mask;
    - g_queue_push_head(&frames, new_f);
    - new_f = zframe_new("\">", FALSE);
    - new_f->href = NULL;
    - new_f->is_href = TRUE;
    - new_f->closer_mask = frame->closer_mask;
    - g_queue_push_head(&frames, new_f);
    - } else if (!g_ascii_strncasecmp(message + 1, "font", 4)) {
    - new_f = zframe_new("</font>", TRUE);
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->closer_mask = 15;
    - g_queue_push_head(&frames, new_f);
    - message += 5;
    - while (*message == ' ') {
    - message++;
    - }
    - if (!g_ascii_strncasecmp(message, "color=\"", 7)) {
    - message += 7;
    - new_f->env = "@";
    - new_f = zframe_new("\">", TRUE);
    - new_f->env = "@color";
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->closer_mask = 15;
    - g_queue_push_head(&frames, new_f);
    - } else if (!g_ascii_strncasecmp(message, "face=\"", 6)) {
    - message += 6;
    - new_f->env = "@";
    - new_f = zframe_new("\">", TRUE);
    - new_f->env = "@font";
    - new_f->href = NULL;
    - new_f->is_href = FALSE;
    - new_f->closer_mask = 15;
    - g_queue_push_head(&frames, new_f);
    - } else if (!g_ascii_strncasecmp(message, "size=\"", 6)) {
    - message += 6;
    - if ((*message == '1') || (*message == '2')) {
    - new_f->env = "@small";
    - } else if ((*message == '3') || (*message == '4')) {
    - new_f->env = "@medium";
    - } else if ((*message == '5') || (*message == '6')
    - || (*message == '7')) {
    - new_f->env = "@large";
    - } else {
    - new_f->env = "";
    - new_f->has_closer = FALSE;
    - new_f->closer_mask = frame->closer_mask;
    - }
    - message += 3;
    - } else {
    - /* Drop all unrecognized/misparsed font tags */
    - new_f->env = "";
    - new_f->has_closer = FALSE;
    - new_f->closer_mask = frame->closer_mask;
    - while (g_ascii_strncasecmp(message, "\">", 2) != 0) {
    - message++;
    - }
    - if (*message != '\0') {
    - message += 2;
    - }
    - }
    - } else {
    - /* Catch all for all unrecognized/misparsed <foo> tags */
    - g_string_append_c(frame->text, *message++);
    - }
    - } else if (*message == '@') {
    - g_string_append(frame->text, "@@");
    - message++;
    - } else if (*message == '}') {
    - if (frame->closer_mask & ~1) {
    - frame->closer_mask &= ~1;
    - g_string_append_c(frame->text, *message++);
    - } else {
    - g_string_append(frame->text, "@[}]");
    - message++;
    - }
    - } else if (*message == ']') {
    - if (frame->closer_mask & ~2) {
    - frame->closer_mask &= ~2;
    - g_string_append_c(frame->text, *message++);
    - } else {
    - g_string_append(frame->text, "@{]}");
    - message++;
    - }
    - } else if (*message == ')') {
    - if (frame->closer_mask & ~4) {
    - frame->closer_mask &= ~4;
    - g_string_append_c(frame->text, *message++);
    - } else {
    - g_string_append(frame->text, "@{)}");
    - message++;
    - }
    - } else if (!g_ascii_strncasecmp(message, "&gt;", 4)) {
    - if (frame->closer_mask & ~8) {
    - frame->closer_mask &= ~8;
    - g_string_append_c(frame->text, *message++);
    - } else {
    - g_string_append(frame->text, "@{>}");
    - message += 4;
    - }
    - } else {
    - g_string_append_c(frame->text, *message++);
    - }
    - }
    - frame = (zframe *)g_queue_pop_head(&frames);
    - ret = g_string_free(frame->text, FALSE);
    - g_free(frame);
    - purple_debug_info("zephyr", "zephyr outputted %s\n", ret);
    - return ret;
    -}
    -
    -static void
    -zephyr_to_html_pop(GQueue *frames, gboolean *last_had_closer)
    -{
    - zframe *popped = (zframe *)g_queue_pop_head(frames);
    - zframe *head = (zframe *)g_queue_peek_head(frames);
    -
    - g_string_append(head->text, popped->text->str);
    - g_string_append(head->text, popped->closing);
    -
    - if (last_had_closer != NULL) {
    - *last_had_closer = popped->has_closer;
    - }
    -
    - g_string_free(popped->text, TRUE);
    - g_free(popped);
    -}
    -
    -char *
    -zephyr_to_html(const char *message)
    -{
    - GQueue frames = G_QUEUE_INIT;
    - zframe *frame;
    - char *ret;
    -
    - frame = zframe_new("", FALSE);
    - frame->closer = NULL;
    -
    - g_queue_push_head(&frames, frame);
    -
    - while (*message) {
    - frame = (zframe *)g_queue_peek_head(&frames);
    - if (*message == '@' && message[1] == '@') {
    - g_string_append(frame->text, "@");
    - message += 2;
    - } else if (*message == '@') {
    - int end = 1;
    - while (message[end] && (isalnum(message[end]) || message[end] == '_')) {
    - end++;
    - }
    - if (message[end] &&
    - (message[end] == '{' || message[end] == '[' || message[end] == '(' ||
    - !g_ascii_strncasecmp(message + end, "&lt;", 4))) {
    - zframe *new_f;
    - char *buf;
    - char *closer;
    - buf = g_new0(char, end);
    - g_snprintf(buf, end, "%s", message + 1);
    - message += end;
    - closer = (*message == '{' ? "}" :
    - *message == '[' ? "]" :
    - *message == '(' ? ")" :
    - "&gt;");
    - message += (*message == '&' ? 4 : 1);
    - if (!g_ascii_strcasecmp(buf, "italic") || !g_ascii_strcasecmp(buf, "i")) {
    - new_f = zframe_new_with_text("<i>", "</i>", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "small")) {
    - new_f = zframe_new_with_text("<font size=\"1\">", "</font>", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "medium")) {
    - new_f = zframe_new_with_text("<font size=\"3\">", "</font>", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "large")) {
    - new_f = zframe_new_with_text("<font size=\"7\">", "</font>", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "bold")
    - || !g_ascii_strcasecmp(buf, "b")) {
    - new_f = zframe_new_with_text("<b>", "</b>", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "font")) {
    - zframe *extra_f;
    - extra_f = zframe_new("</font>", FALSE);
    - extra_f->closer = frame->closer;
    - g_queue_push_head(&frames, extra_f);
    - new_f = zframe_new_with_text("<font face=\"", "\">", TRUE);
    - } else if (!g_ascii_strcasecmp(buf, "color")) {
    - zframe *extra_f;
    - extra_f = zframe_new("</font>", FALSE);
    - extra_f->closer = frame->closer;
    - g_queue_push_head(&frames, extra_f);
    - new_f = zframe_new_with_text("<font color=\"", "\">", TRUE);
    - } else {
    - new_f = zframe_new("", TRUE);
    - }
    - new_f->closer = closer;
    - g_queue_push_head(&frames, new_f);
    - g_free(buf);
    - } else {
    - /* Not a formatting tag, add the character as normal. */
    - g_string_append_c(frame->text, *message++);
    - }
    - } else if (frame->closer && purple_str_has_caseprefix(message, frame->closer)) {
    - message += strlen(frame->closer);
    - if (g_queue_get_length(&frames) > 1) {
    - gboolean last_had_closer;
    -
    - do {
    - zephyr_to_html_pop(&frames, &last_had_closer);
    - } while (g_queue_get_length(&frames) > 1 && !last_had_closer);
    - } else {
    - g_string_append_c(frame->text, *message);
    - }
    - } else if (*message == '\n') {
    - g_string_append(frame->text, "<br>");
    - message++;
    - } else {
    - g_string_append_c(frame->text, *message++);
    - }
    - }
    - /* go through all the stuff that they didn't close */
    - while (g_queue_get_length(&frames) > 1) {
    - zephyr_to_html_pop(&frames, NULL);
    - }
    - frame = (zframe *)g_queue_pop_head(&frames);
    - ret = g_string_free(frame->text, FALSE);
    - g_free(frame);
    - return ret;
    -}
    --- a/libpurple/protocols/zephyr/zephyr_html.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,43 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_HTML_H
    -#define PURPLE_ZEPHYR_ZEPHYR_HTML_H
    -
    -/* This parses HTML formatting (put out by one of the gtkimhtml widgets
    - And converts it to zephyr formatting.
    - It currently deals properly with <b>, <br>, <i>, <font face=...>, <font color=...>,
    - It ignores <font back=...>
    - It does
    - <font size = "1 or 2" -> @small
    - 3 or 4 @medium()
    - 5,6, or 7 @large()
    - <a href is dealt with by outputting "description <link>" or just "description" as appropriate
    -*/
    -char *html_to_zephyr(const char *message);
    -
    -/* This parses zephyr formatting and converts it to html. For example, if
    - * you pass in "@{@color(blue)@i(hello)}" you should get out
    - * "<font color=blue><i>hello</i></font>". */
    -char *zephyr_to_html(const char *message);
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_HTML_H */
    --- a/libpurple/protocols/zephyr/zephyr_internal.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,370 +0,0 @@
    -/* This file is part of the Project Athena Zephyr Notification System.
    - * It contains global definitions
    - *
    - * Created by: Robert French
    - *
    - * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of
    - * Technology. For copying and distribution information, see the
    - * file "mit-copyright.h".
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_INTERNAL_H
    -#define PURPLE_ZEPHYR_ZEPHYR_INTERNAL_H
    -
    -#ifdef HAVE_CONFIG_H
    -# include <config.h>
    -#endif
    -
    -#include <glib.h>
    -#include <gio/gio.h>
    -
    -#include <sys/types.h>
    -#include <sys/time.h>
    -
    -#include <zephyr_err.h>
    -
    -#ifndef IPPROTO_MAX /* Make sure not already included */
    -#ifndef WIN32
    -#include <netinet/in.h>
    -#endif
    -#endif
    -
    -#include <stdarg.h>
    -
    -#ifdef WIN32
    -/* this really should be uint32_t */
    -/*typedef unsigned int in_addr_t;
    -struct in_addr
    -{
    - in_addr_t s_addr;
    -}; */
    -#include <winsock2.h>
    -#endif
    -
    -/* Service names */
    -#define HM_SVCNAME "zephyr-hm"
    -#define HM_SRV_SVCNAME "zephyr-hm-srv"
    -#define SERVER_SVCNAME "zephyr-clt"
    -#define SERVER_SERVICE "zephyr"
    -#define SERVER_INSTANCE "zephyr"
    -
    -#define ZVERSIONHDR "ZEPH"
    -#define ZVERSIONMAJOR 0
    -#define ZVERSIONMINOR 2
    -
    -#define Z_MAXPKTLEN 1024
    -#define Z_MAXHEADERLEN 800
    -#define Z_MAXOTHERFIELDS 10 /* Max unknown fields in ZNotice_t */
    -#define Z_NUMFIELDS 17
    -
    -/* Authentication levels returned by ZCheckAuthentication */
    -#define ZAUTH_FAILED (-1)
    -#define ZAUTH_YES 1
    -#define ZAUTH_NO 0
    -
    -#define SERVER_SVC_FALLBACK (2103)
    -#define HM_SVC_FALLBACK (2104)
    -#define HM_SRV_SVC_FALLBACK (2105)
    -
    -#define ZAUTH_UNSET (-3) /* Internal to client library. */
    -#define Z_MAXFRAGS 500 /* Max number of packet fragments */
    -#define Z_MAXNOTICESIZE 400000 /* Max size of incoming notice */
    -#define Z_MAXQUEUESIZE 1500000 /* Max size of input queue notices */
    -#define Z_FRAGFUDGE 13 /* Room to for multinotice field */
    -#define Z_NOTICETIMELIMIT 30 /* Time to wait for fragments */
    -#define Z_INITFILTERSIZE 30 /* Starting size of uid filter */
    -
    -typedef char ZPacket_t[Z_MAXPKTLEN];
    -
    -/* Packet type */
    -typedef enum {
    - UNSAFE, UNACKED, ACKED, HMACK, HMCTL, SERVACK, SERVNAK, CLIENTACK, STAT
    -} ZNotice_Kind_t;
    -
    -/* Unique ID format */
    -typedef struct {
    - guint32 zuid_addr;
    - struct timeval tv;
    -} ZUnique_Id_t;
    -
    -/* Checksum */
    -typedef unsigned long ZChecksum_t;
    -
    -/* Notice definition */
    -typedef struct {
    - char *z_packet;
    - char *z_version;
    - ZNotice_Kind_t z_kind;
    - ZUnique_Id_t z_uid;
    -#define z_sender_addr z_uid.zuid_addr
    - struct timeval z_time;
    - unsigned short z_port;
    - int z_auth;
    - int z_checked_auth;
    - int z_authent_len;
    - char *z_ascii_authent;
    - char *z_class;
    - const char *z_class_inst;
    - char *z_opcode;
    - char *z_sender;
    - const char *z_recipient;
    - char *z_default_format;
    - char *z_multinotice;
    - ZUnique_Id_t z_multiuid;
    - ZChecksum_t z_checksum;
    - int z_num_other_fields;
    - char *z_other_fields[Z_MAXOTHERFIELDS];
    - caddr_t z_message;
    - int z_message_len;
    -} ZNotice_t;
    -
    -/* Subscription structure */
    -typedef struct {
    - char *zsub_recipient;
    - char *zsub_class;
    - char *zsub_classinst;
    -} ZSubscription_t;
    -
    -/* Function return code */
    -typedef int Code_t;
    -
    -/* Locations structure */
    -typedef struct {
    - char *host;
    - char *time;
    - char *tty;
    -} ZLocations_t;
    -
    -typedef struct {
    - char *user;
    - ZUnique_Id_t uid;
    - char *version;
    -} ZAsyncLocateData_t;
    -
    -typedef struct {
    - gint first;
    - gint last;
    -} Z_Hole;
    -
    -typedef struct {
    - ZNotice_Kind_t kind;
    - gint64 time;
    - gint packet_len;
    - gchar *packet;
    - gboolean complete;
    - GSocketAddress *from;
    - GSList *holelist; /* element-type: Z_Hole* */
    - ZUnique_Id_t uid;
    - int auth;
    - gint header_len;
    - gchar *header;
    - gint msg_len;
    - gchar *msg;
    -} Z_InputQ;
    -
    -int ZCompareUIDPred(ZNotice_t *, void *);
    -int ZCompareMultiUIDPred(ZNotice_t *, void *);
    -
    -/* Defines for ZFormatNotice, et al. */
    -typedef Code_t (*Z_AuthProc)(ZNotice_t *, char *, int, int *);
    -Code_t ZMakeAuthentication(ZNotice_t *, char *, int, int *);
    -
    -char *ZGetSender(void);
    -const gchar *ZGetVariable(const gchar *);
    -Code_t ZSetVariable(char *var, char *value);
    -Code_t ZUnsetVariable(char *var);
    -int ZGetWGPort(void);
    -Code_t ZSetDestAddr(GSocketAddress *);
    -Code_t ZFormatNoticeList(ZNotice_t *, char **, int, char **, int *, Z_AuthProc);
    -Code_t ZParseNotice(char *, int, ZNotice_t *);
    -Code_t ZReadAscii(char *, int, unsigned char *, int);
    -Code_t ZReadAscii32(char *, int, unsigned long *);
    -Code_t ZReadAscii16(char *, int, unsigned short *);
    -Code_t ZSendPacket(char *, int, int);
    -Code_t ZSendList(ZNotice_t *, char *[], int, Z_AuthProc);
    -Code_t ZSrvSendList(ZNotice_t *, char *[], int, Z_AuthProc, Code_t (*)());
    -Code_t ZSendNotice(ZNotice_t *, Z_AuthProc);
    -Code_t ZSrvSendNotice(ZNotice_t *, Z_AuthProc, Code_t (*)());
    -Code_t ZFormatNotice(ZNotice_t *, char **, int *, Z_AuthProc);
    -Code_t ZFormatSmallNotice(ZNotice_t *, ZPacket_t, int *, Z_AuthProc);
    -Code_t ZFormatRawNoticeList(ZNotice_t *notice, char *list[], int nitems,
    - char **buffer, int *ret_len);
    -Code_t ZLocateUser(char *, int *, Z_AuthProc);
    -Code_t ZRequestLocations(const char *, ZAsyncLocateData_t *, ZNotice_Kind_t,
    - Z_AuthProc);
    -Code_t ZhmStat(ZNotice_t *);
    -Code_t ZInitialize(void);
    -Code_t ZFormatSmallRawNotice(ZNotice_t *, ZPacket_t, int *);
    -int ZCompareUID(ZUnique_Id_t *, ZUnique_Id_t *);
    -Code_t ZMakeAscii(char *, int, unsigned char *, int);
    -Code_t ZMakeAscii32(char *, int, unsigned long);
    -Code_t ZMakeAscii16(char *, int, unsigned int);
    -Code_t ZReceivePacket(ZPacket_t, int *, GSocketAddress **);
    -Code_t ZCheckAuthentication(ZNotice_t *);
    -Code_t ZSetLocation(char *exposure);
    -Code_t ZUnsetLocation(void);
    -Code_t ZFlushMyLocations(void);
    -Code_t ZFormatRawNotice(ZNotice_t *, char **, int *);
    -Code_t ZRetrieveSubscriptions(unsigned short, int *);
    -Code_t ZGetSubscriptions(ZSubscription_t *, int *);
    -Code_t ZOpenPort(unsigned short *port);
    -Code_t ZClosePort(void);
    -Code_t ZFlushLocations(void);
    -Code_t ZFlushSubscriptions(void);
    -Code_t ZFreeNotice(ZNotice_t *notice);
    -Code_t ZGetLocations(ZLocations_t *, int *);
    -Code_t ZParseLocations(register ZNotice_t *notice,
    - register ZAsyncLocateData_t *zald, int *nlocs,
    - char **user);
    -int ZCompareALDPred(ZNotice_t *notice, void *zald);
    -void ZFreeALD(register ZAsyncLocateData_t *zald);
    -Code_t ZCheckIfNotice(ZNotice_t *notice, GSocketAddress **from,
    - register int (*predicate)(ZNotice_t *, void *),
    - void *args);
    -Code_t ZPeekPacket(char **buffer, int *ret_len, GSocketAddress **from);
    -Code_t ZPeekNotice(ZNotice_t *notice, GSocketAddress **from);
    -Code_t ZIfNotice(ZNotice_t *notice, GSocketAddress **from,
    - int (*predicate)(ZNotice_t *, void *), void *args);
    -Code_t ZSubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port);
    -Code_t ZSubscribeToSansDefaults(ZSubscription_t *sublist, int nitems,
    - unsigned int port);
    -Code_t ZUnsubscribeTo(ZSubscription_t *sublist, int nitems, unsigned int port);
    -Code_t ZCancelSubscriptions(unsigned int port);
    -int ZPending(void);
    -Code_t ZReceiveNotice(ZNotice_t *notice, GSocketAddress **from);
    -
    -typedef Code_t (*Z_SendProc)(ZNotice_t *, char *, int, int);
    -
    -Z_InputQ *Z_GetFirstComplete(void);
    -Z_InputQ *Z_GetNextComplete(Z_InputQ *);
    -Code_t Z_XmitFragment(ZNotice_t *, char *, int, int);
    -void Z_RemQueue(Z_InputQ *);
    -Code_t Z_AddNoticeToEntry(Z_InputQ *, ZNotice_t *, int);
    -Code_t Z_FormatAuthHeader(ZNotice_t *, char *, int, int *, Z_AuthProc);
    -Code_t Z_FormatHeader(ZNotice_t *, char *, int, int *, Z_AuthProc);
    -Code_t Z_FormatRawHeader(ZNotice_t *, char *, gsize, int *, char **, char **);
    -Code_t Z_ReadEnqueue(void);
    -Code_t Z_ReadWait(void);
    -Code_t Z_SendLocation(char *, char *, Z_AuthProc, char *);
    -Code_t Z_SendFragmentedNotice(ZNotice_t *notice, int len, Z_AuthProc cert_func,
    - Z_SendProc send_func);
    -Code_t Z_WaitForComplete(void);
    -Code_t Z_WaitForNotice(ZNotice_t *notice, int (*pred)(ZNotice_t *, void *),
    - void *arg, int timeout);
    -
    -extern GQueue Z_input_queue;
    -
    -extern ZLocations_t *__locate_list;
    -extern int __locate_num;
    -extern int __locate_next;
    -
    -extern ZSubscription_t *__subscriptions_list;
    -extern int __subscriptions_num;
    -extern int __subscriptions_next;
    -
    -extern gint __Zephyr_port; /* Port number */
    -extern guint32 __My_addr;
    -
    -/* Macros to retrieve Zephyr library values. */
    -extern GSocket *__Zephyr_socket;
    -extern int __Q_CompleteLength;
    -extern GSocketAddress *__HM_addr;
    -extern char __Zephyr_realm[];
    -#define ZGetSocket() __Zephyr_socket
    -#define ZQLength() __Q_CompleteLength
    -#define ZGetDestAddr() __HM_addr
    -#define ZGetRealm() __Zephyr_realm
    -
    -/* Maximum queue length */
    -#define Z_MAXQLEN 30
    -
    -/* Successful function return */
    -#define ZERR_NONE 0
    -
    -/* Hostmanager wait time (in secs) */
    -#define HM_TIMEOUT 1
    -
    -/* Server wait time (in secs) */
    -#define SRV_TIMEOUT 30
    -
    -#define ZAUTH (ZMakeAuthentication)
    -#define ZNOAUTH ((Z_AuthProc)0)
    -
    -/* Packet strings */
    -#define ZSRVACK_SENT "SENT" /* SERVACK codes */
    -#define ZSRVACK_NOTSENT "LOST"
    -#define ZSRVACK_FAIL "FAIL"
    -
    -/* Server internal class */
    -#define ZEPHYR_ADMIN_CLASS "ZEPHYR_ADMIN" /* Class */
    -
    -/* Control codes sent to a server */
    -#define ZEPHYR_CTL_CLASS "ZEPHYR_CTL" /* Class */
    -
    -#define ZEPHYR_CTL_CLIENT "CLIENT" /* Inst: From client */
    -#define CLIENT_SUBSCRIBE "SUBSCRIBE" /* Opcode: Subscribe */
    -#define CLIENT_SUBSCRIBE_NODEFS "SUBSCRIBE_NODEFS" /* Opcode: Subscribe */
    -#define CLIENT_UNSUBSCRIBE "UNSUBSCRIBE" /* Opcode: Unsubsubscribe */
    -#define CLIENT_CANCELSUB "CLEARSUB" /* Opcode: Clear all subs */
    -#define CLIENT_GIMMESUBS "GIMME" /* Opcode: Give me subs */
    -#define CLIENT_GIMMEDEFS "GIMMEDEFS" /* Opcode: Give me default
    - * subscriptions */
    -
    -#define ZEPHYR_CTL_HM "HM" /* Inst: From HM */
    -#define HM_BOOT "BOOT" /* Opcode: Boot msg */
    -#define HM_FLUSH "FLUSH" /* Opcode: Flush me */
    -#define HM_DETACH "DETACH" /* Opcode: Detach me */
    -#define HM_ATTACH "ATTACH" /* Opcode: Attach me */
    -
    -/* Control codes send to a HostManager */
    -#define HM_CTL_CLASS "HM_CTL" /* Class */
    -
    -#define HM_CTL_SERVER "SERVER" /* Inst: From server */
    -#define SERVER_SHUTDOWN "SHUTDOWN" /* Opcode: Server shutdown */
    -#define SERVER_PING "PING" /* Opcode: PING */
    -
    -#define HM_CTL_CLIENT "CLIENT" /* Inst: From client */
    -#define CLIENT_FLUSH "FLUSH" /* Opcode: Send flush to srv */
    -#define CLIENT_NEW_SERVER "NEWSERV" /* Opcode: Find new server */
    -
    -/* HM Statistics */
    -#define HM_STAT_CLASS "HM_STAT" /* Class */
    -
    -#define HM_STAT_CLIENT "HMST_CLIENT" /* Inst: From client */
    -#define HM_GIMMESTATS "GIMMESTATS" /* Opcode: get stats */
    -
    -/* Login class messages */
    -#define LOGIN_CLASS "LOGIN" /* Class */
    -
    -/* Class Instance is principal of user who is logging in or logging out */
    -
    -#define EXPOSE_NONE "NONE" /* Opcode: Not visible */
    -#define EXPOSE_OPSTAFF "OPSTAFF" /* Opcode: Opstaff visible */
    -#define EXPOSE_REALMVIS "REALM-VISIBLE" /* Opcode: Realm visible */
    -#define EXPOSE_REALMANN "REALM-ANNOUNCED"/* Opcode: Realm announced */
    -#define EXPOSE_NETVIS "NET-VISIBLE" /* Opcode: Net visible */
    -#define EXPOSE_NETANN "NET-ANNOUNCED" /* Opcode: Net announced */
    -#define LOGIN_USER_LOGIN "USER_LOGIN" /* Opcode: user login
    - (from server) */
    -#define LOGIN_USER_LOGOUT "USER_LOGOUT" /* Opcode: User logout */
    -#define LOGIN_USER_FLUSH "USER_FLUSH" /* Opcode: flush all locs */
    -
    -/* Locate class messages */
    -#define LOCATE_CLASS "USER_LOCATE" /* Class */
    -
    -#define LOCATE_HIDE "USER_HIDE" /* Opcode: Hide me */
    -#define LOCATE_UNHIDE "USER_UNHIDE" /* Opcode: Unhide me */
    -
    -/* Class Instance is principal of user to locate */
    -#define LOCATE_LOCATE "LOCATE" /* Opcode: Locate user */
    -
    -/* WG_CTL class messages */
    -#define WG_CTL_CLASS "WG_CTL" /* Class */
    -
    -#define WG_CTL_USER "USER" /* Inst: User request */
    -#define USER_REREAD "REREAD" /* Opcode: Reread desc file */
    -#define USER_SHUTDOWN "SHUTDOWN" /* Opcode: Go catatonic */
    -#define USER_STARTUP "STARTUP" /* Opcode: Come out of it */
    -#define USER_EXIT "EXIT" /* Opcode: Exit the client */
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_INTERNAL_H */
    --- a/libpurple/protocols/zephyr/zephyr_tzc.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,619 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#include <glib/gi18n-lib.h>
    -
    -#include "zephyr_tzc.h"
    -
    -#define MAXCHILDREN 20
    -
    -typedef gssize (*PollableInputStreamReadFunc)(GPollableInputStream *stream, void *bufcur, GError **error);
    -
    -static gboolean tzc_write(zephyr_account *zephyr, const gchar *format, ...) G_GNUC_PRINTF(2, 3);
    -
    -static gchar *
    -tzc_read(zephyr_account *zephyr, PollableInputStreamReadFunc read_func)
    -{
    - GPollableInputStream *stream = G_POLLABLE_INPUT_STREAM(zephyr->tzc_stdout);
    - gsize bufsize = 2048;
    - gchar *buf = g_new(gchar, bufsize);
    - gchar *bufcur = buf;
    - gboolean selected = FALSE;
    -
    - while (TRUE) {
    - GError *error = NULL;
    - if (read_func(stream, bufcur, &error) < 0) {
    - if (error->code == G_IO_ERROR_WOULD_BLOCK ||
    - error->code == G_IO_ERROR_TIMED_OUT) {
    - g_error_free(error);
    - break;
    - }
    - purple_debug_error("zephyr", "couldn't read: %s", error->message);
    - purple_connection_error(purple_account_get_connection(zephyr->account), PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "couldn't read");
    - g_error_free(error);
    - g_free(buf);
    - return NULL;
    - }
    - selected = TRUE;
    - bufcur++;
    - if ((bufcur - buf) > (bufsize - 1)) {
    - if ((buf = g_realloc(buf, bufsize * 2)) == NULL) {
    - purple_debug_error("zephyr","Ran out of memory\n");
    - exit(-1);
    - } else {
    - bufcur = buf + bufsize;
    - bufsize *= 2;
    - }
    - }
    - }
    - *bufcur = '\0';
    -
    - if (!selected) {
    - g_free(buf);
    - buf = NULL;
    - }
    - return buf;
    -}
    -
    -static gboolean
    -tzc_write(zephyr_account *zephyr, const gchar *format, ...)
    -{
    - va_list args;
    - gchar *message;
    - GError *error = NULL;
    - gboolean success;
    -
    - va_start(args, format);
    - message = g_strdup_vprintf(format, args);
    - va_end(args);
    -
    - success = g_output_stream_write_all(zephyr->tzc_stdin, message, strlen(message),
    - NULL, NULL, &error);
    - if (!success) {
    - purple_debug_error("zephyr", "Unable to write a message: %s", error->message);
    - g_error_free(error);
    - }
    - g_free(message);
    - return success;
    -}
    -
    -/* Munge the outgoing zephyr so that any quotes or backslashes are
    - escaped and do not confuse tzc: */
    -static char *
    -tzc_escape_msg(const char *message)
    -{
    - gsize msglen;
    - char *newmsg;
    -
    - if (!message || !*message) {
    - return g_strdup("");
    - }
    -
    - msglen = strlen(message);
    - newmsg = g_new0(char, msglen*2 + 1);
    - for (gsize pos = 0, pos2 = 0; pos < msglen; pos++, pos2++) {
    - if (message[pos] == '\\' || message[pos] == '"') {
    - newmsg[pos2] = '\\';
    - pos2++;
    - }
    - newmsg[pos2] = message[pos];
    - }
    -
    - return newmsg;
    -}
    -
    -static char *
    -tzc_deescape_str(const char *message)
    -{
    - gsize msglen;
    - char *newmsg;
    -
    - if (!message || !*message) {
    - return g_strdup("");
    - }
    -
    - msglen = strlen(message);
    - newmsg = g_new0(char, msglen + 1);
    - for (gsize pos = 0, pos2 = 0; pos < msglen; pos++, pos2++) {
    - if (message[pos] == '\\') {
    - pos++;
    - }
    - newmsg[pos2] = message[pos];
    - }
    -
    - return newmsg;
    -}
    -
    -static GSubprocess *
    -get_tzc_process(const zephyr_account *zephyr)
    -{
    - GSubprocess *tzc_process = NULL;
    - const gchar *tzc_cmd;
    - gchar **tzc_cmd_array = NULL;
    - GError *error = NULL;
    - gboolean found_ps = FALSE;
    - gint i;
    -
    - /* tzc_command should really be of the form
    - path/to/tzc -e %s
    - or
    - ssh username@hostname pathtotzc -e %s
    - -- this should not require a password, and ideally should be
    - kerberized ssh --
    - or
    - fsh username@hostname pathtotzc -e %s
    - */
    - tzc_cmd = purple_account_get_string(zephyr->account, "tzc_command", "/usr/bin/tzc -e %s");
    - if (!g_shell_parse_argv(tzc_cmd, NULL, &tzc_cmd_array, &error)) {
    - purple_debug_error("zephyr", "Unable to parse tzc_command: %s", error->message);
    - purple_connection_error(
    - purple_account_get_connection(zephyr->account),
    - PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
    - "invalid tzc_command setting");
    - g_error_free(error);
    - return NULL;
    - }
    - for (i = 0; tzc_cmd_array[i] != NULL; i++) {
    - if (purple_strequal(tzc_cmd_array[i], "%s")) {
    - g_free(tzc_cmd_array[i]);
    - tzc_cmd_array[i] = g_strdup(zephyr->exposure);
    - found_ps = TRUE;
    - }
    - }
    -
    - if (!found_ps) {
    - purple_debug_error("zephyr", "tzc exited early");
    - purple_connection_error(
    - purple_account_get_connection(zephyr->account),
    - PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "invalid output by tzc (or bad parsing code)");
    - g_strfreev(tzc_cmd_array);
    - return NULL;
    - }
    -
    - tzc_process = g_subprocess_newv(
    - (const gchar *const *)tzc_cmd_array,
    - G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
    - &error);
    - if (tzc_process == NULL) {
    - purple_debug_error("zephyr", "tzc exited early: %s", error->message);
    - purple_connection_error(
    - purple_account_get_connection(zephyr->account),
    - PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "invalid output by tzc (or bad parsing code)");
    - g_error_free(error);
    - }
    -
    - g_strfreev(tzc_cmd_array);
    - return tzc_process;
    -}
    -
    -static gssize
    -pollable_input_stream_read(GPollableInputStream *stream, void *bufcur, GError **error)
    -{
    - return g_pollable_input_stream_read_nonblocking(stream, bufcur, 1, NULL, error);
    -}
    -
    -static gssize
    -pollable_input_stream_read_with_timeout(GPollableInputStream *stream,
    - void *bufcur, GError **error)
    -{
    - const gint64 timeout = 10 * G_USEC_PER_SEC;
    - gint64 now = g_get_monotonic_time();
    -
    - while (g_get_monotonic_time() < now + timeout) {
    - GError *local_error = NULL;
    - gssize ret = g_pollable_input_stream_read_nonblocking(
    - stream, bufcur, 1, NULL, &local_error);
    - if (ret == 1) {
    - return ret;
    - }
    - if (local_error->code != G_IO_ERROR_WOULD_BLOCK) {
    - g_propagate_error(error, local_error);
    - return ret;
    - }
    - /* Keep on waiting if this is a blocking error. */
    - g_clear_error(&local_error);
    - }
    -
    - g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
    - "tzc did not respond in time");
    - return -1;
    -}
    -
    -static gint
    -get_paren_level(gint paren_level, gchar ch)
    -{
    - switch (ch) {
    - case '(': return paren_level + 1;
    - case ')': return paren_level - 1;
    - default: return paren_level;
    - }
    -}
    -
    -static void
    -parse_tzc_login_data(zephyr_account *zephyr, const gchar *buf, gint buflen)
    -{
    - gchar *str = g_strndup(buf, buflen);
    -
    - purple_debug_info("zephyr", "tempstr parsed");
    -
    - /* str should now be a string containing all characters from
    - * buf after the first ( to the one before the last paren ).
    - * We should have the following possible lisp strings but we don't care
    - * (tzcspew . start) (version . "something") (pid . number)
    - * We care about 'zephyrid . "username@REALM.NAME"' and
    - * 'exposure . "SOMETHING"' */
    - if (!g_ascii_strncasecmp(str, "zephyrid", 8)) {
    - gchar **strv;
    - gchar *username;
    - const char *at;
    -
    - purple_debug_info("zephyr", "zephyrid found");
    -
    - strv = g_strsplit(str + 8, "\"", -1);
    - username = strv[1] ? strv[1] : "";
    - zephyr->username = g_strdup(username);
    -
    - at = strchr(username, '@');
    - if (at != NULL) {
    - zephyr->realm = g_strdup(at + 1);
    - } else {
    - zephyr->realm = get_zephyr_realm(zephyr->account, "local-realm");
    - }
    -
    - g_strfreev(strv);
    - } else {
    - purple_debug_info("zephyr", "something that's not zephyr id found %s", str);
    - }
    -
    - /* We don't care about anything else yet */
    - g_free(str);
    -}
    -
    -static gchar *
    -tree_child_contents(GNode *tree, int index)
    -{
    - GNode *child = g_node_nth_child(tree, index);
    - return child ? child->data : "";
    -}
    -
    -static GNode *
    -find_node(GNode *ptree, gchar *key)
    -{
    - guint num_children;
    - gchar* tc;
    -
    - if (!ptree || ! key)
    - return NULL;
    -
    - num_children = g_node_n_children(ptree);
    - tc = tree_child_contents(ptree, 0);
    -
    - /* g_strcasecmp() is deprecated. What is the encoding here??? */
    - if (num_children > 0 && tc && !g_ascii_strcasecmp(tc, key)) {
    - return ptree;
    - } else {
    - GNode *result = NULL;
    - guint i;
    - for (i = 0; i < num_children; i++) {
    - result = find_node(g_node_nth_child(ptree, i), key);
    - if(result != NULL) {
    - break;
    - }
    - }
    - return result;
    - }
    -}
    -
    -static GNode *
    -parse_buffer(const gchar *source, gboolean do_parse)
    -{
    - GNode *ptree = g_node_new(NULL);
    -
    - if (do_parse) {
    - unsigned int p = 0;
    - while(p < strlen(source)) {
    - unsigned int end;
    - gchar *newstr;
    -
    - /* Eat white space: */
    - if(g_ascii_isspace(source[p]) || source[p] == '\001') {
    - p++;
    - continue;
    - }
    -
    - /* Skip comments */
    - if(source[p] == ';') {
    - while(source[p] != '\n' && p < strlen(source)) {
    - p++;
    - }
    - continue;
    - }
    -
    - if(source[p] == '(') {
    - int nesting = 0;
    - gboolean in_quote = FALSE;
    - gboolean escape_next = FALSE;
    - p++;
    - end = p;
    - while(!(source[end] == ')' && nesting == 0 && !in_quote) && end < strlen(source)) {
    - if(!escape_next) {
    - if(source[end] == '\\') {
    - escape_next = TRUE;
    - }
    - if(!in_quote) {
    - nesting = get_paren_level(nesting, source[end]);
    - }
    - if(source[end] == '"') {
    - in_quote = !in_quote;
    - }
    - } else {
    - escape_next = FALSE;
    - }
    - end++;
    - }
    - do_parse = TRUE;
    -
    - } else {
    - gchar end_char;
    - if(source[p] == '"') {
    - end_char = '"';
    - p++;
    - } else {
    - end_char = ' ';
    - }
    - do_parse = FALSE;
    -
    - end = p;
    - while(source[end] != end_char && end < strlen(source)) {
    - if(source[end] == '\\')
    - end++;
    - end++;
    - }
    - }
    - newstr = g_new0(gchar, end+1-p);
    - strncpy(newstr,source+p,end-p);
    - if (g_node_n_children(ptree) < MAXCHILDREN) {
    - /* In case we surpass maxchildren, ignore this */
    - g_node_append(ptree, parse_buffer(newstr, do_parse));
    - } else {
    - purple_debug_error("zephyr","too many children in tzc output. skipping\n");
    - }
    - g_free(newstr);
    - p = end + 1;
    - }
    - } else {
    - /* XXX does this have to be strdup'd */
    - ptree->data = g_strdup(source);
    - }
    -
    - return ptree;
    -}
    -
    -gboolean
    -tzc_login(zephyr_account *zephyr)
    -{
    - gchar *buf = NULL;
    - const gchar *bufend = NULL;
    - const gchar *ptr;
    - const gchar *tmp;
    - gint parenlevel = 0;
    -
    - zephyr->tzc_proc = get_tzc_process(zephyr);
    - if (zephyr->tzc_proc == NULL) {
    - return FALSE;
    - }
    - zephyr->tzc_stdin = g_subprocess_get_stdin_pipe(zephyr->tzc_proc);
    - zephyr->tzc_stdout = g_subprocess_get_stdout_pipe(zephyr->tzc_proc);
    -
    - purple_debug_info("zephyr", "about to read from tzc");
    - buf = tzc_read(zephyr, pollable_input_stream_read_with_timeout);
    - if (buf == NULL) {
    - return FALSE;
    - }
    - bufend = buf + strlen(buf);
    - ptr = buf;
    -
    - /* ignore all tzcoutput till we've received the first ( */
    - while (ptr < bufend && (*ptr != '(')) {
    - ptr++;
    - }
    - if (ptr >= bufend) {
    - purple_connection_error(
    - purple_account_get_connection(zephyr->account),
    - PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "invalid output by tzc (or bad parsing code)");
    - g_free(buf);
    - return FALSE;
    - }
    -
    - do {
    - parenlevel = get_paren_level(parenlevel, *ptr);
    - purple_debug_info("zephyr", "tzc parenlevel is %d", parenlevel);
    - switch (parenlevel) {
    - case 1:
    - /* Search for next beginning (, or for the ending */
    - do {
    - ptr++;
    - } while ((ptr < bufend) && (*ptr != '(') && (*ptr != ')'));
    - if (ptr >= bufend) {
    - purple_debug_error("zephyr", "tzc parsing error");
    - }
    - break;
    - case 2:
    - /* You are probably at
    - (foo . bar ) or (foo . "bar") or (foo . chars) or (foo . numbers) or (foo . () )
    - Parse all the data between the first and last f, and move past )
    - */
    - tmp = ptr;
    - do {
    - ptr++;
    - parenlevel = get_paren_level(parenlevel, *ptr);
    - } while (parenlevel > 1);
    - parse_tzc_login_data(zephyr, tmp + 1, ptr - tmp);
    - ptr++;
    - break;
    - default:
    - purple_debug_info("zephyr", "parenlevel is not 1 or 2");
    - /* This shouldn't be happening */
    - break;
    - }
    - } while (ptr < bufend && parenlevel != 0);
    - purple_debug_info("zephyr", "tzc startup done");
    - g_free(buf);
    -
    - return TRUE;
    -}
    -
    -gint
    -tzc_check_notify(gpointer data)
    -{
    - PurpleConnection *gc = (PurpleConnection *)data;
    - zephyr_account* zephyr = purple_connection_get_protocol_data(gc);
    - GNode *newparsetree = NULL;
    - gchar *buf = tzc_read(zephyr, pollable_input_stream_read);
    -
    - if (buf != NULL) {
    - newparsetree = parse_buffer(buf, TRUE);
    - g_free(buf);
    - }
    -
    - if (newparsetree != NULL) {
    - gchar *spewtype;
    - if ( (spewtype = tree_child_contents(find_node(newparsetree, "tzcspew"), 2)) ) {
    - if (!g_ascii_strncasecmp(spewtype,"message",7)) {
    - ZNotice_t notice;
    - GNode *msgnode = g_node_nth_child(find_node(newparsetree, "message"), 2);
    - /*char *zsig = g_strdup(" ");*/ /* purple doesn't care about zsigs */
    - char *msg = tzc_deescape_str(tree_child_contents(msgnode, 1));
    - char *buf = g_strdup_printf(" %c%s", '\0', msg);
    - memset((char *)&notice, 0, sizeof(notice));
    - notice.z_kind = ACKED;
    - notice.z_port = 0;
    - notice.z_opcode = tree_child_contents(find_node(newparsetree, "opcode"), 2);
    - notice.z_class = tzc_deescape_str(tree_child_contents(find_node(newparsetree, "class"), 2));
    - notice.z_class_inst = tree_child_contents(find_node(newparsetree, "instance"), 2);
    - notice.z_recipient = zephyr_normalize_local_realm(zephyr, tree_child_contents(find_node(newparsetree, "recipient"), 2));
    - notice.z_sender = zephyr_normalize_local_realm(zephyr, tree_child_contents(find_node(newparsetree, "sender"), 2));
    - notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2";
    - notice.z_message_len = 1 + 1 + strlen(msg) + 1;
    - notice.z_message = buf;
    - handle_message(gc, &notice);
    - g_free(msg);
    - /*g_free(zsig);*/
    - g_free(buf);
    - }
    - else if (!g_ascii_strncasecmp(spewtype,"zlocation",9)) {
    - /* check_loc or zephyr_zloc respectively */
    - /* XXX fix */
    - GNode *locations = g_node_nth_child(g_node_nth_child(find_node(newparsetree, "locations"), 2), 0);
    - ZLocations_t zloc = {
    - .host = tree_child_contents(g_node_nth_child(locations, 0), 2),
    - .time = tree_child_contents(g_node_nth_child(locations, 2), 2),
    - .tty = NULL
    - };
    -
    - handle_locations(gc, tree_child_contents(find_node(newparsetree, "user"), 2),
    - (zloc.host && *zloc.host && !purple_strequal(zloc.host, " ")) ? 1 : 0,
    - &zloc);
    - }
    - else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) {
    - }
    - else if (!g_ascii_strncasecmp(spewtype,"start",5)) {
    - }
    - else if (!g_ascii_strncasecmp(spewtype,"error",5)) {
    - /* XXX handle */
    - }
    - } else {
    - }
    - } else {
    - }
    -
    - g_node_destroy(newparsetree);
    - return TRUE;
    -}
    -
    -gboolean
    -tzc_subscribe_to(zephyr_account *zephyr, ZSubscription_t *sub)
    -{
    - /* ((tzcfodder . subscribe) ("class" "instance" "recipient")) */
    - return tzc_write(zephyr, "((tzcfodder . subscribe) (\"%s\" \"%s\" \"%s\"))\n",
    - sub->zsub_class, sub->zsub_classinst, sub->zsub_recipient);
    -}
    -
    -gboolean
    -tzc_request_locations(zephyr_account *zephyr, gchar *who)
    -{
    - return tzc_write(zephyr, "((tzcfodder . zlocate) \"%s\")\n", who);
    -}
    -
    -gboolean
    -tzc_send_message(zephyr_account *zephyr, gchar *zclass, gchar *instance, gchar *recipient,
    - const gchar *html_buf, const gchar *sig, G_GNUC_UNUSED const gchar *opcode)
    -{
    - /* CMU cclub tzc doesn't grok opcodes for now */
    - char *tzc_sig = tzc_escape_msg(sig);
    - char *tzc_body = tzc_escape_msg(html_buf);
    - gboolean result;
    -
    - result = tzc_write(zephyr, "((tzcfodder . send) (class . \"%s\") (auth . t) (recipients (\"%s\" . \"%s\")) (message . (\"%s\" \"%s\")) ) \n",
    - zclass, instance, recipient, tzc_sig, tzc_body);
    - g_free(tzc_sig);
    - g_free(tzc_body);
    - return result;
    -}
    -
    -void
    -tzc_set_location(zephyr_account *zephyr, char *exposure)
    -{
    - tzc_write(zephyr, "((tzcfodder . set-location) (hostname . \"%s\") (exposure . \"%s\"))\n",
    - zephyr->ourhost, exposure);
    -}
    -
    -void
    -tzc_get_subs_from_server(G_GNUC_UNUSED zephyr_account *zephyr, PurpleConnection *gc)
    -{
    - /* XXX fix */
    - purple_notify_error(gc, "", "tzc doesn't support this action",
    - NULL, purple_request_cpar_from_connection(gc));
    -}
    -
    -void
    -tzc_close(zephyr_account *zephyr)
    -{
    -#ifdef G_OS_UNIX
    - GError *error = NULL;
    - g_subprocess_send_signal(zephyr->tzc_proc, SIGTERM);
    - if (!g_subprocess_wait(zephyr->tzc_proc, NULL, &error)) {
    - purple_debug_error("zephyr",
    - "error while attempting to close tzc: %s",
    - error->message);
    - g_error_free(error);
    - }
    -#else
    - g_subprocess_force_exit(zephyr->tzc_proc);
    -#endif
    - zephyr->tzc_stdin = NULL;
    - zephyr->tzc_stdout = NULL;
    - g_clear_object(&zephyr->tzc_proc);
    -}
    --- a/libpurple/protocols/zephyr/zephyr_tzc.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,38 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_TZC_H
    -#define PURPLE_ZEPHYR_ZEPHYR_TZC_H
    -
    -#include "zephyr_account.h"
    -
    -gboolean tzc_login(zephyr_account *zephyr);
    -gint tzc_check_notify(gpointer data);
    -gboolean tzc_subscribe_to(zephyr_account *zephyr, ZSubscription_t *sub);
    -gboolean tzc_request_locations(zephyr_account *zephyr, gchar *who);
    -gboolean tzc_send_message(zephyr_account *zephyr, gchar *zclass, gchar *instance, gchar *recipient,
    - const gchar *html_buf, const gchar *sig, const gchar *opcode);
    -void tzc_set_location(zephyr_account *zephyr, char *exposure);
    -void tzc_get_subs_from_server(zephyr_account *zephyr, PurpleConnection *gc);
    -void tzc_close(zephyr_account *zephyr);
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_TZC_H */
    --- a/libpurple/protocols/zephyr/zephyr_zeph02.c Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,241 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#include <glib/gi18n-lib.h>
    -
    -#include "zephyr_zeph02.h"
    -
    -gboolean
    -zeph02_login(zephyr_account *zephyr)
    -{
    - PurpleConnection *pc = purple_account_get_connection(zephyr->account);
    -
    - /* XXX Should actually try to report the com_err determined error */
    - if (ZInitialize() != ZERR_NONE) {
    - purple_connection_error(pc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "Couldn't initialize zephyr");
    - return FALSE;
    - }
    -
    - if (ZOpenPort(&(zephyr->port)) != ZERR_NONE) {
    - purple_connection_error(pc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "Couldn't open port");
    - return FALSE;
    - }
    -
    - if (ZSetLocation(zephyr->exposure) != ZERR_NONE) {
    - purple_connection_error(pc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
    - "Couldn't set location");
    - return FALSE;
    - }
    -
    - zephyr->username = g_strdup(ZGetSender());
    - zephyr->realm = get_zephyr_realm(zephyr->account, ZGetRealm());
    -
    - return TRUE;
    -}
    -
    -/* Called when the server notifies us a message couldn't get sent */
    -static void
    -message_failed(PurpleConnection *gc, ZNotice_t *notice)
    -{
    - const gchar *title;
    - gchar *notify_msg;
    -
    - if (g_ascii_strcasecmp(notice->z_class, "message")) {
    - title = "";
    - notify_msg = g_strdup_printf(_("Unable to send to chat %s,%s,%s"),
    - notice->z_class, notice->z_class_inst, notice->z_recipient);
    - } else {
    - title = notice->z_recipient;
    - notify_msg = g_strdup(_("User is offline"));
    - }
    - purple_notify_error(gc, title, notify_msg, NULL, purple_request_cpar_from_connection(gc));
    - g_free(notify_msg);
    -}
    -
    -/* just for debugging */
    -static void
    -handle_unknown(ZNotice_t *notice)
    -{
    - purple_debug_error("zephyr", "z_packet: %s\n", notice->z_packet);
    - purple_debug_error("zephyr", "z_version: %s\n", notice->z_version);
    - purple_debug_error("zephyr", "z_kind: %d\n", (int)(notice->z_kind));
    - purple_debug_error("zephyr", "z_class: %s\n", notice->z_class);
    - purple_debug_error("zephyr", "z_class_inst: %s\n", notice->z_class_inst);
    - purple_debug_error("zephyr", "z_opcode: %s\n", notice->z_opcode);
    - purple_debug_error("zephyr", "z_sender: %s\n", notice->z_sender);
    - purple_debug_error("zephyr", "z_recipient: %s\n", notice->z_recipient);
    - purple_debug_error("zephyr", "z_message: %s\n", notice->z_message);
    - purple_debug_error("zephyr", "z_message_len: %d\n", notice->z_message_len);
    -}
    -
    -gint
    -zeph02_check_notify(gpointer data)
    -{
    - /* XXX add real error reporting */
    - PurpleConnection *gc = (PurpleConnection*) data;
    - while (ZPending()) {
    - ZNotice_t notice;
    - /* XXX add real error reporting */
    -
    - if (ZReceiveNotice(&notice, NULL) != ZERR_NONE) {
    - return TRUE;
    - }
    -
    - switch (notice.z_kind) {
    - case UNSAFE:
    - case UNACKED:
    - case ACKED:
    - handle_message(gc, &notice);
    - break;
    - case SERVACK:
    - if (!(g_ascii_strcasecmp(notice.z_message, ZSRVACK_NOTSENT))) {
    - message_failed(gc, &notice);
    - }
    - break;
    - case CLIENTACK:
    - purple_debug_error("zephyr", "Client ack received\n");
    - handle_unknown(&notice); /* XXX: is it really unknown? */
    - break;
    - default:
    - /* we'll just ignore things for now */
    - handle_unknown(&notice);
    - purple_debug_error("zephyr", "Unhandled notice.\n");
    - break;
    - }
    - /* XXX add real error reporting */
    - ZFreeNotice(&notice);
    - }
    -
    - return TRUE;
    -}
    -
    -gboolean
    -zeph02_subscribe_to(G_GNUC_UNUSED zephyr_account *zephyr, ZSubscription_t *sub)
    -{
    - return ZSubscribeTo(sub, 1, 0) == ZERR_NONE;
    -}
    -
    -gboolean
    -zeph02_request_locations(G_GNUC_UNUSED zephyr_account *zephyr, gchar *who)
    -{
    - ZAsyncLocateData_t ald;
    - Code_t zerr;
    -
    - zerr = ZRequestLocations(who, &ald, UNACKED, ZAUTH);
    - g_free(ald.user);
    - g_free(ald.version);
    - return zerr == ZERR_NONE;
    -}
    -
    -gboolean
    -zeph02_send_message(G_GNUC_UNUSED zephyr_account *zephyr, gchar *zclass, gchar *instance, gchar *recipient,
    - const gchar *html_buf, const gchar *sig, const gchar *opcode)
    -{
    - ZNotice_t notice;
    - char *buf = g_strdup_printf("%s%c%s", sig, '\0', html_buf);
    - gboolean result = TRUE;
    -
    - memset((char *)&notice, 0, sizeof(notice));
    - notice.z_kind = ACKED;
    - notice.z_port = 0;
    - notice.z_class = zclass;
    - notice.z_class_inst = instance;
    - notice.z_recipient = recipient;
    - notice.z_sender = 0;
    - notice.z_default_format = "Class $class, Instance $instance:\n" "To: @bold($recipient) at $time $date\n" "From: @bold($1) <$sender>\n\n$2";
    - notice.z_message_len = strlen(sig) + 1 + strlen(html_buf) + 1;
    - notice.z_message = buf;
    - notice.z_opcode = g_strdup(opcode);
    -
    - purple_debug_info("zephyr","About to send notice\n");
    - if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
    - /* XXX handle errors here */
    - result = FALSE;
    - } else {
    - purple_debug_info("zephyr", "notice sent\n");
    - }
    - g_free(buf);
    - return result;
    -}
    -
    -void
    -zeph02_set_location(G_GNUC_UNUSED zephyr_account *zephyr, char *exposure)
    -{
    - ZSetLocation(exposure);
    -}
    -
    -void
    -zeph02_get_subs_from_server(zephyr_account *zephyr, PurpleConnection *gc)
    -{
    - Code_t retval;
    - int nsubs;
    - GString *subout;
    -
    - if (zephyr->port == 0) {
    - purple_debug_error("zephyr", "error while retrieving port\n");
    - return;
    - }
    - if ((retval = ZRetrieveSubscriptions(zephyr->port, &nsubs)) != ZERR_NONE) {
    - /* XXX better error handling */
    - purple_debug_error("zephyr", "error while retrieving subscriptions from server\n");
    - return;
    - }
    -
    - subout = g_string_new("Subscription list<br>");
    - for (int i = 0; i < nsubs; i++) {
    - ZSubscription_t subs;
    - int one = 1;
    -
    - if ((retval = ZGetSubscriptions(&subs, &one)) != ZERR_NONE) {
    - break;
    - }
    - g_string_append_printf(subout, "Class %s Instance %s Recipient %s<br>",
    - subs.zsub_class, subs.zsub_classinst, subs.zsub_recipient);
    - }
    -
    - if (retval == ZERR_NONE) {
    - gchar *title = g_strdup_printf("Server subscriptions for %s", zephyr->username);
    - purple_notify_formatted(gc, title, title, NULL, subout->str, NULL, NULL);
    - g_free(title);
    - } else {
    - /* XXX better error handling */
    - purple_debug_error("zephyr", "error while retrieving individual subscription\n");
    - }
    -
    - g_string_free(subout, TRUE);
    -}
    -
    -void
    -zeph02_close(G_GNUC_UNUSED zephyr_account *zephyr)
    -{
    - if (ZCancelSubscriptions(0) != ZERR_NONE) {
    - return;
    - }
    - if (ZUnsetLocation() != ZERR_NONE) {
    - return;
    - }
    - if (ZClosePort() != ZERR_NONE) {
    - return;
    - }
    -}
    --- a/libpurple/protocols/zephyr/zephyr_zeph02.h Wed Oct 26 01:22:53 2022 -0500
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,38 +0,0 @@
    -/*
    - * Purple - Internet Messaging Library
    - * Copyright (C) Pidgin Developers <devel@pidgin.im>
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * This program is free software; you can redistribute it and/or modify
    - * it under the terms of the GNU General Public License as published by
    - * the Free Software Foundation; either version 2 of the License, or
    - * (at your option) any later version.
    - *
    - * This program is distributed in the hope that it will be useful,
    - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    - * GNU General Public License for more details.
    - *
    - * You should have received a copy of the GNU General Public License
    - * along with this program; if not, see <https://www.gnu.org/licenses/>.
    - */
    -
    -#ifndef PURPLE_ZEPHYR_ZEPHYR_ZEPH02_H
    -#define PURPLE_ZEPHYR_ZEPHYR_ZEPH02_H
    -
    -#include "zephyr_account.h"
    -
    -gboolean zeph02_login(zephyr_account *zephyr);
    -gint zeph02_check_notify(gpointer data);
    -gboolean zeph02_subscribe_to(zephyr_account *zephyr, ZSubscription_t *sub);
    -gboolean zeph02_request_locations(zephyr_account *zephyr, gchar *who);
    -gboolean zeph02_send_message(zephyr_account *zephyr, gchar *zclass, gchar *instance, gchar *recipient,
    - const gchar *html_buf, const gchar *sig, const gchar *opcode);
    -void zeph02_set_location(zephyr_account *zephyr, char *exposure);
    -void zeph02_get_subs_from_server(zephyr_account *zephyr, PurpleConnection *gc);
    -void zeph02_close(zephyr_account *zephyr);
    -
    -#endif /* PURPLE_ZEPHYR_ZEPHYR_ZEPH02_H */
    --- a/libpurple/purpleprotocol.h Wed Oct 26 01:22:53 2022 -0500
    +++ b/libpurple/purpleprotocol.h Wed Oct 26 01:39:49 2022 -0500
    @@ -63,7 +63,7 @@
    * @OPT_PROTO_CHAT_TOPIC: Chat rooms have topics.<sbr/>
    * IRC and XMPP support this.
    * @OPT_PROTO_NO_PASSWORD: Don't require passwords for sign-in.<sbr/>
    - * Zephyr doesn't require passwords, so there's no need for a
    + * IRC doesn't require passwords, so there's no need for a
    * password prompt.
    * @OPT_PROTO_MAIL_CHECK: Notify on new mail.<sbr/>
    * MSN and Yahoo notify you when you have new mail.
    --- a/meson.build Wed Oct 26 01:22:53 2022 -0500
    +++ b/meson.build Wed Oct 26 01:39:49 2022 -0500
    @@ -364,7 +364,7 @@
    DEFAULT_PRPLS = ['bonjour', 'demo', 'facebook', 'gg', 'irc', 'ircv3', 'jabber',
    - 'novell', 'null', 'sametime', 'zephyr']
    + 'novell', 'null', 'sametime']
    ALL_PRPLS = DEFAULT_PRPLS + ['null']
    dynamic_list = get_option('dynamic-prpls').split(',')
    @@ -381,8 +381,6 @@
    # Do nothing.
    elif prpl == 'gg' and not libgadu.found()
    # Do nothing.
    - elif prpl == 'zephyr' and IS_WIN32
    - # Do nothing.
    else
    DYNAMIC_PRPLS += [prpl]
    endif
    @@ -398,7 +396,6 @@
    DYNAMIC_NOVELL = DYNAMIC_PRPLS.contains('novell')
    DYNAMIC_NULL = DYNAMIC_PRPLS.contains('null')
    DYNAMIC_SAMETIME = DYNAMIC_PRPLS.contains('sametime')
    -DYNAMIC_ZEPHYR = DYNAMIC_PRPLS.contains('zephyr')
    conf.set('HAVE_SYS_UTSNAME_H',
    compiler.has_header('sys/utsname.h'))
    @@ -525,49 +522,6 @@
    endforeach
    sasl = dependency('libsasl2', version : '>= 2.0')
    -#######################################################################
    -# Check for external libzephyr
    -#######################################################################
    -ext_zephyr = dependency('zephyr', required : get_option('zephyr'))
    -conf.set('LIBZEPHYR_EXT', ext_zephyr.found())
    -
    -#######################################################################
    -# Check for Kerberos (for Zephyr)
    -#######################################################################
    -conf.set('ZEPHYR_INT32', 'long')
    -#AC_SUBST(KRB4_CFLAGS)
    -#AC_SUBST(KRB4_LDFLAGS)
    -#AC_SUBST(KRB4_LIBS)
    -kerberos = get_option('krb4')
    -if kerberos
    - if kerberos != 'yes'
    -# KRB4_CFLAGS='-I${kerberos}/include'
    -# if test -d '$kerberos/include/kerberosIV' ; then
    -# KRB4_CFLAGS='$KRB4_CFLAGS -I${kerberos}/include/kerberosIV'
    -# fi
    -# KRB4_LDFLAGS='-L${kerberos}/lib'
    - elif run_command('test', '-d', '/usr/local/include/kerberosIV').returncode() == 0
    -# KRB4_CFLAGS='-I/usr/local/include/kerberosIV'
    - elif run_command('test', '-d', '/usr/include/kerberosIV').returncode() == 0
    -# KRB4_CFLAGS='-I/usr/include/kerberosIV'
    - endif
    - conf.set('ZEPHYR_USES_KERBEROS', true)
    -
    -# AC_CHECK_LIB(krb4, krb_rd_req,
    -# [KRB4_LIBS='-lkrb4 -ldes425 -lkrb5 -lk5crypto -lcom_err'],
    -# [AC_CHECK_LIB(krb, krb_rd_req,
    -# [KRB4_LIBS='-lkrb -ldes'],
    -# [AC_MSG_ERROR([Kerberos 4 libraries not found])],
    -# -ldes)],
    -# -ldes425 -lkrb5 -lk5crypto -lcom_err)
    -# AC_CHECK_FUNCS(krb_set_key krb_rd_req krb_get_lrealm)
    -# AC_CHECK_FUNCS(krb_get_err_text krb_log)
    - krb4 = []
    -endif
    -if not kerberos
    - krb4 = []
    -endif
    -
    #AC_MSG_CHECKING(for me pot o' gold)
    #AC_MSG_RESULT(no)
    foreach func : ['timegm']
    @@ -660,8 +614,6 @@
    summary({
    'Dynamic protocols': DYNAMIC_PRPLS,
    'Cyrus SASL support (IRC and XMPP)': sasl,
    - 'External libzephyr': ext_zephyr,
    - 'Use kerberos 4 with zephyr': kerberos,
    }, section: 'Protocol Support', bool_yn: true, list_sep: ', ')
    # TODO: Remove `.found()` once https://github.com/mesonbuild/meson/pull/10949
    --- a/meson_options.txt Wed Oct 26 01:22:53 2022 -0500
    +++ b/meson_options.txt Wed Oct 26 01:39:49 2022 -0500
    @@ -37,18 +37,12 @@
    option('dynamic-prpls', type : 'string', value: 'all',
    description : 'specify which protocols to build dynamically')
    -option('krb4', type : 'boolean', value : false,
    - description : 'compile Zephyr plugin with Kerberos 4 support')
    -
    option('libgadu', type : 'feature',
    description : 'compile with libgadu (required for GaduGadu support)')
    option('meanwhile', type : 'feature',
    description : 'compile with meanwhile')
    -option('zephyr', type : 'feature',
    - description : 'compile Zephyr plugin against external libzephyr')
    -
    ##############################################################################
    # Pidgin Options
    --- a/pidgin/data/im.pidgin.Pidgin3.desktop.in.in Wed Oct 26 01:22:53 2022 -0500
    +++ b/pidgin/data/im.pidgin.Pidgin3.desktop.in.in Wed Oct 26 01:39:49 2022 -0500
    @@ -4,7 +4,7 @@
    X-GNOME-FullName=Pidgin Internet Messenger
    Comment=Chat over IM. Supports XMPP, IRC, and more
    # TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
    -Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;simple;xmpp;zephyr
    +Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;simple;xmpp
    Exec=pidgin3 %U
    Icon=im.pidgin.Pidgin3
    StartupNotify=true
    --- a/po/POTFILES.in Wed Oct 26 01:22:53 2022 -0500
    +++ b/po/POTFILES.in Wed Oct 26 01:39:49 2022 -0500
    @@ -174,53 +174,6 @@
    libpurple/protocols/sametime/im_mime.c
    libpurple/protocols/sametime/sametime.c
    libpurple/protocols/sametime/tests/test_sametime_im_mime.c
    -libpurple/protocols/zephyr/ZAsyncLocate.c
    -libpurple/protocols/zephyr/ZCkAuth.c
    -libpurple/protocols/zephyr/ZCkIfNot.c
    -libpurple/protocols/zephyr/ZClosePort.c
    -libpurple/protocols/zephyr/ZCmpUID.c
    -libpurple/protocols/zephyr/ZCmpUIDP.c
    -libpurple/protocols/zephyr/zephyr.c
    -libpurple/protocols/zephyr/zephyr_html.c
    -libpurple/protocols/zephyr/zephyr_tzc.c
    -libpurple/protocols/zephyr/zephyr_zeph02.c
    -libpurple/protocols/zephyr/ZFlsLocs.c
    -libpurple/protocols/zephyr/ZFlsSubs.c
    -libpurple/protocols/zephyr/ZFmtAuth.c
    -libpurple/protocols/zephyr/ZFmtList.c
    -libpurple/protocols/zephyr/ZFmtNotice.c
    -libpurple/protocols/zephyr/ZFmtRaw.c
    -libpurple/protocols/zephyr/ZFmtRawLst.c
    -libpurple/protocols/zephyr/ZFmtSmRaw.c
    -libpurple/protocols/zephyr/ZFreeNot.c
    -libpurple/protocols/zephyr/ZGetLocs.c
    -libpurple/protocols/zephyr/ZGetSender.c
    -libpurple/protocols/zephyr/ZGetSubs.c
    -libpurple/protocols/zephyr/ZGetWGPort.c
    -libpurple/protocols/zephyr/ZhmStat.c
    -libpurple/protocols/zephyr/ZIfNotice.c
    -libpurple/protocols/zephyr/ZInit.c
    -libpurple/protocols/zephyr/Zinternal.c
    -libpurple/protocols/zephyr/ZLocations.c
    -libpurple/protocols/zephyr/ZMakeAscii.c
    -libpurple/protocols/zephyr/ZMkAuth.c
    -libpurple/protocols/zephyr/ZNewLocU.c
    -libpurple/protocols/zephyr/ZOpenPort.c
    -libpurple/protocols/zephyr/ZParseNot.c
    -libpurple/protocols/zephyr/ZPeekNot.c
    -libpurple/protocols/zephyr/ZPeekPkt.c
    -libpurple/protocols/zephyr/ZPending.c
    -libpurple/protocols/zephyr/ZReadAscii.c
    -libpurple/protocols/zephyr/ZRecvNot.c
    -libpurple/protocols/zephyr/ZRecvPkt.c
    -libpurple/protocols/zephyr/ZRetSubs.c
    -libpurple/protocols/zephyr/ZSendList.c
    -libpurple/protocols/zephyr/ZSendNot.c
    -libpurple/protocols/zephyr/ZSendPkt.c
    -libpurple/protocols/zephyr/ZSetDest.c
    -libpurple/protocols/zephyr/ZSubs.c
    -libpurple/protocols/zephyr/ZVariables.c
    -libpurple/protocols/zephyr/ZWait4Not.c
    libpurple/proxy.c
    libpurple/purpleaccountmanager.c
    libpurple/purpleaccountoption.c