source: message.c @ e50cd56

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since e50cd56 was e50cd56, checked in by Erik Nygren <nygren@mit.edu>, 22 years ago
Fixed some buffer overruns in the "reply" command. When repying to "all" on a message that begins with "CC:" (eg, sent with "zwrite -C", the reply line will be constructed from the sender and the usernames on the CC: line of the message being replied to. There is no such thing as C-R, so left C-r as it is but added: M-r --- edit reply to all M-R --- edit reply to sender
  • Property mode set to 100644
File size: 16.7 KB
Line 
1#include <zephyr/zephyr.h>
2#include <stdlib.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
13static const char fileIdent[] = "$Id$";
14
15void owl_message_create_admin(owl_message *m, char *header, char *text) {
16  char *indent;
17  time_t t;
18
19  m->id=owl_global_get_nextmsgid(&g);
20  m->type=OWL_MESSAGE_TYPE_ADMIN;
21  m->admintype=OWL_MESSAGE_ADMINTYPE_GENERIC;
22  m->delete=0;
23  m->sender=owl_strdup("-owl");
24  m->class=owl_strdup("");
25  m->inst=owl_strdup("");
26  m->recip=owl_strdup("");
27  m->opcode=owl_strdup("");
28  m->realm=owl_strdup("");
29  strcpy(m->hostname, "");
30  m->zwriteline=strdup("");
31
32  /* save the time */
33  t=time(NULL);
34  m->time=owl_strdup(ctime(&t));
35  m->time[strlen(m->time)-1]='\0';
36
37  m->body=owl_strdup(text);
38
39  /* do something to make it clear the notice shouldn't be used for now */
40
41  indent=owl_malloc(strlen(text)+owl_text_num_lines(text)*OWL_MSGTAB+10);
42  owl_text_indent(indent, text, OWL_MSGTAB);
43  owl_fmtext_init_null(&(m->fmtext));
44  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
45  owl_fmtext_append_bold(&(m->fmtext), "OWL ADMIN ");
46  owl_fmtext_append_ztext(&(m->fmtext), header);
47  owl_fmtext_append_normal(&(m->fmtext), "\n");
48  owl_fmtext_append_ztext(&(m->fmtext), indent);
49  if (text[strlen(text)-1]!='\n') {
50    owl_fmtext_append_normal(&(m->fmtext), "\n");
51  }
52
53  owl_free(indent);
54}
55
56void owl_message_create_from_zephyr(owl_message *m, ZNotice_t *n) {
57  struct hostent *hent;
58  int k;
59  char *ptr;
60
61  m->id=owl_global_get_nextmsgid(&g);
62  m->type=OWL_MESSAGE_TYPE_ZEPHYR;
63 
64  /* first save the full notice */
65  memcpy(&(m->notice), n, sizeof(ZNotice_t));
66
67  /* a little gross, we'll reaplace \r's with ' ' for now */
68  owl_zephyr_hackaway_cr(&(m->notice));
69 
70  m->delete=0;
71
72  /* set other info */
73  m->sender=owl_strdup(n->z_sender);
74  m->class=owl_strdup(n->z_class);
75  m->inst=owl_strdup(n->z_class_inst);
76  m->recip=owl_strdup(n->z_recipient);
77  if (n->z_opcode) {
78    m->opcode=owl_strdup(n->z_opcode);
79  } else {
80    n->z_opcode=owl_strdup("");
81  }
82
83  if ((ptr=strchr(n->z_recipient, '@'))!=NULL) {
84    m->realm=owl_strdup(ptr+1);
85  } else {
86    m->realm=owl_strdup(ZGetRealm());
87  }
88
89  m->zwriteline=strdup("");
90
91  ptr=owl_zephyr_get_message(n, &k);
92  m->body=owl_malloc(k+10);
93  memcpy(m->body, ptr, k);
94  m->body[k]='\0';
95
96  /* save the hostname */
97  owl_function_debugmsg("About to do get hostbyaddr");
98  hent=gethostbyaddr((char *) &(n->z_uid.zuid_addr), sizeof(n->z_uid.zuid_addr), AF_INET);
99  if (hent && hent->h_name) {
100    strcpy(m->hostname, hent->h_name);
101  } else {
102    strcpy(m->hostname, inet_ntoa(n->z_sender_addr));
103  }
104
105  /* save the time */
106  m->time=owl_strdup(ctime((time_t *) &n->z_time.tv_sec));
107  m->time[strlen(m->time)-1]='\0';
108
109  /* create the formatted message */
110  if (owl_global_is_config_format(&g)) {
111    _owl_message_make_text_from_config(m);
112  } else if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
113    _owl_message_make_text_from_notice_standard(m);
114  } else {
115    _owl_message_make_text_from_notice_simple(m);
116  }
117
118}
119
120
121void _owl_message_make_text_from_config(owl_message *m) {
122  char *body, *indent;
123 
124  owl_fmtext_init_null(&(m->fmtext));
125
126  /* get body from the config */
127  body=owl_config_getmsg(m, 1);
128 
129  /* indent */
130  indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_TAB+10);
131  owl_text_indent(indent, body, OWL_TAB);
132
133  /* fmtext_append.  This needs to change */
134  owl_fmtext_append_ztext(&(m->fmtext), indent);
135
136  owl_free(indent);
137  owl_free(body);
138}
139
140void _owl_message_make_text_from_notice_standard(owl_message *m) {
141  char *body, *indent, *ptr;
142  char frombuff[1024];
143  char zsigbuff[LINE];
144  ZNotice_t *n;
145  int len;
146
147  /* get the body */
148  n=&(m->notice);
149  ptr=(owl_zephyr_get_message(n, &len));
150  body=owl_malloc(len+20);
151  strncpy(body, ptr, len);
152  body[len]='\0';
153
154  /* add a newline if we need to */
155  if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
156    strcat(body, "\n");
157  }
158
159  /* do the indenting into indent */
160  indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_MSGTAB+10);
161  owl_text_indent(indent, body, OWL_MSGTAB);
162
163  /* edit the from addr for printing */
164  strcpy(frombuff, m->sender);
165  ptr=strchr(frombuff, '@');
166  if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
167    *ptr='\0';
168  }
169
170  /* set the message for printing */
171  owl_fmtext_init_null(&(m->fmtext));
172  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
173
174  if (!strcasecmp(n->z_opcode, "ping")) {
175    owl_fmtext_append_bold(&(m->fmtext), "PING");
176    owl_fmtext_append_normal(&(m->fmtext), " from ");
177    owl_fmtext_append_bold(&(m->fmtext), frombuff);
178    owl_fmtext_append_normal(&(m->fmtext), "\n");
179  } else if (!strcasecmp(n->z_class, "login")) {
180    char *ptr, host[LINE], tty[LINE];
181    int len;
182
183    ptr=owl_zephyr_get_field(n, 1, &len);
184    strncpy(host, ptr, len);
185    host[len]='\0';
186    ptr=owl_zephyr_get_field(n, 3, &len);
187    strncpy(tty, ptr, len);
188    tty[len]='\0';
189   
190    if (!strcasecmp(n->z_opcode, "user_login")) {
191      owl_fmtext_append_bold(&(m->fmtext), "LOGIN");
192    } else if (!strcasecmp(n->z_opcode, "user_logout")) {
193      owl_fmtext_append_bold(&(m->fmtext), "LOGOUT");
194    }
195    owl_fmtext_append_normal(&(m->fmtext), " for ");
196    ptr=pretty_sender(n->z_class_inst);
197    owl_fmtext_append_bold(&(m->fmtext), ptr);
198    owl_free(ptr);
199    owl_fmtext_append_normal(&(m->fmtext), " at ");
200    owl_fmtext_append_normal(&(m->fmtext), host);
201    owl_fmtext_append_normal(&(m->fmtext), " ");
202    owl_fmtext_append_normal(&(m->fmtext), tty);
203    owl_fmtext_append_normal(&(m->fmtext), "\n");
204  } else {
205    owl_fmtext_append_normal(&(m->fmtext), m->class);
206    owl_fmtext_append_normal(&(m->fmtext), " / ");
207    owl_fmtext_append_normal(&(m->fmtext), m->inst);
208    owl_fmtext_append_normal(&(m->fmtext), " / ");
209    owl_fmtext_append_bold(&(m->fmtext), frombuff);
210    if (strcasecmp(owl_message_get_realm(m), ZGetRealm())) {
211      owl_fmtext_append_normal(&(m->fmtext), " {");
212      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_realm(m));
213      owl_fmtext_append_normal(&(m->fmtext), "} ");
214    }
215    if (n->z_opcode[0]!='\0') {
216      owl_fmtext_append_normal(&(m->fmtext), " [");
217      owl_fmtext_append_normal(&(m->fmtext), n->z_opcode);
218      owl_fmtext_append_normal(&(m->fmtext), "] ");
219    }
220
221    /* stick on the zsig */
222    _owl_message_get_zsig(m, zsigbuff, LINE);
223    if (zsigbuff[0]!='\0') {
224      owl_fmtext_append_normal(&(m->fmtext), "    (");
225      owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
226      owl_fmtext_append_normal(&(m->fmtext), ")");
227    }
228    owl_fmtext_append_normal(&(m->fmtext), "\n");
229    owl_fmtext_append_ztext(&(m->fmtext), indent);
230
231    /* make personal messages bold for smaat users */
232    if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
233      if (owl_message_is_personal(m)) {
234        owl_fmtext_addattr((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
235      }
236    }
237  }
238
239  owl_free(body);
240  owl_free(indent);
241}
242
243void _owl_message_make_text_from_notice_simple(owl_message *m) {
244  char *body, *indent, *ptr;
245  char frombuff[1024];
246  char zsigbuff[LINE];
247  ZNotice_t *n;
248  int len;
249
250  /* get the body */
251  n=&(m->notice);
252  ptr=(owl_zephyr_get_message(n, &len));
253  body=owl_malloc(len+20);
254  strncpy(body, ptr, len);
255  body[len]='\0';
256
257  /* add a newline if we need to */
258  if (body[0]!='\0' && body[strlen(body)-1]!='\n') {
259    strcat(body, "\n");
260  }
261
262  /* do the indenting into indent */
263  indent=owl_malloc(strlen(body)+owl_text_num_lines(body)*OWL_MSGTAB+10);
264  owl_text_indent(indent, body, OWL_MSGTAB);
265
266  /* edit the from addr for printing */
267  strcpy(frombuff, m->sender);
268  ptr=strchr(frombuff, '@');
269  if (ptr && !strncmp(ptr+1, ZGetRealm(), strlen(ZGetRealm()))) {
270    *ptr='\0';
271  }
272
273  /* set the message for printing */
274  owl_fmtext_init_null(&(m->fmtext));
275  owl_fmtext_append_normal(&(m->fmtext), OWL_TABSTR);
276
277  if (!strcasecmp(n->z_opcode, "ping")) {
278    owl_fmtext_append_bold(&(m->fmtext), "PING");
279    owl_fmtext_append_normal(&(m->fmtext), " from ");
280    owl_fmtext_append_bold(&(m->fmtext), frombuff);
281    owl_fmtext_append_normal(&(m->fmtext), "\n");
282  } else if (!strcasecmp(n->z_class, "login")) {
283    char *ptr, host[LINE], tty[LINE];
284    int len;
285
286    ptr=owl_zephyr_get_field(n, 1, &len);
287    strncpy(host, ptr, len);
288    host[len]='\0';
289    ptr=owl_zephyr_get_field(n, 3, &len);
290    strncpy(tty, ptr, len);
291    tty[len]='\0';
292   
293    if (!strcasecmp(n->z_opcode, "user_login")) {
294      owl_fmtext_append_bold(&(m->fmtext), "LOGIN");
295    } else if (!strcasecmp(n->z_opcode, "user_logout")) {
296      owl_fmtext_append_bold(&(m->fmtext), "LOGOUT");
297    }
298    owl_fmtext_append_normal(&(m->fmtext), " for ");
299    ptr=pretty_sender(n->z_class_inst);
300    owl_fmtext_append_bold(&(m->fmtext), ptr);
301    owl_free(ptr);
302    owl_fmtext_append_normal(&(m->fmtext), " at ");
303    owl_fmtext_append_normal(&(m->fmtext), host);
304    owl_fmtext_append_normal(&(m->fmtext), " ");
305    owl_fmtext_append_normal(&(m->fmtext), tty);
306    owl_fmtext_append_normal(&(m->fmtext), "\n");
307  } else {
308    owl_fmtext_append_normal(&(m->fmtext), "From: ");
309    if (strcasecmp(m->class, "message")) {
310      owl_fmtext_append_normal(&(m->fmtext), "Class ");
311      owl_fmtext_append_normal(&(m->fmtext), m->class);
312      owl_fmtext_append_normal(&(m->fmtext), " / Instance ");
313      owl_fmtext_append_normal(&(m->fmtext), m->inst);
314      owl_fmtext_append_normal(&(m->fmtext), " / ");
315    }
316    owl_fmtext_append_normal(&(m->fmtext), frombuff);
317    if (strcasecmp(owl_message_get_realm(m), ZGetRealm())) {
318      owl_fmtext_append_normal(&(m->fmtext), " {");
319      owl_fmtext_append_normal(&(m->fmtext), owl_message_get_realm(m));
320      owl_fmtext_append_normal(&(m->fmtext), "} ");
321    }
322
323    /* stick on the zsig */
324    _owl_message_get_zsig(m, zsigbuff, LINE);
325    if (zsigbuff[0]!='\0') {
326      owl_fmtext_append_normal(&(m->fmtext), "    (");
327      owl_fmtext_append_ztext(&(m->fmtext), zsigbuff);
328      owl_fmtext_append_normal(&(m->fmtext), ")");
329    }
330    owl_fmtext_append_normal(&(m->fmtext), "\n");
331    owl_fmtext_append_ztext(&(m->fmtext), indent);
332
333    /* make personal messages bold for smaat users */
334    if (owl_global_is_userclue(&g, OWL_USERCLUE_CLASSES)) {
335      if (owl_message_is_personal(m)) {
336        owl_fmtext_addattr((&m->fmtext), OWL_FMTEXT_ATTR_BOLD);
337      }
338    }
339  }
340
341  owl_free(body);
342  owl_free(indent);
343}
344
345void _owl_message_get_zsig(owl_message *m, char *buff, int size) {
346  char *ptr;
347  ZNotice_t n;
348  int len;
349  /* just a hackish thing for now.  We'll only present the first line
350     or the first 'size'. characters.  If the message is not
351     appropriate for having a zsig we'll return an empty string */
352  n=m->notice;
353
354
355  /* bail if it shouldn't have a zsig */
356  buff[0]='\0';
357  if (!strcasecmp(n.z_opcode, "ping")) {
358    return;
359  }
360
361  /* find the right length to copy */
362  len=strlen(n.z_message);
363  if (size < len) {
364    len=size;
365  }
366  if ((ptr=strchr(n.z_message, '\n'))!=NULL) {
367    if ((ptr-n.z_message) < len) {
368      len=ptr-n.z_message;
369    }
370  }
371
372  /* copy */
373  strncpy(buff, n.z_message, len);
374  buff[len]='\0';
375}
376
377
378int owl_message_get_numlines(owl_message *m) {
379  if (m == NULL) return(0);
380  return(owl_fmtext_num_lines(&(m->fmtext)));
381}
382
383
384void owl_message_mark_delete(owl_message *m) {
385  if (m == NULL) return;
386  m->delete=1;
387  /* _owl_message_make_text_from_notice(m); */
388}
389
390
391void owl_message_unmark_delete(owl_message *m) {
392  if (m == NULL) return;
393  m->delete=0;
394}
395
396
397int owl_message_set_admintype(owl_message *m, int admintype) {
398  if (m->type != OWL_MESSAGE_TYPE_ADMIN) return(-1);
399  m->admintype=admintype;
400  return(0);
401}
402
403
404int owl_message_get_admintype(owl_message *m) {
405  return(m->admintype);
406}
407
408void owl_message_set_admin_outgoing(owl_message *m, char *zwriteline) {
409  owl_message_set_admintype(m, OWL_MESSAGE_ADMINTYPE_OUTGOING);
410  if (m->zwriteline) {
411    owl_free(m->zwriteline);
412    m->zwriteline=owl_strdup(zwriteline);
413  }
414}
415
416char *owl_message_get_zwriteline(owl_message *m) {
417  return(m->zwriteline);
418}
419
420int owl_message_is_delete(owl_message *m) {
421  if (m == NULL) return(0);
422  if (m->delete==1) return(1);
423  return(0);
424}
425
426ZNotice_t *owl_message_get_notice(owl_message *m) {
427  return(&(m->notice));
428}
429
430
431void owl_message_free(owl_message *m) {
432  if (owl_message_is_zephyr(m)) {
433    ZFreeNotice(&(m->notice));
434  }
435  if (m->sender) owl_free(m->sender);
436  if (m->recip) owl_free(m->recip);
437  if (m->class) owl_free(m->class);
438  if (m->inst) owl_free(m->inst);
439  if (m->opcode) owl_free(m->opcode);
440  if (m->time) owl_free(m->time);
441  if (m->realm) owl_free(m->realm);
442  if (m->body) owl_free(m->body);
443  if (m->zwriteline) owl_free(m->zwriteline);
444 
445  owl_fmtext_free(&(m->fmtext));
446}
447
448
449char *owl_message_get_hostname(owl_message *m) {
450  return(m->hostname);
451}
452
453
454void owl_message_curs_waddstr(owl_message *m, WINDOW *win, int aline, int bline, int acol, int bcol, int color) {
455  owl_fmtext a, b;
456
457  owl_fmtext_truncate_lines(&(m->fmtext), aline, bline-aline+1, &a);
458  owl_fmtext_truncate_cols(&a, acol, bcol, &b);
459  if (color!=OWL_COLOR_DEFAULT) {
460    owl_fmtext_colorize(&b, color);
461  }
462  owl_fmtext_curs_waddstr(&b, win);
463
464  owl_fmtext_free(&a);
465  owl_fmtext_free(&b);
466}
467
468owl_fmtext *owl_message_get_fmtext(owl_message *m) {
469  return(&(m->fmtext));
470}
471
472void owl_message_set_class(owl_message *m, char *class) {
473  if (m->class) owl_free(m->class);
474  m->class=owl_strdup(class);
475}
476
477
478char *owl_message_get_class(owl_message *m) {
479  return(m->class);
480}
481
482void owl_message_set_instance(owl_message *m, char *inst) {
483  if (m->inst) owl_free(m->inst);
484  m->inst=owl_strdup(inst);
485}
486
487char *owl_message_get_instance(owl_message *m) {
488  return(m->inst);
489}
490
491void owl_message_set_sender(owl_message *m, char *sender) {
492  if (m->sender) owl_free(m->sender);
493  m->sender=owl_strdup(sender);
494}
495
496char *owl_message_get_sender(owl_message *m) {
497  return(m->sender);
498}
499
500void owl_message_set_recipient(owl_message *m, char *recip) {
501  if (m->recip) owl_free(m->recip);
502  m->recip=owl_strdup(recip);
503}
504
505char *owl_message_get_recipient(owl_message *m) {
506  /* this is very, very stupid for outgoing messages, we need to
507     fix that. */
508     
509  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) {
510    return(m->recip);
511  } else if (m->type==OWL_MESSAGE_TYPE_ADMIN &&
512             m->admintype==OWL_MESSAGE_ADMINTYPE_OUTGOING) {
513    return(m->zwriteline);
514  } else {
515    return(m->recip);
516  }
517}
518
519void owl_message_set_realm(owl_message *m, char *realm) {
520  if (m->realm) owl_free(m->realm);
521  m->realm=owl_strdup(realm);
522}
523
524char *owl_message_get_realm(owl_message *m) {
525  return(m->realm);
526}
527
528void owl_message_set_opcode(owl_message *m, char *opcode) {
529  if (m->opcode) free(m->opcode);
530  m->opcode=owl_strdup(opcode);
531}
532
533char *owl_message_get_opcode(owl_message *m) {
534  return(m->opcode);
535}
536
537char *owl_message_get_timestr(owl_message *m) {
538  return(m->time);
539}
540
541int owl_message_is_admin(owl_message *m) {
542  if (m->type==OWL_MESSAGE_TYPE_ADMIN) return(1);
543  return(0);
544}
545
546int owl_message_is_zephyr(owl_message *m) {
547  if (m->type==OWL_MESSAGE_TYPE_ZEPHYR) return(1);
548  return(0);
549}
550
551char *owl_message_get_text(owl_message *m) {
552  return(owl_fmtext_get_text(&(m->fmtext)));
553}
554
555char *owl_message_get_body(owl_message *m) {
556  return(m->body);
557}
558
559int owl_message_is_personal(owl_message *m) {
560  if (!strcasecmp(owl_message_get_class(m), "message") &&
561      !strcasecmp(owl_message_get_instance(m), "personal") &&
562      !strcmp(owl_message_get_recipient(m), ZGetSender())) {
563    return(1);
564  }
565  return(0);
566}
567
568int owl_message_is_private(owl_message *m) {
569  if (!strcmp(owl_message_get_recipient(m), ZGetSender())) return(1);
570  return(0);
571}
572
573int owl_message_is_mail(owl_message *m) {
574  if (!strcasecmp(owl_message_get_class(m), "mail") && owl_message_is_private(m)) {
575    return(1);
576  }
577  return(0);
578}
579
580int owl_message_is_ping(owl_message *m) {
581  if (!strcasecmp(owl_message_get_opcode(m), "ping")) return(1);
582  return(0);
583}
584
585int owl_message_is_login(owl_message *m) {
586  if (!strcasecmp(owl_message_get_class(m), "login")) return(1);
587  return(0);
588  /* is this good enough? */
589}
590
591int owl_message_is_burningears(owl_message *m) {
592  /* we should add a global to cache the short zsender */
593  char sender[LINE], *ptr;
594
595  /* if the message is from us or to us, it doesn't count */
596  if (!strcasecmp(ZGetSender(), owl_message_get_sender(m))) return(0);
597  if (!strcasecmp(ZGetSender(), owl_message_get_recipient(m))) return(0);
598
599  strcpy(sender, ZGetSender());
600  ptr=strchr(sender, '@');
601  if (ptr) *ptr='\0';
602
603  if (stristr(owl_message_get_body(m), sender)) {
604    return(1);
605  }
606  return(0);
607}
608
609/* caller must free return value. */
610char *owl_message_get_cc(owl_message *m) {
611  char *cur, *out, *end;
612
613  cur = owl_message_get_body(m);
614  while (*cur && *cur==' ') cur++;
615  if (strncasecmp(cur, "cc:", 2)) return(NULL);
616  cur+=3;
617  while (*cur && *cur==' ') cur++;
618  out = owl_strdup(cur);
619  end = strchr(out, '\n');
620  if (end) end[0] = '\0';
621  return(out);
622}
623
624int owl_message_get_id(owl_message *m) {
625  return(m->id);
626}
627                                       
Note: See TracBrowser for help on using the repository browser.