Changeset 8861654
- Timestamp:
- Jun 26, 2019, 11:12:14 PM (6 years ago)
- Parents:
- 9a0d25d (diff), 0147aef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - git-author:
- Karl Ramm <xyzzy-github@1ts.org> (06/26/19 23:12:14)
- git-committer:
- GitHub <noreply@github.com> (06/26/19 23:12:14)
- Files:
-
- 8 added
- 44 deleted
- 40 edited
Legend:
- Unmodified
- Added
- Removed
-
AUTHORS
r80c0fc7 r9e219d3 32 32 Betsy Riley 33 33 Robert Jacobs 34 Google Inc. 34 35 35 36 BarnOwl is based on code from Owl, which was originally primarily -
Makefile.am
r4fd3c04 r8861654 60 60 CODELIST_SRCS=message.c mainwin.c popwin.c zephyr.c messagelist.c \ 61 61 commands.c global.c text.c fmtext.c editwin.c \ 62 util.c logging.c \62 util.c logging.c ztext.c \ 63 63 perlconfig.c keys.c functions.c zwrite.c viewwin.c help.c filter.c \ 64 64 regex.c history.c view.c dict.c variable.c filterelement.c pair.c \ … … 68 68 mainpanel.c msgwin.c sepbar.c editcontext.c signal.c closures.c 69 69 70 NORMAL_SRCS = filterproc.c filterproc.h window.c window.h windowcb.c 70 NORMAL_SRCS = filterproc.c filterproc.h window.c window.h windowcb.c ztext.h 71 71 72 72 BASE_SRCS = $(CODELIST_SRCS) $(NORMAL_SRCS) -
fmtext.c
rf271129 r4b2eef6 549 549 } 550 550 551 /* flattens a ztext parse tree into fmtext */ 552 static void owl_fmtext_append_ztext_tree(owl_fmtext *f, ztext_env *tree, char attr, short fg) 553 { 554 char *s; 555 int i; 556 bool handled = false; 557 const struct { 558 const char *tag; 559 enum {SET, MASK} mode; 560 const char val; 561 } TAGS[] = { 562 {"", MASK, 0}, 563 {"@", MASK, 0}, 564 {"@bold", MASK, OWL_FMTEXT_ATTR_BOLD}, 565 {"@b", MASK, OWL_FMTEXT_ATTR_BOLD}, 566 {"@italic", MASK, OWL_FMTEXT_ATTR_UNDERLINE}, 567 {"@i", MASK, OWL_FMTEXT_ATTR_UNDERLINE}, 568 {"@roman", SET, OWL_FMTEXT_ATTR_NONE}, 569 {NULL, 0}, 570 }; 571 572 if (tree->closer == '@' && tree->content == NULL) { 573 owl_fmtext_append_attr(f, "@", attr, fg, OWL_COLOR_DEFAULT); 574 return; 575 } 576 577 for (i = 0; TAGS[i].tag != NULL; i++) { 578 if (!strcasecmp(tree->label, TAGS[i].tag)) { 579 if (TAGS[i].mode == MASK) { 580 attr |= TAGS[i].val; 581 } else if (TAGS[i].mode == SET) { 582 attr = TAGS[i].val; 583 } 584 handled = true; 585 break; 586 } 587 } 588 589 if (!handled) { 590 /* continue the dubious practice of printing codes we don't understand */ 591 s = g_strdup_printf("%s%c", tree->label, tree->opener); 592 owl_fmtext_append_attr(f, s, attr, fg, OWL_COLOR_DEFAULT); 593 g_free(s); 594 } 595 596 for (ztext_node *p = tree->content; p != NULL; p = p->next) { 597 if (p->type == ZTEXT_NODE_STRING) { 598 owl_fmtext_append_attr(f, p->string, attr, fg, OWL_COLOR_DEFAULT); 599 } else if (p->type == ZTEXT_NODE_ENV) { 600 if (!strcasecmp(p->env->label, "@color")) { 601 s = ztext_strip(p->env); 602 fg = owl_util_string_to_color(s); 603 if (fg == OWL_COLOR_INVALID) 604 fg = OWL_COLOR_DEFAULT; 605 g_free(s); 606 } else { 607 owl_fmtext_append_ztext_tree(f, p->env, attr, fg); 608 } 609 } 610 } 611 612 if (!handled) { 613 s = g_strdup_printf("%c", tree->closer); 614 owl_fmtext_append_attr(f, s, attr, fg, OWL_COLOR_DEFAULT); 615 g_free(s); 616 } 617 } 551 618 552 619 /* Append the text 'text' to 'f' and interpret the zephyr style … … 555 622 void owl_fmtext_append_ztext(owl_fmtext *f, const char *text) 556 623 { 557 int stacksize, curattrs, curcolor; 558 const char *ptr, *txtptr, *tmpptr; 559 char *buff; 560 int attrstack[32], chrstack[32], colorstack[32]; 561 562 curattrs=OWL_FMTEXT_ATTR_NONE; 563 curcolor=OWL_COLOR_DEFAULT; 564 stacksize=0; 565 txtptr=text; 566 while (1) { 567 ptr=strpbrk(txtptr, "@{[<()>]}"); 568 if (!ptr) { 569 /* add all the rest of the text and exit */ 570 owl_fmtext_append_attr(f, txtptr, curattrs, curcolor, OWL_COLOR_DEFAULT); 571 return; 572 } else if (ptr[0]=='@') { 573 /* add the text up to this point then deal with the stack */ 574 buff=g_new(char, ptr-txtptr+20); 575 strncpy(buff, txtptr, ptr-txtptr); 576 buff[ptr-txtptr]='\0'; 577 owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); 578 g_free(buff); 579 580 /* update pointer to point at the @ */ 581 txtptr=ptr; 582 583 /* now the stack */ 584 585 /* if we've hit our max stack depth, print the @ and move on */ 586 if (stacksize==32) { 587 owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); 588 txtptr++; 589 continue; 590 } 591 592 /* if it's an @@, print an @ and continue */ 593 if (txtptr[1]=='@') { 594 owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); 595 txtptr+=2; 596 continue; 597 } 598 599 /* if there's no opener, print the @ and continue */ 600 tmpptr=strpbrk(txtptr, "(<[{ "); 601 if (!tmpptr || tmpptr[0]==' ') { 602 owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); 603 txtptr++; 604 continue; 605 } 606 607 /* check what command we've got, push it on the stack, start 608 using it, and continue ... unless it's a color command */ 609 buff=g_new(char, tmpptr-ptr+20); 610 strncpy(buff, ptr, tmpptr-ptr); 611 buff[tmpptr-ptr]='\0'; 612 if (!strcasecmp(buff, "@bold")) { 613 attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD; 614 chrstack[stacksize]=tmpptr[0]; 615 colorstack[stacksize]=curcolor; 616 stacksize++; 617 curattrs|=OWL_FMTEXT_ATTR_BOLD; 618 txtptr+=6; 619 g_free(buff); 620 continue; 621 } else if (!strcasecmp(buff, "@b")) { 622 attrstack[stacksize]=OWL_FMTEXT_ATTR_BOLD; 623 chrstack[stacksize]=tmpptr[0]; 624 colorstack[stacksize]=curcolor; 625 stacksize++; 626 curattrs|=OWL_FMTEXT_ATTR_BOLD; 627 txtptr+=3; 628 g_free(buff); 629 continue; 630 } else if (!strcasecmp(buff, "@i")) { 631 attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE; 632 chrstack[stacksize]=tmpptr[0]; 633 colorstack[stacksize]=curcolor; 634 stacksize++; 635 curattrs|=OWL_FMTEXT_ATTR_UNDERLINE; 636 txtptr+=3; 637 g_free(buff); 638 continue; 639 } else if (!strcasecmp(buff, "@italic")) { 640 attrstack[stacksize]=OWL_FMTEXT_ATTR_UNDERLINE; 641 chrstack[stacksize]=tmpptr[0]; 642 colorstack[stacksize]=curcolor; 643 stacksize++; 644 curattrs|=OWL_FMTEXT_ATTR_UNDERLINE; 645 txtptr+=8; 646 g_free(buff); 647 continue; 648 } else if (!strcasecmp(buff, "@")) { 649 attrstack[stacksize]=OWL_FMTEXT_ATTR_NONE; 650 chrstack[stacksize]=tmpptr[0]; 651 colorstack[stacksize]=curcolor; 652 stacksize++; 653 txtptr+=2; 654 g_free(buff); 655 continue; 656 657 /* if it's a color read the color, set the current color and 658 continue */ 659 } else if (!strcasecmp(buff, "@color") 660 && owl_global_is_colorztext(&g)) { 661 g_free(buff); 662 txtptr+=7; 663 tmpptr=strpbrk(txtptr, "@{[<()>]}"); 664 if (tmpptr && 665 ((txtptr[-1]=='(' && tmpptr[0]==')') || 666 (txtptr[-1]=='<' && tmpptr[0]=='>') || 667 (txtptr[-1]=='[' && tmpptr[0]==']') || 668 (txtptr[-1]=='{' && tmpptr[0]=='}'))) { 669 670 /* grab the color name */ 671 buff=g_new(char, tmpptr-txtptr+20); 672 strncpy(buff, txtptr, tmpptr-txtptr); 673 buff[tmpptr-txtptr]='\0'; 674 675 /* set it as the current color */ 676 curcolor=owl_util_string_to_color(buff); 677 if (curcolor == OWL_COLOR_INVALID) 678 curcolor = OWL_COLOR_DEFAULT; 679 g_free(buff); 680 txtptr=tmpptr+1; 681 continue; 682 683 } else { 684 685 } 686 687 } else { 688 /* if we didn't understand it, we'll print it. This is different from zwgc 689 * but zwgc seems to be smarter about some screw cases than I am 690 */ 691 g_free(buff); 692 owl_fmtext_append_attr(f, "@", curattrs, curcolor, OWL_COLOR_DEFAULT); 693 txtptr++; 694 continue; 695 } 696 697 } else if (ptr[0]=='}' || ptr[0]==']' || ptr[0]==')' || ptr[0]=='>') { 698 /* add the text up to this point first */ 699 buff=g_new(char, ptr-txtptr+20); 700 strncpy(buff, txtptr, ptr-txtptr); 701 buff[ptr-txtptr]='\0'; 702 owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); 703 g_free(buff); 704 705 /* now deal with the closer */ 706 txtptr=ptr; 707 708 /* first, if the stack is empty we must bail (just print and go) */ 709 if (stacksize==0) { 710 buff=g_new(char, 5); 711 buff[0]=ptr[0]; 712 buff[1]='\0'; 713 owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); 714 g_free(buff); 715 txtptr++; 716 continue; 717 } 718 719 /* if the closing char is what's on the stack, turn off the 720 attribue and pop the stack */ 721 if ((ptr[0]==')' && chrstack[stacksize-1]=='(') || 722 (ptr[0]=='>' && chrstack[stacksize-1]=='<') || 723 (ptr[0]==']' && chrstack[stacksize-1]=='[') || 724 (ptr[0]=='}' && chrstack[stacksize-1]=='{')) { 725 int i; 726 stacksize--; 727 curattrs=OWL_FMTEXT_ATTR_NONE; 728 curcolor = colorstack[stacksize]; 729 for (i=0; i<stacksize; i++) { 730 curattrs|=attrstack[i]; 731 } 732 txtptr+=1; 733 continue; 734 } else { 735 /* otherwise print and continue */ 736 buff=g_new(char, 5); 737 buff[0]=ptr[0]; 738 buff[1]='\0'; 739 owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); 740 g_free(buff); 741 txtptr++; 742 continue; 743 } 744 } else { 745 /* we've found an unattached opener, print everything and move on */ 746 buff=g_new(char, ptr-txtptr+20); 747 strncpy(buff, txtptr, ptr-txtptr+1); 748 buff[ptr-txtptr+1]='\0'; 749 owl_fmtext_append_attr(f, buff, curattrs, curcolor, OWL_COLOR_DEFAULT); 750 g_free(buff); 751 txtptr=ptr+1; 752 continue; 753 } 754 } 755 } 624 ztext_env *tree = ztext_tree(text); 625 626 owl_fmtext_append_ztext_tree(f, tree, 627 OWL_FMTEXT_ATTR_NONE, OWL_COLOR_DEFAULT); 628 629 ztext_env_free(tree); 630 } 631 756 632 757 633 /* requires that the list values are strings or NULL. -
owl.h
r4fd3c04 r8861654 62 62 63 63 #include "window.h" 64 #include "ztext.h" 64 65 65 66 extern const char *version; -
perl/lib/BarnOwl.pm
reea7bed4 r8861654 110 110 =head2 ztext_stylestrip STRING 111 111 112 Strips zephyr formatting from a string and returns the result 112 Strips zephyr formatting barnowl understands from a string and returns the result 113 114 =head2 ztext_stylestrip_full STRING 115 116 Strips all the zephyr formatting from a string an returns the reuslt 117 118 =head2 ztext_protect STRING 119 120 Massage zephyr formatting to make it not interfere with more zephyr formatting. 113 121 114 122 =head2 zephyr_getsubs -
perl/lib/BarnOwl/Style.pm
rfd8dfe7 ra13ad6f 14 14 { 15 15 local $_ = shift; 16 if ( !(/\)/) ) { 17 return '@b(' . $_ . ')'; 18 } elsif ( !(/\>/) ) { 19 return '@b<' . $_ . '>'; 20 } elsif ( !(/\}/) ) { 21 return '@b{' . $_ . '}'; 22 } elsif ( !(/\]/) ) { 23 return '@b[' . $_ . ']'; 24 } else { 25 my $txt = "\@b($_"; 26 $txt =~ s/\)/\)\@b\[\)\]\@b\(/g; 27 return $txt . ')'; 28 } 16 return '@b{' . BarnOwl::ztext_protect($_) . '}' 29 17 } 30 18 -
perlglue.xs
rd2ba33c r8861654 110 110 111 111 const utf8 * 112 ztext_protect(ztext) 113 const char *ztext 114 PREINIT: 115 char *rv = NULL; 116 CODE: 117 rv = ztext_protect(ztext); 118 RETVAL = rv; 119 OUTPUT: 120 RETVAL 121 CLEANUP: 122 g_free(rv); 123 124 const utf8 * 125 ztext_stylestrip_full(ztext) 126 const char *ztext 127 PREINIT: 128 char *rv = NULL; 129 CODE: 130 ztext_env *tree = ztext_tree(ztext); 131 rv = ztext_strip(tree); 132 ztext_env_free(tree); 133 RETVAL = rv; 134 OUTPUT: 135 RETVAL 136 CLEANUP: 137 g_free(rv); 138 139 const utf8 * 112 140 zephyr_smartstrip_user(in) 113 141 const char *in -
tester.c
ra882637 r8861654 26 26 int call_filter_regtest(void); 27 27 int owl_smartstrip_regtest(void); 28 int ztext_test(void); 28 29 29 30 extern void owl_perl_xs_init(pTHX); … … 116 117 numfailures += call_filter_regtest(); 117 118 numfailures += owl_smartstrip_regtest(); 119 numfailures += ztext_test(); 118 120 if (numfailures) { 119 121 fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures); … … 1053 1055 return numfailed; 1054 1056 } 1057 1058 static char *ztext_str(ztext_env *tree) 1059 { 1060 /* Unambiguous representation of the parse tree */ 1061 char *s, *t, *u; 1062 1063 if (tree->opener) { 1064 s = g_strdup_printf("{'%s%c'", tree->label, tree->opener); 1065 } else { 1066 s = g_strdup("{-"); 1067 } 1068 1069 for (ztext_node *p = tree->content; p != NULL; p = p->next) { 1070 t = s; 1071 if (p->type== ZTEXT_NODE_STRING) { 1072 s = g_strdup_printf("%s |%s|", s, p->string); 1073 } else if (p->type == ZTEXT_NODE_ENV) { 1074 u = ztext_str(p->env); 1075 s = g_strconcat(s, " ", u, NULL); 1076 g_free(u); 1077 } 1078 g_free(t); 1079 } 1080 1081 t = s; 1082 if (tree->closer) { 1083 s = g_strdup_printf("%s '%c'}", s, tree->closer); 1084 } else { 1085 s = g_strconcat(s, "}", NULL); 1086 } 1087 g_free(t); 1088 1089 return s; 1090 } 1091 1092 char *ztext_ztext(ztext_env *tree) 1093 { 1094 char *s, *t, *u; 1095 1096 if (tree->closer == '@' && tree->content == NULL) 1097 return g_strdup("@@"); 1098 1099 if (tree->opener) { 1100 s = g_strdup_printf("%s%c", tree->label, tree->opener); 1101 } else { 1102 s = g_strdup(""); 1103 } 1104 1105 for (ztext_node *p = tree->content; p != NULL; p = p->next) { 1106 t = s; 1107 if (p->type == ZTEXT_NODE_STRING) { 1108 s = g_strconcat(s, p->string, NULL); 1109 } else if (p->type == ZTEXT_NODE_ENV) { 1110 u = ztext_ztext(p->env); 1111 s = g_strconcat(s, u, NULL); 1112 g_free(u); 1113 } 1114 g_free(t); 1115 } 1116 1117 if (tree->closer) { 1118 t = s; 1119 s = g_strdup_printf("%s%c", s, tree->closer); 1120 g_free(t); 1121 } 1122 1123 return s; 1124 } 1125 1126 int ztext_test(void) 1127 { 1128 int numfailed = 0; 1129 char *s; 1130 ztext_env *t; 1131 char *d; 1132 1133 #define CHECK_ZTEXT_STR(in, expected) \ 1134 do { \ 1135 t = ztext_tree(in); \ 1136 s = ztext_str(t); \ 1137 d = g_strdup_printf("ztext decode \"%s\" expected \"%s\" got \"%s\"", \ 1138 in, expected, s); \ 1139 FAIL_UNLESS(d, !strcmp(s, expected)); \ 1140 ztext_env_free(t); \ 1141 g_free(d); \ 1142 g_free(s); \ 1143 } while (0) 1144 1145 CHECK_ZTEXT_STR("", "{-}"); 1146 CHECK_ZTEXT_STR("foo", "{- |foo|}"); 1147 CHECK_ZTEXT_STR("@{foo}", "{- {'@{' |foo| '}'}}"); 1148 CHECK_ZTEXT_STR("@bar{foo}", "{- {'@bar{' |foo| '}'}}"); 1149 CHECK_ZTEXT_STR("@bar{foo@bar}", "{- {'@bar{' |foo@bar| '}'}}"); 1150 CHECK_ZTEXT_STR("@bar{foo@@bar}", "{- {'@bar{' |foo| {'@@' '@'} |bar| '}'}}"); 1151 CHECK_ZTEXT_STR("@{foo@}bar}baz", "{- {'@{' |foo@| '}'} |bar}baz|}"); 1152 CHECK_ZTEXT_STR("foo@bar{baz@(bang})}", 1153 "{- |foo| {'@bar{' |baz| {'@(' |bang}| ')'} '}'}}"); 1154 CHECK_ZTEXT_STR("foo@bar{baz}", "{- |foo| {'@bar{' |baz| '}'}}"); 1155 CHECK_ZTEXT_STR("@bloop", "{- |@bloop|}"); 1156 CHECK_ZTEXT_STR("@{)}@{>}", "{- {'@{' |)| '}'} {'@{' |>| '}'}}"); 1157 1158 #define CHECK_ZTEXT_STRIP(in, expected) \ 1159 do { \ 1160 t = ztext_tree(in); \ 1161 s = ztext_strip(t); \ 1162 d = g_strdup_printf("ztext strip \"%s\" expected \"%s\" got \"%s\"", \ 1163 in, expected, s); \ 1164 FAIL_UNLESS(d, !strcmp(s, expected)); \ 1165 ztext_env_free(t); \ 1166 g_free(d); \ 1167 g_free(s); \ 1168 } while (0) 1169 1170 CHECK_ZTEXT_STRIP("", ""); 1171 CHECK_ZTEXT_STRIP("foo", "foo"); 1172 CHECK_ZTEXT_STRIP("@{foo}", "foo"); 1173 CHECK_ZTEXT_STRIP("@bar{foo}", "foo"); 1174 CHECK_ZTEXT_STRIP("@bar{foo@bar}", "foo@bar"); 1175 CHECK_ZTEXT_STRIP("@bar{foo@@bar}", "foo@bar"); 1176 CHECK_ZTEXT_STRIP("@{foo@}bar}baz", "foo@bar}baz"); 1177 CHECK_ZTEXT_STRIP("foo@bar{baz@(bang})}", "foobazbang}"); 1178 CHECK_ZTEXT_STRIP("foo@bar{baz}", "foobaz"); 1179 CHECK_ZTEXT_STRIP("@bloop", "@bloop"); 1180 CHECK_ZTEXT_STRIP("@{)}@{>}", ")>"); 1181 CHECK_ZTEXT_STRIP("@color(blue)@font(fixed)marzipan", "marzipan"); 1182 1183 #define CHECK_ZTEXT_RT(in) \ 1184 do { \ 1185 t = ztext_tree(in); \ 1186 s = ztext_ztext(t); \ 1187 d = g_strdup_printf("ztext round-trip \"%s\" got \"%s\"", in, s); \ 1188 FAIL_UNLESS(d, !strcmp(s, in)); \ 1189 ztext_env_free(t); \ 1190 g_free(s); \ 1191 } while (0) 1192 1193 CHECK_ZTEXT_RT(""); 1194 CHECK_ZTEXT_RT("foo"); 1195 CHECK_ZTEXT_RT("@{foo}"); 1196 CHECK_ZTEXT_RT("@bar{foo}"); 1197 CHECK_ZTEXT_RT("@bar{foo@bar}"); 1198 CHECK_ZTEXT_RT("@bar{foo@@bar}"); 1199 CHECK_ZTEXT_RT("@{foo@}bar}baz"); 1200 CHECK_ZTEXT_RT("foo@bar{baz@(bang})}"); 1201 CHECK_ZTEXT_RT("foo@bar{baz}"); 1202 CHECK_ZTEXT_RT("@bloop"); 1203 CHECK_ZTEXT_RT("@{)}@{>}"); 1204 1205 /* fuzzzzzz */ 1206 srand48(getpid() + time(0)); 1207 1208 char tango[32]; 1209 const char CHARS[] = "@abc ({<[]>})"; 1210 1211 for(int i=0; i < 1000; i++) { 1212 memset(tango, 0, sizeof(tango)); 1213 int l = lrand48() % sizeof(tango); 1214 for (int j=0; j < l; j++) { 1215 tango[j] = CHARS[lrand48() % (sizeof(CHARS) -1)]; 1216 } 1217 CHECK_ZTEXT_RT(tango); 1218 } 1219 1220 #define CHECK_ZTEXT_PROTECT(in, expected) \ 1221 do { \ 1222 s = ztext_protect(in); \ 1223 d = g_strdup_printf("ztext protect \"%s\" expected \"%s\" got \"%s\"", \ 1224 in, expected, s); \ 1225 FAIL_UNLESS(d, !strcmp(s, expected)); \ 1226 g_free(d); \ 1227 g_free(s); \ 1228 } while (0) 1229 1230 CHECK_ZTEXT_PROTECT("", ""); 1231 CHECK_ZTEXT_PROTECT("foo", "foo"); 1232 CHECK_ZTEXT_PROTECT("fo}o", "fo@(})o"); 1233 CHECK_ZTEXT_PROTECT("@[foo", "@[foo]"); 1234 CHECK_ZTEXT_PROTECT("})>]", "@(})@<)>@[>]@{]}"); 1235 1236 return numfailed; 1237 } -
ChangeLog
r6f87658 r678a7650 1 1.10 2 * No changes above what's already in 1.10rc1 3 4 1.10rc1 5 * Numerous autotools/build machinery fixes -andersk@mit.edu 6 * Numerous code correctness and simplification/cleanup fixes -andersk@mit.edu 7 * Add and use a cpanfile documenting perl module dependencies -jgross@mit.edu 8 * Add Travis configuration -jgross@mit.edu 9 * Avoid strchrnul -andersk@mit.edu 10 * Numerous IRC fixes -jgross@mit.edu 11 * Improve smartnarrow and smartfilter documentation -jgross@mit.edu 12 * filterproc: Rewrite using GIOChannel -andersk@mit.edu 13 * Implement :twitter-favorite -nelhage@nelhage.com 14 * Kill the client-side tweet length check. -nelhage@nelhage.com 15 * squelch the Twitter legacy_list_api warnings -nelhage@nelhage.com 16 * Use SSL for Twitter by default -adehnert@mit.edu 17 * Humanize zsigs -andersk@mit.edu 18 * Show Zephyr charset in info popup -andersk@mit.edu 19 * Fix Jabber SRV record support (at one point fixed connecting via jabber to google talk or facebook) -james2vegas@aim.com 20 * fix cmd_join in BarnOwl/Module/IRC.pm -james2vegas@aim.com 21 * Add a ~/.owl/ircchannels file, persist channels -jgross@mit.edu 22 * Added hooks for user going idle or active. -jgross@mit.edu 23 * Support channel-or-user IRC commands, and setup irc-msg to use it. -ezyang@mit.edu 24 * Refactor perl calls through a single method -jgross@mit.edu 25 * Really support building Perl modules from a separate builddir -andersk@mit.edu 26 * Get rid of all our embedded copies of Module::Install -andersk@mit.edu 27 * Don't let new_variable_* overriding previously set values -rnjacobs@mit.edu 28 * Messages sent to 'class messages' are not personal -jgross@mit.edu 29 * Expose message_matches_filter to perl -jgross@mit.edu 30 * Fail fast on -c filsrv, which most people won't have permission to send to -rnjacobs@mit.edu 31 * zcrypt: Use getopt_long for argument parsing -andersk@mit.edu 32 * zcrypt: Accept -help and --version -andersk@mit.edu 33 * barnowl --help: Write to stdout and exit successfully -andersk@mit.edu 34 * Don't swallow errors in :unsuball -davidben@mit.edu 35 * Allow testing in a separate build directory -andersk@mit.edu 36 * Add support for arbitrary Perl subs for getters and setters for barnowl variables -glasgall@mit.edu 37 * owl_zephyr_loadsubs: Don’t leak memory on error opening ~/.zephyr.subs -andersk@mit.edu 38 * Make :loadsubs reload instanced personals too -davidben@mit.edu 39 * Fix some undefined behavior in filter.c, caught by clang scan-build -jgross@mit.edu 40 * Die on a failed zephyr_zwrite; don't silently ignore it -jgross@mit.edu 41 * Fix a memory leak in zcrypt.c, caught by clang scan-build -jgross@mit.edu 42 * zcrypt: Make gpg stop messing around in ~/.gnupg -andersk@mit.edu 43 * Fix display of pseudologins -davidben@mit.edu 44 * Unbundle random Facebook module libraries -davidben@mit.edu 45 * Replace deprecated GLib < 2.31.0 APIs -andersk@mit.edu 46 * Abstract g->interrupt_lock -andersk@mit.edu 47 * zephyr: Replace outgoing default format with a small URL -geofft@mit.edu 48 1 49 1.9 2 50 * Update Jabber module for Net::DNS changes -james2vegas@aim.com -
codelist.pl
r06adc25 r4fd3c04 18 18 && !/^XS/ 19 19 && !/\/\*/ 20 && !/ZWRITEOPTIONS/ 21 && !/owlfaim_priv/) 20 && !/ZWRITEOPTIONS/) 22 21 { 23 22 -
commands.c
r8fcd3e7 r4fd3c04 122 122 " Send to the specified opcode\n"), 123 123 124 OWLCMD_ARGS("aimwrite", owl_command_aimwrite, OWL_CTX_INTERACTIVE,125 "send an AIM message",126 "aimwrite <user> [-m <message...>]",127 "Send an aim message to a user.\n\n"128 "The following options are available:\n\n"129 "-m Specifies a message to send without prompting.\n"),130 131 124 OWLCMD_ARGS("loopwrite", owl_command_loopwrite, OWL_CTX_INTERACTIVE, 132 125 "send a loopback message", … … 153 146 OWLCMD_ARGS("set", owl_command_set, OWL_CTX_ANY, 154 147 "set a variable value", 155 "set [-q] [<variable>][<value>]\n"148 "set [-q] <variable> [<value>]\n" 156 149 "set", 157 150 "Set the named variable to the specified value. If no\n" … … 234 227 "Execute the BarnOwl commands in <filename>.\n"), 235 228 236 OWLCMD_ARGS("aim", owl_command_aim, OWL_CTX_INTERACTIVE,237 "AIM specific commands",238 "aim search <email>",239 ""),240 241 229 OWLCMD_ARGS("addbuddy", owl_command_addbuddy, OWL_CTX_INTERACTIVE, 242 230 "add a buddy to a buddylist", 243 231 "addbuddy <protocol> <screenname>", 244 "Add the named buddy to your buddylist. <protocol> can be aim orzephyr\n"),232 "Add the named buddy to your buddylist. <protocol> must be zephyr\n"), 245 233 246 234 OWLCMD_ARGS("delbuddy", owl_command_delbuddy, OWL_CTX_INTERACTIVE, 247 235 "delete a buddy from a buddylist", 248 236 "delbuddy <protocol> <screenname>", 249 "Delete the named buddy from your buddylist. <protocol> can be aim or zephyr\n"), 250 251 OWLCMD_ARGS("join", owl_command_join, OWL_CTX_INTERACTIVE, 252 "join a chat group", 253 "join aim <groupname> [exchange]", 254 "Join the AIM chatroom with 'groupname'.\n"), 237 "Delete the named buddy from your buddylist. <protocol> must be zephyr\n"), 255 238 256 239 OWLCMD_ARGS("smartzpunt", owl_command_smartzpunt, OWL_CTX_INTERACTIVE, … … 308 291 "znol [-f file]", 309 292 "Print a znol-style listing of users logged in"), 310 311 OWLCMD_VOID("alist", owl_command_alist, OWL_CTX_INTERACTIVE,312 "List AIM users logged in",313 "alist",314 "Print a listing of AIM users logged in"),315 293 316 294 OWLCMD_VOID("blist", owl_command_blist, OWL_CTX_INTERACTIVE, … … 470 448 "use the default.\n"), 471 449 472 OWLCMD_ARGS("aaway", owl_command_aaway, OWL_CTX_INTERACTIVE,473 "Set, enable or disable AIM away message",474 "aaway [ on | off | toggle ]\n"475 "aaway <message>",476 "Turn on or off the AIM away message. If 'message' is\n"477 "specified turn on aaway with that message, otherwise\n"478 "use the default.\n"),479 480 450 OWLCMD_ARGS("away", owl_command_away, OWL_CTX_INTERACTIVE, 481 451 "Set, enable or disable all away messages", … … 486 456 "otherwise use the default.\n" 487 457 "\n" 488 "SEE ALSO: aaway, zaway"), 458 "SEE ALSO: zaway"), 459 460 OWLCMD_ARGS("flush-logs", owl_command_flushlogs, OWL_CTX_ANY, 461 "flush the queue of messages waiting to be logged", 462 "flush-logs [-f | --force] [-q | --quiet]", 463 "If BarnOwl failed to log a file, this command tells\n" 464 "BarnOwl to try logging the messages that have since\n" 465 "come in, and to resume logging normally.\n" 466 "\n" 467 "Normally, if logging any of these messages fails,\n" 468 "that message is added to the queue of messages waiting\n" 469 "to be logged, and any new messages are deferred until\n" 470 "the next :flush-logs. If the --force flag is passed,\n" 471 "any messages on the queue which cannot successfully be\n" 472 "logged are dropped, and BarnOwl will resume logging\n" 473 "normally.\n" 474 "\n" 475 "Unless --quiet is passed, a message is printed about\n" 476 "how many logs there are to flush."), 489 477 490 478 OWLCMD_ARGS("load-subs", owl_command_loadsubs, OWL_CTX_ANY, … … 530 518 " body - message body\n" 531 519 " hostname - hostname of sending host\n" 532 " type - message type (zephyr, a im, admin)\n"520 " type - message type (zephyr, admin)\n" 533 521 " direction - either 'in' 'out' or 'none'\n" 534 522 " login - either 'login' 'logout' or 'none'\n" … … 754 742 "no argument, it makes search highlighting inactive."), 755 743 756 OWLCMD_ARGS("aimlogin", owl_command_aimlogin, OWL_CTX_ANY,757 "login to an AIM account",758 "aimlogin <screenname> [<password>]\n",759 ""),760 761 OWLCMD_ARGS("aimlogout", owl_command_aimlogout, OWL_CTX_ANY,762 "logout from AIM",763 "aimlogout\n",764 ""),765 766 744 OWLCMD_ARGS("error", owl_command_error, OWL_CTX_ANY, 767 745 "Display an error message", … … 1090 1068 } 1091 1069 } 1092 owl_function_buddylist( 0,1, file);1070 owl_function_buddylist(1, file); 1093 1071 return(NULL); 1094 1072 } 1095 1073 1096 void owl_command_alist(void)1097 {1098 owl_function_buddylist(1, 0, NULL);1099 }1100 1101 1074 void owl_command_blist(void) 1102 1075 { 1103 owl_function_buddylist(1, 1,NULL);1076 owl_function_buddylist(1, NULL); 1104 1077 } 1105 1078 … … 1117 1090 { 1118 1091 owl_function_makemsg("BarnOwl version %s", version); 1119 }1120 1121 char *owl_command_aim(int argc, const char *const *argv, const char *buff)1122 {1123 if (argc<2) {1124 owl_function_makemsg("not enough arguments to aim command");1125 return(NULL);1126 }1127 1128 if (!strcmp(argv[1], "search")) {1129 if (argc!=3) {1130 owl_function_makemsg("not enough arguments to aim search command");1131 return(NULL);1132 }1133 owl_aim_search(argv[2]);1134 } else {1135 owl_function_makemsg("unknown subcommand '%s' for aim command", argv[1]);1136 return(NULL);1137 }1138 return(NULL);1139 1092 } 1140 1093 … … 1146 1099 } 1147 1100 1148 if (!strcasecmp(argv[1], "aim")) { 1149 if (!owl_global_is_aimloggedin(&g)) { 1150 owl_function_makemsg("addbuddy: You must be logged into aim to use this command."); 1151 return(NULL); 1152 } 1153 /* 1154 owl_function_makemsg("This function is not yet operational. Stay tuned."); 1155 return(NULL); 1156 */ 1157 owl_aim_addbuddy(argv[2]); 1158 owl_function_makemsg("%s added as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g)); 1159 } else if (!strcasecmp(argv[1], "zephyr")) { 1101 if (!strcasecmp(argv[1], "zephyr")) { 1160 1102 owl_zephyr_addbuddy(argv[2]); 1161 1103 owl_function_makemsg("%s added as zephyr buddy", argv[2]); 1162 1104 } else { 1163 owl_function_makemsg("addbuddy: currently the only supported protocol s are 'zephyr' and 'aim'");1105 owl_function_makemsg("addbuddy: currently the only supported protocol is 'zephyr'"); 1164 1106 } 1165 1107 … … 1174 1116 } 1175 1117 1176 if (!strcasecmp(argv[1], "aim")) { 1177 if (!owl_global_is_aimloggedin(&g)) { 1178 owl_function_makemsg("delbuddy: You must be logged into aim to use this command."); 1179 return(NULL); 1180 } 1181 owl_aim_delbuddy(argv[2]); 1182 owl_function_makemsg("%s deleted as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g)); 1183 } else if (!strcasecmp(argv[1], "zephyr")) { 1118 if (!strcasecmp(argv[1], "zephyr")) { 1184 1119 owl_zephyr_delbuddy(argv[2]); 1185 1120 owl_function_makemsg("%s deleted as zephyr buddy", argv[2]); 1186 1121 } else { 1187 owl_function_makemsg("delbuddy: currently the only supported protocols are 'zephyr' and 'aim'"); 1188 } 1189 1190 return(NULL); 1191 } 1192 1193 char *owl_command_join(int argc, const char *const *argv, const char *buff) 1194 { 1195 if (argc!=3 && argc!=4) { 1196 owl_function_makemsg("usage: join <protocol> <buddyname> [exchange]"); 1197 return(NULL); 1198 } 1199 1200 if (!strcasecmp(argv[1], "aim")) { 1201 if (!owl_global_is_aimloggedin(&g)) { 1202 owl_function_makemsg("join aim: You must be logged into aim to use this command."); 1203 return(NULL); 1204 } 1205 if (argc==3) { 1206 owl_aim_chat_join(argv[2], 4); 1207 } else { 1208 owl_aim_chat_join(argv[2], atoi(argv[3])); 1209 } 1210 /* owl_function_makemsg("%s deleted as AIM buddy for %s", argv[2], owl_global_get_aim_screenname(&g)); */ 1211 } else { 1212 owl_function_makemsg("join: currently the only supported protocol is 'aim'"); 1213 } 1122 owl_function_makemsg("delbuddy: currently the only supported protocol is 'zephyr'"); 1123 } 1124 1214 1125 return(NULL); 1215 1126 } … … 1437 1348 } 1438 1349 1350 char *owl_command_flushlogs(int argc, const char *const *argv, const char *buff) 1351 { 1352 bool force = false; 1353 bool quiet = false; 1354 int i; 1355 1356 for (i = 1; i < argc; i++) { 1357 if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force")) { 1358 force = true; 1359 } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--quiet")) { 1360 quiet = true; 1361 } else { 1362 owl_function_makemsg("Invalid flag to flush-logs: %s", argv[i]); 1363 } 1364 } 1365 owl_log_flush_logs(force, quiet); 1366 return NULL; 1367 } 1368 1439 1369 char *owl_command_loadsubs(int argc, const char *const *argv, const char *buff) 1440 1370 { … … 1502 1432 1503 1433 1504 char *owl_command_aaway(int argc, const char *const *argv, const char *buff)1505 {1506 if ((argc==1) ||1507 ((argc==2) && !strcmp(argv[1], "on"))) {1508 owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));1509 owl_function_aaway_on();1510 return NULL;1511 }1512 1513 if (argc==2 && !strcmp(argv[1], "off")) {1514 owl_function_aaway_off();1515 return NULL;1516 }1517 1518 if (argc==2 && !strcmp(argv[1], "toggle")) {1519 owl_function_aaway_toggle();1520 return NULL;1521 }1522 1523 buff = skiptokens(buff, 1);1524 owl_global_set_aaway_msg(&g, buff);1525 owl_function_aaway_on();1526 return NULL;1527 }1528 1529 1530 1434 char *owl_command_away(int argc, const char *const *argv, const char *buff) 1531 1435 { … … 1536 1440 (argc == 2 && !strcmp(argv[1], "on"))) { 1537 1441 away_off = false; 1538 owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));1539 1442 owl_global_set_zaway_msg(&g, owl_global_get_zaway_msg_default(&g)); 1540 1443 } else if (argc == 2 && !strcmp(argv[1], "off")) { … … 1548 1451 1549 1452 if (away_off) { 1550 owl_function_aaway_off();1551 1453 owl_function_zaway_off(); 1552 1454 owl_perlconfig_perl_call_norv("BarnOwl::Hooks::_away_off", 0, NULL); 1553 1455 owl_function_makemsg("Away messages off."); 1554 1456 } else if (message != NULL) { 1555 owl_global_set_aaway_msg(&g, message);1556 1457 owl_global_set_zaway_msg(&g, message); 1557 owl_function_aaway_on();1558 1458 owl_function_zaway_on(); 1559 1459 owl_perlconfig_perl_call_norv("BarnOwl::Hooks::_away_on", 1, &message); 1560 1460 owl_function_makemsg("Away messages set (%s).", message); 1561 1461 } else { 1562 owl_function_aaway_on();1563 1462 owl_function_zaway_on(); 1564 1463 owl_perlconfig_perl_call_norv("BarnOwl::Hooks::_away_on", 0, NULL); … … 2001 1900 } 2002 1901 return(NULL); 2003 }2004 2005 char *owl_command_aimwrite(int argc, const char *const *argv, const char *buff)2006 {2007 char *message = NULL;2008 GString *recip = g_string_new("");2009 const char *const *myargv;2010 int myargc;2011 2012 if (!owl_global_is_aimloggedin(&g)) {2013 owl_function_error("You are not logged in to AIM.");2014 goto err;2015 }2016 2017 /* Skip argv[0]. */2018 myargv = argv+1;2019 myargc = argc-1;2020 while (myargc) {2021 if (!strcmp(myargv[0], "-m")) {2022 if (myargc <= 1) {2023 owl_function_error("No message specified.");2024 goto err;2025 }2026 /* Once we have -m, gobble up everything else on the line */2027 myargv++;2028 myargc--;2029 message = g_strjoinv(" ", (char**)myargv);2030 break;2031 } else {2032 /* squish arguments together to make one screenname w/o spaces for now */2033 g_string_append(recip, myargv[0]);2034 myargv++;2035 myargc--;2036 }2037 }2038 2039 if (recip->str[0] == '\0') {2040 owl_function_error("No recipient specified");2041 goto err;2042 }2043 2044 if (message != NULL)2045 owl_function_aimwrite(recip->str, message, false);2046 else2047 owl_function_aimwrite_setup(recip->str);2048 err:2049 g_string_free(recip, true);2050 g_free(message);2051 return NULL;2052 1902 } 2053 1903 … … 2617 2467 } 2618 2468 2619 char *owl_command_aimlogin(int argc, const char *const *argv, const char *buff)2620 {2621 if ((argc<2) || (argc>3)) {2622 owl_function_makemsg("Wrong number of arguments to aimlogin command");2623 return(NULL);2624 }2625 2626 /* if we get two arguments, ask for the password */2627 if (argc==2) {2628 owl_editwin *e = owl_function_start_password("AIM Password: ");2629 owl_editwin_set_cbdata(e, g_strdup(argv[1]), g_free);2630 owl_editwin_set_callback(e, owl_callback_aimlogin);2631 return(NULL);2632 } else {2633 owl_function_aimlogin(argv[1], argv[2]);2634 }2635 2636 /* this is a test */2637 return(NULL);2638 }2639 2640 char *owl_command_aimlogout(int argc, const char *const *argv, const char *buff)2641 {2642 /* clear the buddylist */2643 owl_buddylist_clear(owl_global_get_buddylist(&g));2644 2645 owl_aim_logout();2646 return(NULL);2647 }2648 2649 2469 CALLER_OWN char *owl_command_getstyle(int argc, const char *const *argv, const char *buff) 2650 2470 { -
configure.ac
r77dfeb1 r9a0d25d 1 1 dnl Process this file with autoconf to produce a configure script. 2 AC_INIT([BarnOwl],[1.1 0dev],[bug-barnowl@mit.edu])2 AC_INIT([BarnOwl],[1.11dev],[bug-barnowl@mit.edu]) 3 3 AM_INIT_AUTOMAKE([1.7.0 foreign std-options -Wall -Wno-portability]) 4 4 AM_MAINTAINER_MODE([enable]) … … 54 54 [with_zephyr=check]) 55 55 56 AC_ARG_WITH([krb4],57 AS_HELP_STRING([--with-krb4],58 [Build with kerberos IV]))59 60 56 AS_IF([test "x$with_zephyr" != xno], 61 [have_krb4=no 62 63 AS_IF([test "x$with_krb4" != "xno"], 64 [AC_MSG_CHECKING([for Kerberos IV]) 65 AS_IF([krb5-config krb4 --libs >/dev/null 2>&1], 66 [AC_MSG_RESULT([yes]) 67 have_krb4=yes 68 AC_DEFINE([HAVE_KERBEROS_IV], [1], [Define if you have kerberos IV]) 69 AM_CFLAGS="${AM_CFLAGS} `krb5-config krb4 --cflags`" 70 LIBS="${LIBS} `krb5-config krb4 --libs`" 71 ], 72 [AC_MSG_RESULT([no]) 73 AS_IF([test "x$with_krb4" = "xyes"], 74 [AC_MSG_ERROR([Kerberos IV requested but not found])])])]) 75 76 AS_IF([test "x$have_krb4" != xyes], 77 [PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto], 78 [AM_CFLAGS="${AM_CFLAGS} ${LIBCRYPTO_CFLAGS}" 79 LIBS="${LIBS} ${LIBCRYPTO_LIBS}" 80 ], 81 [PKG_CHECK_MODULES([OPENSSL], [openssl], 82 [AM_CFLAGS="${AM_CFLAGS} ${OPENSSL_CFLAGS}" 83 LIBS="${LIBS} ${OPENSSL_LIBS}" 84 ])])]) 57 [PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto], 58 [AM_CFLAGS="${AM_CFLAGS} ${LIBCRYPTO_CFLAGS}" 59 LIBS="${LIBS} ${LIBCRYPTO_LIBS}" 60 ], 61 [PKG_CHECK_MODULES([OPENSSL], [openssl], 62 [AM_CFLAGS="${AM_CFLAGS} ${OPENSSL_CFLAGS}" 63 LIBS="${LIBS} ${OPENSSL_LIBS}" 64 ])]) 85 65 86 66 AC_CHECK_LIB([zephyr], [ZGetSender], … … 102 82 AC_CHECK_FUNCS([use_default_colors]) 103 83 AC_CHECK_FUNCS([resizeterm], [], [AC_MSG_ERROR([No resizeterm found])]) 104 AC_CHECK_FUNCS([ des_string_to_keyDES_string_to_key], [HAVE_DES_STRING_TO_KEY=1])105 AC_CHECK_FUNCS([ des_ecb_encryptDES_ecb_encrypt], [HAVE_DES_ECB_ENCRYPT=1])106 AC_CHECK_FUNCS([ des_key_schedDES_key_sched], [HAVE_DES_KEY_SCHED=1])84 AC_CHECK_FUNCS([DES_string_to_key], [HAVE_DES_STRING_TO_KEY=1]) 85 AC_CHECK_FUNCS([DES_ecb_encrypt], [HAVE_DES_ECB_ENCRYPT=1]) 86 AC_CHECK_FUNCS([DES_key_sched], [HAVE_DES_KEY_SCHED=1]) 107 87 108 88 dnl Checks for header files. … … 176 156 AX_APPEND_COMPILE_FLAGS([-Wno-format-zero-length],[AM_CFLAGS]) 177 157 178 AX_APPEND_COMPILE_FLAGS([-Wno-pointer-sign -Wno-empty-body -Wno-unused-value],[LIBFAIM_CFLAGS])179 180 158 AM_CONDITIONAL([ENABLE_ZCRYPT], [test "$HAVE_DES_STRING_TO_KEY" && dnl 181 159 test "$HAVE_DES_KEY_SCHED" && dnl … … 183 161 184 162 AM_CFLAGS="$AM_CFLAGS -D_XOPEN_SOURCE=600" 185 dnl Define _BSD_SOURCE because zephyr needs caddr_t.186 AM_CFLAGS="$AM_CFLAGS -D_BSD_SOURCE "163 dnl Define _BSD_SOURCE/_DEFAULT_SOURCE because zephyr needs caddr_t. 164 AM_CFLAGS="$AM_CFLAGS -D_BSD_SOURCE -D_DEFAULT_SOURCE" 187 165 dnl Define __EXTENSIONS__ for strcasecmp on Solaris. 188 166 AM_CFLAGS="$AM_CFLAGS -D__EXTENSIONS__" … … 194 172 195 173 AC_SUBST([AM_CFLAGS]) 196 AC_SUBST([LIBFAIM_CFLAGS])197 174 198 175 AC_SUBST(XSUBPPDIR) … … 213 190 AC_SUBST([abs_srcdir]) 214 191 215 AC_CONFIG_FILES([Makefile compat/Makefile libfaim/Makefileperl/Makefile perl/modules/Makefile])192 AC_CONFIG_FILES([Makefile compat/Makefile perl/Makefile perl/modules/Makefile]) 216 193 AC_OUTPUT -
doc/advanced.txt
rc82b055 r4fd3c04 42 42 realm zephyr realm 43 43 body message body 44 type message type ('zephyr', 'a im', 'admin')44 type message type ('zephyr', 'admin') 45 45 direction either 'in' 'out' or 'none'\n" 46 46 login either 'login' 'logout' or 'none'\n" … … 103 103 All owl::Message objects contain the following methods: 104 104 105 type - returns the type of the message ("zephyr", "a im", "admin")105 type - returns the type of the message ("zephyr", "admin") 106 106 direction - returns "in" or "out" for incoming or outgoing messages 107 107 time - returns a string of the time when the message showed up … … 126 126 127 127 header - returns the admin message header line (admin) 128 is_personal - returns true if this is a personal message ( aim,zephyr)128 is_personal - returns true if this is a personal message (zephyr) 129 129 is_private - returns true if this was a private message (zephyr) 130 130 login_tty - returns the login tty for login messages (zephyr) -
doc/intro.txt
rd7cc50b r4fd3c04 8 8 9 9 Owl is a tty, curses-based instant messaging client. This is a quick 10 guide to learning how to use it. Currently Owl supports AIM &zephyr,10 guide to learning how to use it. Currently Owl supports zephyr, 11 11 but other messaging protocols, including Jabber, are on the way. Some 12 12 major features of owl include: … … 73 73 If you wish to send to a class/instance pair simply supply -c and -i 74 74 arguments to the zwrite command as you normally would. 75 76 Sending an AIM message77 ----------------------78 79 Before sending an AIM message you must login to AOL Instant Messenger.80 Use the 'aimlogin' command, with your screenname as an argument:81 82 aimlogin <screenname>83 84 You will be prompted for your password, which you must enter. Once85 you are successfully logged in you can send an AIM message by pressing86 the 'a' key, which will bring up an 'aimwrite' command:87 88 aimwrite <screenname>89 90 Supply the screen name you wish to write to as an argument and then91 send the message just as you would send a zephyr, as described above.92 75 93 76 Manipulating Messages … … 256 239 auto Messages generated by automated programs 257 240 out Messages sent from you to another user 258 aim AIM messages259 241 zephyr Zephyr messages 260 242 trash "Trash" messages -
filter.c
r7dcef03 r9e596f5 16 16 owl_filter *owl_filter_new(const char *name, int argc, const char *const *argv) 17 17 { 18 return owl_filter_new_colored(name, argc, argv, OWL_COLOR_DEFAULT, OWL_COLOR_DEFAULT); 19 } 20 21 owl_filter *owl_filter_new_colored(const char *name, int argc, const char *const *argv, int fgcolor, int bgcolor) 22 { 18 23 owl_filter *f; 19 24 … … 21 26 22 27 f->name=g_strdup(name); 23 f->fgcolor=OWL_COLOR_DEFAULT; 24 f->bgcolor=OWL_COLOR_DEFAULT; 25 26 /* first take arguments that have to come first */ 27 /* set the color */ 28 while ( argc>=2 && ( !strcmp(argv[0], "-c") || 29 !strcmp(argv[0], "-b") ) ) { 30 if (owl_util_string_to_color(argv[1])==OWL_COLOR_INVALID) { 31 owl_function_error("The color '%s' is not available, using default.", argv[1]); 32 } else { 33 switch (argv[0][1]) { 34 case 'c': 35 f->fgcolor=owl_util_string_to_color(argv[1]); 36 break; 37 case 'b': 38 f->bgcolor=owl_util_string_to_color(argv[1]); 39 break; 40 } 41 } 42 argc-=2; 43 argv+=2; 44 } 28 f->fgcolor = fgcolor; 29 f->bgcolor = bgcolor; 45 30 46 31 if (!(f->root = owl_filter_parse_expression(argc, argv, NULL))) { -
filterproc.c
r7155955 re8db357 1 1 #include "filterproc.h" 2 2 #include <sys/wait.h> 3 #include < fcntl.h>3 #include <string.h> 4 4 #include <glib.h> 5 #include <poll.h>6 #include <string.h>7 #include <unistd.h>8 5 9 /* Even in case of error, send_receive is responsible for closing wfd 10 * (to EOF the child) and rfd (for consistency). */ 11 static int send_receive(int rfd, int wfd, const char *out, char **in) 6 struct filter_data { 7 const char **in; 8 const char *in_end; 9 GString *out_str; 10 GMainLoop *loop; 11 int err; 12 }; 13 14 static gboolean filter_stdin(GIOChannel *channel, GIOCondition condition, gpointer data_) 12 15 { 13 GString *str = g_string_new(""); 14 char buf[1024]; 15 nfds_t nfds; 16 int err = 0; 17 struct pollfd fds[2]; 16 struct filter_data *data = data_; 17 gboolean done = condition & (G_IO_ERR | G_IO_HUP); 18 18 19 fcntl(rfd, F_SETFL, O_NONBLOCK | fcntl(rfd, F_GETFL)); 20 fcntl(wfd, F_SETFL, O_NONBLOCK | fcntl(wfd, F_GETFL)); 21 22 fds[0].fd = rfd; 23 fds[0].events = POLLIN; 24 fds[1].fd = wfd; 25 fds[1].events = POLLOUT; 26 27 if(!out || !*out) { 28 /* Nothing to write. Close our end so the child doesn't hang waiting. */ 29 close(wfd); wfd = -1; 30 out = NULL; 19 if (condition & G_IO_OUT) { 20 gsize n; 21 GIOStatus ret = g_io_channel_write_chars(channel, *data->in, data->in_end - *data->in, &n, NULL); 22 *data->in += n; 23 if (ret == G_IO_STATUS_ERROR) 24 data->err = 1; 25 if (ret == G_IO_STATUS_ERROR || *data->in == data->in_end) 26 done = TRUE; 31 27 } 32 28 33 while(1) { 34 if(out && *out) { 35 nfds = 2; 36 } else { 37 nfds = 1; 38 } 39 err = poll(fds, nfds, -1); 40 if(err < 0) { 41 break; 42 } 43 if(out && *out) { 44 if(fds[1].revents & POLLOUT) { 45 err = write(wfd, out, strlen(out)); 46 if(err > 0) { 47 out += err; 48 } 49 if(err < 0) { 50 out = NULL; 51 } 52 } 53 if(!out || !*out || fds[1].revents & (POLLERR | POLLHUP)) { 54 close(wfd); wfd = -1; 55 out = NULL; 56 } 57 } 58 if(fds[0].revents & POLLIN) { 59 err = read(rfd, buf, sizeof(buf)); 60 if(err <= 0) { 61 break; 62 } 63 g_string_append_len(str, buf, err); 64 } else if(fds[0].revents & (POLLHUP | POLLERR)) { 65 err = 0; 66 break; 29 if (condition & G_IO_ERR) 30 data->err = 1; 31 32 if (done) 33 g_io_channel_shutdown(channel, TRUE, NULL); 34 return !done; 35 } 36 37 static gboolean filter_stdout(GIOChannel *channel, GIOCondition condition, gpointer data_) 38 { 39 struct filter_data *data = data_; 40 gboolean done = condition & (G_IO_ERR | G_IO_HUP); 41 42 if (condition & (G_IO_IN | G_IO_HUP)) { 43 gchar *buf; 44 gsize n; 45 GIOStatus ret = g_io_channel_read_to_end(channel, &buf, &n, NULL); 46 g_string_append_len(data->out_str, buf, n); 47 g_free(buf); 48 if (ret == G_IO_STATUS_ERROR) { 49 data->err = 1; 50 done = TRUE; 67 51 } 68 52 } 69 53 70 if (wfd >= 0) close(wfd); 71 close(rfd); 72 *in = g_string_free(str, err < 0); 73 return err; 54 if (condition & G_IO_ERR) 55 data->err = 1; 56 57 if (done) { 58 g_io_channel_shutdown(channel, TRUE, NULL); 59 g_main_loop_quit(data->loop); 60 } 61 return !done; 74 62 } 75 63 76 64 int call_filter(const char *const *argv, const char *in, char **out, int *status) 77 65 { 78 int err;79 66 GPid child_pid; 80 67 int child_stdin, child_stdout; … … 89 76 } 90 77 91 err = send_receive(child_stdout, child_stdin, in, out); 92 if (err == 0) { 93 waitpid(child_pid, status, 0); 94 } 95 return err; 78 if (in == NULL) in = ""; 79 GMainContext *context = g_main_context_new(); 80 struct filter_data data = {&in, in + strlen(in), g_string_new(""), g_main_loop_new(context, FALSE), 0}; 81 82 GIOChannel *channel = g_io_channel_unix_new(child_stdin); 83 g_io_channel_set_encoding(channel, NULL, NULL); 84 g_io_channel_set_flags(channel, g_io_channel_get_flags(channel) | G_IO_FLAG_NONBLOCK, NULL); 85 GSource *source = g_io_create_watch(channel, G_IO_OUT | G_IO_ERR | G_IO_HUP); 86 g_io_channel_unref(channel); 87 g_source_set_callback(source, (GSourceFunc)filter_stdin, &data, NULL); 88 g_source_attach(source, context); 89 g_source_unref(source); 90 91 channel = g_io_channel_unix_new(child_stdout); 92 g_io_channel_set_encoding(channel, NULL, NULL); 93 g_io_channel_set_flags(channel, g_io_channel_get_flags(channel) | G_IO_FLAG_NONBLOCK, NULL); 94 source = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP); 95 g_io_channel_unref(channel); 96 g_source_set_callback(source, (GSourceFunc)filter_stdout, &data, NULL); 97 g_source_attach(source, context); 98 g_source_unref(source); 99 100 g_main_loop_run(data.loop); 101 102 g_main_loop_unref(data.loop); 103 g_main_context_unref(context); 104 105 waitpid(child_pid, status, 0); 106 g_spawn_close_pid(child_pid); 107 *out = g_string_free(data.out_str, data.err); 108 return data.err; 96 109 } -
functions.c
rb61ad80 r9e596f5 170 170 "':sub @b(class)', and then type ':zwrite -c @b(class)' to send.\n\n" 171 171 #endif 172 "@b(AIM:)\n"173 "Log in to AIM with ':aimlogin @b(screenname)'. Use ':aimwrite @b(screenname)',\n"174 "or 'a' and then the screen name, to send someone a message.\n\n"175 172 ; 176 173 … … 239 236 } 240 237 241 /* Create an outgoing AIM message, returns a pointer to the created242 * message or NULL if we're not logged into AIM (and thus unable to243 * create the message). Does not put it on the global queue. Use244 * owl_global_messagequeue_addmsg() for that.245 */246 CALLER_OWN owl_message *owl_function_make_outgoing_aim(const char *body, const char *to)247 {248 owl_message *m;249 250 /* error if we're not logged into aim */251 if (!owl_global_is_aimloggedin(&g)) return(NULL);252 253 m=g_slice_new(owl_message);254 owl_message_create_aim(m,255 owl_global_get_aim_screenname(&g),256 to,257 body,258 OWL_MESSAGE_DIRECTION_OUT,259 0);260 return(m);261 }262 263 238 /* Create an outgoing loopback message and return a pointer to it. 264 239 * Does not append it to the global queue, use … … 325 300 } 326 301 327 void owl_function_aimwrite_setup(const char *to)328 {329 owl_editwin *e;330 /* TODO: We probably actually want an owl_aimwrite object like331 * owl_zwrite. */332 char *line = g_strdup_printf("aimwrite %s", to);333 owl_function_write_setup("message");334 e = owl_function_start_edit_win(line);335 owl_editwin_set_cbdata(e, g_strdup(to), g_free);336 owl_editwin_set_callback(e, &owl_callback_aimwrite);337 g_free(line);338 }339 340 302 void owl_function_loopwrite_setup(void) 341 303 { … … 436 398 g_free(cryptmsg); 437 399 g_free(old_msg); 438 }439 440 void owl_callback_aimwrite(owl_editwin *e, bool success)441 {442 if (!success) return;443 char *to = owl_editwin_get_cbdata(e);444 owl_function_aimwrite(to, owl_editwin_get_text(e), true);445 }446 447 void owl_function_aimwrite(const char *to, const char *msg, bool unwrap)448 {449 int ret;450 char *format_msg;451 owl_message *m;452 453 /* make a formatted copy of the message */454 format_msg = g_strdup(msg);455 if (unwrap)456 owl_text_wordunwrap(format_msg);457 458 /* send the message */459 ret=owl_aim_send_im(to, format_msg);460 if (!ret) {461 owl_function_makemsg("AIM message sent.");462 } else {463 owl_function_error("Could not send AIM message.");464 }465 466 /* create the outgoing message */467 m=owl_function_make_outgoing_aim(msg, to);468 469 if (m) {470 owl_global_messagequeue_addmsg(&g, m);471 } else {472 owl_function_error("Could not create outgoing AIM message");473 }474 475 g_free(format_msg);476 }477 478 void owl_function_send_aimawymsg(const char *to, const char *msg)479 {480 int ret;481 char *format_msg;482 owl_message *m;483 484 /* make a formatted copy of the message */485 format_msg=g_strdup(msg);486 owl_text_wordunwrap(format_msg);487 488 /* send the message */489 ret=owl_aim_send_awaymsg(to, format_msg);490 if (!ret) {491 /* owl_function_makemsg("AIM message sent."); */492 } else {493 owl_function_error("Could not send AIM message.");494 }495 496 /* create the message */497 m=owl_function_make_outgoing_aim(msg, to);498 if (m) {499 owl_global_messagequeue_addmsg(&g, m);500 } else {501 owl_function_error("Could not create AIM message");502 }503 g_free(format_msg);504 400 } 505 401 … … 918 814 } 919 815 920 void owl_callback_aimlogin(owl_editwin *e, bool success)921 {922 if (!success) return;923 char *user = owl_editwin_get_cbdata(e);924 owl_function_aimlogin(user,925 owl_editwin_get_text(e));926 }927 928 void owl_function_aimlogin(const char *user, const char *passwd) {929 int ret;930 931 /* clear the buddylist */932 owl_buddylist_clear(owl_global_get_buddylist(&g));933 934 /* try to login */935 ret=owl_aim_login(user, passwd);936 if (ret) owl_function_makemsg("Warning: login for %s failed.\n", user);937 }938 939 816 void owl_function_suspend(void) 940 817 { … … 969 846 } 970 847 971 void owl_function_aaway_toggle(void)972 {973 if (!owl_global_is_aaway(&g)) {974 owl_global_set_aaway_msg(&g, owl_global_get_aaway_msg_default(&g));975 owl_function_aaway_on();976 } else {977 owl_function_aaway_off();978 }979 }980 981 void owl_function_aaway_on(void)982 {983 owl_global_set_aaway_on(&g);984 /* owl_aim_set_awaymsg(owl_global_get_zaway_msg(&g)); */985 owl_function_makemsg("AIM away set (%s)", owl_global_get_aaway_msg(&g));986 }987 988 void owl_function_aaway_off(void)989 {990 owl_global_set_aaway_off(&g);991 /* owl_aim_set_awaymsg(""); */992 owl_function_makemsg("AIM away off");993 }994 995 848 bool owl_function_is_away(void) 996 849 { 997 850 return owl_global_is_zaway(&g) || 998 owl_global_is_aaway(&g) ||999 851 owl_perlconfig_perl_call_bool("BarnOwl::Hooks::_get_is_away", 0, NULL); 1000 852 } … … 1017 869 if (owl_global_get_newmsgproc_pid(&g)) { 1018 870 kill(owl_global_get_newmsgproc_pid(&g), SIGHUP); 1019 }1020 1021 /* Quit AIM */1022 if (owl_global_is_aimloggedin(&g)) {1023 owl_aim_logout();1024 871 } 1025 872 … … 1226 1073 FILE *file; 1227 1074 time_t now; 1075 struct tm tm; 1228 1076 va_list ap; 1229 1077 … … 1237 1085 now = time(NULL); 1238 1086 1239 tmpbuff = owl_util_format_time(localtime (&now));1087 tmpbuff = owl_util_format_time(localtime_r(&now, &tm)); 1240 1088 fprintf(file, "[%d - %s - %lds]: ", 1241 1089 (int) getpid(), tmpbuff, now - owl_global_get_starttime(&g)); … … 1775 1623 char buff[MAXPATHLEN+1]; 1776 1624 time_t start; 1625 struct tm tm; 1777 1626 int up, days, hours, minutes; 1778 1627 owl_fmtext fm; … … 1800 1649 owl_fmtext_append_normal(&fm, "\n"); 1801 1650 1802 tmpbuff = owl_util_format_time(localtime (&start));1651 tmpbuff = owl_util_format_time(localtime_r(&start, &tm)); 1803 1652 owl_fmtext_appendf_normal(&fm, " Startup Time: %s\n", tmpbuff); 1804 1653 g_free(tmpbuff); … … 1820 1669 owl_fmtext_append_normal(&fm, "no\n"); 1821 1670 } 1822 owl_fmtext_append_normal(&fm, " AIM included : yes\n");1823 1671 owl_fmtext_append_normal(&fm, " Loopback included : yes\n"); 1824 1672 … … 1831 1679 owl_fmtext_append_normal(&fm, "no\n"); 1832 1680 #endif 1833 1834 1835 owl_fmtext_append_normal(&fm, "\nAIM Status:\n");1836 owl_fmtext_append_normal(&fm, " Logged in: ");1837 if (owl_global_is_aimloggedin(&g)) {1838 owl_fmtext_append_normal(&fm, owl_global_get_aim_screenname(&g));1839 owl_fmtext_append_normal(&fm, "\n");1840 } else {1841 owl_fmtext_append_normal(&fm, "(not logged in)\n");1842 }1843 1844 owl_fmtext_append_normal(&fm, " Processing events: ");1845 if (owl_global_is_doaimevents(&g)) {1846 owl_fmtext_append_normal(&fm, "yes\n");1847 } else {1848 owl_fmtext_append_normal(&fm, "no\n");1849 }1850 1681 1851 1682 owl_function_popless_fmtext(&fm); … … 2149 1980 const owl_view *v; 2150 1981 int inuse = 0; 1982 int i = 2; 1983 int fgcolor = OWL_COLOR_DEFAULT; 1984 bool set_fgcolor = false; 1985 int bgcolor = OWL_COLOR_DEFAULT; 1986 bool set_bgcolor = false; 2151 1987 2152 1988 if (argc < 2) { … … 2165 2001 } 2166 2002 2167 /* deal with the case of trying change the filter color */ 2168 if (argc==4 && !strcmp(argv[2], "-c")) { 2003 /* set the color */ 2004 while (i + 2 <= argc && (!strcmp(argv[i], "-c") || 2005 !strcmp(argv[i], "-b"))) { 2006 int color = owl_util_string_to_color(argv[i + 1]); 2007 if (color == OWL_COLOR_INVALID) { 2008 owl_function_error("The color '%s' is not available.", argv[i + 1]); 2009 } else if (argv[i][1] == 'c') { 2010 fgcolor = color; 2011 set_fgcolor = true; 2012 } else { 2013 bgcolor = color; 2014 set_bgcolor = true; 2015 } 2016 i += 2; 2017 } 2018 2019 if (i > 2 && i == argc) { 2169 2020 f=owl_global_get_filter(&g, argv[1]); 2170 2021 if (!f) { … … 2172 2023 return false; 2173 2024 } 2174 if (owl_util_string_to_color(argv[3])==OWL_COLOR_INVALID) { 2175 owl_function_error("The color '%s' is not available.", argv[3]); 2025 if (!set_fgcolor && !set_bgcolor) 2176 2026 return false; 2177 } 2178 owl_filter_set_fgcolor(f, owl_util_string_to_color(argv[3])); 2179 owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 2180 return false; 2181 } 2182 if (argc==4 && !strcmp(argv[2], "-b")) { 2183 f=owl_global_get_filter(&g, argv[1]); 2184 if (!f) { 2185 owl_function_error("The filter '%s' does not exist.", argv[1]); 2186 return false; 2187 } 2188 if (owl_util_string_to_color(argv[3])==OWL_COLOR_INVALID) { 2189 owl_function_error("The color '%s' is not available.", argv[3]); 2190 return false; 2191 } 2192 owl_filter_set_bgcolor(f, owl_util_string_to_color(argv[3])); 2027 if (set_fgcolor) 2028 owl_filter_set_fgcolor(f, fgcolor); 2029 if (set_bgcolor) 2030 owl_filter_set_bgcolor(f, bgcolor); 2193 2031 owl_mainwin_redisplay(owl_global_get_mainwin(&g)); 2194 2032 return true; … … 2196 2034 2197 2035 /* create the filter and check for errors */ 2198 f = owl_filter_new (argv[1], argc-2, argv+2);2036 f = owl_filter_new_colored(argv[1], argc - i, argv + i, fgcolor, bgcolor); 2199 2037 if (f == NULL) { 2200 2038 owl_function_error("Invalid filter: %s", argv[1]); … … 2444 2282 if (f == NULL) { 2445 2283 /* Couldn't make a filter for some reason. Return NULL. */ 2446 owl_function_error("Error creating filter '%s'", filtname);2447 g_free(filtname);2448 return NULL;2449 }2450 2451 /* add it to the global list */2452 owl_global_add_filter(&g, f);2453 2454 return(filtname);2455 }2456 2457 /* Create a filter for AIM IM messages to or from the specified2458 * screenname. The name of the filter will be 'aimuser-<user>'. If a2459 * filter already exists with this name, no new filter will be2460 * created. This allows the configuration to override this function.2461 * Returns the name of the filter, which the caller must free.2462 */2463 CALLER_OWN char *owl_function_aimuserfilt(const char *user)2464 {2465 owl_filter *f;2466 char *argbuff, *filtname;2467 char *escuser;2468 2469 /* name for the filter */2470 filtname=g_strdup_printf("aimuser-%s", user);2471 2472 /* if it already exists then go with it. This lets users override */2473 if (owl_global_get_filter(&g, filtname)) {2474 return filtname;2475 }2476 2477 /* create the new-internal filter */2478 escuser = owl_text_quote(user, OWL_REGEX_QUOTECHARS, OWL_REGEX_QUOTEWITH);2479 2480 argbuff = g_strdup_printf(2481 "( type ^aim$ and ( ( sender ^%1$s$ and recipient ^%2$s$ ) or "2482 "( sender ^%2$s$ and recipient ^%1$s$ ) ) )",2483 escuser, owl_global_get_aim_screenname_for_filters(&g));2484 g_free(escuser);2485 2486 f = owl_filter_new_fromstring(filtname, argbuff);2487 g_free(argbuff);2488 2489 if (f == NULL) {2490 2284 owl_function_error("Error creating filter '%s'", filtname); 2491 2285 g_free(filtname); … … 2604 2398 * If the curmsg is a zephyr class message and type==1 then 2605 2399 * return a filter name for the class and instance. 2606 * If the curmsg is a personal AIM message returna filter2607 * name to the AIM conversation with that user2608 2400 */ 2609 2401 CALLER_OWN char *owl_function_smartfilter(int type, int invert_related) … … 2631 2423 if (owl_message_is_type_loopback(m)) { 2632 2424 return(owl_function_typefilt("loopback")); 2633 }2634 2635 /* aim messages */2636 if (owl_message_is_type_aim(m)) {2637 if (owl_message_is_direction_in(m)) {2638 filtname=owl_function_aimuserfilt(owl_message_get_sender(m));2639 } else if (owl_message_is_direction_out(m)) {2640 filtname=owl_function_aimuserfilt(owl_message_get_recipient(m));2641 }2642 return(filtname);2643 2425 } 2644 2426 … … 3068 2850 3069 2851 /* Popup a buddylisting. If filename is NULL use the default .anyone */ 3070 void owl_function_buddylist(int aim, intzephyr, const char *filename)3071 { 3072 int i , j, idle;2852 void owl_function_buddylist(int zephyr, const char *filename) 2853 { 2854 int i; 3073 2855 int interrupted = 0; 3074 2856 owl_fmtext fm; 3075 const owl_buddylist *bl;3076 const owl_buddy *b;3077 char *timestr;3078 2857 #ifdef HAVE_LIBZEPHYR 3079 2858 int x; … … 3086 2865 3087 2866 owl_fmtext_init_null(&fm); 3088 3089 /* AIM first */3090 if (aim && owl_global_is_aimloggedin(&g)) {3091 bl=owl_global_get_buddylist(&g);3092 3093 owl_fmtext_append_bold(&fm, "AIM users logged in:\n");3094 /* we're assuming AIM for now */3095 j=owl_buddylist_get_size(bl);3096 for (i=0; i<j; i++) {3097 b=owl_buddylist_get_buddy_n(bl, i);3098 idle=owl_buddy_get_idle_time(b);3099 if (idle!=0) {3100 timestr=owl_util_format_minutes(idle);3101 } else {3102 timestr=g_strdup("");3103 }3104 owl_fmtext_appendf_normal(&fm, " %-20.20s %-12.12s\n", owl_buddy_get_name(b), timestr);3105 g_free(timestr);3106 }3107 }3108 2867 3109 2868 #ifdef HAVE_LIBZEPHYR … … 3162 2921 #endif 3163 2922 3164 if ( aim &&zephyr) {2923 if (zephyr) { 3165 2924 if (owl_perlconfig_is_function("BarnOwl::Hooks::_get_blist")) { 3166 2925 char * perlblist = owl_perlconfig_execute("BarnOwl::Hooks::_get_blist()"); … … 3424 3183 char *date; 3425 3184 time_t now; 3185 struct tm tm; 3426 3186 char *buff; 3427 3187 3428 3188 now = time(NULL); 3429 date = owl_util_format_time(localtime (&now));3189 date = owl_util_format_time(localtime_r(&now, &tm)); 3430 3190 3431 3191 buff = g_strdup_printf("%s %s", date, string); … … 3505 3265 } 3506 3266 3507 void owl_function_aimsearch_results(const char *email, GPtrArray *namelist)3508 {3509 owl_fmtext fm;3510 int i;3511 3512 owl_fmtext_init_null(&fm);3513 owl_fmtext_append_normal(&fm, "AIM screennames associated with ");3514 owl_fmtext_append_normal(&fm, email);3515 owl_fmtext_append_normal(&fm, ":\n");3516 3517 for (i = 0; i < namelist->len; i++) {3518 owl_fmtext_append_normal(&fm, " ");3519 owl_fmtext_append_normal(&fm, namelist->pdata[i]);3520 owl_fmtext_append_normal(&fm, "\n");3521 }3522 3523 owl_function_popless_fmtext(&fm);3524 owl_fmtext_cleanup(&fm);3525 }3526 3527 3267 int owl_function_get_color_count(void) 3528 3268 { -
global.c
r7dcef03 r4fd3c04 84 84 _owl_global_init_windows(g); 85 85 86 g->aim_screenname=NULL;87 g->aim_screenname_for_filters=NULL;88 g->aim_loggedin=0;89 owl_buddylist_init(&(g->buddylist));90 91 86 g->havezephyr=0; 92 g->haveaim=0;93 g->ignoreaimlogin=0;94 owl_global_set_no_doaimevents(g);95 87 96 88 owl_errqueue_init(&(g->errqueue)); … … 646 638 } 647 639 648 /* AIM stuff */649 650 int owl_global_is_aimloggedin(const owl_global *g)651 {652 if (g->aim_loggedin) return(1);653 return(0);654 }655 656 const char *owl_global_get_aim_screenname(const owl_global *g)657 {658 if (owl_global_is_aimloggedin(g)) {659 return (g->aim_screenname);660 }661 return("");662 }663 664 const char *owl_global_get_aim_screenname_for_filters(const owl_global *g)665 {666 if (owl_global_is_aimloggedin(g)) {667 return (g->aim_screenname_for_filters);668 }669 return("");670 }671 672 void owl_global_set_aimloggedin(owl_global *g, const char *screenname)673 {674 char *sn_escaped;675 g->aim_loggedin=1;676 if (g->aim_screenname) g_free(g->aim_screenname);677 if (g->aim_screenname_for_filters) g_free(g->aim_screenname_for_filters);678 g->aim_screenname=g_strdup(screenname);679 sn_escaped = owl_text_quote(screenname, OWL_REGEX_QUOTECHARS, OWL_REGEX_QUOTEWITH);680 g->aim_screenname_for_filters = owl_arg_quote(sn_escaped);681 g_free(sn_escaped);682 }683 684 void owl_global_set_aimnologgedin(owl_global *g)685 {686 g->aim_loggedin=0;687 }688 689 bool owl_global_is_doaimevents(const owl_global *g)690 {691 return g->aim_event_source != NULL;692 }693 694 void owl_global_set_doaimevents(owl_global *g)695 {696 if (g->aim_event_source)697 return;698 g->aim_event_source = owl_aim_event_source_new(owl_global_get_aimsess(g));699 g_source_attach(g->aim_event_source, NULL);700 }701 702 void owl_global_set_no_doaimevents(owl_global *g)703 {704 if (!g->aim_event_source)705 return;706 g_source_destroy(g->aim_event_source);707 g_source_unref(g->aim_event_source);708 g->aim_event_source = NULL;709 }710 711 aim_session_t *owl_global_get_aimsess(owl_global *g)712 {713 return(&(g->aimsess));714 }715 716 aim_conn_t *owl_global_get_bosconn(owl_global *g)717 {718 return(&(g->bosconn));719 }720 721 void owl_global_set_bossconn(owl_global *g, aim_conn_t *conn)722 {723 g->bosconn=*conn;724 }725 726 640 /* message queue */ 727 641 … … 750 664 } 751 665 752 owl_buddylist *owl_global_get_buddylist(owl_global *g)753 {754 return(&(g->buddylist));755 }756 757 666 /* style */ 758 667 … … 781 690 owl_dict_insert_element(&(g->styledict), owl_style_get_name(s), 782 691 s, (void (*)(void *))owl_style_delete); 783 }784 785 void owl_global_set_haveaim(owl_global *g)786 {787 g->haveaim=1;788 }789 790 int owl_global_is_haveaim(const owl_global *g)791 {792 if (g->haveaim) return(1);793 return(0);794 }795 796 void owl_global_set_ignore_aimlogin(owl_global *g)797 {798 g->ignoreaimlogin = 1;799 }800 801 void owl_global_unset_ignore_aimlogin(owl_global *g)802 {803 g->ignoreaimlogin = 0;804 }805 806 int owl_global_is_ignore_aimlogin(const owl_global *g)807 {808 return g->ignoreaimlogin;809 692 } 810 693 … … 867 750 { "reply-lockout", "class ^mail$ or class ^filsrv$" }, 868 751 { "out", "direction ^out$" }, 869 { "aim", "type ^aim$" },870 752 { "zephyr", "type ^zephyr$" }, 871 753 { "none", "false" }, -
help.c
r8258ea5 r4fd3c04 52 52 "\n" 53 53 " z Start a zwrite command\n" 54 " a Start an aimwrite command\n"55 54 " r Reply to the current message\n" 56 55 " R Reply to sender\n" … … 64 63 " ! Invert the current view\n" 65 64 "\n" 66 " l Print a zephyr /AIMbuddy listing\n"65 " l Print a zephyr buddy listing\n" 67 66 " A Toggle away\n" 68 67 " o Toggle one-line display mode\n" … … 88 87 "\n" 89 88 " zwrite Send a zephyr\n" 90 " aimlogin Login to AIM\n"91 " aimwrite Send an AIM message\n"92 89 "\n" 93 " addbuddy Add a zephyr or AIMbuddy\n"90 " addbuddy Add a zephyr buddy\n" 94 91 " zaway Turn zaway on or off, or set the message\n" 95 92 " zlocate Locate a user\n" 96 93 " subscribe Subscribe to a zephyr class or instance\n" 97 94 " unsubscribe Unsubscribe to a zephyr class or instance\n" 98 " blist Print a list of zephyr and AIMbuddies logged in\n"95 " blist Print a list of zephyr buddies logged in\n" 99 96 " search Search for a text string\n" 100 97 "\n" … … 110 107 " zlog Send a login or logout notification\n" 111 108 " zlist Print a list of zephyr buddies logged in\n" 112 " alist Print a list of AIM buddies logged in\n"113 109 " info Print detailed information about the current message\n" 114 110 " filter Create a message filter\n" -
keys.c
rdcd48ad r4fd3c04 44 44 BIND_CMD("M-RIGHT", "edit:move-next-word", ""); 45 45 BIND_CMD("M-[ 1 ; 3 D", "edit:move-next-word", ""); 46 BIND_CMD("M-[ 1 ; 5 D", "edit:move-next-word", ""); 46 47 BIND_CMD("M-b", "edit:move-prev-word", ""); 47 48 BIND_CMD("M-O 3 D", "edit:move-prev-word", ""); 48 49 BIND_CMD("M-LEFT", "edit:move-prev-word", ""); 49 BIND_CMD("M-[ 1 ; 3 C", "edit:move-next-word", ""); 50 BIND_CMD("M-[ 1 ; 3 C", "edit:move-prev-word", ""); 51 BIND_CMD("M-[ 1 ; 5 C", "edit:move-prev-word", ""); 50 52 51 53 BIND_CMD("LEFT", "edit:move-left", ""); … … 315 317 316 318 BIND_CMD("z", "start-command zwrite ", "start a zwrite command"); 317 BIND_CMD("a", "start-command aimwrite ", "start an aimwrite command");318 319 BIND_CMD("r", "reply", "reply to the current message"); 319 320 BIND_CMD("R", "reply sender", "reply to sender of the current message"); -
logging.c
r7dcef03 r0c059f0 7 7 } owl_log_entry; 8 8 9 typedef struct _owl_log_options { /* noproto */ 10 bool drop_failed_logs; 11 bool display_initial_log_count; 12 } owl_log_options; 9 13 10 14 static GMainContext *log_context; 11 15 static GMainLoop *log_loop; 12 16 static GThread *logging_thread; 13 14 /* This is now the one function that should be called to log a 15 * message. It will do all the work necessary by calling the other 16 * functions in this file as necessary. 17 static bool defer_logs; /* to be accessed only on the disk-writing thread */ 18 static GQueue *deferred_entry_queue; 19 20 static void owl_log_error_main_thread(gpointer data) 21 { 22 owl_function_error("%s", (const char*)data); 23 } 24 25 static void owl_log_adminmsg_main_thread(gpointer data) 26 { 27 owl_function_adminmsg("Logging", (const char*)data); 28 } 29 30 static void owl_log_makemsg_main_thread(gpointer data) 31 { 32 owl_function_makemsg("%s", (const char*)data); 33 } 34 35 static void G_GNUC_PRINTF(1, 2) owl_log_error(const char *fmt, ...) 36 { 37 va_list ap; 38 char *data; 39 40 va_start(ap, fmt); 41 data = g_strdup_vprintf(fmt, ap); 42 va_end(ap); 43 44 owl_select_post_task(owl_log_error_main_thread, 45 data, g_free, g_main_context_default()); 46 } 47 48 static void G_GNUC_PRINTF(1, 2) owl_log_adminmsg(const char *fmt, ...) 49 { 50 va_list ap; 51 char *data; 52 53 va_start(ap, fmt); 54 data = g_strdup_vprintf(fmt, ap); 55 va_end(ap); 56 57 owl_select_post_task(owl_log_adminmsg_main_thread, 58 data, g_free, g_main_context_default()); 59 } 60 61 static void G_GNUC_PRINTF(1, 2) owl_log_makemsg(const char *fmt, ...) 62 { 63 va_list ap; 64 char *data; 65 66 va_start(ap, fmt); 67 data = g_strdup_vprintf(fmt, ap); 68 va_end(ap); 69 70 owl_select_post_task(owl_log_makemsg_main_thread, 71 data, g_free, g_main_context_default()); 72 } 73 74 static CALLER_OWN owl_log_entry *owl_log_new_entry(const char *buffer, const char *filename) 75 { 76 owl_log_entry *log_msg = g_slice_new(owl_log_entry); 77 log_msg->message = g_strdup(buffer); 78 log_msg->filename = g_strdup(filename); 79 return log_msg; 80 } 81 82 static void owl_log_deferred_enqueue_message(const char *buffer, const char *filename) 83 { 84 g_queue_push_tail(deferred_entry_queue, owl_log_new_entry(buffer, filename)); 85 } 86 87 static void owl_log_deferred_enqueue_first_message(const char *buffer, const char *filename) 88 { 89 g_queue_push_head(deferred_entry_queue, owl_log_new_entry(buffer, filename)); 90 } 91 92 /* write out the entry if possible 93 * return 0 on success, errno on failure to open 17 94 */ 18 void owl_log_message(const owl_message *m) { 19 owl_function_debugmsg("owl_log_message: entering"); 20 21 if (m == NULL) { 22 owl_function_debugmsg("owl_log_message: passed null message"); 23 return; 24 } 25 26 /* should we be logging this message? */ 27 if (!owl_log_shouldlog_message(m)) { 28 owl_function_debugmsg("owl_log_message: not logging message"); 29 return; 30 } 31 32 /* handle incmoing messages */ 33 if (owl_message_is_direction_in(m)) { 34 owl_log_incoming(m); 35 owl_function_debugmsg("owl_log_message: leaving"); 36 return; 37 } 38 39 /* handle outgoing messages */ 40 owl_log_outgoing(m); 41 42 owl_function_debugmsg("owl_log_message: leaving"); 43 } 44 45 /* Return 1 if we should log the given message, otherwise return 0 */ 46 int owl_log_shouldlog_message(const owl_message *m) { 47 const owl_filter *f; 48 49 /* If there's a logfilter and this message matches it, log */ 50 f=owl_global_get_filter(&g, owl_global_get_logfilter(&g)); 51 if (f && owl_filter_message_match(f, m)) return(1); 52 53 /* otherwise we do things based on the logging variables */ 54 55 /* skip login/logout messages if appropriate */ 56 if (!owl_global_is_loglogins(&g) && owl_message_is_loginout(m)) return(0); 57 58 /* check direction */ 59 if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_IN) && owl_message_is_direction_out(m)) { 60 return(0); 61 } 62 if ((owl_global_get_loggingdirection(&g)==OWL_LOGGING_DIRECTION_OUT) && owl_message_is_direction_in(m)) { 63 return(0); 64 } 65 66 if (owl_message_is_type_zephyr(m)) { 67 if (owl_message_is_personal(m) && !owl_global_is_logging(&g)) return(0); 68 if (!owl_message_is_personal(m) && !owl_global_is_classlogging(&g)) return(0); 69 } else { 70 if (owl_message_is_private(m) || owl_message_is_loginout(m)) { 71 if (!owl_global_is_logging(&g)) return(0); 72 } else { 73 if (!owl_global_is_classlogging(&g)) return(0); 74 } 75 } 76 return(1); 77 } 78 79 CALLER_OWN char *owl_log_zephyr(const owl_message *m) 80 { 81 char *tmp = NULL; 82 GString *buffer = NULL; 83 buffer = g_string_new(""); 84 tmp = short_zuser(owl_message_get_sender(m)); 85 g_string_append_printf(buffer, "Class: %s Instance: %s", 86 owl_message_get_class(m), 87 owl_message_get_instance(m)); 88 if (strcmp(owl_message_get_opcode(m), "")) { 89 g_string_append_printf(buffer, " Opcode: %s", 90 owl_message_get_opcode(m)); 91 } 92 g_string_append_printf(buffer, "\n"); 93 g_string_append_printf(buffer, "Time: %s Host: %s\n", 94 owl_message_get_timestr(m), 95 owl_message_get_hostname(m)); 96 g_string_append_printf(buffer, "From: %s <%s>\n\n", 97 owl_message_get_zsig(m), tmp); 98 g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m)); 99 g_free(tmp); 100 return g_string_free(buffer, FALSE); 101 } 102 103 CALLER_OWN char *owl_log_aim(const owl_message *m) 104 { 105 GString *buffer = NULL; 106 buffer = g_string_new(""); 107 g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 108 owl_message_get_sender(m), owl_message_get_recipient(m)); 109 g_string_append_printf(buffer, "Time: %s\n\n", 110 owl_message_get_timestr(m)); 111 if (owl_message_is_login(m)) { 112 g_string_append_printf(buffer, "LOGIN\n\n"); 113 } else if (owl_message_is_logout(m)) { 114 g_string_append_printf(buffer, "LOGOUT\n\n"); 115 } else { 116 g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m)); 117 } 118 return g_string_free(buffer, FALSE); 119 } 120 121 CALLER_OWN char *owl_log_jabber(const owl_message *m) 122 { 123 GString *buffer = NULL; 124 buffer = g_string_new(""); 125 g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 126 owl_message_get_sender(m), 127 owl_message_get_recipient(m)); 128 g_string_append_printf(buffer, "Time: %s\n\n", 129 owl_message_get_timestr(m)); 130 g_string_append_printf(buffer, "%s\n\n", owl_message_get_body(m)); 131 return g_string_free(buffer, FALSE); 132 } 133 134 CALLER_OWN char *owl_log_generic(const owl_message *m) 135 { 136 GString *buffer; 137 buffer = g_string_new(""); 138 g_string_append_printf(buffer, "From: <%s> To: <%s>\n", 139 owl_message_get_sender(m), 140 owl_message_get_recipient(m)); 141 g_string_append_printf(buffer, "Time: %s\n\n", 142 owl_message_get_timestr(m)); 143 g_string_append_printf(buffer, "%s\n\n", 144 owl_message_get_body(m)); 145 return g_string_free(buffer, FALSE); 146 } 147 148 static void owl_log_error_main_thread(gpointer data) 149 { 150 owl_function_error("%s", (const char*)data); 151 } 152 153 static void owl_log_error(const char *message) 154 { 155 char *data = g_strdup(message); 156 owl_select_post_task(owl_log_error_main_thread, 157 data, g_free, g_main_context_default()); 158 } 159 160 static void owl_log_write_entry(gpointer data) 161 { 162 owl_log_entry *msg = (owl_log_entry*)data; 95 static int owl_log_try_write_entry(owl_log_entry *msg) 96 { 163 97 FILE *file = NULL; 164 98 file = fopen(msg->filename, "a"); 165 99 if (!file) { 166 owl_log_error("Unable to open file for logging"); 167 return; 100 return errno; 168 101 } 169 102 fprintf(file, "%s", msg->message); 170 103 fclose(file); 171 } 172 173 static void owl_log_entry_free(void *data) 104 return 0; 105 } 106 107 static void owl_log_entry_delete(void *data) 174 108 { 175 109 owl_log_entry *msg = (owl_log_entry*)data; 176 if (msg) { 177 g_free(msg->message); 178 g_free(msg->filename); 179 g_slice_free(owl_log_entry, msg); 180 } 110 g_free(msg->message); 111 g_free(msg->filename); 112 g_slice_free(owl_log_entry, msg); 113 } 114 115 #if GLIB_CHECK_VERSION(2, 32, 0) 116 #else 117 static void owl_log_entry_delete_gfunc(gpointer data, gpointer user_data) 118 { 119 owl_log_entry_delete(data); 120 } 121 #endif 122 123 static void owl_log_file_error(owl_log_entry *msg, int errnum) 124 { 125 owl_log_error("Unable to open file for logging: %s (file %s)", 126 g_strerror(errnum), 127 msg->filename); 128 } 129 130 /* If we are deferring log messages, enqueue this entry for writing. 131 * Otherwise, try to write this log message, and, if it fails with 132 * EPERM, EACCES, or ETIMEDOUT, go into deferred logging mode and 133 * queue an admin message. If it fails with anything else, display an 134 * error message, drop the log message, and do not go into deferred 135 * logging mode. 136 * 137 * N.B. This function is called only on the disk-writing thread. */ 138 static void owl_log_eventually_write_entry(gpointer data) 139 { 140 int ret; 141 owl_log_entry *msg = (owl_log_entry*)data; 142 if (defer_logs) { 143 owl_log_deferred_enqueue_message(msg->message, msg->filename); 144 } else { 145 ret = owl_log_try_write_entry(msg); 146 if (ret == EPERM || ret == EACCES || ret == ETIMEDOUT) { 147 defer_logs = true; 148 owl_log_error("Unable to open file for logging (%s): \n" 149 "%s. \n" 150 "Consider renewing your tickets. Logging has been \n" 151 "suspended, and your messages will be saved. To \n" 152 "resume logging, use the command :flush-logs.\n\n", 153 msg->filename, 154 g_strerror(ret)); 155 /* If we were not in deferred logging mode, either the queue should be 156 * empty, or we are attempting to log a message that we just popped off 157 * the head of the queue. Either way, we should enqueue this message as 158 * the first message in the queue, rather than the last, so that we 159 * preserve message ordering. */ 160 owl_log_deferred_enqueue_first_message(msg->message, msg->filename); 161 } else if (ret != 0) { 162 owl_log_file_error(msg, ret); 163 } 164 } 165 } 166 167 /* tries to write the deferred log entries 168 * 169 * N.B. This function is called only on the disk-writing thread. */ 170 static void owl_log_write_deferred_entries(gpointer data) 171 { 172 owl_log_entry *entry; 173 owl_log_options *opts = (owl_log_options *)data; 174 int ret; 175 int logged_message_count = 0; 176 bool all_succeeded = true; 177 178 if (opts->display_initial_log_count) { 179 if (g_queue_is_empty(deferred_entry_queue)) { 180 owl_log_makemsg("There are no logs to flush."); 181 } else { 182 owl_log_makemsg("Attempting to flush %u logs...", 183 g_queue_get_length(deferred_entry_queue)); 184 } 185 } 186 187 defer_logs = false; 188 while (!g_queue_is_empty(deferred_entry_queue) && !defer_logs) { 189 logged_message_count++; 190 entry = (owl_log_entry*)g_queue_pop_head(deferred_entry_queue); 191 if (!opts->drop_failed_logs) { 192 /* Attempt to write the log entry. If it fails, re-queue the entry at 193 * the head of the queue. */ 194 owl_log_eventually_write_entry(entry); 195 } else { 196 /* Attempt to write the log entry. If it fails, print an error message, 197 * drop the log, and keep going through the queue. */ 198 ret = owl_log_try_write_entry(entry); 199 if (ret != 0) { 200 all_succeeded = false; 201 owl_log_file_error(entry, ret); 202 } 203 } 204 owl_log_entry_delete(entry); 205 } 206 if (logged_message_count > 0) { 207 if (opts->display_initial_log_count) { 208 /* first clear the "attempting to flush" message from the status bar */ 209 owl_log_makemsg(""); 210 } 211 if (!defer_logs) { 212 if (all_succeeded) { 213 owl_log_adminmsg("Flushed %d logs and resumed logging.", 214 logged_message_count); 215 } else { 216 owl_log_adminmsg("Flushed or dropped %d logs and resumed logging.", 217 logged_message_count); 218 } 219 } else { 220 owl_log_error("Attempted to flush %d logs; %u deferred logs remain.", 221 logged_message_count, g_queue_get_length(deferred_entry_queue)); 222 } 223 } 224 } 225 226 void owl_log_flush_logs(bool drop_failed_logs, bool quiet) 227 { 228 owl_log_options *data = g_new(owl_log_options, 1); 229 data->drop_failed_logs = drop_failed_logs; 230 data->display_initial_log_count = !quiet; 231 232 owl_select_post_task(owl_log_write_deferred_entries, 233 data, 234 g_free, 235 log_context); 181 236 } 182 237 183 238 void owl_log_enqueue_message(const char *buffer, const char *filename) 184 239 { 185 owl_log_entry *log_msg = NULL; 186 log_msg = g_slice_new(owl_log_entry); 187 log_msg->message = g_strdup(buffer); 188 log_msg->filename = g_strdup(filename); 189 owl_select_post_task(owl_log_write_entry, log_msg, 190 owl_log_entry_free, log_context); 191 } 192 193 void owl_log_append(const owl_message *m, const char *filename) { 194 char *buffer = NULL; 195 if (owl_message_is_type_zephyr(m)) { 196 buffer = owl_log_zephyr(m); 197 } else if (owl_message_is_type_jabber(m)) { 198 buffer = owl_log_jabber(m); 199 } else if (owl_message_is_type_aim(m)) { 200 buffer = owl_log_aim(m); 201 } else { 202 buffer = owl_log_generic(m); 203 } 204 owl_log_enqueue_message(buffer, filename); 205 g_free(buffer); 206 } 207 208 void owl_log_outgoing(const owl_message *m) 209 { 210 char *filename, *logpath; 211 char *to, *temp; 212 GList *cc; 213 214 /* expand ~ in path names */ 215 logpath = owl_util_makepath(owl_global_get_logpath(&g)); 216 217 /* Figure out what path to log to */ 218 if (owl_message_is_type_zephyr(m)) { 219 /* If this has CC's, do all but the "recipient" which we'll do below */ 220 cc = owl_message_get_cc_without_recipient(m); 221 while (cc != NULL) { 222 temp = short_zuser(cc->data); 223 filename = g_build_filename(logpath, temp, NULL); 224 owl_log_append(m, filename); 225 226 g_free(filename); 227 g_free(temp); 228 g_free(cc->data); 229 cc = g_list_delete_link(cc, cc); 230 } 231 232 to = short_zuser(owl_message_get_recipient(m)); 233 } else if (owl_message_is_type_jabber(m)) { 234 to = g_strdup_printf("jabber:%s", owl_message_get_recipient(m)); 235 g_strdelimit(to, "/", '_'); 236 } else if (owl_message_is_type_aim(m)) { 237 char *temp2; 238 temp = owl_aim_normalize_screenname(owl_message_get_recipient(m)); 239 temp2 = g_utf8_strdown(temp,-1); 240 to = g_strdup_printf("aim:%s", temp2); 241 g_free(temp2); 242 g_free(temp); 243 } else { 244 to = g_strdup("loopback"); 245 } 246 247 filename = g_build_filename(logpath, to, NULL); 248 owl_log_append(m, filename); 249 g_free(to); 250 g_free(filename); 251 252 filename = g_build_filename(logpath, "all", NULL); 253 owl_log_append(m, filename); 254 g_free(logpath); 255 g_free(filename); 256 } 257 240 owl_log_entry *log_msg = owl_log_new_entry(buffer, filename); 241 owl_select_post_task(owl_log_eventually_write_entry, log_msg, 242 owl_log_entry_delete, log_context); 243 } 258 244 259 245 void owl_log_outgoing_zephyr_error(const owl_zwrite *zw, const char *text) 260 246 { 261 char *filename, *logpath; 262 char *tobuff, *recip; 263 owl_message *m; 264 GString *msgbuf; 265 /* create a present message so we can pass it to 266 * owl_log_shouldlog_message(void) 267 */ 268 m = g_slice_new(owl_message); 247 owl_message *m = g_slice_new(owl_message); 269 248 /* recip_index = 0 because there can only be one recipient anyway */ 270 249 owl_message_create_from_zwrite(m, zw, text, 0); 271 if (!owl_log_shouldlog_message(m)) { 272 owl_message_delete(m); 273 return; 274 } 250 g_free(owl_perlconfig_call_with_message("BarnOwl::Logging::log_outgoing_error", m)); 275 251 owl_message_delete(m); 276 277 /* chop off a local realm */278 recip = owl_zwrite_get_recip_n_with_realm(zw, 0);279 tobuff = short_zuser(recip);280 g_free(recip);281 282 /* expand ~ in path names */283 logpath = owl_util_makepath(owl_global_get_logpath(&g));284 filename = g_build_filename(logpath, tobuff, NULL);285 msgbuf = g_string_new("");286 g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);287 if (text[strlen(text)-1] != '\n') {288 g_string_append_printf(msgbuf, "\n");289 }290 owl_log_enqueue_message(msgbuf->str, filename);291 g_string_free(msgbuf, TRUE);292 293 filename = g_build_filename(logpath, "all", NULL);294 g_free(logpath);295 msgbuf = g_string_new("");296 g_string_printf(msgbuf, "ERROR (owl): %s\n%s\n", tobuff, text);297 if (text[strlen(text)-1] != '\n') {298 g_string_append_printf(msgbuf, "\n");299 }300 owl_log_enqueue_message(msgbuf->str, filename);301 g_string_free(msgbuf, TRUE);302 303 g_free(tobuff);304 }305 306 void owl_log_incoming(const owl_message *m)307 {308 char *filename, *allfilename, *logpath;309 const char *from=NULL;310 char *frombuff=NULL;311 int len, ch, i, personal;312 313 /* figure out if it's a "personal" message or not */314 if (owl_message_is_type_zephyr(m)) {315 if (owl_message_is_personal(m)) {316 personal = 1;317 } else {318 personal = 0;319 }320 } else if (owl_message_is_type_jabber(m)) {321 /* This needs to be fixed to handle groupchat */322 const char* msgtype = owl_message_get_attribute_value(m,"jtype");323 if (msgtype && !strcmp(msgtype,"groupchat")) {324 personal = 0;325 } else {326 personal = 1;327 }328 } else {329 if (owl_message_is_private(m) || owl_message_is_loginout(m)) {330 personal = 1;331 } else {332 personal = 0;333 }334 }335 336 337 if (owl_message_is_type_zephyr(m)) {338 if (personal) {339 from=frombuff=short_zuser(owl_message_get_sender(m));340 } else {341 from=frombuff=g_strdup(owl_message_get_class(m));342 }343 } else if (owl_message_is_type_aim(m)) {344 /* we do not yet handle chat rooms */345 char *normalto, *temp;346 temp = owl_aim_normalize_screenname(owl_message_get_sender(m));347 normalto = g_utf8_strdown(temp, -1);348 from=frombuff=g_strdup_printf("aim:%s", normalto);349 g_free(normalto);350 g_free(temp);351 } else if (owl_message_is_type_loopback(m)) {352 from=frombuff=g_strdup("loopback");353 } else if (owl_message_is_type_jabber(m)) {354 if (personal) {355 from=frombuff=g_strdup_printf("jabber:%s",356 owl_message_get_sender(m));357 } else {358 from=frombuff=g_strdup_printf("jabber:%s",359 owl_message_get_recipient(m));360 }361 } else {362 from=frombuff=g_strdup("unknown");363 }364 365 /* check for malicious sender formats */366 len=strlen(frombuff);367 if (len<1 || len>35) from="weird";368 if (strchr(frombuff, '/')) from="weird";369 370 ch=frombuff[0];371 if (!g_ascii_isalnum(ch)) from="weird";372 373 for (i=0; i<len; i++) {374 if (frombuff[i]<'!' || frombuff[i]>='~') from="weird";375 }376 377 if (!strcmp(frombuff, ".") || !strcasecmp(frombuff, "..")) from="weird";378 379 if (!personal) {380 if (strcmp(from, "weird")) {381 char* temp = g_utf8_strdown(frombuff, -1);382 if (temp) {383 g_free(frombuff);384 from = frombuff = temp;385 }386 }387 }388 389 /* create the filename (expanding ~ in path names) */390 if (personal) {391 logpath = owl_util_makepath(owl_global_get_logpath(&g));392 filename = g_build_filename(logpath, from, NULL);393 allfilename = g_build_filename(logpath, "all", NULL);394 owl_log_append(m, allfilename);395 g_free(allfilename);396 } else {397 logpath = owl_util_makepath(owl_global_get_classlogpath(&g));398 filename = g_build_filename(logpath, from, NULL);399 }400 401 owl_log_append(m, filename);402 g_free(filename);403 404 if (personal && owl_message_is_type_zephyr(m)) {405 /* We want to log to all of the CC'd people who were not us, or406 * the sender, as well.407 */408 char *temp;409 GList *cc;410 cc = owl_message_get_cc_without_recipient(m);411 while (cc != NULL) {412 temp = short_zuser(cc->data);413 if (strcasecmp(temp, frombuff) != 0) {414 filename = g_build_filename(logpath, temp, NULL);415 owl_log_append(m, filename);416 g_free(filename);417 }418 419 g_free(temp);420 g_free(cc->data);421 cc = g_list_delete_link(cc, cc);422 }423 }424 425 g_free(frombuff);426 g_free(logpath);427 252 } 428 253 429 254 static gpointer owl_log_thread_func(gpointer data) 430 255 { 256 log_context = g_main_context_new(); 431 257 log_loop = g_main_loop_new(log_context, FALSE); 432 258 g_main_loop_run(log_loop); … … 434 260 } 435 261 436 void owl_log_init(void) 262 void owl_log_init(void) 437 263 { 438 264 log_context = g_main_context_new(); … … 454 280 } 455 281 #endif 456 282 283 deferred_entry_queue = g_queue_new(); 457 284 } 458 285 459 286 static void owl_log_quit_func(gpointer data) 460 287 { 288 /* flush the deferred logs queue, trying to write the 289 * entries to the disk one last time. Drop any failed 290 * entries, and be quiet about it. */ 291 owl_log_options opts; 292 opts.drop_failed_logs = true; 293 opts.display_initial_log_count = false; 294 owl_log_write_deferred_entries(&opts); 295 #if GLIB_CHECK_VERSION(2, 32, 0) 296 g_queue_free_full(deferred_entry_queue, owl_log_entry_delete); 297 #else 298 g_queue_foreach(deferred_entry_queue, owl_log_entry_delete_gfunc, NULL); 299 g_queue_free(deferred_entry_queue); 300 #endif 301 461 302 g_main_loop_quit(log_loop); 462 303 } -
message.c
r7dcef03 r4fd3c04 30 30 void owl_message_init(owl_message *m) 31 31 { 32 /* ctime_r requires a 26-byte buffer */ 33 char timestr[26]; 34 32 35 m->id=owl_global_get_nextmsgid(&g); 33 36 owl_message_set_direction_none(m); … … 43 46 /* save the time */ 44 47 m->time = time(NULL); 45 m->timestr = g_strdup(ctime(&m->time));46 m->timestr [strlen(m->timestr)-1] = '\0';48 ctime_r(&m->time, timestr); 49 m->timestr = g_strndup(timestr, strlen(timestr) - 1); 47 50 48 51 m->fmtext = NULL; … … 349 352 CALLER_OWN char *owl_message_format_time(const owl_message *m) 350 353 { 351 return owl_util_format_time(localtime(&m->time)); 354 struct tm tm; 355 return owl_util_format_time(localtime_r(&m->time, &tm)); 352 356 } 353 357 … … 365 369 { 366 370 owl_message_set_attribute(m, "type", "zephyr"); 367 }368 369 void owl_message_set_type_aim(owl_message *m)370 {371 owl_message_set_attribute(m, "type", "AIM");372 371 } 373 372 … … 391 390 { 392 391 return owl_message_is_type(m, "zephyr"); 393 }394 395 int 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 */401 int owl_message_is_type_jabber(const owl_message *m)402 {403 return owl_message_is_type(m, "jabber");404 392 } 405 393 … … 599 587 CALLER_OWN GList *owl_message_get_cc_without_recipient(const owl_message *m) 600 588 { 601 char *cc, *shortuser, *recip ;589 char *cc, *shortuser, *recip, *saveptr; 602 590 const char *user; 603 591 GList *out = NULL; … … 609 597 recip = short_zuser(owl_message_get_recipient(m)); 610 598 611 user = strtok (cc, " ");599 user = strtok_r(cc, " ", &saveptr); 612 600 while (user != NULL) { 613 601 shortuser = short_zuser(user); … … 616 604 } 617 605 g_free(shortuser); 618 user = strtok (NULL, " ");606 user = strtok_r(NULL, " ", &saveptr); 619 607 } 620 608 … … 689 677 690 678 691 /* if loginout == -1 it's a logout message692 * 0 it's not a login/logout message693 * 1 it's a login message694 */695 void 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 721 679 void owl_message_create_admin(owl_message *m, const char *header, const char *text) 722 680 { … … 781 739 struct hostent *hent; 782 740 #endif /* ZNOTICE_SOCKADDR */ 783 char *tmp, *tmp2; 741 /* ctime_r requires a 26-byte buffer */ 742 char timestr[26], *tmp, *tmp2; 784 743 int len; 785 744 … … 799 758 if (m->timestr) g_free(m->timestr); 800 759 m->time = n->z_time.tv_sec; 801 m->timestr = g_strdup(ctime(&m->time));802 m->timestr [strlen(m->timestr)-1] = '\0';760 ctime_r(&m->time, timestr); 761 m->timestr = g_strndup(timestr, strlen(timestr) - 1); 803 762 804 763 /* set other info */ -
owl.c
r441fd42 r4fd3c04 187 187 if (owl_message_is_type_zephyr(m)) { 188 188 owl_zephyr_zaway(m); 189 } else if (owl_message_is_type_aim(m)) {190 if (owl_message_is_private(m)) {191 owl_function_send_aimawymsg(owl_message_get_sender(m), owl_global_get_zaway_msg(&g));192 }193 189 } 194 190 } … … 230 226 /* let perl know about it */ 231 227 owl_perlconfig_newmsg(m, NULL); 232 /* log the message if we need to */233 owl_log_message(m);234 228 /* redraw the sepbar; TODO: don't violate layering */ 235 229 owl_global_sepbar_dirty(&g); … … 506 500 owl_global_set_startupargs(&g, argc_copy, argv_copy); 507 501 g_strfreev(argv_copy); 508 owl_global_set_haveaim(&g);509 502 510 503 owl_register_signal_handlers(); … … 566 559 owl_global_get_filter(&g, "all"), 567 560 owl_global_get_style_by_name(&g, "default")); 568 569 /* AIM init */570 owl_function_debugmsg("startup: doing AIM initialization");571 owl_aim_init();572 561 573 562 /* execute the startup function in the configfile */ -
perl/Makefile.am
ra870319 r4fd3c04 2 2 nobase_dist_pkgdata_DATA = \ 3 3 lib/BarnOwl.pm \ 4 lib/BarnOwl/Complete/AIM.pm \5 4 lib/BarnOwl/Complete/Client.pm \ 6 5 lib/BarnOwl/Complete/Filter.pm \ … … 9 8 lib/BarnOwl/Completion/Context.pm \ 10 9 lib/BarnOwl/Completion/Util.pm \ 10 lib/BarnOwl/DeferredLogging.pm \ 11 11 lib/BarnOwl/Editwin.pm \ 12 12 lib/BarnOwl/Help.pm \ 13 13 lib/BarnOwl/Hook.pm \ 14 14 lib/BarnOwl/Hooks.pm \ 15 lib/BarnOwl/Logging.pm \ 15 16 lib/BarnOwl/MainLoopCompatHook.pm \ 16 17 lib/BarnOwl/Message.pm \ 17 lib/BarnOwl/Message/AIM.pm \18 18 lib/BarnOwl/Message/Admin.pm \ 19 19 lib/BarnOwl/Message/Generic.pm \ -
perl/lib/BarnOwl/Complete/Client.pm
r4626016 r1f92f39 146 146 sub complete_set { 147 147 my $ctx = shift; 148 return complete_flags($ctx, 149 [qw(-q)], 150 { 151 }, 152 \&complete_set_args 153 ); 154 } 155 sub complete_set_args { 156 my $ctx = shift; 157 my $arg = shift; 158 return if $arg; 159 return complete_variable(); 148 my $is_unset = ($ctx->words->[0] eq "unset"); 149 150 # Shift away the -q if seen. 151 my $seen_q = 0; 152 if ($ctx->word > 1 && $ctx->words->[1] eq "-q") { 153 $seen_q = 1; 154 $ctx = $ctx->shift_words(1); 155 } 156 157 # First argument is the variable. 158 if ($ctx->word == 1) { 159 my @vars = complete_variable(); 160 if ($is_unset) { 161 # Only complete the variables which are unsettable. 162 @vars = grep { BarnOwl::get_variable_info($_)->{takes_on_off} } @vars; 163 } 164 unshift(@vars, "-q") unless $seen_q; 165 return @vars; 166 } 167 # For set, second argument is the value. 168 if (!$is_unset && $ctx->word == 2) { 169 # Parse what we can out of validsettings. 170 my $info; 171 eval { $info = BarnOwl::get_variable_info($ctx->words->[1]) }; 172 return if $@; 173 if ($info->{validsettings} eq "<path>") { 174 return complete_file($ctx->words->[2]); 175 } elsif ($info->{validsettings} !~ /^<.*>$/) { 176 # Assume it's a comma-separated list of values; 177 return split(",", $info->{validsettings}); 178 } 179 } 180 return; 160 181 } 161 182 -
perl/lib/BarnOwl/Complete/Filter.pm
r6dba228 r4fd3c04 36 36 body => undef, 37 37 hostname => undef, 38 type => sub { qw(zephyr a im admin); },38 type => sub { qw(zephyr admin); }, 39 39 direction => sub { qw(in out none); }, 40 40 login => sub { qw(login logout none); }, -
perl/lib/BarnOwl/Message.pm
r0adbce1 r4fd3c04 4 4 package BarnOwl::Message; 5 5 6 use File::Spec; 7 6 8 use BarnOwl::Message::Admin; 7 use BarnOwl::Message::AIM;8 9 use BarnOwl::Message::Generic; 9 10 use BarnOwl::Message::Loopback; … … 41 42 sub is_generic { return (shift->{"type"} eq "generic"); } 42 43 sub is_zephyr { return (shift->{"type"} eq "zephyr"); } 43 sub is_aim { return (shift->{"type"} eq "AIM"); }44 sub is_aim { return ''; } 44 45 sub is_jabber { return (shift->{"type"} eq "jabber"); } 45 46 sub is_icq { return (shift->{"type"} eq "icq"); } … … 115 116 } 116 117 return $s; 118 } 119 120 =head2 log MESSAGE 121 122 Returns the text that should be written to a file to log C<MESSAGE>. 123 124 =cut 125 126 sub log { 127 my ($m) = @_; 128 return $m->log_header . "\n\n" . $m->log_body . "\n\n"; 129 } 130 131 =head2 log_header MESSAGE 132 133 Returns the header of the message, for logging purposes. 134 If you override L<BarnOwl::Message::log>, this method is not called. 135 136 =cut 137 138 sub log_header { 139 my ($m) = @_; 140 my $sender = $m->sender; 141 my $recipient = $m->recipient; 142 my $timestr = $m->time; 143 return "From: <$sender> To: <$recipient>\n" 144 . "Time: $timestr"; 145 } 146 147 =head2 log_body MESSAGE 148 149 Returns the body of the message, for logging purposes. 150 If you override L<BarnOwl::Message::log>, this method is not called. 151 152 =cut 153 154 sub log_body { 155 my ($m) = @_; 156 if ($m->is_loginout) { 157 return uc($m->login) 158 . $m->login_type 159 . ($m->login_extra ? ' at ' . $m->login_extra : ''); 160 } else { 161 return $m->body; 162 } 163 } 164 165 =head2 log_filenames MESSAGE 166 167 Returns a list of filenames to which this message should be logged. 168 The filenames should be relative to the path returned by C<log_path>. 169 See L<BarnOwl::Logging::get_filenames> for the specification of valid 170 filenames, and for what happens if this method returns an invalid 171 filename. 172 173 =cut 174 175 sub log_filenames { 176 my ($m) = @_; 177 my $filename; 178 if ($m->is_incoming) { 179 $filename = $m->pretty_sender; 180 } elsif ($m->is_outgoing) { 181 $filename = $m->pretty_recipient; 182 } 183 $filename = "unknown" if !defined($filename) || $filename eq ''; 184 if (BarnOwl::getvar('log-to-subdirectories') eq 'on') { 185 return ($filename); 186 } else { 187 return ($m->log_subfolder . ':' . $filename); 188 } 189 } 190 191 =head2 log_to_all_file MESSAGE 192 193 There is an C<all> file. This method determines if C<MESSAGE> 194 should get logged to it, in addition to any files returned by 195 C<log_filenames>. 196 197 It defaults to returning true if and only if C<MESSAGE> is outgoing. 198 199 =cut 200 201 sub log_to_all_file { 202 my ($m) = @_; 203 return $m->is_outgoing; 204 } 205 206 =head2 log_path MESSAGE 207 208 Returns the folder in which all messages of this class get logged. 209 210 Defaults to C<log_base_path/log_subfolder> if C<log-to-subdirectories> 211 is enabled, or to the C<logpath> BarnOwl variable if it is not. 212 213 Most protocols should override C<log_subfolder> rather than 214 C<log_path>, in order to properly take into account the value of 215 C<log-to-subdirectories>. 216 217 =cut 218 219 sub log_path { 220 my ($m) = @_; 221 if (BarnOwl::getvar('log-to-subdirectories') eq 'on') { 222 return File::Spec->catfile($m->log_base_path, $m->log_subfolder); 223 } else { 224 return BarnOwl::getvar('logpath'); 225 } 226 } 227 228 =head2 log_base_path MESSAGE 229 230 Returns the base path for logging. See C<log_path> for more information. 231 232 Defaults to the BarnOwl variable C<logbasepath>. 233 234 =cut 235 236 sub log_base_path { 237 return BarnOwl::getvar('logbasepath'); 238 } 239 240 =head2 log_subfolder MESSAGE 241 242 Returns the subfolder of C<log_base_path> to log messages in. 243 244 Defaults to C<lc($m->type)>. 245 246 =cut 247 248 sub log_subfolder { 249 return lc(shift->type); 250 } 251 252 =head2 log_outgoing_error MESSAGE 253 254 Returns the string that should be logged if there is an error sending 255 an outgoing message. 256 257 =cut 258 259 sub log_outgoing_error { 260 my ($m) = @_; 261 my $recipient = $m->pretty_recipient; 262 my $body = $m->body; 263 chomp $body; 264 return "ERROR (BarnOwl): $recipient\n$body\n\n"; 265 } 266 267 =head2 should_log MESSAGE 268 269 Returns true if we should log C<MESSAGE>. This does not override 270 user settings; if the BarnOwl variable C<loggingdirection> is in, 271 and C<MESSAGE> is outgoing and does not match the C<logfilter>, it 272 will not get logged regardless of what this method returns. 273 274 Note that this method I<does> override the BarnOwl C<logging> 275 variable; if a derived class overrides this method and does not 276 provide an alternative BarnOwl variable (such as C<classlogging>), 277 the overriding method should check the BarnOwl C<logging> variable. 278 279 Defaults to returning the value of the BarnOwl variable C<logging>. 280 281 =cut 282 283 sub should_log { 284 return BarnOwl::getvar('logging') eq 'on'; 117 285 } 118 286 -
perl/lib/BarnOwl/Message/Loopback.pm
ree183be r8cec8f7 14 14 sub replysendercmd {return 'loopwrite';} 15 15 16 sub log_subfolder { return ''; } 17 sub log_filenames { return ('loopback'); } 16 18 17 19 1; -
perl/lib/BarnOwl/Message/Zephyr.pm
r0adbce1 r8f91a70 21 21 my ($user, $realm) = split(/@/,$principal); 22 22 return $realm; 23 } 24 25 sub casefold_principal { 26 my $principal = shift; 27 # split the principal right after the final @, without eating any 28 # characters; this way, we always get at least '@' in $user 29 my ($user, $realm) = split(/(?<=@)(?=[^@]+$)/, $principal); 30 $user = '' if !defined $user; 31 $user = lc($user); 32 $user = $user . uc($realm) if defined $realm; 33 return $user; 23 34 } 24 35 … … 132 143 return $1 if $self->body =~ /^\s*cc:\s+([^\n]+)/i; 133 144 return undef; 145 } 146 147 # Note: This is the cc-line without the recipient; it does not include 148 # the sender. 149 sub zephyr_cc_without_recipient { 150 my $self = shift; 151 my $recipient = lc(strip_realm($self->recipient)); 152 my $cc = $self->zephyr_cc; 153 return grep { lc(strip_realm($_)) ne $recipient } split(/\s+/, $cc) if defined $cc; 154 return (); 134 155 } 135 156 … … 223 244 } 224 245 246 # Logging 247 sub log_header { 248 my ($m) = @_; 249 my $class = $m->class; 250 my $instance = $m->instance; 251 my $opcode = $m->opcode; 252 my $timestr = $m->time; 253 my $host = $m->host; 254 my $sender = $m->pretty_sender; 255 my $zsig = $m->zsig; 256 my $rtn = "Class: $class Instance: $instance"; 257 $rtn .= " Opcode: $opcode" unless !defined $opcode || $opcode eq ''; 258 $rtn .= "\nTime: $timestr Host: $host" 259 . "\nFrom: $zsig <$sender>"; 260 return $rtn; 261 } 262 263 sub log_filenames { 264 my ($m) = @_; 265 my @filenames = (); 266 if ($m->is_personal) { 267 # If this has CC's, add all but the "recipient" which we'll add below 268 @filenames = $m->zephyr_cc_without_recipient; 269 } 270 if ($m->is_incoming) { 271 if ($m->is_personal) { 272 push @filenames, $m->sender; 273 } else { 274 my $realm = ''; 275 $realm .= '@' . $m->realm if $m->realm ne BarnOwl::zephyr_getrealm(); 276 return (BarnOwl::compat_casefold($m->class) . uc($realm)); 277 } 278 } else { 279 push @filenames, $m->recipient; 280 } 281 return map { casefold_principal(BarnOwl::zephyr_smartstrip_user(strip_realm($_))) } @filenames; 282 } 283 284 sub log_to_class_file { 285 my ($m) = @_; 286 return !$m->is_personal; 287 } 288 289 sub log_path { 290 my ($m) = @_; 291 if ($m->log_to_class_file) { 292 return BarnOwl::getvar('classlogpath'); 293 } else { 294 return BarnOwl::getvar('logpath'); 295 } 296 } 297 298 sub should_log { 299 my ($m) = @_; 300 if ($m->log_to_class_file) { 301 return BarnOwl::getvar('classlogging') eq 'on'; 302 } else { 303 return BarnOwl::getvar('logging') eq 'on'; 304 } 305 } 225 306 226 307 1; -
perl/modules/IRC/lib/BarnOwl/Message/IRC.pm
r60b49a7 r3f0c209 92 92 } 93 93 94 # logging 95 sub log_filenames { 96 my ($m) = @_; 97 die "IRC should not be handling non-IRC messages" if lc($m->type) ne "irc"; 98 BarnOwl::error("IRC message without a network") if !defined($m->network) || $m->network eq ''; 99 my $filename = lc($m->network); 100 # Note: Channel names generally start with '#', which 101 # disambiguates channels from individuals; for example, personals 102 # will look like, e.g., "~/zlog/irc/freenode:john-doe", whereas 103 # channels will look like, e.g., "~/zlog/irc/freenode:#barnowl" 104 if ($m->is_personal) { 105 if ($m->is_incoming) { 106 $filename .= ":" . $m->sender; 107 } elsif ($m->is_outgoing) { 108 $filename .= ":" . $m->recipient; 109 } 110 } else { 111 $filename .= ":" . $m->channel; 112 } 113 return ($filename); 114 } 115 116 sub log { 117 my ($m) = @_; 118 my $sender = $m->sender; 119 my $timestr = $m->time; 120 my $body = $m->body; 121 if ($m->is_loginout) { 122 return BarnOwl::Message::log($m); 123 } else { 124 return "[$timestr] <$sender> $body\n"; 125 } 126 } 127 94 128 1; -
perl/modules/Jabber/lib/BarnOwl/Message/Jabber.pm
ra27acf7 rd2ba33c 172 172 } 173 173 174 sub log_filenames { 175 return map { BarnOwl::compat_casefold($_) } BarnOwl::Message::log_filenames(@_); 176 } 177 174 178 =head1 SEE ALSO 175 179 -
perl/modules/Makefile.am
re4b8f93 r268c7e8 1 MODULES = Jabber IRC WordWrap Twitter Facebook 1 MODULES = Jabber IRC WordWrap Twitter Facebook Kerberos 2 2 3 3 EXTRA_DIST = $(MODULES:=/Makefile.PL) $(MODULES:=/lib) -
perlconfig.c
r7dcef03 r09530e6 211 211 g_free(m->timestr); 212 212 m->timestr = g_strdup(val); 213 // FIXME: Daylight saving time will be guessed wrongly one hour per year! 214 tm.tm_isdst = -1; 213 215 strptime(val, "%a %b %d %T %Y", &tm); 214 216 m->time = mktime(&tm); -
scripts/do-release
rb8a3e00 rbc308eb 1 #!/bin/sh -e 1 #!/bin/bash 2 set -eu 2 3 3 4 die() { … … 55 56 fi 56 57 58 [ -e Makefile.in ] || autoreconf -fvi 59 [ -e config.status ] || ./configure 60 make -j4 distcheck VERSION="$VERS" 61 62 echo 'Checking distributed files against Git:' 63 if comm -3 <(tar -tzf "$TAG.tar.gz" | grep -v '/$' | sed "s%^$TAG/%%" | sort) \ 64 <(git ls-files | sort) | grep -vxf scripts/dist-ignore; then 65 echo 66 echo 'Error: Please fix Makefile.am and/or scripts/dist-ignore.' 67 exit 1 68 fi 69 echo 'ok' 70 71 mv "$TAG.tar.gz" "$TGZ.tgz" 72 57 73 if ! [ "$no_tag" ]; then 58 74 if git cat-file -t "$TAG" > /dev/null 2>&1; then … … 65 81 fi 66 82 67 exittrap() { :; } 68 for sig in 1 2 13 15; do trap "exit $(($sig + 128))" $sig; done 69 trap 'exittrap' EXIT 70 71 TMPDIR=$(mktemp -d /tmp/barnowl.XXXXXX) 72 73 exittrap() { rm -rf "$TMPDIR"; } 74 75 git archive --format=tar --prefix="$TGZ/" "$TAG" | tar -x -C "$TMPDIR" 76 77 CODIR=$(pwd) 78 cd "$TMPDIR/$TGZ" 79 [ "$git" ] && perl -i -pe 's{^(AC_INIT\(\[[^\]]+\],\s*)\[([^\]]+)\]}{${1}['$VERS']}' configure.ac 80 autoreconf -fvi 81 rm -r autom4te.cache/ 82 cd "$TMPDIR" 83 tar czvf "$TGZ.tgz" "$TGZ" 84 cd "$CODIR" 85 86 mv "$TMPDIR/$TGZ.tgz" . 87 rm -rf "$TMPDIR" 88 89 exittrap() { :; } 90 91 echo "Created release tarball for BarnOwl $VERS in $(pwd)" 83 echo "Created release tarball for BarnOwl $VERS at $(pwd)/$TGZ.tgz" 92 84 echo "Remember to bump OWL_VERSION_STRING for future development." 93 85 -
t/completion.t
re59d775 r4fd3c04 6 6 7 7 use File::Basename; 8 BEGIN {require (dirname($0) . "/mock.pl");}; 8 use File::Spec; 9 BEGIN {require File::Spec->rel2abs("mock.pl", dirname($0));}; 9 10 10 11 use BarnOwl::Complete::Filter qw(complete_filter_expr); … … 292 293 293 294 test_complete('type ', '', 294 [qw[admin aimzephyr]],295 [qw[admin zephyr]], 295 296 \&complete_filter_expr); 296 297 -
util.c
rcba6b9c rd2ba33c 643 643 } 644 644 645 CALLER_OWN char *owl_util_compat_casefold(const char *str) 646 { 647 /* 648 * Quoting Anders Kaseorg at https://github.com/barnowl/barnowl/pull/54#issuecomment-31452543: 649 * 650 * The Unicode specification calls this compatibility caseless matching, and 651 * the correct transformation actually has five calls: 652 * NFKC(toCasefold(NFKD(toCasefold(NFD(string))))) Zephyr’s current 653 * implementation incorrectly omits the innermost NFD, but that difference 654 * only matters for characters including U+0345 ◌ͅ COMBINING GREEK 655 * YPOGEGRAMMENI. I think we should just write the correct version and get 656 * Zephyr fixed. 657 * 658 * Neither of these operations should be called toNFKC_Casefold, because that 659 * has slightly different behavior regarding Default_Ignorable_Code_Point. I 660 * propose compat_casefold. And I guess if Jabber wants it too, we should 661 * move it to util.c. 662 */ 663 char *tmp0 = g_utf8_normalize(str, -1, G_NORMALIZE_NFD); 664 char *tmp1 = g_utf8_casefold(tmp0, -1); 665 char *tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_NFKD); 666 char *tmp3 = g_utf8_casefold(tmp2, -1); 667 char *out = g_utf8_normalize(tmp3, -1, G_NORMALIZE_NFKC); 668 g_free(tmp0); 669 g_free(tmp1); 670 g_free(tmp2); 671 g_free(tmp3); 672 673 return out; 674 } 675 645 676 /* This is based on _extract() and _isCJ() from perl's Text::WrapI18N */ 646 677 int owl_util_can_break_after(gunichar c) -
variable.c
r94b9ee0 r4fd3c04 136 136 "load logins from .anyone on startup", "" ); 137 137 138 OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,139 "turn personal logging on or off",140 "If this is set to on, personal messages are\n"141 "logged in the directory specified\n"142 "by the 'logpath' variable. The filename in that\n"143 "directory is derived from the sender of the message.\n" );144 145 OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,146 "turn class logging on or off",147 "If this is set to on, class messages are\n"148 "logged in the directory specified\n"149 "by the 'classlogpath' variable.\n"150 "The filename in that directory is derived from\n"151 "the name of the class to which the message was sent.\n" );152 153 OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH,154 "specifies which kind of messages should be logged",155 "Can be one of 'both', 'in', or 'out'. If 'in' is\n"156 "selected, only incoming messages are logged, if 'out'\n"157 "is selected only outgoing messages are logged. If 'both'\n"158 "is selected both incoming and outgoing messages are\n"159 "logged.",160 "both,in,out");161 162 138 OWLVAR_BOOL_FULL( "colorztext" /* %OwlVarStub */, 1, 163 139 "allow @color() in zephyrs to change color", 164 NULL, NULL, owl_variable_colorztext_set, NULL);140 "", NULL, owl_variable_colorztext_set, NULL); 165 141 166 142 OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1, … … 185 161 "Enable printing of login notifications", 186 162 "When this is enabled, BarnOwl will print login and logout notifications\n" 187 "for AIM, zephyr, or other protocols. If disabled BarnOwl will not print\n" 188 "login or logout notifications.\n"); 189 190 OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "", 191 "name of a filter controlling which messages to log", 192 193 "If non empty, any messages matching the given filter will be logged.\n" 194 "This is a completely separate mechanism from the other logging\n" 195 "variables like logging, classlogging, loglogins, loggingdirection,\n" 196 "etc. If you want this variable to control all logging, make sure\n" 197 "all other logging variables are in their default state.\n"); 198 199 OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0, 200 "Enable logging of login notifications", 201 "When this is enabled, BarnOwl will log login and logout notifications\n" 202 "for AIM, zephyr, or other protocols. If disabled BarnOwl will not print\n" 163 "for zephyr or other protocols. If disabled BarnOwl will not print\n" 203 164 "login or logout notifications.\n"); 204 165 … … 214 175 "off,middle,on", 215 176 NULL, owl_variable_disable_ctrl_d_set, NULL); 216 217 OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",218 "path for logging personal zephyrs",219 "Specifies a directory which must exist.\n"220 "Files will be created in the directory for each sender.\n");221 222 OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",223 "path for logging class zephyrs",224 "Specifies a directory which must exist.\n"225 "Files will be created in the directory for each class.\n");226 177 227 178 OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE, … … 282 233 "default zaway message", "" ); 283 234 284 OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,285 "Set AIM away status",286 "",287 NULL, owl_variable_aaway_set, NULL);288 289 OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */,290 OWL_DEFAULT_AAWAYMSG,291 "AIM away msg for responding when away", "" );292 293 OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */,294 OWL_DEFAULT_AAWAYMSG,295 "default AIM away message", "" );296 297 235 OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all", 298 236 "home view to switch to after 'X' and 'V'", … … 337 275 "Zephyr messages be no wider than 70 columns.\n"); 338 276 339 OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,340 "number of seconds after AIM login to ignore login messages",341 "This specifies the number of seconds to wait after an\n"342 "AIM login before allowing the receipt of AIM login notifications.\n"343 "By default this is set to 15. If you would like to view login\n"344 "notifications of buddies as soon as you login, set it to 0 instead.");345 346 347 277 OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 348 278 OWL_TYPWIN_SIZE, … … 510 440 } 511 441 512 /* When 'aaway' is changed, need to notify the AIM server */513 int owl_variable_aaway_set(owl_variable *v, bool newval)514 {515 if (newval) {516 owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));517 } else {518 owl_aim_set_awaymsg("");519 }520 return owl_variable_bool_set_default(v, newval);521 }522 523 442 int owl_variable_colorztext_set(owl_variable *v, bool newval) 524 443 { … … 814 733 } 815 734 735 bool owl_variable_takes_on_off(const owl_variable *v) { 736 return v->takes_on_off; 737 } 738 816 739 int owl_variable_get_type(const owl_variable *v) 817 740 { -
zcrypt.c
rca1fb26a r9a0d25d 21 21 #include <config.h> 22 22 23 #ifdef HAVE_KERBEROS_IV24 #include <kerberosIV/des.h>25 #else26 23 #include <openssl/des.h> 27 #endif28 24 29 25 #include "filterproc.h" … … 99 95 }; 100 96 101 static void owl_zcrypt_string_to_schedule(char *keystring, des_key_schedule *schedule) { 102 #ifdef HAVE_KERBEROS_IV 103 des_cblock key; 104 #else 105 des_cblock _key, *key = &_key; 106 #endif 107 108 des_string_to_key(keystring, key); 109 des_key_sched(key, *schedule); 97 static void owl_zcrypt_string_to_schedule(char *keystring, DES_key_schedule *schedule) { 98 DES_cblock key; 99 100 DES_string_to_key(keystring, &key); 101 DES_key_sched(&key, schedule); 110 102 } 111 103 … … 728 720 int do_encrypt_des(const char *keyfile, const char *in, int length, FILE *outfile) 729 721 { 730 des_key_schedule schedule;722 DES_key_schedule schedule; 731 723 unsigned char input[8], output[8]; 732 724 const char *inptr; … … 774 766 775 767 /* Encrypt and output the block */ 776 des_ecb_encrypt(&input, &output,schedule, TRUE);768 DES_ecb_encrypt(&input, &output, &schedule, TRUE); 777 769 block_to_ascii(output, outfile); 778 770 … … 790 782 char *out; 791 783 int err, status; 784 int tried_gpg1 = FALSE; 792 785 const char *argv[] = { 793 "gpg ",786 "gpg1", 794 787 "--symmetric", 795 788 "--no-options", … … 805 798 NULL 806 799 }; 807 err = call_filter(argv, in, &out, &status); 800 while ((err = call_filter(argv, in, &out, &status)) && !out && !tried_gpg1) { 801 tried_gpg1 = TRUE; 802 argv[0] = "gpg"; 803 } 808 804 if(err || status) { 809 805 g_free(out); … … 874 870 char *in, *out; 875 871 int length; 872 int tried_gpg1 = FALSE; 876 873 const char *argv[] = { 877 "gpg ",874 "gpg1", 878 875 "--decrypt", 879 876 "--no-options", … … 892 889 if(!in) return FALSE; 893 890 894 err = call_filter(argv, in, &out, &status); 891 while ((err = call_filter(argv, in, &out, &status)) && !out && !tried_gpg1) { 892 tried_gpg1 = TRUE; 893 argv[0] = "gpg"; 894 } 895 895 free(in); 896 896 if(err || status) { … … 905 905 906 906 int do_decrypt_des(const char *keyfile) { 907 des_key_schedule schedule;907 DES_key_schedule schedule; 908 908 unsigned char input[8], output[8]; 909 909 char tmp[9]; … … 915 915 have a NULL-terminated string we can call printf/strlen on. 916 916 917 We don't pass 'tmp' to des_ecb_encrypt directly, because it's917 We don't pass 'tmp' to DES_ecb_encrypt directly, because it's 918 918 prototyped as taking 'unsigned char[8]', and this avoids a stupid 919 919 cast. … … 933 933 while (read_ascii_block(input)) 934 934 { 935 des_ecb_encrypt(&input, &output,schedule, FALSE);935 DES_ecb_encrypt(&input, &output, &schedule, FALSE); 936 936 memcpy(tmp, output, 8); 937 937 printf("%s", tmp); -
zephyr.c
rff58239 ree6b30f 284 284 FILE *file; 285 285 int fopen_errno; 286 char *tmp, *start ;286 char *tmp, *start, *saveptr; 287 287 char *buffer = NULL; 288 288 char *subsfile; … … 319 319 320 320 /* add it to the list of subs */ 321 if ((tmp = strtok (start, ",\n\r")) == NULL)321 if ((tmp = strtok_r(start, ",\n\r", &saveptr)) == NULL) 322 322 continue; 323 323 subs[count].zsub_class = g_strdup(tmp); 324 if ((tmp =strtok(NULL, ",\n\r")) == NULL)324 if ((tmp = strtok_r(NULL, ",\n\r", &saveptr)) == NULL) 325 325 continue; 326 326 subs[count].zsub_classinst = g_strdup(tmp); 327 if ((tmp = strtok (NULL, " \t\n\r")) == NULL)327 if ((tmp = strtok_r(NULL, " \t\n\r", &saveptr)) == NULL) 328 328 continue; 329 329 subs[count].zsub_recipient = g_strdup(tmp); -
zwrite.c
r7dcef03 r1958790 270 270 rv = owl_zwrite_create_from_line(&z, cmd); 271 271 if (rv != 0) return rv; 272 if (!owl_zwrite_is_message_set(&z)) { 273 owl_zwrite_set_message(&z, msg); 274 } 275 owl_zwrite_populate_zsig(&z); 276 owl_zwrite_send_message(&z); 272 owl_function_zwrite(&z, msg); 277 273 owl_zwrite_cleanup(&z); 278 274 return(0);
Note: See TracChangeset
for help on using the changeset viewer.