source: message.c @ f43c777

release-1.10release-1.9
Last change on this file since f43c777 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
RevLine 
[7d4fbcd]1#include "owl.h"
[d564c3d]2#include "filterproc.h"
[f271129]3#include <sys/socket.h>
4#include <arpa/inet.h>
[7d4fbcd]5
[a387d12e]6static owl_fmtext_cache fmtext_cache[OWL_FMTEXT_CACHE_SIZE];
7static owl_fmtext_cache * fmtext_cache_next = fmtext_cache;
8
[c79a047]9void owl_message_init_fmtext_cache(void)
[a387d12e]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
[e9c6fc8]18static owl_fmtext_cache *owl_message_next_fmtext(void)
[a387d12e]19{
[ad15610]20    owl_fmtext_cache * f = fmtext_cache_next;
[a387d12e]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
[0ff8fb57]30void owl_message_init(owl_message *m)
31{
[7d4fbcd]32  m->id=owl_global_get_nextmsgid(&g);
[4b464a4]33  owl_message_set_direction_none(m);
[7d4fbcd]34  m->delete=0;
35
[b9517cf]36#ifdef HAVE_LIBZEPHYR
37  m->has_notice = false;
38#endif
39
[2d1feac]40  owl_message_set_hostname(m, "");
[f9df2f0]41  m->attributes = g_ptr_array_new();
[d0d65df]42 
[7d4fbcd]43  /* save the time */
[4ebbfbc]44  m->time = time(NULL);
[6646fdb]45  m->timestr = g_strdup(ctime(&m->time));
46  m->timestr[strlen(m->timestr)-1] = '\0';
[25dd31a]47
[a387d12e]48  m->fmtext = NULL;
[4b464a4]49}
50
[5a95b69]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 */
[e19eb97]54void owl_message_set_attribute(owl_message *m, const char *attrname, const char *attrvalue)
[0ff8fb57]55{
[f9df2f0]56  int i;
[e849734]57  owl_pair *p = NULL, *pair = NULL;
[d0d65df]58
[c314f39]59  attrname = g_intern_string(attrname);
60
[e849734]61  /* look for an existing pair with this key, */
[f9df2f0]62  for (i = 0; i < m->attributes->len; i++) {
63    p = m->attributes->pdata[i];
[c314f39]64    if (owl_pair_get_key(p) == attrname) {
[ddbbcffa]65      g_free(owl_pair_get_value(p));
[e849734]66      pair = p;
[d0d65df]67      break;
68    }
69  }
70
[e849734]71  if(pair ==  NULL) {
[96828e4]72    pair = g_new(owl_pair, 1);
[c314f39]73    owl_pair_create(pair, attrname, NULL);
[f9df2f0]74    g_ptr_array_add(m->attributes, pair);
[e849734]75  }
[6201646]76  owl_pair_set_value(pair, owl_validate_or_convert(attrvalue));
[d0d65df]77}
78
[5a95b69]79/* return the value associated with the named attribute, or NULL if
80 * the attribute does not exist
81 */
[c08c70a]82const char *owl_message_get_attribute_value(const owl_message *m, const char *attrname)
[0ff8fb57]83{
[f9df2f0]84  int i;
[d0d65df]85  owl_pair *p;
[c314f39]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);
[d0d65df]93
[f9df2f0]94  for (i = 0; i < m->attributes->len; i++) {
95    p = m->attributes->pdata[i];
[c314f39]96    if (owl_pair_get_key(p) == attrname) {
[d0d65df]97      return(owl_pair_get_value(p));
98    }
99  }
[f4d0975]100
101  /*
102  owl_function_debugmsg("No attribute %s found for message %i",
103                        attrname,
104                        owl_message_get_id(m));
105  */
[d0d65df]106  return(NULL);
107}
108
[5789230]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 */
[c08c70a]113void owl_message_attributes_tofmtext(const owl_message *m, owl_fmtext *fm) {
[f9df2f0]114  int i;
[5789230]115  owl_pair *p;
[259e60a8]116  char *buff, *tmpbuff;
[5789230]117
118  owl_fmtext_init_null(fm);
119
[f9df2f0]120  for (i = 0; i < m->attributes->len; i++) {
121    p = m->attributes->pdata[i];
[259e60a8]122
[6500907]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    }
[259e60a8]130
[6711361]131    if(buff == NULL) {
[259e60a8]132      buff = g_strdup_printf("  %-15.15s: %s\n", owl_pair_get_key(p), "<error>");
[6711361]133      if(buff == NULL)
[d4927a7]134        buff=g_strdup("   <error>\n");
[6711361]135    }
[5789230]136    owl_fmtext_append_normal(fm, buff);
[ddbbcffa]137    g_free(buff);
[5789230]138  }
139}
[4b464a4]140
[bd3f232]141void owl_message_invalidate_format(owl_message *m)
142{
[a387d12e]143  if(m->fmtext) {
144    m->fmtext->message = NULL;
145    owl_fmtext_clear(&(m->fmtext->fmtext));
146    m->fmtext=NULL;
147  }
[bd3f232]148}
149
[0ff8fb57]150owl_fmtext *owl_message_get_fmtext(owl_message *m)
151{
[f14a7ee]152  owl_message_format(m);
[a387d12e]153  return(&(m->fmtext->fmtext));
[f14a7ee]154}
155
156void owl_message_format(owl_message *m)
157{
[1fdab04]158  const owl_style *s;
[9e5c9f3]159  const owl_view *v;
[bd3f232]160
[a387d12e]161  if (!m->fmtext) {
162    m->fmtext = owl_message_next_fmtext();
163    m->fmtext->message = m;
[421c8ef7]164    /* for now we assume there's just the one view and use that style */
[ef56a67]165    v=owl_global_get_current_view(&g);
166    s=owl_view_get_style(v);
167
[a387d12e]168    owl_style_get_formattext(s, &(m->fmtext->fmtext), m);
[bd3f232]169  }
[4b464a4]170}
171
[e19eb97]172void owl_message_set_class(owl_message *m, const char *class)
[0ff8fb57]173{
[d0d65df]174  owl_message_set_attribute(m, "class", class);
[4b464a4]175}
176
[c08c70a]177const char *owl_message_get_class(const owl_message *m)
[0ff8fb57]178{
[e19eb97]179  const char *class;
[d0d65df]180
181  class=owl_message_get_attribute_value(m, "class");
182  if (!class) return("");
183  return(class);
[4b464a4]184}
185
[e19eb97]186void owl_message_set_instance(owl_message *m, const char *inst)
[0ff8fb57]187{
[d0d65df]188  owl_message_set_attribute(m, "instance", inst);
[4b464a4]189}
190
[c08c70a]191const char *owl_message_get_instance(const owl_message *m)
[0ff8fb57]192{
[e19eb97]193  const char *instance;
[d0d65df]194
195  instance=owl_message_get_attribute_value(m, "instance");
196  if (!instance) return("");
197  return(instance);
[4b464a4]198}
199
[e19eb97]200void owl_message_set_sender(owl_message *m, const char *sender)
[0ff8fb57]201{
[d0d65df]202  owl_message_set_attribute(m, "sender", sender);
[4b464a4]203}
204
[c08c70a]205const char *owl_message_get_sender(const owl_message *m)
[0ff8fb57]206{
[e19eb97]207  const char *sender;
[d0d65df]208
209  sender=owl_message_get_attribute_value(m, "sender");
210  if (!sender) return("");
211  return(sender);
[4b464a4]212}
213
[e19eb97]214void owl_message_set_zsig(owl_message *m, const char *zsig)
[0ff8fb57]215{
[d0d65df]216  owl_message_set_attribute(m, "zsig", zsig);
[b45293f]217}
218
[c08c70a]219const char *owl_message_get_zsig(const owl_message *m)
[0ff8fb57]220{
[e19eb97]221  const char *zsig;
[d0d65df]222
223  zsig=owl_message_get_attribute_value(m, "zsig");
224  if (!zsig) return("");
225  return(zsig);
[b45293f]226}
227
[e19eb97]228void owl_message_set_recipient(owl_message *m, const char *recip)
[0ff8fb57]229{
[d0d65df]230  owl_message_set_attribute(m, "recipient", recip);
[4b464a4]231}
232
[c08c70a]233const char *owl_message_get_recipient(const owl_message *m)
[0ff8fb57]234{
[4b464a4]235  /* this is stupid for outgoing messages, we need to fix it. */
[d0d65df]236
[e19eb97]237  const char *recip;
[0ff8fb57]238
239  recip=owl_message_get_attribute_value(m, "recipient");
[d0d65df]240  if (!recip) return("");
241  return(recip);
[4b464a4]242}
243
[7f6a8a2]244void owl_message_set_realm(owl_message *m, const char *realm)
[0ff8fb57]245{
[d0d65df]246  owl_message_set_attribute(m, "realm", realm);
[4b464a4]247}
248
[c08c70a]249const char *owl_message_get_realm(const owl_message *m)
[0ff8fb57]250{
[e19eb97]251  const char *realm;
[d0d65df]252 
253  realm=owl_message_get_attribute_value(m, "realm");
254  if (!realm) return("");
255  return(realm);
256}
257
[e19eb97]258void owl_message_set_body(owl_message *m, const char *body)
[0ff8fb57]259{
[d0d65df]260  owl_message_set_attribute(m, "body", body);
261}
262
[c08c70a]263const char *owl_message_get_body(const owl_message *m)
[0ff8fb57]264{
[e19eb97]265  const char *body;
[d0d65df]266
267  body=owl_message_get_attribute_value(m, "body");
268  if (!body) return("");
269  return(body);
[4b464a4]270}
271
[d0d65df]272
[e19eb97]273void owl_message_set_opcode(owl_message *m, const char *opcode)
[0ff8fb57]274{
[d0d65df]275  owl_message_set_attribute(m, "opcode", opcode);
[4b464a4]276}
277
[c08c70a]278const char *owl_message_get_opcode(const owl_message *m)
[0ff8fb57]279{
[e19eb97]280  const char *opcode;
[d0d65df]281
282  opcode=owl_message_get_attribute_value(m, "opcode");
283  if (!opcode) return("");
284  return(opcode);
[4b464a4]285}
286
[5789230]287
[d559df9]288void owl_message_set_islogin(owl_message *m)
[5789230]289{
[d559df9]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");
[5789230]297}
298
[c08c70a]299int owl_message_is_loginout(const owl_message *m)
[5789230]300{
[e19eb97]301  const char *res;
[5789230]302
[d559df9]303  res=owl_message_get_attribute_value(m, "loginout");
[5789230]304  if (!res) return(0);
305  return(1);
306}
307
[c08c70a]308int owl_message_is_login(const owl_message *m)
[d559df9]309{
[e19eb97]310  const char *res;
[d559df9]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
[c08c70a]319int owl_message_is_logout(const owl_message *m)
[d559df9]320{
[e19eb97]321  const char *res;
[d559df9]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
[5789230]329void owl_message_set_isprivate(owl_message *m)
330{
[312675c]331  owl_message_set_attribute(m, "isprivate", "true");
[5789230]332}
333
[c08c70a]334int owl_message_is_private(const owl_message *m)
[5789230]335{
[e19eb97]336  const char *res;
[5789230]337
338  res=owl_message_get_attribute_value(m, "isprivate");
339  if (!res) return(0);
[635881c]340  return !strcmp(res, "true");
[5789230]341}
342
[c08c70a]343const char *owl_message_get_timestr(const owl_message *m)
[0ff8fb57]344{
[25dd31a]345  if (m->timestr) return(m->timestr);
346  return("");
347}
348
[6646fdb]349CALLER_OWN char *owl_message_format_time(const owl_message *m)
350{
351  return owl_util_format_time(localtime(&m->time));
352}
353
[0ff8fb57]354void owl_message_set_type_admin(owl_message *m)
355{
[30678ae]356  owl_message_set_attribute(m, "type", "admin");
[4b464a4]357}
358
[37eab7f]359void owl_message_set_type_loopback(owl_message *m)
360{
[30678ae]361  owl_message_set_attribute(m, "type", "loopback");
[37eab7f]362}
363
[0ff8fb57]364void owl_message_set_type_zephyr(owl_message *m)
365{
[30678ae]366  owl_message_set_attribute(m, "type", "zephyr");
[4b464a4]367}
[d09e5a1]368
[0ff8fb57]369void owl_message_set_type_aim(owl_message *m)
370{
[e363375]371  owl_message_set_attribute(m, "type", "AIM");
[d09e5a1]372}
[dd16bdd]373
[e19eb97]374void owl_message_set_type(owl_message *m, const char* type)
[dd16bdd]375{
[30678ae]376  owl_message_set_attribute(m, "type", type);
377}
378
[c08c70a]379int owl_message_is_type(const owl_message *m, const char *type) {
[e19eb97]380  const char * t = owl_message_get_attribute_value(m, "type");
[30678ae]381  if(!t) return 0;
[e363375]382  return !strcasecmp(t, type);
[dd16bdd]383}
[4b464a4]384                                               
[c08c70a]385int owl_message_is_type_admin(const owl_message *m)
[0ff8fb57]386{
[30678ae]387  return owl_message_is_type(m, "admin");
[4b464a4]388}
389
[c08c70a]390int owl_message_is_type_zephyr(const owl_message *m)
[0ff8fb57]391{
[30678ae]392  return owl_message_is_type(m, "zephyr");
[4b464a4]393}
394
[c08c70a]395int owl_message_is_type_aim(const owl_message *m)
[0ff8fb57]396{
[30678ae]397  return owl_message_is_type(m, "aim");
[d09e5a1]398}
399
[30678ae]400/* XXX TODO: deprecate this */
[c08c70a]401int owl_message_is_type_jabber(const owl_message *m)
[5a95b69]402{
[30678ae]403  return owl_message_is_type(m, "jabber");
[421c8ef7]404}
405
[c08c70a]406int owl_message_is_type_loopback(const owl_message *m)
[421c8ef7]407{
[30678ae]408  return owl_message_is_type(m, "loopback");
[421c8ef7]409}
410
[c08c70a]411int owl_message_is_pseudo(const owl_message *m)
[421c8ef7]412{
413  if (owl_message_get_attribute_value(m, "pseudo")) return(1);
[4b464a4]414  return(0);
415}
416
[e19eb97]417const char *owl_message_get_text(owl_message *m)
[0ff8fb57]418{
[21f0a9d]419  owl_message_format(m);
[a387d12e]420  return(owl_fmtext_get_text(&(m->fmtext->fmtext)));
[4b464a4]421}
422
[0ff8fb57]423void owl_message_set_direction_in(owl_message *m)
424{
[4b464a4]425  m->direction=OWL_MESSAGE_DIRECTION_IN;
426}
427
[0ff8fb57]428void owl_message_set_direction_out(owl_message *m)
429{
[4b464a4]430  m->direction=OWL_MESSAGE_DIRECTION_OUT;
431}
432
[0ff8fb57]433void owl_message_set_direction_none(owl_message *m)
434{
[4b464a4]435  m->direction=OWL_MESSAGE_DIRECTION_NONE;
436}
437
[dd16bdd]438void owl_message_set_direction(owl_message *m, int direction)
439{
440  m->direction=direction;
441}
442
[c08c70a]443int owl_message_is_direction_in(const owl_message *m)
[0ff8fb57]444{
[4b464a4]445  if (m->direction==OWL_MESSAGE_DIRECTION_IN) return(1);
446  return(0);
447}
448
[c08c70a]449int owl_message_is_direction_out(const owl_message *m)
[0ff8fb57]450{
[4b464a4]451  if (m->direction==OWL_MESSAGE_DIRECTION_OUT) return(1);
452  return(0);
453}
454
[c08c70a]455int owl_message_is_direction_none(const owl_message *m)
[0ff8fb57]456{
[4b464a4]457  if (m->direction==OWL_MESSAGE_DIRECTION_NONE) return(1);
458  return(0);
459}
460
[0ff8fb57]461int owl_message_get_numlines(owl_message *m)
462{
[4b464a4]463  if (m == NULL) return(0);
[f14a7ee]464  owl_message_format(m);
[a387d12e]465  return(owl_fmtext_num_lines(&(m->fmtext->fmtext)));
[4b464a4]466}
467
[0ff8fb57]468void owl_message_mark_delete(owl_message *m)
469{
[4b464a4]470  if (m == NULL) return;
471  m->delete=1;
472}
473
[0ff8fb57]474void owl_message_unmark_delete(owl_message *m)
475{
[4b464a4]476  if (m == NULL) return;
477  m->delete=0;
478}
479
[c08c70a]480const char *owl_message_get_zwriteline(const owl_message *m)
[0ff8fb57]481{
[e19eb97]482  const char *z = owl_message_get_attribute_value(m, "zwriteline");
[147d880]483  if (!z) return "";
484  return z;
[4b464a4]485}
486
[e19eb97]487void owl_message_set_zwriteline(owl_message *m, const char *line)
[0ff8fb57]488{
[147d880]489  owl_message_set_attribute(m, "zwriteline", line);
[4b464a4]490}
491
[c08c70a]492int owl_message_is_delete(const owl_message *m)
[0ff8fb57]493{
[4b464a4]494  if (m == NULL) return(0);
495  if (m->delete==1) return(1);
496  return(0);
497}
498
[be0a79f]499#ifdef HAVE_LIBZEPHYR
[c08c70a]500const ZNotice_t *owl_message_get_notice(const owl_message *m)
[0ff8fb57]501{
[b9517cf]502  return m->has_notice ? &m->notice : NULL;
[4b464a4]503}
[09489b89]504#else
[c08c70a]505void *owl_message_get_notice(const owl_message *m)
[09489b89]506{
507  return(NULL);
508}
[be0a79f]509#endif
[4b464a4]510
[e19eb97]511void owl_message_set_hostname(owl_message *m, const char *hostname)
[8298425]512{
[3f6555d]513  m->hostname = g_intern_string(hostname);
[8298425]514}
515
[c08c70a]516const char *owl_message_get_hostname(const owl_message *m)
[0ff8fb57]517{
[4b464a4]518  return(m->hostname);
519}
520
[8fa9562]521void owl_message_curs_waddstr(owl_message *m, WINDOW *win, int aline, int bline, int acol, int bcol, int fgcolor, int bgcolor)
[0ff8fb57]522{
[4b464a4]523  owl_fmtext a, b;
524
[bd3f232]525  /* this will ensure that our cached copy is up to date */
[f14a7ee]526  owl_message_format(m);
[bd3f232]527
[af2ca19]528  owl_fmtext_init_null(&a);
529  owl_fmtext_init_null(&b);
530 
[3a7cf49]531  owl_fmtext_truncate_lines(&(m->fmtext->fmtext), aline, bline-aline, &a);
[4b464a4]532  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
533
[237d02c]534  owl_fmtext_curs_waddstr(&b, win, OWL_FMTEXT_ATTR_NONE, fgcolor, bgcolor);
[4b464a4]535
[7ab0020]536  owl_fmtext_cleanup(&a);
537  owl_fmtext_cleanup(&b);
[4b464a4]538}
539
[c08c70a]540int owl_message_is_personal(const owl_message *m)
[0ff8fb57]541{
[4542047]542  const owl_filter * f = owl_global_get_filter(&g, "personal");
[ce74deb]543  if(!f) {
544      owl_function_error("personal filter is not defined");
545      return (0);
[0ff8fb57]546  }
[ce74deb]547  return owl_filter_message_match(f, m);
[0ff8fb57]548}
549
[c08c70a]550int owl_message_is_question(const owl_message *m)
[f4d32cd]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
[c08c70a]557int owl_message_is_answered(const owl_message *m) {
[e19eb97]558  const char *q;
[f4d32cd]559  if(!owl_message_is_question(m)) return 0;
[ad15610]560  q = owl_message_get_attribute_value(m, "question");
[f4d32cd]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
[c08c70a]569int owl_message_is_mail(const owl_message *m)
[0ff8fb57]570{
571  if (owl_message_is_type_zephyr(m)) {
[5789230]572    if (!strcasecmp(owl_message_get_class(m), "mail") && owl_message_is_private(m)) {
[0ff8fb57]573      return(1);
574    } else {
575      return(0);
576    }
[4b464a4]577  }
578  return(0);
579}
580
581/* caller must free return value. */
[6829afc]582CALLER_OWN char *owl_message_get_cc(const owl_message *m)
[0ff8fb57]583{
[e19eb97]584  const char *cur;
[65b2173]585  char *out, *end;
[4b464a4]586
587  cur = owl_message_get_body(m);
588  while (*cur && *cur==' ') cur++;
[985f85b]589  if (strncasecmp(cur, "cc:", 3)) return(NULL);
[4b464a4]590  cur+=3;
591  while (*cur && *cur==' ') cur++;
[d4927a7]592  out = g_strdup(cur);
[4b464a4]593  end = strchr(out, '\n');
594  if (end) end[0] = '\0';
595  return(out);
596}
597
[48609ce]598/* caller must free return value */
[6829afc]599CALLER_OWN GList *owl_message_get_cc_without_recipient(const owl_message *m)
[48609ce]600{
[839697d]601  char *cc, *shortuser, *recip;
[e19eb97]602  const char *user;
[839697d]603  GList *out = NULL;
[48609ce]604
605  cc = owl_message_get_cc(m);
[9c590d4]606  if (cc == NULL)
607    return NULL;
608
609  recip = short_zuser(owl_message_get_recipient(m));
[48609ce]610
611  user = strtok(cc, " ");
612  while (user != NULL) {
[18108b1e]613    shortuser = short_zuser(user);
614    if (strcasecmp(shortuser, recip) != 0) {
[d4927a7]615      out = g_list_prepend(out, g_strdup(user));
[48609ce]616    }
[ddbbcffa]617    g_free(shortuser);
[48609ce]618    user = strtok(NULL, " ");
619  }
620
[ddbbcffa]621  g_free(recip);
622  g_free(cc);
[9c590d4]623
[48609ce]624  return(out);
625}
626
[c08c70a]627int owl_message_get_id(const owl_message *m)
[0ff8fb57]628{
[4b464a4]629  return(m->id);
630}
[bd3f232]631
[c08c70a]632const char *owl_message_get_type(const owl_message *m) {
[e19eb97]633  const char * type = owl_message_get_attribute_value(m, "type");
[30678ae]634  if(!type) {
635    return "generic";
[dd16bdd]636  }
[30678ae]637  return type;
[dd16bdd]638}
639
[c08c70a]640const char *owl_message_get_direction(const owl_message *m) {
[f1e629d]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
[e19eb97]653int owl_message_parse_direction(const char *d) {
[dd16bdd]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
[c08c70a]664const char *owl_message_get_login(const owl_message *m) {
[f1e629d]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
[dd16bdd]674
[c08c70a]675const char *owl_message_get_header(const owl_message *m) {
[f1e629d]676  return owl_message_get_attribute_value(m, "adminheader");
677}
678
[bd3f232]679/* return 1 if the message contains "string", 0 otherwise.  This is
680 * case insensitive because the functions it uses are
681 */
[89b2daf]682int owl_message_search(owl_message *m, const owl_regex *re)
[0ff8fb57]683{
[4b464a4]684
[f14a7ee]685  owl_message_format(m); /* is this necessary? */
[bd3f232]686 
[72f613a]687  return owl_fmtext_search(&(m->fmtext->fmtext), re, 0) >= 0;
[4b464a4]688}
689
690
[d559df9]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 */
[e19eb97]695void owl_message_create_aim(owl_message *m, const char *sender, const char *recipient, const char *text, int direction, int loginout)
[0ff8fb57]696{
[d09e5a1]697  owl_message_init(m);
698  owl_message_set_body(m, text);
699  owl_message_set_sender(m, sender);
[440ce01]700  owl_message_set_recipient(m, recipient);
[d09e5a1]701  owl_message_set_type_aim(m);
[3abf28b]702
[d559df9]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);
[3abf28b]707  }
708
[d559df9]709  /* for now all messages that aren't loginout are private */
710  if (!loginout) {
711    owl_message_set_isprivate(m);
712  }
[3abf28b]713
[d559df9]714  if (loginout==-1) {
715    owl_message_set_islogout(m);
716  } else if (loginout==1) {
717    owl_message_set_islogin(m);
718  }
[aa5f725]719}
720
[e19eb97]721void owl_message_create_admin(owl_message *m, const char *header, const char *text)
[0ff8fb57]722{
[d0d65df]723  owl_message_init(m);
[4b464a4]724  owl_message_set_type_admin(m);
[d0d65df]725  owl_message_set_body(m, text);
[bd3f232]726  owl_message_set_attribute(m, "adminheader", header); /* just a hack for now */
[7d4fbcd]727}
728
[37eab7f]729/* caller should set the direction */
[e19eb97]730void owl_message_create_loopback(owl_message *m, const char *text)
[37eab7f]731{
732  owl_message_init(m);
733  owl_message_set_type_loopback(m);
734  owl_message_set_body(m, text);
[eec69e1]735  owl_message_set_sender(m, "loopsender");
736  owl_message_set_recipient(m, "looprecip");
[37eab7f]737  owl_message_set_isprivate(m);
738}
739
[4727d31]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) {
[ddbbcffa]755        g_free(cc->data);
[4727d31]756        cc = g_list_delete_link(cc, cc);
757      }
758
759      tmp = short_zuser(cc->data);
760      g_string_append(recips, tmp);
761
[ddbbcffa]762      g_free(tmp);
763      g_free(cc->data);
[4727d31]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
[09489b89]775#ifdef HAVE_LIBZEPHYR
[1077891a]776void owl_message_create_from_znotice(owl_message *m, const ZNotice_t *n)
[0ff8fb57]777{
[ba88ae7]778#ifdef ZNOTICE_SOCKADDR
779  char hbuf[NI_MAXHOST];
780#else /* !ZNOTICE_SOCKADDR */
[7d4fbcd]781  struct hostent *hent;
[ba88ae7]782#endif /* ZNOTICE_SOCKADDR */
[65b2173]783  char *tmp, *tmp2;
[804ab8a]784  int len;
[7d4fbcd]785
[d0d65df]786  owl_message_init(m);
787 
[4b464a4]788  owl_message_set_type_zephyr(m);
789  owl_message_set_direction_in(m);
[7d4fbcd]790 
791  /* first save the full notice */
[66a8cd6]792  m->notice = *n;
[b9517cf]793  m->has_notice = true;
[7d4fbcd]794
[25dd31a]795  /* a little gross, we'll replace \r's with ' ' for now */
[7d4fbcd]796  owl_zephyr_hackaway_cr(&(m->notice));
797 
[25dd31a]798  /* save the time, we need to nuke the string saved by message_init */
[ddbbcffa]799  if (m->timestr) g_free(m->timestr);
[4ebbfbc]800  m->time = n->z_time.tv_sec;
[6646fdb]801  m->timestr = g_strdup(ctime(&m->time));
802  m->timestr[strlen(m->timestr)-1] = '\0';
[25dd31a]803
[7d4fbcd]804  /* set other info */
[d0d65df]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);
[7d4fbcd]809  if (n->z_opcode) {
[d0d65df]810    owl_message_set_opcode(m, n->z_opcode);
[7d4fbcd]811  } else {
[d0d65df]812    owl_message_set_opcode(m, "");
[7d4fbcd]813  }
[804ab8a]814  owl_message_set_zsig(m, owl_zephyr_get_zsig(n, &len));
[7d4fbcd]815
[4e29ecb]816  owl_message_set_realm(m, zuser_realm(n->z_recipient));
[7d4fbcd]817
[5789230]818  /* Set the "isloginout" attribute if it's a login message */
[1d3e925]819  if (!strcasecmp(n->z_class, "login") || !strcasecmp(n->z_class, OWL_WEBZEPHYR_CLASS)) {
[5a95b69]820    if (!strcasecmp(n->z_opcode, "user_login") || !strcasecmp(n->z_opcode, "user_logout")) {
[b0430a6]821      tmp=owl_zephyr_get_field(n, 1);
[5a95b69]822      owl_message_set_attribute(m, "loginhost", tmp);
[ddbbcffa]823      g_free(tmp);
[5a95b69]824
[b0430a6]825      tmp=owl_zephyr_get_field(n, 3);
[5a95b69]826      owl_message_set_attribute(m, "logintty", tmp);
[ddbbcffa]827      g_free(tmp);
[5a95b69]828    }
829
[d559df9]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    }
[5789230]835  }
836
[5a95b69]837 
[bff1f22]838  /* set the "isprivate" attribute if it's a private zephyr. */
839  if (owl_zwrite_recip_is_personal(n->z_recipient)) {
[5789230]840    owl_message_set_isprivate(m);
841  }
842
[9854278]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
[85d1795]849  /* save the hostname */
[ba88ae7]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 */
[85d1795]855  owl_function_debugmsg("About to do gethostbyaddr");
[ba88ae7]856  hent = gethostbyaddr(&n->z_uid.zuid_addr, sizeof(n->z_uid.zuid_addr), AF_INET);
857  if (hent && hent->h_name)
[85d1795]858    owl_message_set_hostname(m, hent->h_name);
[ba88ae7]859  else
[85d1795]860    owl_message_set_hostname(m, inet_ntoa(n->z_sender_addr));
[ba88ae7]861#endif /* ZNOTICE_SOCKADDR */
[85d1795]862
[b45293f]863  /* set the body */
[85d1795]864  tmp=owl_zephyr_get_message(n, m);
[7e3e00a]865  if (owl_global_is_newlinestrip(&g)) {
[d0d65df]866    tmp2=owl_util_stripnewlines(tmp);
867    owl_message_set_body(m, tmp2);
[ddbbcffa]868    g_free(tmp2);
[7e3e00a]869  } else {
[d0d65df]870    owl_message_set_body(m, tmp);
[7e3e00a]871  }
[ddbbcffa]872  g_free(tmp);
[7d4fbcd]873
[d309eb3]874  /* if zcrypt is enabled try to decrypt the message */
875  if (owl_global_is_zcrypt(&g) && !strcasecmp(n->z_opcode, "crypt")) {
[d564c3d]876    const char *argv[] = {
[97cdbaf5]877      NULL,
[d564c3d]878      "-D",
879      "-c", owl_message_get_class(m),
880      "-i", owl_message_get_instance(m),
881      NULL
882    };
[2354e9a]883    char *out = NULL;
[d564c3d]884    int rv;
885    int status;
[9a7b4f2]886    char *zcrypt;
[d564c3d]887
[dde1b4d]888    zcrypt = g_build_filename(owl_get_bindir(), "zcrypt", NULL);
[97cdbaf5]889    argv[0] = zcrypt;
[9a7b4f2]890
[97cdbaf5]891    rv = call_filter(argv, owl_message_get_body(m), &out, &status);
[ddbbcffa]892    g_free(zcrypt);
[d564c3d]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      }
[d0d65df]899      owl_message_set_body(m, out);
[2354e9a]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");
[dacb555]904    }
[2354e9a]905    g_free(out);
[d309eb3]906  }
[4727d31]907
908  owl_message_save_ccs(m);
[7d4fbcd]909}
[09489b89]910#else
[1077891a]911void owl_message_create_from_znotice(owl_message *m, const void *n)
[09489b89]912{
913}
914#endif
[7d4fbcd]915
[5a95b69]916/* If 'direction' is '0' it is a login message, '1' is a logout message. */
[e19eb97]917void owl_message_create_pseudo_zlogin(owl_message *m, int direction, const char *user, const char *host, const char *time, const char *tty)
[5a95b69]918{
[65b2173]919  char *longuser;
[5a95b69]920
[ba9f236]921#ifdef HAVE_LIBZEPHYR
[5a95b69]922  memset(&(m->notice), 0, sizeof(ZNotice_t));
[ba9f236]923#endif
924 
[5a95b69]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
[4e29ecb]948  owl_message_set_realm(m, zuser_realm(longuser));
[5a95b69]949
950  owl_message_set_body(m, "<uninitialized>");
951
952  /* save the hostname */
[2de4f20]953  owl_function_debugmsg("create_pseudo_login: host is %s", host ? host : "");
[8298425]954  owl_message_set_hostname(m, host ? host : "");
[ddbbcffa]955  g_free(longuser);
[5a95b69]956}
957
[e5da3fe]958void owl_message_create_from_zwrite(owl_message *m, const owl_zwrite *z, const char *body, int recip_index)
[0ff8fb57]959{
[719119de]960  char *replyline;
[b45293f]961 
[d0d65df]962  owl_message_init(m);
[b45293f]963
964  /* set things */
965  owl_message_set_direction_out(m);
966  owl_message_set_type_zephyr(m);
[09489b89]967  owl_message_set_sender(m, owl_zephyr_get_sender());
[24ccc01]968  owl_message_set_class(m, owl_zwrite_get_class(z));
969  owl_message_set_instance(m, owl_zwrite_get_instance(z));
[e5da3fe]970  if (recip_index < owl_zwrite_get_numrecips(z)) {
[3a3863e]971    char *zuser = owl_zwrite_get_recip_n_with_realm(z, recip_index);
972    char *longzuser = long_zuser(zuser);
[e5da3fe]973    owl_message_set_recipient(m, longzuser);
[3a3863e]974    owl_message_set_realm(m, zuser_realm(longzuser));
[ddbbcffa]975    g_free(longzuser);
[3a3863e]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());
[9ceee9d]983  }
[24ccc01]984  owl_message_set_opcode(m, owl_zwrite_get_opcode(z));
[719119de]985
986  /* Although not strictly the zwriteline, anyone using the unsantized version
987   * of it probably has a bug. */
[a5b5d00]988  replyline = owl_zwrite_get_replyline(z, recip_index);
[719119de]989  owl_message_set_zwriteline(m, replyline);
[ddbbcffa]990  g_free(replyline);
[719119de]991
[d0d65df]992  owl_message_set_body(m, body);
[24ccc01]993  owl_message_set_zsig(m, owl_zwrite_get_zsig(z));
[b45293f]994 
995  /* save the hostname */
[f54b07d]996  owl_message_set_hostname(m, g_get_host_name());
[312675c]997
[ce74deb]998  /* set the "isprivate" attribute if it's a private zephyr. */
[24ccc01]999  if (owl_zwrite_is_personal(z)) {
[312675c]1000    owl_message_set_isprivate(m);
[ce74deb]1001  }
[4727d31]1002
1003  owl_message_save_ccs(m);
[b45293f]1004}
[7d4fbcd]1005
[a44cd91]1006void owl_message_cleanup(owl_message *m)
[0ff8fb57]1007{
[f9df2f0]1008  int i;
[d0d65df]1009  owl_pair *p;
[09489b89]1010#ifdef HAVE_LIBZEPHYR   
[b9517cf]1011  if (m->has_notice) {
[7d4fbcd]1012    ZFreeNotice(&(m->notice));
1013  }
[09489b89]1014#endif
[ddbbcffa]1015  if (m->timestr) g_free(m->timestr);
[d0d65df]1016
1017  /* free all the attributes */
[f9df2f0]1018  for (i = 0; i < m->attributes->len; i++) {
1019    p = m->attributes->pdata[i];
[ddbbcffa]1020    g_free(owl_pair_get_value(p));
1021    g_free(p);
[d0d65df]1022  }
1023
[f9df2f0]1024  g_ptr_array_free(m->attributes, true);
[7d4fbcd]1025 
[a387d12e]1026  owl_message_invalidate_format(m);
[7d4fbcd]1027}
[91634ec]1028
1029void owl_message_delete(owl_message *m)
1030{
[a44cd91]1031  owl_message_cleanup(m);
[ddbbcffa]1032  g_free(m);
[91634ec]1033}
Note: See TracBrowser for help on using the repository browser.