source: message.c @ f271129

release-1.10release-1.9
Last change on this file since f271129 was f271129, checked in by Jason Gross <jgross@mit.edu>, 13 years ago
Fix up headers The additions to owl.h and some of the removals were done by Alejandro Sedeño <asedeno@mit.edu> in commit 77a0258b3919468fc9d7f7602588ac427ab36e6c. Notes: * I think owl.c lost the need for sys/time.h when we punted select() in favor of glib's main loop. * We don't actually need to include things like stdarg.h, stdio.h, glib/gstdio.h, glib-object.h. I think they get indirectly included via owl.h and/or glib.h. They're left in (or added in to) the files that use functions/types from them. * I'm not entirely sure what sys/socket.h is doing in message.c. It is there from the initial commit. I suspect it might have had something to do with the call to getnameinfo. message.c compiles without it, but http://pubs.opengroup.org/onlinepubs/009695399/functions/getnameinfo.html suggests that we're supposed to include it? *shrugs* I'm leaving it in, for now. (Rather, I'll leave one copy of the #include in.)
  • Property mode set to 100644
File size: 24.4 KB
Line 
1#include "owl.h"
2#include "filterproc.h"
3#include <sys/socket.h>
4#include <arpa/inet.h>
5
6static owl_fmtext_cache fmtext_cache[OWL_FMTEXT_CACHE_SIZE];
7static owl_fmtext_cache * fmtext_cache_next = fmtext_cache;
8
9void owl_message_init_fmtext_cache(void)
10{
11    int i;
12    for(i = 0; i < OWL_FMTEXT_CACHE_SIZE; i++) {
13        owl_fmtext_init_null(&(fmtext_cache[i].fmtext));
14        fmtext_cache[i].message = NULL;
15    }
16}
17
18static owl_fmtext_cache *owl_message_next_fmtext(void)
19{
20    owl_fmtext_cache * f = fmtext_cache_next;
21    if(fmtext_cache_next->message != NULL) {
22        owl_message_invalidate_format(fmtext_cache_next->message);
23    }
24    fmtext_cache_next++;
25    if(fmtext_cache_next - fmtext_cache == OWL_FMTEXT_CACHE_SIZE)
26        fmtext_cache_next = fmtext_cache;
27    return f;
28}
29
30void owl_message_init(owl_message *m)
31{
32  m->id=owl_global_get_nextmsgid(&g);
33  owl_message_set_direction_none(m);
34  m->delete=0;
35
36  owl_message_set_hostname(m, "");
37  m->attributes = g_ptr_array_new();
38 
39  /* save the time */
40  m->time = time(NULL);
41  m->timestr = owl_util_time_to_timestr(localtime(&m->time));
42
43  m->fmtext = NULL;
44}
45
46/* add the named attribute to the message.  If an attribute with the
47 * name already exists, replace the old value with the new value
48 */
49void owl_message_set_attribute(owl_message *m, const char *attrname, const char *attrvalue)
50{
51  int i;
52  owl_pair *p = NULL, *pair = NULL;
53
54  attrname = g_intern_string(attrname);
55
56  /* look for an existing pair with this key, */
57  for (i = 0; i < m->attributes->len; i++) {
58    p = m->attributes->pdata[i];
59    if (owl_pair_get_key(p) == attrname) {
60      g_free(owl_pair_get_value(p));
61      pair = p;
62      break;
63    }
64  }
65
66  if(pair ==  NULL) {
67    pair = g_new(owl_pair, 1);
68    owl_pair_create(pair, attrname, NULL);
69    g_ptr_array_add(m->attributes, pair);
70  }
71  owl_pair_set_value(pair, owl_validate_or_convert(attrvalue));
72}
73
74/* return the value associated with the named attribute, or NULL if
75 * the attribute does not exist
76 */
77const char *owl_message_get_attribute_value(const owl_message *m, const char *attrname)
78{
79  int i;
80  owl_pair *p;
81  GQuark quark;
82
83  quark = g_quark_try_string(attrname);
84  if (quark == 0)
85    /* don't bother inserting into string table */
86    return NULL;
87  attrname = g_quark_to_string(quark);
88
89  for (i = 0; i < m->attributes->len; i++) {
90    p = m->attributes->pdata[i];
91    if (owl_pair_get_key(p) == attrname) {
92      return(owl_pair_get_value(p));
93    }
94  }
95
96  /*
97  owl_function_debugmsg("No attribute %s found for message %i",
98                        attrname,
99                        owl_message_get_id(m));
100  */
101  return(NULL);
102}
103
104/* We cheat and indent it for now, since we really want this for
105 * the 'info' function.  Later there should just be a generic
106 * function to indent fmtext.
107 */
108void owl_message_attributes_tofmtext(const owl_message *m, owl_fmtext *fm) {
109  int i;
110  owl_pair *p;
111  char *buff, *tmpbuff;
112
113  owl_fmtext_init_null(fm);
114
115  for (i = 0; i < m->attributes->len; i++) {
116    p = m->attributes->pdata[i];
117
118    buff = g_strdup(owl_pair_get_value(p));
119    if (buff) {
120      tmpbuff = owl_text_indent(buff, 19, false);
121      g_free(buff);
122      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), tmpbuff);
123      g_free(tmpbuff);
124    }
125
126    if(buff == NULL) {
127      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), "<error>");
128      if(buff == NULL)
129        buff=g_strdup("   <error>\n");
130    }
131    owl_fmtext_append_normal(fm, buff);
132    g_free(buff);
133  }
134}
135
136void owl_message_invalidate_format(owl_message *m)
137{
138  if(m->fmtext) {
139    m->fmtext->message = NULL;
140    owl_fmtext_clear(&(m->fmtext->fmtext));
141    m->fmtext=NULL;
142  }
143}
144
145owl_fmtext *owl_message_get_fmtext(owl_message *m)
146{
147  owl_message_format(m);
148  return(&(m->fmtext->fmtext));
149}
150
151void owl_message_format(owl_message *m)
152{
153  const owl_style *s;
154  const owl_view *v;
155
156  if (!m->fmtext) {
157    m->fmtext = owl_message_next_fmtext();
158    m->fmtext->message = m;
159    /* for now we assume there's just the one view and use that style */
160    v=owl_global_get_current_view(&g);
161    s=owl_view_get_style(v);
162
163    owl_style_get_formattext(s, &(m->fmtext->fmtext), m);
164  }
165}
166
167void owl_message_set_class(owl_message *m, const char *class)
168{
169  owl_message_set_attribute(m, "class", class);
170}
171
172const char *owl_message_get_class(const owl_message *m)
173{
174  const char *class;
175
176  class=owl_message_get_attribute_value(m, "class");
177  if (!class) return("");
178  return(class);
179}
180
181void owl_message_set_instance(owl_message *m, const char *inst)
182{
183  owl_message_set_attribute(m, "instance", inst);
184}
185
186const char *owl_message_get_instance(const owl_message *m)
187{
188  const char *instance;
189
190  instance=owl_message_get_attribute_value(m, "instance");
191  if (!instance) return("");
192  return(instance);
193}
194
195void owl_message_set_sender(owl_message *m, const char *sender)
196{
197  owl_message_set_attribute(m, "sender", sender);
198}
199
200const char *owl_message_get_sender(const owl_message *m)
201{
202  const char *sender;
203
204  sender=owl_message_get_attribute_value(m, "sender");
205  if (!sender) return("");
206  return(sender);
207}
208
209void owl_message_set_zsig(owl_message *m, const char *zsig)
210{
211  owl_message_set_attribute(m, "zsig", zsig);
212}
213
214const char *owl_message_get_zsig(const owl_message *m)
215{
216  const char *zsig;
217
218  zsig=owl_message_get_attribute_value(m, "zsig");
219  if (!zsig) return("");
220  return(zsig);
221}
222
223void owl_message_set_recipient(owl_message *m, const char *recip)
224{
225  owl_message_set_attribute(m, "recipient", recip);
226}
227
228const char *owl_message_get_recipient(const owl_message *m)
229{
230  /* this is stupid for outgoing messages, we need to fix it. */
231
232  const char *recip;
233
234  recip=owl_message_get_attribute_value(m, "recipient");
235  if (!recip) return("");
236  return(recip);
237}
238
239void owl_message_set_realm(owl_message *m, const char *realm)
240{
241  owl_message_set_attribute(m, "realm", realm);
242}
243
244const char *owl_message_get_realm(const owl_message *m)
245{
246  const char *realm;
247 
248  realm=owl_message_get_attribute_value(m, "realm");
249  if (!realm) return("");
250  return(realm);
251}
252
253void owl_message_set_body(owl_message *m, const char *body)
254{
255  owl_message_set_attribute(m, "body", body);
256}
257
258const char *owl_message_get_body(const owl_message *m)
259{
260  const char *body;
261
262  body=owl_message_get_attribute_value(m, "body");
263  if (!body) return("");
264  return(body);
265}
266
267
268void owl_message_set_opcode(owl_message *m, const char *opcode)
269{
270  owl_message_set_attribute(m, "opcode", opcode);
271}
272
273const char *owl_message_get_opcode(const owl_message *m)
274{
275  const char *opcode;
276
277  opcode=owl_message_get_attribute_value(m, "opcode");
278  if (!opcode) return("");
279  return(opcode);
280}
281
282
283void owl_message_set_islogin(owl_message *m)
284{
285  owl_message_set_attribute(m, "loginout", "login");
286}
287
288
289void owl_message_set_islogout(owl_message *m)
290{
291  owl_message_set_attribute(m, "loginout", "logout");
292}
293
294int owl_message_is_loginout(const owl_message *m)
295{
296  const char *res;
297
298  res=owl_message_get_attribute_value(m, "loginout");
299  if (!res) return(0);
300  return(1);
301}
302
303int owl_message_is_login(const owl_message *m)
304{
305  const char *res;
306
307  res=owl_message_get_attribute_value(m, "loginout");
308  if (!res) return(0);
309  if (!strcmp(res, "login")) return(1);
310  return(0);
311}
312
313
314int owl_message_is_logout(const owl_message *m)
315{
316  const char *res;
317
318  res=owl_message_get_attribute_value(m, "loginout");
319  if (!res) return(0);
320  if (!strcmp(res, "logout")) return(1);
321  return(0);
322}
323
324void owl_message_set_isprivate(owl_message *m)
325{
326  owl_message_set_attribute(m, "isprivate", "true");
327}
328
329int owl_message_is_private(const owl_message *m)
330{
331  const char *res;
332
333  res=owl_message_get_attribute_value(m, "isprivate");
334  if (!res) return(0);
335  return !strcmp(res, "true");
336}
337
338const char *owl_message_get_timestr(const owl_message *m)
339{
340  if (m->timestr) return(m->timestr);
341  return("");
342}
343
344void owl_message_set_type_admin(owl_message *m)
345{
346  owl_message_set_attribute(m, "type", "admin");
347}
348
349void owl_message_set_type_loopback(owl_message *m)
350{
351  owl_message_set_attribute(m, "type", "loopback");
352}
353
354void owl_message_set_type_zephyr(owl_message *m)
355{
356  owl_message_set_attribute(m, "type", "zephyr");
357}
358
359void owl_message_set_type_aim(owl_message *m)
360{
361  owl_message_set_attribute(m, "type", "AIM");
362}
363
364void owl_message_set_type(owl_message *m, const char* type)
365{
366  owl_message_set_attribute(m, "type", type);
367}
368
369int owl_message_is_type(const owl_message *m, const char *type) {
370  const char * t = owl_message_get_attribute_value(m, "type");
371  if(!t) return 0;
372  return !strcasecmp(t, type);
373}
374                                               
375int owl_message_is_type_admin(const owl_message *m)
376{
377  return owl_message_is_type(m, "admin");
378}
379
380int owl_message_is_type_zephyr(const owl_message *m)
381{
382  return owl_message_is_type(m, "zephyr");
383}
384
385int owl_message_is_type_aim(const owl_message *m)
386{
387  return owl_message_is_type(m, "aim");
388}
389
390/* XXX TODO: deprecate this */
391int owl_message_is_type_jabber(const owl_message *m)
392{
393  return owl_message_is_type(m, "jabber");
394}
395
396int owl_message_is_type_loopback(const owl_message *m)
397{
398  return owl_message_is_type(m, "loopback");
399}
400
401int owl_message_is_pseudo(const owl_message *m)
402{
403  if (owl_message_get_attribute_value(m, "pseudo")) return(1);
404  return(0);
405}
406
407const char *owl_message_get_text(owl_message *m)
408{
409  owl_message_format(m);
410  return(owl_fmtext_get_text(&(m->fmtext->fmtext)));
411}
412
413void owl_message_set_direction_in(owl_message *m)
414{
415  m->direction=OWL_MESSAGE_DIRECTION_IN;
416}
417
418void owl_message_set_direction_out(owl_message *m)
419{
420  m->direction=OWL_MESSAGE_DIRECTION_OUT;
421}
422
423void owl_message_set_direction_none(owl_message *m)
424{
425  m->direction=OWL_MESSAGE_DIRECTION_NONE;
426}
427
428void owl_message_set_direction(owl_message *m, int direction)
429{
430  m->direction=direction;
431}
432
433int owl_message_is_direction_in(const owl_message *m)
434{
435  if (m->direction==OWL_MESSAGE_DIRECTION_IN) return(1);
436  return(0);
437}
438
439int owl_message_is_direction_out(const owl_message *m)
440{
441  if (m->direction==OWL_MESSAGE_DIRECTION_OUT) return(1);
442  return(0);
443}
444
445int owl_message_is_direction_none(const owl_message *m)
446{
447  if (m->direction==OWL_MESSAGE_DIRECTION_NONE) return(1);
448  return(0);
449}
450
451int owl_message_get_numlines(owl_message *m)
452{
453  if (m == NULL) return(0);
454  owl_message_format(m);
455  return(owl_fmtext_num_lines(&(m->fmtext->fmtext)));
456}
457
458void owl_message_mark_delete(owl_message *m)
459{
460  if (m == NULL) return;
461  m->delete=1;
462}
463
464void owl_message_unmark_delete(owl_message *m)
465{
466  if (m == NULL) return;
467  m->delete=0;
468}
469
470const char *owl_message_get_zwriteline(const owl_message *m)
471{
472  const char *z = owl_message_get_attribute_value(m, "zwriteline");
473  if (!z) return "";
474  return z;
475}
476
477void owl_message_set_zwriteline(owl_message *m, const char *line)
478{
479  owl_message_set_attribute(m, "zwriteline", line);
480}
481
482int owl_message_is_delete(const owl_message *m)
483{
484  if (m == NULL) return(0);
485  if (m->delete==1) return(1);
486  return(0);
487}
488
489#ifdef HAVE_LIBZEPHYR
490const ZNotice_t *owl_message_get_notice(const owl_message *m)
491{
492  return(&(m->notice));
493}
494#else
495void *owl_message_get_notice(const owl_message *m)
496{
497  return(NULL);
498}
499#endif
500
501void owl_message_set_hostname(owl_message *m, const char *hostname)
502{
503  m->hostname = g_intern_string(hostname);
504}
505
506const char *owl_message_get_hostname(const owl_message *m)
507{
508  return(m->hostname);
509}
510
511void owl_message_curs_waddstr(owl_message *m, WINDOW *win, int aline, int bline, int acol, int bcol, int fgcolor, int bgcolor)
512{
513  owl_fmtext a, b;
514
515  /* this will ensure that our cached copy is up to date */
516  owl_message_format(m);
517
518  owl_fmtext_init_null(&a);
519  owl_fmtext_init_null(&b);
520 
521  owl_fmtext_truncate_lines(&(m->fmtext->fmtext), aline, bline-aline, &a);
522  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
523
524  owl_fmtext_curs_waddstr(&b, win, OWL_FMTEXT_ATTR_NONE, fgcolor, bgcolor);
525
526  owl_fmtext_cleanup(&a);
527  owl_fmtext_cleanup(&b);
528}
529
530int owl_message_is_personal(const owl_message *m)
531{
532  const owl_filter * f = owl_global_get_filter(&g, "personal");
533  if(!f) {
534      owl_function_error("personal filter is not defined");
535      return (0);
536  }
537  return owl_filter_message_match(f, m);
538}
539
540int owl_message_is_question(const owl_message *m)
541{
542  if(!owl_message_is_type_admin(m)) return 0;
543  if(owl_message_get_attribute_value(m, "question") != NULL) return 1;
544  return 0;
545}
546
547int owl_message_is_answered(const owl_message *m) {
548  const char *q;
549  if(!owl_message_is_question(m)) return 0;
550  q = owl_message_get_attribute_value(m, "question");
551  if(!q) return 0;
552  return !strcmp(q, "answered");
553}
554
555void owl_message_set_isanswered(owl_message *m) {
556  owl_message_set_attribute(m, "question", "answered");
557}
558
559int owl_message_is_mail(const owl_message *m)
560{
561  if (owl_message_is_type_zephyr(m)) {
562    if (!strcasecmp(owl_message_get_class(m), "mail") && owl_message_is_private(m)) {
563      return(1);
564    } else {
565      return(0);
566    }
567  }
568  return(0);
569}
570
571/* caller must free return value. */
572CALLER_OWN char *owl_message_get_cc(const owl_message *m)
573{
574  const char *cur;
575  char *out, *end;
576
577  cur = owl_message_get_body(m);
578  while (*cur && *cur==' ') cur++;
579  if (strncasecmp(cur, "cc:", 3)) return(NULL);
580  cur+=3;
581  while (*cur && *cur==' ') cur++;
582  out = g_strdup(cur);
583  end = strchr(out, '\n');
584  if (end) end[0] = '\0';
585  return(out);
586}
587
588/* caller must free return value */
589CALLER_OWN GList *owl_message_get_cc_without_recipient(const owl_message *m)
590{
591  char *cc, *shortuser, *recip;
592  const char *user;
593  GList *out = NULL;
594
595  cc = owl_message_get_cc(m);
596  if (cc == NULL)
597    return NULL;
598
599  recip = short_zuser(owl_message_get_recipient(m));
600
601  user = strtok(cc, " ");
602  while (user != NULL) {
603    shortuser = short_zuser(user);
604    if (strcasecmp(shortuser, recip) != 0) {
605      out = g_list_prepend(out, g_strdup(user));
606    }
607    g_free(shortuser);
608    user = strtok(NULL, " ");
609  }
610
611  g_free(recip);
612  g_free(cc);
613
614  return(out);
615}
616
617int owl_message_get_id(const owl_message *m)
618{
619  return(m->id);
620}
621
622const char *owl_message_get_type(const owl_message *m) {
623  const char * type = owl_message_get_attribute_value(m, "type");
624  if(!type) {
625    return "generic";
626  }
627  return type;
628}
629
630const char *owl_message_get_direction(const owl_message *m) {
631  switch (m->direction) {
632  case OWL_MESSAGE_DIRECTION_IN:
633    return("in");
634  case OWL_MESSAGE_DIRECTION_OUT:
635    return("out");
636  case OWL_MESSAGE_DIRECTION_NONE:
637    return("none");
638  default:
639    return("unknown");
640  }
641}
642
643int owl_message_parse_direction(const char *d) {
644  if(!strcmp(d, "in")) {
645    return OWL_MESSAGE_DIRECTION_IN;
646  } else if(!strcmp(d, "out")) {
647    return OWL_MESSAGE_DIRECTION_OUT;
648  } else {
649    return OWL_MESSAGE_DIRECTION_NONE;
650  }
651}
652
653
654const char *owl_message_get_login(const owl_message *m) {
655  if (owl_message_is_login(m)) {
656    return "login";
657  } else if (owl_message_is_logout(m)) {
658    return "logout";
659  } else {
660    return "none";
661  }
662}
663
664
665const char *owl_message_get_header(const owl_message *m) {
666  return owl_message_get_attribute_value(m, "adminheader");
667}
668
669/* return 1 if the message contains "string", 0 otherwise.  This is
670 * case insensitive because the functions it uses are
671 */
672int owl_message_search(owl_message *m, const owl_regex *re)
673{
674
675  owl_message_format(m); /* is this necessary? */
676 
677  return owl_fmtext_search(&(m->fmtext->fmtext), re, 0) >= 0;
678}
679
680
681/* if loginout == -1 it's a logout message
682 *                 0 it's not a login/logout message
683 *                 1 it's a login message
684 */
685void owl_message_create_aim(owl_message *m, const char *sender, const char *recipient, const char *text, int direction, int loginout)
686{
687  owl_message_init(m);
688  owl_message_set_body(m, text);
689  owl_message_set_sender(m, sender);
690  owl_message_set_recipient(m, recipient);
691  owl_message_set_type_aim(m);
692
693  if (direction==OWL_MESSAGE_DIRECTION_IN) {
694    owl_message_set_direction_in(m);
695  } else if (direction==OWL_MESSAGE_DIRECTION_OUT) {
696    owl_message_set_direction_out(m);
697  }
698
699  /* for now all messages that aren't loginout are private */
700  if (!loginout) {
701    owl_message_set_isprivate(m);
702  }
703
704  if (loginout==-1) {
705    owl_message_set_islogout(m);
706  } else if (loginout==1) {
707    owl_message_set_islogin(m);
708  }
709}
710
711void owl_message_create_admin(owl_message *m, const char *header, const char *text)
712{
713  owl_message_init(m);
714  owl_message_set_type_admin(m);
715  owl_message_set_body(m, text);
716  owl_message_set_attribute(m, "adminheader", header); /* just a hack for now */
717}
718
719/* caller should set the direction */
720void owl_message_create_loopback(owl_message *m, const char *text)
721{
722  owl_message_init(m);
723  owl_message_set_type_loopback(m);
724  owl_message_set_body(m, text);
725  owl_message_set_sender(m, "loopsender");
726  owl_message_set_recipient(m, "looprecip");
727  owl_message_set_isprivate(m);
728}
729
730void owl_message_save_ccs(owl_message *m) {
731  GList *cc;
732  char *tmp;
733
734  cc = owl_message_get_cc_without_recipient(m);
735
736  if (cc != NULL) {
737    GString *recips = g_string_new("");
738    cc = g_list_prepend(cc, short_zuser(owl_message_get_sender(m)));
739    cc = g_list_prepend(cc, short_zuser(owl_message_get_recipient(m)));
740    cc = g_list_sort(cc, (GCompareFunc)strcasecmp);
741
742    while(cc != NULL) {
743      /* Collapse any identical entries */
744      while (cc->next && strcasecmp(cc->data, cc->next->data) == 0) {
745        g_free(cc->data);
746        cc = g_list_delete_link(cc, cc);
747      }
748
749      tmp = short_zuser(cc->data);
750      g_string_append(recips, tmp);
751
752      g_free(tmp);
753      g_free(cc->data);
754      cc = g_list_delete_link(cc, cc);
755
756      if (cc)
757        g_string_append_c(recips, ' ');
758    }
759
760    owl_message_set_attribute(m, "zephyr_ccs", recips->str);
761    g_string_free(recips, true);
762  }
763}
764
765#ifdef HAVE_LIBZEPHYR
766void owl_message_create_from_znotice(owl_message *m, const ZNotice_t *n)
767{
768#ifdef ZNOTICE_SOCKADDR
769  char hbuf[NI_MAXHOST];
770#else /* !ZNOTICE_SOCKADDR */
771  struct hostent *hent;
772#endif /* ZNOTICE_SOCKADDR */
773  char *tmp, *tmp2;
774  int len;
775
776  owl_message_init(m);
777 
778  owl_message_set_type_zephyr(m);
779  owl_message_set_direction_in(m);
780 
781  /* first save the full notice */
782  m->notice = *n;
783
784  /* a little gross, we'll replace \r's with ' ' for now */
785  owl_zephyr_hackaway_cr(&(m->notice));
786 
787  /* save the time, we need to nuke the string saved by message_init */
788  if (m->timestr) g_free(m->timestr);
789  m->time = n->z_time.tv_sec;
790  m->timestr = owl_util_time_to_timestr(localtime(&m->time));
791
792  /* set other info */
793  owl_message_set_sender(m, n->z_sender);
794  owl_message_set_class(m, n->z_class);
795  owl_message_set_instance(m, n->z_class_inst);
796  owl_message_set_recipient(m, n->z_recipient);
797  if (n->z_opcode) {
798    owl_message_set_opcode(m, n->z_opcode);
799  } else {
800    owl_message_set_opcode(m, "");
801  }
802  owl_message_set_zsig(m, owl_zephyr_get_zsig(n, &len));
803
804  owl_message_set_realm(m, zuser_realm(n->z_recipient));
805
806  /* Set the "isloginout" attribute if it's a login message */
807  if (!strcasecmp(n->z_class, "login") || !strcasecmp(n->z_class, OWL_WEBZEPHYR_CLASS)) {
808    if (!strcasecmp(n->z_opcode, "user_login") || !strcasecmp(n->z_opcode, "user_logout")) {
809      tmp=owl_zephyr_get_field(n, 1);
810      owl_message_set_attribute(m, "loginhost", tmp);
811      g_free(tmp);
812
813      tmp=owl_zephyr_get_field(n, 3);
814      owl_message_set_attribute(m, "logintty", tmp);
815      g_free(tmp);
816    }
817
818    if (!strcasecmp(n->z_opcode, "user_login")) {
819      owl_message_set_islogin(m);
820    } else if (!strcasecmp(n->z_opcode, "user_logout")) {
821      owl_message_set_islogout(m);
822    }
823  }
824
825 
826  /* set the "isprivate" attribute if it's a private zephyr.
827   ``private'' means recipient is non-empty and doesn't start wit
828   `@' */
829  if (*n->z_recipient && *n->z_recipient != '@') {
830    owl_message_set_isprivate(m);
831  }
832
833  /* set the "isauto" attribute if it's an autoreply */
834  if (!strcasecmp(n->z_message, "Automated reply:") ||
835      !strcasecmp(n->z_opcode, "auto")) {
836    owl_message_set_attribute(m, "isauto", "");
837  }
838
839  /* save the hostname */
840#ifdef ZNOTICE_SOCKADDR
841  owl_function_debugmsg("About to do getnameinfo");
842  if (getnameinfo(&n->z_sender_sockaddr.sa, sizeof(n->z_sender_sockaddr), hbuf, sizeof(hbuf), NULL, 0, 0) == 0)
843    owl_message_set_hostname(m, hbuf);
844#else /* !ZNOTICE_SOCKADDR */
845  owl_function_debugmsg("About to do gethostbyaddr");
846  hent = gethostbyaddr(&n->z_uid.zuid_addr, sizeof(n->z_uid.zuid_addr), AF_INET);
847  if (hent && hent->h_name)
848    owl_message_set_hostname(m, hent->h_name);
849  else
850    owl_message_set_hostname(m, inet_ntoa(n->z_sender_addr));
851#endif /* ZNOTICE_SOCKADDR */
852
853  /* set the body */
854  tmp=owl_zephyr_get_message(n, m);
855  if (owl_global_is_newlinestrip(&g)) {
856    tmp2=owl_util_stripnewlines(tmp);
857    owl_message_set_body(m, tmp2);
858    g_free(tmp2);
859  } else {
860    owl_message_set_body(m, tmp);
861  }
862  g_free(tmp);
863
864  /* if zcrypt is enabled try to decrypt the message */
865  if (owl_global_is_zcrypt(&g) && !strcasecmp(n->z_opcode, "crypt")) {
866    const char *argv[] = {
867      "zcrypt",
868      "-D",
869      "-c", owl_message_get_class(m),
870      "-i", owl_message_get_instance(m),
871      NULL
872    };
873    char *out;
874    int rv;
875    int status;
876    char *zcrypt;
877
878    zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
879
880    rv = call_filter(zcrypt, argv, owl_message_get_body(m), &out, &status);
881    g_free(zcrypt);
882
883    if(!rv && !status) {
884      int len = strlen(out);
885      if(len >= 8 && !strcmp(out + len - 8, "**END**\n")) {
886        out[len - 8] = 0;
887      }
888      owl_message_set_body(m, out);
889      g_free(out);
890    } else if(out) {
891      g_free(out);
892    }
893  }
894
895  owl_message_save_ccs(m);
896}
897#else
898void owl_message_create_from_znotice(owl_message *m, const void *n)
899{
900}
901#endif
902
903/* If 'direction' is '0' it is a login message, '1' is a logout message. */
904void owl_message_create_pseudo_zlogin(owl_message *m, int direction, const char *user, const char *host, const char *time, const char *tty)
905{
906  char *longuser;
907
908#ifdef HAVE_LIBZEPHYR
909  memset(&(m->notice), 0, sizeof(ZNotice_t));
910#endif
911 
912  longuser=long_zuser(user);
913 
914  owl_message_init(m);
915 
916  owl_message_set_type_zephyr(m);
917  owl_message_set_direction_in(m);
918
919  owl_message_set_attribute(m, "pseudo", "");
920  owl_message_set_attribute(m, "loginhost", host ? host : "");
921  owl_message_set_attribute(m, "logintty", tty ? tty : "");
922
923  owl_message_set_sender(m, longuser);
924  owl_message_set_class(m, "LOGIN");
925  owl_message_set_instance(m, longuser);
926  owl_message_set_recipient(m, "");
927  if (direction==0) {
928    owl_message_set_opcode(m, "USER_LOGIN");
929    owl_message_set_islogin(m);
930  } else if (direction==1) {
931    owl_message_set_opcode(m, "USER_LOGOUT");
932    owl_message_set_islogout(m);
933  }
934
935  owl_message_set_realm(m, zuser_realm(longuser));
936
937  owl_message_set_body(m, "<uninitialized>");
938
939  /* save the hostname */
940  owl_function_debugmsg("create_pseudo_login: host is %s", host ? host : "");
941  owl_message_set_hostname(m, host ? host : "");
942  g_free(longuser);
943}
944
945void owl_message_create_from_zwrite(owl_message *m, const owl_zwrite *z, const char *body, int recip_index)
946{
947  char *replyline;
948 
949  owl_message_init(m);
950
951  /* set things */
952  owl_message_set_direction_out(m);
953  owl_message_set_type_zephyr(m);
954  owl_message_set_sender(m, owl_zephyr_get_sender());
955  owl_message_set_class(m, owl_zwrite_get_class(z));
956  owl_message_set_instance(m, owl_zwrite_get_instance(z));
957  if (recip_index < owl_zwrite_get_numrecips(z)) {
958    char *zuser = owl_zwrite_get_recip_n_with_realm(z, recip_index);
959    char *longzuser = long_zuser(zuser);
960    owl_message_set_recipient(m, longzuser);
961    owl_message_set_realm(m, zuser_realm(longzuser));
962    g_free(longzuser);
963    g_free(zuser);
964  } else {
965    /* TODO: We should maybe munge this into the case above, as that comparison
966     * is a little overly clever. It's also not clear this codepath ever runs
967     * anyway. */
968    const char *realm = owl_zwrite_get_realm(z);
969    owl_message_set_realm(m, realm[0] ? realm : owl_zephyr_get_realm());
970  }
971  owl_message_set_opcode(m, owl_zwrite_get_opcode(z));
972
973  /* Although not strictly the zwriteline, anyone using the unsantized version
974   * of it probably has a bug. */
975  replyline = owl_zwrite_get_replyline(z, recip_index);
976  owl_message_set_zwriteline(m, replyline);
977  g_free(replyline);
978
979  owl_message_set_body(m, body);
980  owl_message_set_zsig(m, owl_zwrite_get_zsig(z));
981 
982  /* save the hostname */
983  owl_message_set_hostname(m, g_get_host_name());
984
985  /* set the "isprivate" attribute if it's a private zephyr. */
986  if (owl_zwrite_is_personal(z)) {
987    owl_message_set_isprivate(m);
988  }
989
990  owl_message_save_ccs(m);
991}
992
993void owl_message_cleanup(owl_message *m)
994{
995  int i;
996  owl_pair *p;
997#ifdef HAVE_LIBZEPHYR   
998  if (owl_message_is_type_zephyr(m) && owl_message_is_direction_in(m)) {
999    ZFreeNotice(&(m->notice));
1000  }
1001#endif
1002  if (m->timestr) g_free(m->timestr);
1003
1004  /* free all the attributes */
1005  for (i = 0; i < m->attributes->len; i++) {
1006    p = m->attributes->pdata[i];
1007    g_free(owl_pair_get_value(p));
1008    g_free(p);
1009  }
1010
1011  g_ptr_array_free(m->attributes, true);
1012 
1013  owl_message_invalidate_format(m);
1014}
1015
1016void owl_message_delete(owl_message *m)
1017{
1018  owl_message_cleanup(m);
1019  g_free(m);
1020}
Note: See TracBrowser for help on using the repository browser.