source: zephyr.c @ 6b4033f

release-1.10release-1.8release-1.9
Last change on this file since 6b4033f was fe3b017, checked in by David Benjamin <davidben@mit.edu>, 13 years ago
Correctly set the realm in outgoing zwrite errors Don't set the zwrite realm, as that only confuses things. Also take the realm (which we now don't set) into account when extracting the recipient.
  • Property mode set to 100644
File size: 36.3 KB
RevLine 
[7d4fbcd]1#include <stdlib.h>
2#include <unistd.h>
3#include <sys/types.h>
4#include <sys/wait.h>
[4357be8]5#include <sys/stat.h>
[7d4fbcd]6#include <string.h>
7#include "owl.h"
8
[fea7992]9#ifdef HAVE_LIBZEPHYR
[a5e7ed6]10static GList *deferred_subs = NULL;
[79d7d98]11
[a5e7ed6]12typedef struct _owl_sub_list {                            /* noproto */
13  ZSubscription_t *subs;
14  int nsubs;
15} owl_sub_list;
16
[c79a047]17Code_t ZResetAuthentication(void);
[09489b89]18#endif
[8262340]19
[02f55dc]20#define HM_SVC_FALLBACK         htons((unsigned short) 2104)
21
[6ea3890]22static char *owl_zephyr_dotfile(const char *name, const char *input)
23{
24  if (input != NULL)
[d4927a7]25    return g_strdup(input);
[6ea3890]26  else
[3472845]27    return g_strdup_printf("%s/%s", owl_global_get_homedir(&g), name);
[6ea3890]28}
29
[52a0f14]30#ifdef HAVE_LIBZEPHYR
[c79a047]31void owl_zephyr_initialize(void)
[52a0f14]32{
[488913a]33  Code_t ret;
[02f55dc]34  struct servent *sp;
35  struct sockaddr_in sin;
36  ZNotice_t req;
[52a0f14]37
38  /*
39   * Code modified from libzephyr's ZhmStat.c
40   *
41   * Modified to add the fd to our select loop, rather than hanging
42   * until we get an ack.
43   */
44
45  if ((ret = ZOpenPort(NULL)) != ZERR_NONE) {
46    owl_function_error("Error opening Zephyr port: %s", error_message(ret));
47    return;
48  }
[02f55dc]49
[4d86e06]50  (void) memset(&sin, 0, sizeof(struct sockaddr_in));
[02f55dc]51
52  sp = getservbyname(HM_SVCNAME, "udp");
53
54  sin.sin_port = (sp) ? sp->s_port : HM_SVC_FALLBACK;
55  sin.sin_family = AF_INET;
56
57  sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
58
[4d86e06]59  (void) memset(&req, 0, sizeof(req));
[02f55dc]60  req.z_kind = STAT;
61  req.z_port = 0;
[712caac]62  req.z_class = zstr(HM_STAT_CLASS);
63  req.z_class_inst = zstr(HM_STAT_CLIENT);
64  req.z_opcode = zstr(HM_GIMMESTATS);
65  req.z_sender = zstr("");
66  req.z_recipient = zstr("");
67  req.z_default_format = zstr("");
[02f55dc]68  req.z_message_len = 0;
[52a0f14]69
[488913a]70  if ((ret = ZSetDestAddr(&sin)) != ZERR_NONE) {
71    owl_function_error("Initializing Zephyr: %s", error_message(ret));
[52a0f14]72    return;
73  }
74
[488913a]75  if ((ret = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE) {
76    owl_function_error("Initializing Zephyr: %s", error_message(ret));
[52a0f14]77    return;
78  }
79
[18fdd5f9]80  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_finish_initialization, NULL, NULL);
[02f55dc]81}
82
[18fdd5f9]83void owl_zephyr_finish_initialization(const owl_io_dispatch *d, void *data) {
[52a0f14]84  Code_t code;
[df569c5]85  char *perl;
[52a0f14]86
[18fdd5f9]87  owl_select_remove_io_dispatch(d);
[52a0f14]88
89  ZClosePort();
90
91  if ((code = ZInitialize()) != ZERR_NONE) {
92    owl_function_error("Initializing Zephyr: %s", error_message(code));
93    return;
94  }
95
96  if ((code = ZOpenPort(NULL)) != ZERR_NONE) {
97    owl_function_error("Initializing Zephyr: %s", error_message(code));
98    return;
99  }
100
[18fdd5f9]101  owl_select_add_io_dispatch(ZGetFD(), OWL_IO_READ|OWL_IO_EXCEPT, &owl_zephyr_process_events, NULL, NULL);
102
[52a0f14]103  owl_global_set_havezephyr(&g);
104
105  if(g.load_initial_subs) {
106    owl_zephyr_load_initial_subs();
107  }
[a5e7ed6]108  while(deferred_subs != NULL) {
109    owl_sub_list *subs = deferred_subs->data;
110    owl_function_debugmsg("Loading %d deferred subs.", subs->nsubs);
111    owl_zephyr_loadsubs_helper(subs->subs, subs->nsubs);
112    deferred_subs = g_list_delete_link(deferred_subs, deferred_subs);
[ddbbcffa]113    g_free(subs);
[a5e7ed6]114  }
[619d864]115
116  /* zlog in if we need to */
117  if (owl_global_is_startuplogin(&g)) {
118    owl_function_debugmsg("startup: doing zlog in");
119    owl_zephyr_zlog_in();
120  }
[27964fe]121  /* check pseudo-logins if we need to */
122  if (owl_global_is_pseudologins(&g)) {
123    owl_function_debugmsg("startup: checking pseudo-logins");
124    owl_function_zephyr_buddy_check(0);
125  }
[df569c5]126
[12e291a]127  perl = owl_perlconfig_execute("BarnOwl::Zephyr::_zephyr_startup()");
[ddbbcffa]128  g_free(perl);
[12e291a]129
130  owl_select_add_pre_select_action(owl_zephyr_pre_select_action, NULL, NULL);
[52a0f14]131}
132
[c79a047]133void owl_zephyr_load_initial_subs(void) {
[7451af9]134  int ret_sd, ret_bd, ret_u;
[52a0f14]135
136  owl_function_debugmsg("startup: loading initial zephyr subs");
137
138  /* load default subscriptions */
[7451af9]139  ret_sd = owl_zephyr_loaddefaultsubs();
140
141  /* load Barnowl default subscriptions */
142  ret_bd = owl_zephyr_loadbarnowldefaultsubs();
[52a0f14]143
144  /* load subscriptions from subs file */
[7451af9]145  ret_u = owl_zephyr_loadsubs(NULL, 0);
[52a0f14]146
[7451af9]147  if (ret_sd || ret_bd || ret_u) {
[52a0f14]148    owl_function_error("Error loading zephyr subscriptions");
149  }
150
151  /* load login subscriptions */
152  if (owl_global_is_loginsubs(&g)) {
153    owl_function_debugmsg("startup: loading login subs");
154    owl_function_loadloginsubs(NULL);
155  }
156}
157#else
[c79a047]158void owl_zephyr_initialize(void)
[52a0f14]159{
160}
[02f55dc]161#endif
162
[52a0f14]163
[c79a047]164int owl_zephyr_shutdown(void)
[09489b89]165{
166#ifdef HAVE_LIBZEPHYR
[bfbf590]167  if(owl_global_is_havezephyr(&g)) {
168    unsuball();
169    ZClosePort();
170  }
[09489b89]171#endif
[32ad44d]172  return 0;
[be0a79f]173}
174
[c79a047]175int owl_zephyr_zpending(void)
[be0a79f]176{
177#ifdef HAVE_LIBZEPHYR
[8ab1f28]178  Code_t code;
179  if(owl_global_is_havezephyr(&g)) {
180    if((code = ZPending()) < 0) {
181      owl_function_debugmsg("Error (%s) in ZPending()\n",
182                            error_message(code));
183      return 0;
184    }
185    return code;
186  }
[be0a79f]187#endif
[32ad44d]188  return 0;
[be0a79f]189}
190
[c79a047]191const char *owl_zephyr_get_realm(void)
[09489b89]192{
193#ifdef HAVE_LIBZEPHYR
[32ad44d]194  if (owl_global_is_havezephyr(&g))
195    return(ZGetRealm());
[09489b89]196#endif
[32ad44d]197  return "";
[09489b89]198}
199
[c79a047]200const char *owl_zephyr_get_sender(void)
[09489b89]201{
202#ifdef HAVE_LIBZEPHYR
[32ad44d]203  if (owl_global_is_havezephyr(&g))
204    return(ZGetSender());
[09489b89]205#endif
[32ad44d]206  return "";
[09489b89]207}
208
[f6050ee]209#ifdef HAVE_LIBZEPHYR
[93e883d]210int owl_zephyr_loadsubs_helper(ZSubscription_t subs[], int count)
211{
[18105584]212  int ret = 0;
[c73a22d]213  Code_t code;
214
[a5e7ed6]215  if (owl_global_is_havezephyr(&g)) {
216    int i;
217    /* sub without defaults */
[c73a22d]218    code = ZSubscribeToSansDefaults(subs, count, 0);
219    if (code != ZERR_NONE) {
220      owl_function_error("Error subscribing to zephyr notifications: %s",
221                         error_message(code));
[a5e7ed6]222      ret=-2;
223    }
[93e883d]224
[a5e7ed6]225    /* free stuff */
226    for (i=0; i<count; i++) {
[ddbbcffa]227      g_free(subs[i].zsub_class);
228      g_free(subs[i].zsub_classinst);
229      g_free(subs[i].zsub_recipient);
[a5e7ed6]230    }
[bb2c60d]231
[ddbbcffa]232    g_free(subs);
[a5e7ed6]233  } else {
[96828e4]234    owl_sub_list *s = g_new(owl_sub_list, 1);
[a5e7ed6]235    s->subs = subs;
236    s->nsubs = count;
237    deferred_subs = g_list_append(deferred_subs, s);
238  }
[d21efbc]239
[93e883d]240  return ret;
241}
[f6050ee]242#endif
[93e883d]243
[7451af9]244/* Load zephyr subscriptions from 'filename'.  If 'filename' is NULL,
[95474d7]245 * the default file $HOME/.zephyr.subs will be used.
246 *
247 * Returns 0 on success.  If the file does not exist, return -1 if
248 * 'error_on_nofile' is 1, otherwise return 0.  Return -1 if the file
249 * exists but can not be read.  Return -2 if there is a failure from
250 * zephyr to load the subscriptions.
[2de4f20]251 */
[e19eb97]252int owl_zephyr_loadsubs(const char *filename, int error_on_nofile)
[31e48a3]253{
[be0a79f]254#ifdef HAVE_LIBZEPHYR
[7d4fbcd]255  FILE *file;
256  char *tmp, *start;
[b7ee89b]257  char *buffer = NULL;
258  char *subsfile;
[bb2c60d]259  ZSubscription_t *subs;
260  int subSize = 1024;
[b7ee89b]261  int count;
[4357be8]262  struct stat statbuff;
[7d4fbcd]263
[96828e4]264  subs = g_new(ZSubscription_t, subSize);
[6ea3890]265  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[b7ee89b]266
267  if (stat(subsfile, &statbuff) != 0) {
[ddbbcffa]268    g_free(subsfile);
[b7ee89b]269    if (error_on_nofile == 1)
270      return -1;
271    return 0;
[95474d7]272  }
[4357be8]273
[8262340]274  ZResetAuthentication();
[b7ee89b]275  count = 0;
276  file = fopen(subsfile, "r");
[ddbbcffa]277  g_free(subsfile);
[b7ee89b]278  if (!file)
279    return -1;
280  while (owl_getline(&buffer, file)) {
281    if (buffer[0] == '#' || buffer[0] == '\n')
282        continue;
283
284    if (buffer[0] == '-')
285      start = buffer + 1;
286    else
287      start = buffer;
288
[bb2c60d]289    if (count >= subSize) {
[d21efbc]290      subSize *= 2;
[35b6eb9]291      subs = g_renew(ZSubscription_t, subs, subSize);
[93e883d]292    }
[95474d7]293   
294    /* add it to the list of subs */
[b7ee89b]295    if ((tmp = strtok(start, ",\n\r")) == NULL)
296      continue;
[d4927a7]297    subs[count].zsub_class = g_strdup(tmp);
[b7ee89b]298    if ((tmp=strtok(NULL, ",\n\r")) == NULL)
299      continue;
[d4927a7]300    subs[count].zsub_classinst = g_strdup(tmp);
[b7ee89b]301    if ((tmp = strtok(NULL, " \t\n\r")) == NULL)
302      continue;
[d4927a7]303    subs[count].zsub_recipient = g_strdup(tmp);
[b7ee89b]304
[bb2c60d]305    /* if it started with '-' then add it to the global punt list, and
306     * remove it from the list of subs. */
[b7ee89b]307    if (buffer[0] == '-') {
[95474d7]308      owl_function_zpunt(subs[count].zsub_class, subs[count].zsub_classinst, subs[count].zsub_recipient, 0);
[ddbbcffa]309      g_free(subs[count].zsub_class);
310      g_free(subs[count].zsub_classinst);
311      g_free(subs[count].zsub_recipient);
[b7ee89b]312    } else {
[bb2c60d]313      count++;
[95474d7]314    }
[7d4fbcd]315  }
[95474d7]316  fclose(file);
[b7ee89b]317  if (buffer)
[ddbbcffa]318    g_free(buffer);
[7d4fbcd]319
[b7ee89b]320  return owl_zephyr_loadsubs_helper(subs, count);
[7451af9]321#else
[b7ee89b]322  return 0;
[7451af9]323#endif
324}
325
326/* Load default Barnowl subscriptions
327 *
328 * Returns 0 on success.
329 * Return -2 if there is a failure from zephyr to load the subscriptions.
330 */
[c79a047]331int owl_zephyr_loadbarnowldefaultsubs(void)
[7451af9]332{
333#ifdef HAVE_LIBZEPHYR
334  ZSubscription_t *subs;
335  int subSize = 10; /* Max Barnowl default subs we allow */
336  int count, ret;
337
[96828e4]338  subs = g_new(ZSubscription_t, subSize);
[7451af9]339  ZResetAuthentication();
340  count=0;
341
[d4927a7]342  subs[count].zsub_class=g_strdup("message");
343  subs[count].zsub_classinst=g_strdup("*");
344  subs[count].zsub_recipient=g_strdup("%me%");
[7451af9]345  count++;
346
347  ret = owl_zephyr_loadsubs_helper(subs, count);
[7d4fbcd]348  return(ret);
[be0a79f]349#else
350  return(0);
351#endif
[7d4fbcd]352}
353
[c79a047]354int owl_zephyr_loaddefaultsubs(void)
[4357be8]355{
[40d834a]356#ifdef HAVE_LIBZEPHYR
[c73a22d]357  Code_t ret;
358
[2c5ee3e]359  if (owl_global_is_havezephyr(&g)) {
360    ZSubscription_t subs[10];
[c73a22d]361
362    ret = ZSubscribeTo(subs, 0, 0);
363    if (ret != ZERR_NONE) {
364      owl_function_error("Error subscribing to default zephyr notifications: %s.",
365                           error_message(ret));
[2c5ee3e]366      return(-1);
367    }
[4357be8]368  }
369  return(0);
[40d834a]370#else
371  return(0);
372#endif
[4357be8]373}
374
[e19eb97]375int owl_zephyr_loadloginsubs(const char *filename)
[31e48a3]376{
[be0a79f]377#ifdef HAVE_LIBZEPHYR
[7d4fbcd]378  FILE *file;
[d21efbc]379  ZSubscription_t *subs;
380  int numSubs = 100;
[b7ee89b]381  char *subsfile;
382  char *buffer = NULL;
383  int count;
[4357be8]384  struct stat statbuff;
[7d4fbcd]385
[96828e4]386  subs = g_new(ZSubscription_t, numSubs);
[6ea3890]387  subsfile = owl_zephyr_dotfile(".anyone", filename);
[4357be8]388
[922f589]389  if (stat(subsfile, &statbuff) == -1) {
[ddbbcffa]390    g_free(subs);
391    g_free(subsfile);
[b7ee89b]392    return 0;
[922f589]393  }
[7d4fbcd]394
[8262340]395  ZResetAuthentication();
[b7ee89b]396  count = 0;
397  file = fopen(subsfile, "r");
[ddbbcffa]398  g_free(subsfile);
[7d4fbcd]399  if (file) {
[b7ee89b]400    while (owl_getline_chomp(&buffer, file)) {
401      if (buffer[0] == '\0' || buffer[0] == '#')
402        continue;
403
[d21efbc]404      if (count == numSubs) {
405        numSubs *= 2;
[35b6eb9]406        subs = g_renew(ZSubscription_t, subs, numSubs);
[d21efbc]407      }
[7d4fbcd]408
[d4927a7]409      subs[count].zsub_class = g_strdup("login");
410      subs[count].zsub_recipient = g_strdup("*");
[b7ee89b]411      subs[count].zsub_classinst = long_zuser(buffer);
[7d4fbcd]412
413      count++;
414    }
415    fclose(file);
416  } else {
[b7ee89b]417    return 0;
[7d4fbcd]418  }
[b7ee89b]419  if (buffer)
[ddbbcffa]420    g_free(buffer);
[7d4fbcd]421
[b7ee89b]422  return owl_zephyr_loadsubs_helper(subs, count);
[be0a79f]423#else
[b7ee89b]424  return 0;
[be0a79f]425#endif
[7d4fbcd]426}
427
[c79a047]428void unsuball(void)
[31e48a3]429{
[be0a79f]430#if HAVE_LIBZEPHYR
[00842c3]431  Code_t ret;
[8262340]432
433  ZResetAuthentication();
[00842c3]434  ret = ZCancelSubscriptions(0);
435  if (ret != ZERR_NONE)
436    owl_function_error("Zephyr: Cancelling subscriptions: %s",
437                       error_message(ret));
[be0a79f]438#endif
[7d4fbcd]439}
440
[e19eb97]441int owl_zephyr_sub(const char *class, const char *inst, const char *recip)
[31e48a3]442{
[be0a79f]443#ifdef HAVE_LIBZEPHYR
[7d4fbcd]444  ZSubscription_t subs[5];
[c73a22d]445  Code_t ret;
[7d4fbcd]446
[712caac]447  subs[0].zsub_class=zstr(class);
448  subs[0].zsub_classinst=zstr(inst);
449  subs[0].zsub_recipient=zstr(recip);
[7d4fbcd]450
[8262340]451  ZResetAuthentication();
[c73a22d]452  ret = ZSubscribeTo(subs, 1, 0);
453  if (ret != ZERR_NONE) {
454    owl_function_error("Error subbing to <%s,%s,%s>: %s",
455                       class, inst, recip,
456                       error_message(ret));
[97cd00be]457    return(-2);
[7d4fbcd]458  }
459  return(0);
[be0a79f]460#else
461  return(0);
462#endif
[7d4fbcd]463}
464
465
[e19eb97]466int owl_zephyr_unsub(const char *class, const char *inst, const char *recip)
[31e48a3]467{
[be0a79f]468#ifdef HAVE_LIBZEPHYR
[7d4fbcd]469  ZSubscription_t subs[5];
[c73a22d]470  Code_t ret;
[7d4fbcd]471
[712caac]472  subs[0].zsub_class=zstr(class);
473  subs[0].zsub_classinst=zstr(inst);
474  subs[0].zsub_recipient=zstr(recip);
[7d4fbcd]475
[8262340]476  ZResetAuthentication();
[c73a22d]477  ret = ZUnsubscribeTo(subs, 1, 0);
478  if (ret != ZERR_NONE) {
479    owl_function_error("Error unsubbing from <%s,%s,%s>: %s",
480                       class, inst, recip,
481                       error_message(ret));
[97cd00be]482    return(-2);
[7d4fbcd]483  }
484  return(0);
[be0a79f]485#else
486  return(0);
487#endif
[7d4fbcd]488}
489
[b0430a6]490/* return a pointer to the data in the Jth field, (NULL terminated by
491 * definition).  Caller must free the return.
492 */
[be0a79f]493#ifdef HAVE_LIBZEPHYR
[1077891a]494char *owl_zephyr_get_field(const ZNotice_t *n, int j)
[31e48a3]495{
[7d4fbcd]496  int i, count, save;
497
[128171a]498  /* If there's no message here, just run along now */
499  if (n->z_message_len == 0)
[d4927a7]500    return(g_strdup(""));
[128171a]501
[7d4fbcd]502  count=save=0;
503  for (i=0; i<n->z_message_len; i++) {
504    if (n->z_message[i]=='\0') {
505      count++;
506      if (count==j) {
507        /* just found the end of the field we're looking for */
[d4927a7]508        return(g_strdup(n->z_message+save));
[7d4fbcd]509      } else {
510        save=i+1;
511      }
512    }
513  }
[b0430a6]514  /* catch the last field, which might not be null terminated */
[7d4fbcd]515  if (count==j-1) {
[fc7481a]516    return g_strndup(n->z_message + save, n->z_message_len - save);
[7d4fbcd]517  }
[b0430a6]518
[d4927a7]519  return(g_strdup(""));
[7d4fbcd]520}
[5376a95]521
[1077891a]522char *owl_zephyr_get_field_as_utf8(const ZNotice_t *n, int j)
[5376a95]523{
524  int i, count, save;
525
526  /* If there's no message here, just run along now */
527  if (n->z_message_len == 0)
[d4927a7]528    return(g_strdup(""));
[5376a95]529
530  count=save=0;
531  for (i = 0; i < n->z_message_len; i++) {
532    if (n->z_message[i]=='\0') {
533      count++;
534      if (count == j) {
535        /* just found the end of the field we're looking for */
[6201646]536        return(owl_validate_or_convert(n->z_message + save));
[5376a95]537      } else {
538        save = i + 1;
539      }
540    }
541  }
542  /* catch the last field, which might not be null terminated */
543  if (count == j - 1) {
[6201646]544    char *tmp, *out;
[fc7481a]545    tmp = g_strndup(n->z_message + save, n->z_message_len - save);
[6201646]546    out = owl_validate_or_convert(tmp);
[ddbbcffa]547    g_free(tmp);
[6201646]548    return out;
[5376a95]549  }
550
[d4927a7]551  return(g_strdup(""));
[5376a95]552}
[09489b89]553#else
[701a184]554char *owl_zephyr_get_field(void *n, int j)
[09489b89]555{
[d4927a7]556  return(g_strdup(""));
[09489b89]557}
[5577606]558char *owl_zephyr_get_field_as_utf8(void *n, int j)
[5376a95]559{
560  return owl_zephyr_get_field(n, j);
561}
[be0a79f]562#endif
[7d4fbcd]563
[b0430a6]564
[be0a79f]565#ifdef HAVE_LIBZEPHYR
[1077891a]566int owl_zephyr_get_num_fields(const ZNotice_t *n)
[31e48a3]567{
[7d4fbcd]568  int i, fields;
569
[50e29e3]570  if(n->z_message_len == 0)
571    return 0;
572
[7d4fbcd]573  fields=1;
574  for (i=0; i<n->z_message_len; i++) {
575    if (n->z_message[i]=='\0') fields++;
576  }
577 
578  return(fields);
579}
[09489b89]580#else
[1077891a]581int owl_zephyr_get_num_fields(const void *n)
[09489b89]582{
583  return(0);
584}
[be0a79f]585#endif
[7d4fbcd]586
[be0a79f]587#ifdef HAVE_LIBZEPHYR
[bf73bdd]588/* return a pointer to the message, place the message length in k
589 * caller must free the return
590 */
[c08c70a]591char *owl_zephyr_get_message(const ZNotice_t *n, const owl_message *m)
[31e48a3]592{
[c518676]593#define OWL_NFIELDS     5
594  int i;
595  char *fields[OWL_NFIELDS + 1];
596  char *msg = NULL;
597
[405d5e6]598  /* don't let ping messages have a body */
[7d4fbcd]599  if (!strcasecmp(n->z_opcode, "ping")) {
[d4927a7]600    return(g_strdup(""));
[7d4fbcd]601  }
602
[c518676]603  for(i = 0; i < OWL_NFIELDS; i++)
604    fields[i + 1] = owl_zephyr_get_field(n, i + 1);
605
[a1bb198]606  /* deal with MIT NOC messages */
[85d1795]607  if (!strcasecmp(n->z_default_format, "@center(@bold(NOC Message))\n\n@bold(Sender:) $1 <$sender>\n@bold(Time:  ) $time\n\n@italic($opcode service on $instance $3.) $4\n")) {
[a1bb198]608
[c518676]609    msg = g_strdup_printf("%s service on %s %s\n%s", n->z_opcode, n->z_class_inst, fields[3], fields[4]);
[a1bb198]610  }
[fba0f96]611  /* deal with MIT Discuss messages */
[e2a620b]612  else if (!strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3 ($5)\nSubject: $4") ||
613           !strcasecmp(n->z_default_format, "New transaction [$1] entered in $2\nFrom: $3\nSubject: $4")) {
[fba0f96]614   
[c518676]615    msg = g_strdup_printf("New transaction [%s] entered in %s\nFrom: %s (%s)\nSubject: %s",
616                          fields[1], fields[2], fields[3], fields[5], fields[4]);
[fba0f96]617  }
[85d1795]618  /* deal with MIT Moira messages */
619  else if (!strcasecmp(n->z_default_format, "MOIRA $instance on $fromhost:\n $message\n")) {
[c518676]620    msg = g_strdup_printf("MOIRA %s on %s: %s",
621                          n->z_class_inst,
622                          owl_message_get_hostname(m),
623                          fields[1]);
624  } else {
625    if (owl_zephyr_get_num_fields(n) == 1)
626      msg = g_strdup(fields[1]);
627    else
628      msg = g_strdup(fields[2]);
[85d1795]629  }
[405d5e6]630
[c518676]631  for (i = 0; i < OWL_NFIELDS; i++)
632    g_free(fields[i + 1]);
633
634  return msg;
[7d4fbcd]635}
[be0a79f]636#endif
[7d4fbcd]637
[be0a79f]638#ifdef HAVE_LIBZEPHYR
[1077891a]639const char *owl_zephyr_get_zsig(const ZNotice_t *n, int *k)
[31e48a3]640{
[7d4fbcd]641  /* return a pointer to the zsig if there is one */
642
[405d5e6]643  /* message length 0? No zsig */
[7d4fbcd]644  if (n->z_message_len==0) {
645    *k=0;
646    return("");
647  }
[405d5e6]648
[85d1795]649  /* If there's only one field, no zsig */
650  if (owl_zephyr_get_num_fields(n) == 1) {
651    *k=0;
[405d5e6]652    return("");
653  }
654
655  /* Everything else is field 1 */
[7d4fbcd]656  *k=strlen(n->z_message);
657  return(n->z_message);
658}
[09489b89]659#else
[1077891a]660const char *owl_zephyr_get_zsig(const void *n, int *k)
[09489b89]661{
662  return("");
663}
[be0a79f]664#endif
[7d4fbcd]665
[e19eb97]666int send_zephyr(const char *opcode, const char *zsig, const char *class, const char *instance, const char *recipient, const char *message)
[31e48a3]667{
[be0a79f]668#ifdef HAVE_LIBZEPHYR
[c73a22d]669  Code_t ret;
[7d4fbcd]670  ZNotice_t notice;
671   
672  memset(&notice, 0, sizeof(notice));
673
[8262340]674  ZResetAuthentication();
[8ba37ec]675
676  if (!zsig) zsig="";
[8262340]677 
[7d4fbcd]678  notice.z_kind=ACKED;
679  notice.z_port=0;
[712caac]680  notice.z_class=zstr(class);
681  notice.z_class_inst=zstr(instance);
[21882032]682  notice.z_sender=NULL;
[7d4fbcd]683  if (!strcmp(recipient, "*") || !strcmp(recipient, "@")) {
[712caac]684    notice.z_recipient=zstr("");
[21882032]685    if (*owl_global_get_zsender(&g))
[712caac]686        notice.z_sender=zstr(owl_global_get_zsender(&g));
[7d4fbcd]687  } else {
[712caac]688    notice.z_recipient=zstr(recipient);
[7d4fbcd]689  }
[712caac]690  notice.z_default_format=zstr("Class $class, Instance $instance:\nTo: @bold($recipient) at $time $date\nFrom: @bold{$1 <$sender>}\n\n$2");
691  if (opcode) notice.z_opcode=zstr(opcode);
[7d4fbcd]692
[56330ff]693  notice.z_message_len=strlen(zsig)+1+strlen(message);
[96828e4]694  notice.z_message=g_new(char, notice.z_message_len+10);
[56330ff]695  strcpy(notice.z_message, zsig);
696  memcpy(notice.z_message+strlen(zsig)+1, message, strlen(message));
[7d4fbcd]697
698  /* ret=ZSendNotice(&notice, ZAUTH); */
699  ret=ZSrvSendNotice(&notice, ZAUTH, send_zephyr_helper);
700 
701  /* free then check the return */
[ddbbcffa]702  g_free(notice.z_message);
[7d4fbcd]703  ZFreeNotice(&notice);
[c73a22d]704  if (ret != ZERR_NONE) {
705    owl_function_error("Error sending zephyr: %s", error_message(ret));
[7d4fbcd]706    return(ret);
707  }
708  return(0);
[be0a79f]709#else
710  return(0);
711#endif
[7d4fbcd]712}
713
[be0a79f]714#ifdef HAVE_LIBZEPHYR
[31e48a3]715Code_t send_zephyr_helper(ZNotice_t *notice, char *buf, int len, int wait)
716{
[7d4fbcd]717  return(ZSendPacket(buf, len, 0));
718}
[be0a79f]719#endif
[7d4fbcd]720
[e19eb97]721void send_ping(const char *to, const char *zclass, const char *zinstance)
[31e48a3]722{
[be0a79f]723#ifdef HAVE_LIBZEPHYR
[3ef779b]724  send_zephyr("PING", "", zclass, zinstance, to, "");
[be0a79f]725#endif
[7d4fbcd]726}
727
[be0a79f]728#ifdef HAVE_LIBZEPHYR
[1077891a]729void owl_zephyr_handle_ack(const ZNotice_t *retnotice)
[31e48a3]730{
[7d4fbcd]731  char *tmp;
732 
733  /* if it's an HMACK ignore it */
734  if (retnotice->z_kind == HMACK) return;
[aecf3e6]735
[7d4fbcd]736  if (retnotice->z_kind == SERVNAK) {
[ec6ff52]737    owl_function_error("Authorization failure sending zephyr");
[7d4fbcd]738  } else if ((retnotice->z_kind != SERVACK) || !retnotice->z_message_len) {
[ec6ff52]739    owl_function_error("Detected server failure while receiving acknowledgement");
[7d4fbcd]740  } else if (!strcmp(retnotice->z_message, ZSRVACK_SENT)) {
741    if (!strcasecmp(retnotice->z_opcode, "ping")) {
742      return;
743    } else {
[d73e3af]744      if (strcasecmp(retnotice->z_recipient, ""))
[1e550b2]745      { /* personal */
[d73e3af]746        tmp=short_zuser(retnotice->z_recipient);
747        if(!strcasecmp(retnotice->z_class, "message") &&
748           !strcasecmp(retnotice->z_class_inst, "personal")) {
749          owl_function_makemsg("Message sent to %s.", tmp);
[1e550b2]750        } else if(!strcasecmp(retnotice->z_class, "message")) { /* instanced, but not classed, personal */
[d73e3af]751          owl_function_makemsg("Message sent to %s on -i %s\n", tmp, retnotice->z_class_inst);
[1e550b2]752        } else { /* classed personal */
[d73e3af]753          owl_function_makemsg("Message sent to %s on -c %s -i %s\n", tmp, retnotice->z_class, retnotice->z_class_inst);
754        }
[ddbbcffa]755        g_free(tmp);
[d73e3af]756      } else {
[1e550b2]757        /* class / instance message */
[d73e3af]758          owl_function_makemsg("Message sent to -c %s -i %s\n", retnotice->z_class, retnotice->z_class_inst);
759      }
[7d4fbcd]760    }
761  } else if (!strcmp(retnotice->z_message, ZSRVACK_NOTSENT)) {
[44f32fb]762    if (retnotice->z_recipient == NULL
[60c2e1e]763        || *retnotice->z_recipient == 0
[44f32fb]764        || *retnotice->z_recipient == '@') {
[e3a75ed]765      char *buff;
[44f32fb]766      owl_function_error("No one subscribed to class %s", retnotice->z_class);
[e3a75ed]767      buff = g_strdup_printf("Could not send message to class %s: no one subscribed.\n", retnotice->z_class);
[9119a47]768      owl_function_adminmsg("", buff);
[e3a75ed]769      g_free(buff);
[7d4fbcd]770    } else {
[e3a75ed]771      char *buff;
[24ccc01]772      owl_zwrite zw;
773
[4b464a4]774      tmp = short_zuser(retnotice->z_recipient);
[44f32fb]775      owl_function_error("%s: Not logged in or subscribing.", tmp);
[3ef779b]776      /*
777       * These error messages are often over 80 chars, but users who want to
778       * see the whole thing can scroll to the side, and for those with wide
779       * terminals or who don't care, not splitting saves a line in the UI
780       */
781      if(strcasecmp(retnotice->z_class, "message")) {
[e3a75ed]782        buff = g_strdup_printf(
[10e3963]783                 "Could not send message to %s: "
[3ef779b]784                 "not logged in or subscribing to class %s, instance %s.\n",
[10e3963]785                 tmp,
[1151f0b]786                 retnotice->z_class,
787                 retnotice->z_class_inst);
[3ef779b]788      } else if(strcasecmp(retnotice->z_class_inst, "personal")) {
[e3a75ed]789        buff = g_strdup_printf(
[3ef779b]790                 "Could not send message to %s: "
791                 "not logged in or subscribing to instance %s.\n",
792                 tmp,
793                 retnotice->z_class_inst);
[44f32fb]794      } else {
[e3a75ed]795        buff = g_strdup_printf(
[10e3963]796                 "Could not send message to %s: "
797                 "not logged in or subscribing to messages.\n",
798                 tmp);
[44f32fb]799      }
[9119a47]800      owl_function_adminmsg("", buff);
[24ccc01]801
802      memset(&zw, 0, sizeof(zw));
[d4927a7]803      zw.class = g_strdup(retnotice->z_class);
804      zw.inst  = g_strdup(retnotice->z_class_inst);
[fe3b017]805      zw.realm = g_strdup("");
[d4927a7]806      zw.opcode = g_strdup(retnotice->z_opcode);
807      zw.zsig   = g_strdup("");
[24ccc01]808      owl_list_create(&(zw.recips));
[fe3b017]809      owl_list_append_element(&(zw.recips), g_strdup(retnotice->z_recipient));
[24ccc01]810
811      owl_log_outgoing_zephyr_error(&zw, buff);
812
[c230bc1]813      owl_zwrite_cleanup(&zw);
[e3a75ed]814      g_free(buff);
[ddbbcffa]815      g_free(tmp);
[7d4fbcd]816    }
817  } else {
[ec6ff52]818    owl_function_error("Internal error on ack (%s)", retnotice->z_message);
[7d4fbcd]819  }
820}
[09489b89]821#else
[1077891a]822void owl_zephyr_handle_ack(const void *retnotice)
[09489b89]823{
824}
[be0a79f]825#endif
[7d4fbcd]826
[be0a79f]827#ifdef HAVE_LIBZEPHYR
[1077891a]828int owl_zephyr_notice_is_ack(const ZNotice_t *n)
[31e48a3]829{
[7d4fbcd]830  if (n->z_kind == SERVNAK || n->z_kind == SERVACK || n->z_kind == HMACK) {
831    if (!strcasecmp(n->z_class, LOGIN_CLASS)) return(0);
832    return(1);
833  }
834  return(0);
835}
[09489b89]836#else
[1077891a]837int owl_zephyr_notice_is_ack(const void *n)
[09489b89]838{
839  return(0);
840}
[be0a79f]841#endif
[7d4fbcd]842 
[c08c70a]843void owl_zephyr_zaway(const owl_message *m)
[31e48a3]844{
[be0a79f]845#ifdef HAVE_LIBZEPHYR
[7c8060d0]846  char *tmpbuff, *myuser, *to;
[987cf3f]847  owl_zwrite *z;
[7d4fbcd]848 
[aa2f6364]849  /* bail if it doesn't look like a message we should reply to.  Some
[2de4f20]850   * of this defined by the way zaway(1) works
851   */
[7d4fbcd]852  if (strcasecmp(owl_message_get_class(m), "message")) return;
853  if (strcasecmp(owl_message_get_recipient(m), ZGetSender())) return;
854  if (!strcasecmp(owl_message_get_sender(m), "")) return;
855  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return;
856  if (!strcasecmp(owl_message_get_opcode(m), "auto")) return;
[d023c25]857  if (!strcasecmp(owl_message_get_zsig(m), "Automated reply:")) return;
[7d4fbcd]858  if (!strcasecmp(owl_message_get_sender(m), ZGetSender())) return;
[9854278]859  if (owl_message_get_attribute_value(m, "isauto")) return;
[7d4fbcd]860
[7c8060d0]861  if (owl_global_is_smartstrip(&g)) {
[e3d9c77]862    to=owl_zephyr_smartstripped_user(owl_message_get_sender(m));
[7c8060d0]863  } else {
[d4927a7]864    to=g_strdup(owl_message_get_sender(m));
[7c8060d0]865  }
866
[7d4fbcd]867  send_zephyr("",
868              "Automated reply:",
869              owl_message_get_class(m),
870              owl_message_get_instance(m),
[7c8060d0]871              to,
[7d4fbcd]872              owl_global_get_zaway_msg(&g));
873
[7c8060d0]874  myuser=short_zuser(to);
[aa2f6364]875  if (!strcasecmp(owl_message_get_instance(m), "personal")) {
[eb8d9c1]876    tmpbuff = owl_string_build_quoted("zwrite %q", myuser);
[aa2f6364]877  } else {
[eb8d9c1]878    tmpbuff = owl_string_build_quoted("zwrite -i %q %q", owl_message_get_instance(m), myuser);
[aa2f6364]879  }
[ddbbcffa]880  g_free(myuser);
881  g_free(to);
[aa2f6364]882
[987cf3f]883  z = owl_zwrite_new(tmpbuff);
[bb85767]884  g_free(tmpbuff);
885  if (z == NULL) {
886    owl_function_error("Error creating outgoing zephyr.");
887    return;
888  }
[987cf3f]889  owl_zwrite_set_message(z, owl_global_get_zaway_msg(&g));
890  owl_zwrite_set_zsig(z, "Automated reply:");
891
[7d4fbcd]892  /* display the message as an admin message in the receive window */
[e5da3fe]893  owl_function_add_outgoing_zephyrs(z);
[987cf3f]894  owl_zwrite_delete(z);
[be0a79f]895#endif
[7d4fbcd]896}
897
[be0a79f]898#ifdef HAVE_LIBZEPHYR
[31e48a3]899void owl_zephyr_hackaway_cr(ZNotice_t *n)
900{
[7d4fbcd]901  /* replace \r's with ' '.  Gross-ish */
902  int i;
903
904  for (i=0; i<n->z_message_len; i++) {
905    if (n->z_message[i]=='\r') {
906      n->z_message[i]=' ';
907    }
908  }
909}
[be0a79f]910#endif
[7d4fbcd]911
[dca3b27]912char *owl_zephyr_zlocate(const char *user, int auth)
[31e48a3]913{
[be0a79f]914#ifdef HAVE_LIBZEPHYR
[7d4fbcd]915  int ret, numlocs;
916  int one = 1;
917  ZLocations_t locations;
918  char *myuser;
[dca3b27]919  char *p, *result;
920
[8262340]921  ZResetAuthentication();
[dca3b27]922  ret = ZLocateUser(zstr(user), &numlocs, auth ? ZAUTH : ZNOAUTH);
923  if (ret != ZERR_NONE)
[3472845]924    return g_strdup_printf("Error locating user %s: %s\n",
925                           user, error_message(ret));
[dca3b27]926
927  myuser = short_zuser(user);
928  if (numlocs == 0) {
[3472845]929    result = g_strdup_printf("%s: Hidden or not logged in\n", myuser);
[dca3b27]930  } else {
[d4927a7]931    result = g_strdup("");
[dca3b27]932    for (; numlocs; numlocs--) {
933      ZGetLocations(&locations, &one);
[3472845]934      p = g_strdup_printf("%s%s: %s\t%s\t%s\n",
[dca3b27]935                          result, myuser,
936                          locations.host ? locations.host : "?",
937                          locations.tty ? locations.tty : "?",
938                          locations.time ? locations.time : "?");
[ddbbcffa]939      g_free(result);
[dca3b27]940      result = p;
941    }
[7d4fbcd]942  }
[ddbbcffa]943  g_free(myuser);
[7d4fbcd]944
[dca3b27]945  return result;
946#else
[d4927a7]947  return g_strdup("");
[be0a79f]948#endif
[7d4fbcd]949}
[bde7714]950
[e19eb97]951void owl_zephyr_addsub(const char *filename, const char *class, const char *inst, const char *recip)
[31e48a3]952{
[be0a79f]953#ifdef HAVE_LIBZEPHYR
[b7ee89b]954  char *line, *subsfile, *s = NULL;
[bde7714]955  FILE *file;
[b7ee89b]956  int duplicate = 0;
[bde7714]957
[b7ee89b]958  line = owl_zephyr_makesubline(class, inst, recip);
[6ea3890]959  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[bde7714]960
[74037d9]961  /* if the file already exists, check to see if the sub is already there */
[b7ee89b]962  file = fopen(subsfile, "r");
[74037d9]963  if (file) {
[b7ee89b]964    while (owl_getline(&s, file)) {
965      if (strcasecmp(s, line) == 0) {
[74037d9]966        owl_function_error("Subscription already present in %s", subsfile);
[b7ee89b]967        duplicate++;
[74037d9]968      }
[bde7714]969    }
[99dabee]970    fclose(file);
[ddbbcffa]971    g_free(s);
[bde7714]972  }
973
[b7ee89b]974  if (!duplicate) {
975    file = fopen(subsfile, "a");
976    if (file) {
977      fputs(line, file);
978      fclose(file);
979      owl_function_makemsg("Subscription added");
980    } else {
981      owl_function_error("Error opening file %s for writing", subsfile);
982    }
[bde7714]983  }
[b7ee89b]984
[ddbbcffa]985  g_free(line);
[be0a79f]986#endif
[bde7714]987}
988
[e19eb97]989void owl_zephyr_delsub(const char *filename, const char *class, const char *inst, const char *recip)
[31e48a3]990{
[be0a79f]991#ifdef HAVE_LIBZEPHYR
[b2a91b6]992  char *line, *subsfile;
[da60ba9]993  int linesdeleted;
[bde7714]994 
995  line=owl_zephyr_makesubline(class, inst, recip);
[b2a91b6]996  line[strlen(line)-1]='\0';
[bde7714]997
[6ea3890]998  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
[b2a91b6]999 
[da60ba9]1000  linesdeleted = owl_util_file_deleteline(subsfile, line, 1);
1001  if (linesdeleted > 0) {
1002    owl_function_makemsg("Subscription removed");
[5fca55f]1003  } else if (linesdeleted == 0) {
[da60ba9]1004    owl_function_error("No subscription present in %s", subsfile);
1005  }
[ddbbcffa]1006  g_free(subsfile);
1007  g_free(line);
[be0a79f]1008#endif
[bde7714]1009}
1010
[b2a91b6]1011/* caller must free the return */
[e19eb97]1012char *owl_zephyr_makesubline(const char *class, const char *inst, const char *recip)
[31e48a3]1013{
[3472845]1014  return g_strdup_printf("%s,%s,%s\n", class, inst, !strcmp(recip, "") ? "*" : recip);
[bde7714]1015}
[31e48a3]1016
1017
1018void owl_zephyr_zlog_in(void)
1019{
[be0a79f]1020#ifdef HAVE_LIBZEPHYR
[7d969f3]1021  char *exposure, *eset;
1022  Code_t ret;
[31e48a3]1023
1024  ZResetAuthentication();
[7d969f3]1025
1026  eset = EXPOSE_REALMVIS;
1027  exposure = ZGetVariable(zstr("exposure"));
1028  if (exposure)
1029    exposure = ZParseExposureLevel(exposure);
1030  if (exposure)
1031    eset = exposure;
[31e48a3]1032   
[7d969f3]1033  ret = ZSetLocation(eset);
1034  if (ret != ZERR_NONE)
1035    owl_function_error("Error setting location: %s", error_message(ret));
[be0a79f]1036#endif
[31e48a3]1037}
1038
1039void owl_zephyr_zlog_out(void)
1040{
[be0a79f]1041#ifdef HAVE_LIBZEPHYR
[7d969f3]1042  Code_t ret;
[31e48a3]1043
1044  ZResetAuthentication();
[7d969f3]1045  ret = ZUnsetLocation();
1046  if (ret != ZERR_NONE)
1047    owl_function_error("Error unsetting location: %s", error_message(ret));
[be0a79f]1048#endif
[31e48a3]1049}
1050
[e19eb97]1051void owl_zephyr_addbuddy(const char *name)
[65ad073]1052{
1053  char *filename;
1054  FILE *file;
1055 
[6ea3890]1056  filename = owl_zephyr_dotfile(".anyone", NULL);
1057  file = fopen(filename, "a");
[ddbbcffa]1058  g_free(filename);
[65ad073]1059  if (!file) {
[ec6ff52]1060    owl_function_error("Error opening zephyr buddy file for append");
[65ad073]1061    return;
1062  }
1063  fprintf(file, "%s\n", name);
1064  fclose(file);
1065}
1066
[e19eb97]1067void owl_zephyr_delbuddy(const char *name)
[65ad073]1068{
1069  char *filename;
1070
[6ea3890]1071  filename = owl_zephyr_dotfile(".anyone", NULL);
[65ad073]1072  owl_util_file_deleteline(filename, name, 0);
[ddbbcffa]1073  g_free(filename);
[65ad073]1074}
[9381782]1075
1076/* return auth string */
[09489b89]1077#ifdef HAVE_LIBZEPHYR
[1077891a]1078const char *owl_zephyr_get_authstr(const ZNotice_t *n)
[9381782]1079{
1080
[f12d199]1081  if (!n) return("UNKNOWN");
1082
1083  if (n->z_auth == ZAUTH_FAILED) {
[9381782]1084    return ("FAILED");
[f12d199]1085  } else if (n->z_auth == ZAUTH_NO) {
[9381782]1086    return ("NO");
[f12d199]1087  } else if (n->z_auth == ZAUTH_YES) {
[9381782]1088    return ("YES");
1089  } else {
1090    return ("UNKNOWN");
[f12d199]1091  }           
[9381782]1092}
[09489b89]1093#else
[1077891a]1094const char *owl_zephyr_get_authstr(const void *n)
[09489b89]1095{
1096  return("");
1097}
1098#endif
[9381782]1099
[2de4f20]1100/* Returns a buffer of subscriptions or an error message.  Caller must
1101 * free the return.
[09489b89]1102 */
[c79a047]1103char *owl_zephyr_getsubs(void)
[09489b89]1104{
1105#ifdef HAVE_LIBZEPHYR
[c73a22d]1106  Code_t ret;
1107  int num, i, one;
[09489b89]1108  ZSubscription_t sub;
[df3a1f4]1109  GString *buf;
[09489b89]1110
[c73a22d]1111  ret = ZRetrieveSubscriptions(0, &num);
1112  if (ret != ZERR_NONE)
1113    return g_strdup_printf("Zephyr: Requesting subscriptions: %s\n", error_message(ret));
1114  if (num == 0)
1115    return g_strdup("Zephyr: No subscriptions retrieved\n");
[09489b89]1116
[df3a1f4]1117  buf = g_string_new("");
[09489b89]1118  for (i=0; i<num; i++) {
[df3a1f4]1119    one = 1;
[09489b89]1120    if ((ret = ZGetSubscriptions(&sub, &one)) != ZERR_NONE) {
1121      ZFlushSubscriptions();
[df3a1f4]1122      g_string_free(buf, true);
[c73a22d]1123      return g_strdup_printf("Zephyr: Getting subscriptions: %s\n", error_message(ret));
[09489b89]1124    } else {
[df3a1f4]1125      /* g_string_append_printf would be backwards. */
[3472845]1126      char *tmp = g_strdup_printf("<%s,%s,%s>\n",
1127                                  sub.zsub_class,
1128                                  sub.zsub_classinst,
1129                                  sub.zsub_recipient);
[df3a1f4]1130      g_string_prepend(buf, tmp);
[ddbbcffa]1131      g_free(tmp);
[09489b89]1132    }
1133  }
1134
1135  ZFlushSubscriptions();
[df3a1f4]1136  return g_string_free(buf, false);
[09489b89]1137#else
[d4927a7]1138  return(g_strdup("Zephyr not available"));
[09489b89]1139#endif
1140}
1141
[e19eb97]1142const char *owl_zephyr_get_variable(const char *var)
[09489b89]1143{
1144#ifdef HAVE_LIBZEPHYR
[712caac]1145  return(ZGetVariable(zstr(var)));
[09489b89]1146#else
1147  return("");
1148#endif
1149}
1150
[e19eb97]1151void owl_zephyr_set_locationinfo(const char *host, const char *val)
[09489b89]1152{
1153#ifdef HAVE_LIBZEPHYR
[712caac]1154  ZInitLocationInfo(zstr(host), zstr(val));
[09489b89]1155#endif
1156}
1157 
[e3d9c77]1158/* Strip a local realm fron the zephyr user name.
1159 * The caller must free the return
1160 */
[e19eb97]1161char *short_zuser(const char *in)
[e3d9c77]1162{
[5d56a27]1163  char *ptr = strrchr(in, '@');
1164  if (ptr && (ptr[1] == '\0' || !strcasecmp(ptr+1, owl_zephyr_get_realm()))) {
1165    return g_strndup(in, ptr - in);
[e3d9c77]1166  }
[5d56a27]1167  return g_strdup(in);
[e3d9c77]1168}
1169
1170/* Append a local realm to the zephyr user name if necessary.
1171 * The caller must free the return.
1172 */
[e19eb97]1173char *long_zuser(const char *in)
[e3d9c77]1174{
[5d56a27]1175  char *ptr = strrchr(in, '@');
1176  if (ptr) {
1177    if (ptr[1])
1178      return g_strdup(in);
1179    /* Ends in @, so assume default realm. */
1180    return g_strdup_printf("%s%s", in, owl_zephyr_get_realm());
[e3d9c77]1181  }
[5d56a27]1182  return g_strdup_printf("%s@%s", in, owl_zephyr_get_realm());
[e3d9c77]1183}
1184
[4e29ecb]1185/* Return the realm of the zephyr user name. Caller does /not/ free the return.
1186 * The string is valid at least as long as the input is.
1187 */
1188const char *zuser_realm(const char *in)
1189{
1190  char *ptr = strrchr(in, '@');
1191  /* If the name has an @ and does not end with @, use that. Otherwise, take
1192   * the default realm. */
1193  return (ptr && ptr[1]) ? (ptr+1) : owl_zephyr_get_realm();
1194}
1195
[e3d9c77]1196/* strip out the instance from a zsender's principal.  Preserves the
[9d21120]1197 * realm if present.  Leave host/ and daemon/ krb5 principals
1198 * alone. Also leave rcmd. and daemon. krb4 principals alone. The
1199 * caller must free the return.
[e3d9c77]1200 */
[e19eb97]1201char *owl_zephyr_smartstripped_user(const char *in)
[e3d9c77]1202{
[9d21120]1203  char *slash, *dot, *realm, *out;
[e3d9c77]1204
[d4927a7]1205  out = g_strdup(in);
[e3d9c77]1206
1207  /* bail immeaditly if we don't have to do any work */
[9d21120]1208  slash = strchr(out, '/');
1209  dot = strchr(out, '.');
1210  if (!slash && !dot) {
[e3d9c77]1211    return(out);
1212  }
[9d21120]1213
1214  if (!strncasecmp(out, OWL_ZEPHYR_NOSTRIP_HOST, strlen(OWL_ZEPHYR_NOSTRIP_HOST)) ||
1215      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_RCMD, strlen(OWL_ZEPHYR_NOSTRIP_RCMD)) ||
1216      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_DAEMON5, strlen(OWL_ZEPHYR_NOSTRIP_DAEMON5)) ||
1217      !strncasecmp(out, OWL_ZEPHYR_NOSTRIP_DAEMON4, strlen(OWL_ZEPHYR_NOSTRIP_DAEMON4))) {
[e3d9c77]1218    return(out);
1219  }
[9d21120]1220
1221  realm = strchr(out, '@');
1222  if (!slash && dot && realm && (dot > realm)) {
1223    /* There's no '/', and the first '.' is in the realm */
[e3d9c77]1224    return(out);
1225  }
1226
[fa4562c]1227  /* remove the realm from out, but hold on to it */
[e3d9c77]1228  if (realm) realm[0]='\0';
1229
1230  /* strip */
[9d21120]1231  if (slash) slash[0] = '\0';  /* krb5 style user/instance */
1232  else if (dot) dot[0] = '\0'; /* krb4 style user.instance */
[e3d9c77]1233
1234  /* reattach the realm if we had one */
1235  if (realm) {
1236    strcat(out, "@");
1237    strcat(out, realm+1);
1238  }
1239
1240  return(out);
1241}
[5a95b69]1242
1243/* read the list of users in 'filename' as a .anyone file, and put the
1244 * names of the zephyr users in the list 'in'.  If 'filename' is NULL,
1245 * use the default .anyone file in the users home directory.  Returns
1246 * -1 on failure, 0 on success.
1247 */
[e19eb97]1248int owl_zephyr_get_anyone_list(owl_list *in, const char *filename)
[5a95b69]1249{
1250#ifdef HAVE_LIBZEPHYR
[b7ee89b]1251  char *ourfile, *tmp, *s = NULL;
[5a95b69]1252  FILE *f;
1253
[6ea3890]1254  ourfile = owl_zephyr_dotfile(".anyone", filename);
[b7ee89b]1255
1256  f = fopen(ourfile, "r");
[5a95b69]1257  if (!f) {
1258    owl_function_error("Error opening file %s: %s", ourfile, strerror(errno) ? strerror(errno) : "");
[ddbbcffa]1259    g_free(ourfile);
[b7ee89b]1260    return -1;
[5a95b69]1261  }
[ddbbcffa]1262  g_free(ourfile);
[5a95b69]1263
[b7ee89b]1264  while (owl_getline_chomp(&s, f)) {
[5a95b69]1265    /* ignore comments, blank lines etc. */
[b7ee89b]1266    if (s[0] == '#' || s[0] == '\0')
1267      continue;
1268
1269    /* ignore from # on */
1270    tmp = strchr(s, '#');
1271    if (tmp)
1272      tmp[0] = '\0';
1273
1274    /* ignore from SPC */
1275    tmp = strchr(s, ' ');
1276    if (tmp)
1277      tmp[0] = '\0';
1278
1279    owl_list_append_element(in, long_zuser(s));
[5a95b69]1280  }
[ddbbcffa]1281  g_free(s);
[5a95b69]1282  fclose(f);
[b7ee89b]1283  return 0;
[5a95b69]1284#else
[b7ee89b]1285  return -1;
[5a95b69]1286#endif
1287}
[13a3c1db]1288
[f25812b]1289#ifdef HAVE_LIBZEPHYR
1290void owl_zephyr_process_pseudologin(ZNotice_t *n)
1291{
1292  owl_message *m;
1293  owl_zbuddylist *zbl;
1294  GList **zaldlist;
1295  GList *zaldptr;
1296  ZAsyncLocateData_t *zald = NULL;
1297  ZLocations_t location;
1298  int numlocs, ret, notify;
1299
1300  /* Find a ZALD to match this notice. */
1301  zaldlist = owl_global_get_zaldlist(&g);
1302  zaldptr = g_list_first(*zaldlist);
1303  while (zaldptr) {
1304    if (ZCompareALDPred(n, zaldptr->data)) {
1305      zald = zaldptr->data;
1306      *zaldlist = g_list_remove(*zaldlist, zaldptr->data);
1307      break;
1308    }
1309    zaldptr = g_list_next(zaldptr);
1310  }
1311  if (zald) {
1312    /* Deal with notice. */
1313    notify = owl_global_get_pseudologin_notify(&g);
1314    zbl = owl_global_get_zephyr_buddylist(&g);
1315    ret = ZParseLocations(n, zald, &numlocs, NULL);
1316    if (ret == ZERR_NONE) {
1317      if (numlocs > 0 && !owl_zbuddylist_contains_user(zbl, zald->user)) {
1318        if (notify) {
1319          numlocs = 1;
1320          ret = ZGetLocations(&location, &numlocs);
1321          if (ret == ZERR_NONE) {
1322            /* Send a PSEUDO LOGIN! */
[96828e4]1323            m = g_new(owl_message, 1);
[f25812b]1324            owl_message_create_pseudo_zlogin(m, 0, zald->user,
1325                                             location.host,
1326                                             location.time,
1327                                             location.tty);
1328            owl_global_messagequeue_addmsg(&g, m);
1329          }
1330          owl_zbuddylist_adduser(zbl, zald->user);
1331          owl_function_debugmsg("owl_function_zephyr_buddy_check: login for %s ", zald->user);
1332        }
1333      } else if (numlocs == 0 && owl_zbuddylist_contains_user(zbl, zald->user)) {
1334        /* Send a PSEUDO LOGOUT! */
1335        if (notify) {
[96828e4]1336          m = g_new(owl_message, 1);
[f25812b]1337          owl_message_create_pseudo_zlogin(m, 1, zald->user, "", "", "");
1338          owl_global_messagequeue_addmsg(&g, m);
1339        }
1340        owl_zbuddylist_deluser(zbl, zald->user);
1341        owl_function_debugmsg("owl_function_zephyr_buddy_check: logout for %s ", zald->user);
1342      }
1343    }
1344    ZFreeALD(zald);
[ddbbcffa]1345    g_free(zald);
[f25812b]1346  }
1347}
1348#else
1349void owl_zephyr_process_pseudologin(void *n)
1350{
1351}
1352#endif
1353
[3687413]1354void owl_zephyr_buddycheck_timer(owl_timer *t, void *data)
1355{
1356  if (owl_global_is_pseudologins(&g)) {
1357    owl_function_debugmsg("Doing zephyr buddy check");
1358    owl_function_zephyr_buddy_check(1);
1359  } else {
1360    owl_function_debugmsg("Warning: owl_zephyr_buddycheck_timer call pointless; timer should have been disabled");
1361  }
1362}
1363
[12e291a]1364/*
1365 * Process zephyrgrams from libzephyr's queue. To prevent starvation,
1366 * process a maximum of OWL_MAX_ZEPHYRGRAMS_TO_PROCESS.
1367 *
1368 * Returns the number of zephyrgrams processed.
1369 */
1370
1371#define OWL_MAX_ZEPHYRGRAMS_TO_PROCESS 20
1372
[e9c6fc8]1373static int _owl_zephyr_process_events(void)
[12e291a]1374{
[13a3c1db]1375  int zpendcount=0;
[12e291a]1376#ifdef HAVE_LIBZEPHYR
[13a3c1db]1377  ZNotice_t notice;
[8ab1f28]1378  Code_t code;
[13a3c1db]1379  owl_message *m=NULL;
1380
[12e291a]1381  while(owl_zephyr_zpending() && zpendcount < OWL_MAX_ZEPHYRGRAMS_TO_PROCESS) {
[13a3c1db]1382    if (owl_zephyr_zpending()) {
[8ab1f28]1383      if ((code = ZReceiveNotice(&notice, NULL)) != ZERR_NONE) {
1384        owl_function_debugmsg("Error: %s while calling ZReceiveNotice\n",
1385                              error_message(code));
1386        continue;
1387      }
[13a3c1db]1388      zpendcount++;
1389
1390      /* is this an ack from a zephyr we sent? */
1391      if (owl_zephyr_notice_is_ack(&notice)) {
1392        owl_zephyr_handle_ack(&notice);
[46c7f5b]1393        ZFreeNotice(&notice);
[13a3c1db]1394        continue;
1395      }
1396
1397      /* if it's a ping and we're not viewing pings then skip it */
1398      if (!owl_global_is_rxping(&g) && !strcasecmp(notice.z_opcode, "ping")) {
[46c7f5b]1399        ZFreeNotice(&notice);
[13a3c1db]1400        continue;
1401      }
1402
[f25812b]1403      /* if it is a LOCATE message, it's for pseudologins. */
1404      if (strcmp(notice.z_opcode, LOCATE_LOCATE) == 0) {
1405        owl_zephyr_process_pseudologin(&notice);
1406        ZFreeNotice(&notice);
1407        continue;
1408      }
1409
[13a3c1db]1410      /* create the new message */
[96828e4]1411      m=g_new(owl_message, 1);
[13a3c1db]1412      owl_message_create_from_znotice(m, &notice);
1413
1414      owl_global_messagequeue_addmsg(&g, m);
1415    }
1416  }
[12e291a]1417#endif
1418  return zpendcount;
[13a3c1db]1419}
1420
[18fdd5f9]1421void owl_zephyr_process_events(const owl_io_dispatch *d, void *data)
[12e291a]1422{
1423  _owl_zephyr_process_events();
1424}
1425
1426int owl_zephyr_pre_select_action(owl_ps_action *a, void *p)
1427{
1428  return _owl_zephyr_process_events();
[13a3c1db]1429}
Note: See TracBrowser for help on using the repository browser.