source: message.c @ 8f95fc4

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