source: message.c @ 51ff997

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