source: message.c @ f661cee

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