source: message.c @ 4fd3c04

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