source: message.c @ 499224d

release-1.10release-1.9
Last change on this file since 499224d was 2354e9a, checked in by David Benjamin <davidben@mit.edu>, 12 years ago
If zcrypt fails to decrypt, strip away the zcrypt opcode Otherwise you can make a message look encrypted by sending it with a faked 'crypt' opcode. It also confuses the reply command. Replace it with 'failed-decrypt' just so it shows up in the UI somehow. Perhaps someone can write perl code to retry zcrypt on all messages with that opcode. Also has the side effect of marking gibberish so the user has some hope of realizing what happened if they sub to a zcrypted class without the key. And initialize out to NULL since there's actually a codepath where that value never gets set. Reported-by: Melissa Hunt <wings@mit.edu>
  • Property mode set to 100644
File size: 24.7 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  m->attributes = g_ptr_array_new();
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  int i;
57  owl_pair *p = NULL, *pair = NULL;
58
59  attrname = g_intern_string(attrname);
60
61  /* look for an existing pair with this key, */
62  for (i = 0; i < m->attributes->len; i++) {
63    p = m->attributes->pdata[i];
64    if (owl_pair_get_key(p) == attrname) {
65      g_free(owl_pair_get_value(p));
66      pair = p;
67      break;
68    }
69  }
70
71  if(pair ==  NULL) {
72    pair = g_new(owl_pair, 1);
73    owl_pair_create(pair, attrname, NULL);
74    g_ptr_array_add(m->attributes, pair);
75  }
76  owl_pair_set_value(pair, owl_validate_or_convert(attrvalue));
77}
78
79/* return the value associated with the named attribute, or NULL if
80 * the attribute does not exist
81 */
82const char *owl_message_get_attribute_value(const owl_message *m, const char *attrname)
83{
84  int i;
85  owl_pair *p;
86  GQuark quark;
87
88  quark = g_quark_try_string(attrname);
89  if (quark == 0)
90    /* don't bother inserting into string table */
91    return NULL;
92  attrname = g_quark_to_string(quark);
93
94  for (i = 0; i < m->attributes->len; i++) {
95    p = m->attributes->pdata[i];
96    if (owl_pair_get_key(p) == attrname) {
97      return(owl_pair_get_value(p));
98    }
99  }
100
101  /*
102  owl_function_debugmsg("No attribute %s found for message %i",
103                        attrname,
104                        owl_message_get_id(m));
105  */
106  return(NULL);
107}
108
109/* We cheat and indent it for now, since we really want this for
110 * the 'info' function.  Later there should just be a generic
111 * function to indent fmtext.
112 */
113void owl_message_attributes_tofmtext(const owl_message *m, owl_fmtext *fm) {
114  int i;
115  owl_pair *p;
116  char *buff, *tmpbuff;
117
118  owl_fmtext_init_null(fm);
119
120  for (i = 0; i < m->attributes->len; i++) {
121    p = m->attributes->pdata[i];
122
123    buff = g_strdup(owl_pair_get_value(p));
124    if (buff) {
125      tmpbuff = owl_text_indent(buff, 19, false);
126      g_free(buff);
127      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), tmpbuff);
128      g_free(tmpbuff);
129    }
130
131    if(buff == NULL) {
132      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), "<error>");
133      if(buff == NULL)
134        buff=g_strdup("   <error>\n");
135    }
136    owl_fmtext_append_normal(fm, buff);
137    g_free(buff);
138  }
139}
140
141void owl_message_invalidate_format(owl_message *m)
142{
143  if(m->fmtext) {
144    m->fmtext->message = NULL;
145    owl_fmtext_clear(&(m->fmtext->fmtext));
146    m->fmtext=NULL;
147  }
148}
149
150owl_fmtext *owl_message_get_fmtext(owl_message *m)
151{
152  owl_message_format(m);
153  return(&(m->fmtext->fmtext));
154}
155
156void owl_message_format(owl_message *m)
157{
158  const owl_style *s;
159  const owl_view *v;
160
161  if (!m->fmtext) {
162    m->fmtext = owl_message_next_fmtext();
163    m->fmtext->message = m;
164    /* for now we assume there's just the one view and use that style */
165    v=owl_global_get_current_view(&g);
166    s=owl_view_get_style(v);
167
168    owl_style_get_formattext(s, &(m->fmtext->fmtext), m);
169  }
170}
171
172void owl_message_set_class(owl_message *m, const char *class)
173{
174  owl_message_set_attribute(m, "class", class);
175}
176
177const char *owl_message_get_class(const owl_message *m)
178{
179  const char *class;
180
181  class=owl_message_get_attribute_value(m, "class");
182  if (!class) return("");
183  return(class);
184}
185
186void owl_message_set_instance(owl_message *m, const char *inst)
187{
188  owl_message_set_attribute(m, "instance", inst);
189}
190
191const char *owl_message_get_instance(const owl_message *m)
192{
193  const char *instance;
194
195  instance=owl_message_get_attribute_value(m, "instance");
196  if (!instance) return("");
197  return(instance);
198}
199
200void owl_message_set_sender(owl_message *m, const char *sender)
201{
202  owl_message_set_attribute(m, "sender", sender);
203}
204
205const char *owl_message_get_sender(const owl_message *m)
206{
207  const char *sender;
208
209  sender=owl_message_get_attribute_value(m, "sender");
210  if (!sender) return("");
211  return(sender);
212}
213
214void owl_message_set_zsig(owl_message *m, const char *zsig)
215{
216  owl_message_set_attribute(m, "zsig", zsig);
217}
218
219const char *owl_message_get_zsig(const owl_message *m)
220{
221  const char *zsig;
222
223  zsig=owl_message_get_attribute_value(m, "zsig");
224  if (!zsig) return("");
225  return(zsig);
226}
227
228void owl_message_set_recipient(owl_message *m, const char *recip)
229{
230  owl_message_set_attribute(m, "recipient", recip);
231}
232
233const char *owl_message_get_recipient(const owl_message *m)
234{
235  /* this is stupid for outgoing messages, we need to fix it. */
236
237  const char *recip;
238
239  recip=owl_message_get_attribute_value(m, "recipient");
240  if (!recip) return("");
241  return(recip);
242}
243
244void owl_message_set_realm(owl_message *m, const char *realm)
245{
246  owl_message_set_attribute(m, "realm", realm);
247}
248
249const char *owl_message_get_realm(const owl_message *m)
250{
251  const char *realm;
252 
253  realm=owl_message_get_attribute_value(m, "realm");
254  if (!realm) return("");
255  return(realm);
256}
257
258void owl_message_set_body(owl_message *m, const char *body)
259{
260  owl_message_set_attribute(m, "body", body);
261}
262
263const char *owl_message_get_body(const owl_message *m)
264{
265  const char *body;
266
267  body=owl_message_get_attribute_value(m, "body");
268  if (!body) return("");
269  return(body);
270}
271
272
273void owl_message_set_opcode(owl_message *m, const char *opcode)
274{
275  owl_message_set_attribute(m, "opcode", opcode);
276}
277
278const char *owl_message_get_opcode(const owl_message *m)
279{
280  const char *opcode;
281
282  opcode=owl_message_get_attribute_value(m, "opcode");
283  if (!opcode) return("");
284  return(opcode);
285}
286
287
288void owl_message_set_islogin(owl_message *m)
289{
290  owl_message_set_attribute(m, "loginout", "login");
291}
292
293
294void owl_message_set_islogout(owl_message *m)
295{
296  owl_message_set_attribute(m, "loginout", "logout");
297}
298
299int owl_message_is_loginout(const owl_message *m)
300{
301  const char *res;
302
303  res=owl_message_get_attribute_value(m, "loginout");
304  if (!res) return(0);
305  return(1);
306}
307
308int owl_message_is_login(const owl_message *m)
309{
310  const char *res;
311
312  res=owl_message_get_attribute_value(m, "loginout");
313  if (!res) return(0);
314  if (!strcmp(res, "login")) return(1);
315  return(0);
316}
317
318
319int owl_message_is_logout(const owl_message *m)
320{
321  const char *res;
322
323  res=owl_message_get_attribute_value(m, "loginout");
324  if (!res) return(0);
325  if (!strcmp(res, "logout")) return(1);
326  return(0);
327}
328
329void owl_message_set_isprivate(owl_message *m)
330{
331  owl_message_set_attribute(m, "isprivate", "true");
332}
333
334int owl_message_is_private(const owl_message *m)
335{
336  const char *res;
337
338  res=owl_message_get_attribute_value(m, "isprivate");
339  if (!res) return(0);
340  return !strcmp(res, "true");
341}
342
343const char *owl_message_get_timestr(const owl_message *m)
344{
345  if (m->timestr) return(m->timestr);
346  return("");
347}
348
349CALLER_OWN char *owl_message_format_time(const owl_message *m)
350{
351  return owl_util_format_time(localtime(&m->time));
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->has_notice ? &m->notice : NULL;
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. */
582CALLER_OWN 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 */
599CALLER_OWN 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  m->has_notice = true;
794
795  /* a little gross, we'll replace \r's with ' ' for now */
796  owl_zephyr_hackaway_cr(&(m->notice));
797 
798  /* save the time, we need to nuke the string saved by message_init */
799  if (m->timestr) g_free(m->timestr);
800  m->time = n->z_time.tv_sec;
801  m->timestr = g_strdup(ctime(&m->time));
802  m->timestr[strlen(m->timestr)-1] = '\0';
803
804  /* set other info */
805  owl_message_set_sender(m, n->z_sender);
806  owl_message_set_class(m, n->z_class);
807  owl_message_set_instance(m, n->z_class_inst);
808  owl_message_set_recipient(m, n->z_recipient);
809  if (n->z_opcode) {
810    owl_message_set_opcode(m, n->z_opcode);
811  } else {
812    owl_message_set_opcode(m, "");
813  }
814  owl_message_set_zsig(m, owl_zephyr_get_zsig(n, &len));
815
816  owl_message_set_realm(m, zuser_realm(n->z_recipient));
817
818  /* Set the "isloginout" attribute if it's a login message */
819  if (!strcasecmp(n->z_class, "login") || !strcasecmp(n->z_class, OWL_WEBZEPHYR_CLASS)) {
820    if (!strcasecmp(n->z_opcode, "user_login") || !strcasecmp(n->z_opcode, "user_logout")) {
821      tmp=owl_zephyr_get_field(n, 1);
822      owl_message_set_attribute(m, "loginhost", tmp);
823      g_free(tmp);
824
825      tmp=owl_zephyr_get_field(n, 3);
826      owl_message_set_attribute(m, "logintty", tmp);
827      g_free(tmp);
828    }
829
830    if (!strcasecmp(n->z_opcode, "user_login")) {
831      owl_message_set_islogin(m);
832    } else if (!strcasecmp(n->z_opcode, "user_logout")) {
833      owl_message_set_islogout(m);
834    }
835  }
836
837 
838  /* set the "isprivate" attribute if it's a private zephyr. */
839  if (owl_zwrite_recip_is_personal(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      NULL,
878      "-D",
879      "-c", owl_message_get_class(m),
880      "-i", owl_message_get_instance(m),
881      NULL
882    };
883    char *out = NULL;
884    int rv;
885    int status;
886    char *zcrypt;
887
888    zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
889    argv[0] = zcrypt;
890
891    rv = call_filter(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    } else {
901      /* Replace the opcode. Otherwise the UI and other bits of code think the
902       * message was encrypted. */
903      owl_message_set_opcode(m, "failed-decrypt");
904    }
905    g_free(out);
906  }
907
908  owl_message_save_ccs(m);
909}
910#else
911void owl_message_create_from_znotice(owl_message *m, const void *n)
912{
913}
914#endif
915
916/* If 'direction' is '0' it is a login message, '1' is a logout message. */
917void owl_message_create_pseudo_zlogin(owl_message *m, int direction, const char *user, const char *host, const char *time, const char *tty)
918{
919  char *longuser;
920
921#ifdef HAVE_LIBZEPHYR
922  memset(&(m->notice), 0, sizeof(ZNotice_t));
923#endif
924 
925  longuser=long_zuser(user);
926 
927  owl_message_init(m);
928 
929  owl_message_set_type_zephyr(m);
930  owl_message_set_direction_in(m);
931
932  owl_message_set_attribute(m, "pseudo", "");
933  owl_message_set_attribute(m, "loginhost", host ? host : "");
934  owl_message_set_attribute(m, "logintty", tty ? tty : "");
935
936  owl_message_set_sender(m, longuser);
937  owl_message_set_class(m, "LOGIN");
938  owl_message_set_instance(m, longuser);
939  owl_message_set_recipient(m, "");
940  if (direction==0) {
941    owl_message_set_opcode(m, "USER_LOGIN");
942    owl_message_set_islogin(m);
943  } else if (direction==1) {
944    owl_message_set_opcode(m, "USER_LOGOUT");
945    owl_message_set_islogout(m);
946  }
947
948  owl_message_set_realm(m, zuser_realm(longuser));
949
950  owl_message_set_body(m, "<uninitialized>");
951
952  /* save the hostname */
953  owl_function_debugmsg("create_pseudo_login: host is %s", host ? host : "");
954  owl_message_set_hostname(m, host ? host : "");
955  g_free(longuser);
956}
957
958void owl_message_create_from_zwrite(owl_message *m, const owl_zwrite *z, const char *body, int recip_index)
959{
960  char *replyline;
961 
962  owl_message_init(m);
963
964  /* set things */
965  owl_message_set_direction_out(m);
966  owl_message_set_type_zephyr(m);
967  owl_message_set_sender(m, owl_zephyr_get_sender());
968  owl_message_set_class(m, owl_zwrite_get_class(z));
969  owl_message_set_instance(m, owl_zwrite_get_instance(z));
970  if (recip_index < owl_zwrite_get_numrecips(z)) {
971    char *zuser = owl_zwrite_get_recip_n_with_realm(z, recip_index);
972    char *longzuser = long_zuser(zuser);
973    owl_message_set_recipient(m, longzuser);
974    owl_message_set_realm(m, zuser_realm(longzuser));
975    g_free(longzuser);
976    g_free(zuser);
977  } else {
978    /* TODO: We should maybe munge this into the case above, as that comparison
979     * is a little overly clever. It's also not clear this codepath ever runs
980     * anyway. */
981    const char *realm = owl_zwrite_get_realm(z);
982    owl_message_set_realm(m, realm[0] ? realm : owl_zephyr_get_realm());
983  }
984  owl_message_set_opcode(m, owl_zwrite_get_opcode(z));
985
986  /* Although not strictly the zwriteline, anyone using the unsantized version
987   * of it probably has a bug. */
988  replyline = owl_zwrite_get_replyline(z, recip_index);
989  owl_message_set_zwriteline(m, replyline);
990  g_free(replyline);
991
992  owl_message_set_body(m, body);
993  owl_message_set_zsig(m, owl_zwrite_get_zsig(z));
994 
995  /* save the hostname */
996  owl_message_set_hostname(m, g_get_host_name());
997
998  /* set the "isprivate" attribute if it's a private zephyr. */
999  if (owl_zwrite_is_personal(z)) {
1000    owl_message_set_isprivate(m);
1001  }
1002
1003  owl_message_save_ccs(m);
1004}
1005
1006void owl_message_cleanup(owl_message *m)
1007{
1008  int i;
1009  owl_pair *p;
1010#ifdef HAVE_LIBZEPHYR   
1011  if (m->has_notice) {
1012    ZFreeNotice(&(m->notice));
1013  }
1014#endif
1015  if (m->timestr) g_free(m->timestr);
1016
1017  /* free all the attributes */
1018  for (i = 0; i < m->attributes->len; i++) {
1019    p = m->attributes->pdata[i];
1020    g_free(owl_pair_get_value(p));
1021    g_free(p);
1022  }
1023
1024  g_ptr_array_free(m->attributes, true);
1025 
1026  owl_message_invalidate_format(m);
1027}
1028
1029void owl_message_delete(owl_message *m)
1030{
1031  owl_message_cleanup(m);
1032  g_free(m);
1033}
Note: See TracBrowser for help on using the repository browser.