/** ** bsflite - bs-free AIM client ** ** (C) 2003-2007 by Claudio Leite ** ** NO WARRANTY. Read the file COPYING for more details. **/ #include "bsf.h" #if defined(__MINGW32__) || defined(__DJGPP__) #include #endif extern char inputbuf[512]; extern struct Conn *conn; extern struct BuddyList *buddylist; typedef struct InputCallbacks { char *command; int length; void (*callback) (); } i_callbacks; /* PROTO */ void parse_input(void) { /* * Any commands not listed here are handled directly in the keyboard * input routine in bsf.c. */ i_callbacks ic[] = { /* * "m" and "i" are the most used commands, I find * * let's put them sooner to avoid too many iterations on for() * below. */ {"m", 1, input_send_message}, {"i", 1, input_get_info}, {"A", 1, input_get_away}, {"P", 1, input_get_profile}, {"G", 1, input_set_predefaway}, {"a", 1, input_add_buddy}, {"d", 1, input_delete_buddy}, {"g", 1, input_set_away}, {"h", 1, input_show_help}, {"l", 1, input_show_log}, {"p", 1, input_paste}, {"q!", 2, input_quit}, {"R!", 2, input_reconnect}, {"v", 1, input_set_invisible}, {"w", 1, input_show_buddies}, {"z!", 2, input_reload_profile}, {"?", 1, input_show_help}, {NULL, 0, NULL} }; int ix; for (ix = 0; ic[ix].command != NULL; ix++) { if (strncmp(inputbuf, ic[ix].command, ic[ix].length) == 0) { if (inputbuf[ic[ix].length] == ' ') ic[ix].callback(inputbuf + ic[ix].length + 1); else ic[ix].callback(inputbuf + ic[ix].length); return; } } printf("\n"); } /* PROTO */ void input_quit(char *arg) { struct ConnPtr *trav, *temp; restore_tty(); log_buddies_offline(); imcomm_delete_handle_now(conn->conn); if (conn->clist->conn == conn->conn) { temp = conn->clist; conn->clist = conn->clist->next; if (temp->username) free(temp->username); free(temp); } else { for (trav = conn->clist; trav->next;) { if (trav->next->conn == conn->conn) { temp = trav->next; trav->next = trav->next->next; if (temp->username) free(temp->username); free(temp); } } } delete_buddylist(buddylist); if (conn->username) free(conn->username); if (conn->password) free(conn->password); if (conn->awaymsg) free(conn->awaymsg); if (conn->lastsn) free(conn->lastsn); free(conn); printf("\n"); exit(0); } /* PROTO */ void input_reload_profile(char *arg) { if (conn->conn == NULL) return; printf("\n"); b_echostr_s(); printf("Reloading away messages and profile.\n"); set_profile(conn->conn); read_away_messages(); } /* PROTO */ void input_send_message(char *arg) { char *msg, *msg_strip, *temp, *sn; char *fullmsg; size_t fullmsg_len; int offset; if (conn->conn == NULL) return; temp = strchr(arg, ' '); if (temp == NULL) { printf("\n"); b_echostr_s(); printf("No message to send.\n"); return; } if (strlen(temp + 1) == 0) { printf("\nNo message to send.\n"); return; } if (conn->netspeak_filter) msg = undo_netspeak(temp + 1); else msg = temp + 1; sn = malloc(temp - arg + 1); sn[temp - arg] = 0; strncpy(sn, arg, temp - arg); fullmsg_len = strlen(msg) + strlen(SEND_FORMAT_BEGIN) + strlen(SEND_FORMAT_END) + 1; fullmsg = malloc(fullmsg_len + 1); snprintf(fullmsg, fullmsg_len, "%s%s%s", SEND_FORMAT_BEGIN, msg, SEND_FORMAT_END); imcomm_im_send_message(conn->conn, sn, fullmsg, 0); free(fullmsg); eraseline(); if (conn->timestamps) { addts(); putchar(' '); offset = 13; } else { offset = 2; } offset += strlen(sn) + 2; set_color(COLOR_OUTGOING_IM); printf("->%s", sn); set_color(0); printf(": "); msg_strip = strip_html(msg); wordwrap_print(msg_strip, offset); free(msg_strip); if (conn->lastsn != NULL) free(conn->lastsn); conn->lastsn = strdup(sn); log_event(EVENT_IMSEND, sn, msg); free(sn); if (conn->netspeak_filter) free(msg); } /* PROTO */ void input_paste(char *arg) { char *sn, *sendbuf, *pbuf; size_t sendbuflen; ssize_t pbuflen; uint16_t maxmsgsize = imcomm_get_max_message_size(conn->conn); if (conn->conn == NULL) return; sn = arg; if (sn[0] == 0) { printf("\n"); b_echostr_s(); printf("No recipient specified.\n"); return; } printf("\n"); b_echostr_s(); printf("Pasting to %s.\n", sn); b_echostr_s(); printf("Enter '.' on a line by itself to send," " Ctrl-X to cancel."); pbuf = malloc(maxmsgsize + 1); sendbuf = malloc(maxmsgsize + 1); memset(sendbuf, 0, maxmsgsize + 1); sendbuflen = 0; /* * using fgets() produced strange results. had to resort to writing * my own input stuff. */ while (1) { printf("\n-> "); fflush(stdout); pbuflen = bsf_getline(pbuf, maxmsgsize - 5); if (pbuflen == -1) { free(pbuf); free(sendbuf); printf("\n"); return; } if (pbuflen == 1 && pbuf[0] == '.') { if (sendbuflen > 0) { imcomm_im_send_message(conn->conn, sn, sendbuf, 0); } break; } /* * +4 is for "
" */ if (sendbuflen + pbuflen + 4 > maxmsgsize) { imcomm_im_send_message(conn->conn, sn, sendbuf, 0); memset(sendbuf, 0, maxmsgsize + 1); memcpy(sendbuf, pbuf, pbuflen); sendbuflen = pbuflen; } else { #ifdef __OpenBSD__ if (sendbuflen != 0) { strlcat(sendbuf, "
", maxmsgsize + 1); pbuflen += 4; } strlcat(sendbuf, pbuf, maxmsgsize + 1); #else if (sendbuflen != 0) { strcat(sendbuf, "
"); pbuflen += 4; } strcat(sendbuf, pbuf); #endif sendbuflen += pbuflen; } } printf("\n"); free(sendbuf); free(pbuf); } /* PROTO */ void input_show_buddies(char *arg) { printf("\n"); b_echostr_s(); addts(); printf(" %d buddies online:\n", conn->buddiesonline); if (arg[0] == 'f') display_buddylist(); else display_buddylist_sorted(); } /* PROTO */ void input_show_help(char *arg) { printf("\nbsflite commands:\n"); printf(" h............: what you see right now\n"); printf(" w............: show buddy list\n"); printf(" ws...........: show buddy list, sorted (default)\n"); printf(" wf...........: show buddy list, unsorted\n"); printf(" l........: show last 20 lines from \n"); printf(" L............: show last 20 lines from last buddy\n"); printf(" m ..: send msg to sn\n"); printf(" r.......: reply to the last msg received/sent\n"); printf(" p........: paste to sn\n"); printf(" a........: add buddy\n"); printf(" d........: delete buddy\n"); printf(" g.......: set away message\n"); printf(" g............: unset away message\n"); printf(" G............: display pre-defined away messages\n"); printf(" G.......: set pre-defined away message\n"); printf(" i........: get profile and away message\n"); printf(" A........: get away message\n"); printf(" P........: get profile\n"); printf(" R![sn].......: manually reconnect [as [sn]]\n"); printf(" z!...........: reload profile and away messages\n"); printf(" q!...........: quit\n"); } /* PROTO */ void input_show_log(char *arg) { /* * A single 'l' is too short to be a screen name... */ if (arg[0] == 'l' && arg[1] == 0) { if (conn->lastsn != NULL) { show_log(20, conn->lastsn); } else { printf("\n"); } } else { show_log(20, arg); } } /* PROTO */ void input_add_buddy(char *arg) { if (conn->conn == NULL) return; imcomm_im_add_buddy(conn->conn, arg); printf("\n"); b_echostr_s(); printf("Added buddy %s.\n", arg); } /* PROTO */ void input_delete_buddy(char *arg) { if (conn->conn == NULL) return; imcomm_im_remove_buddy(conn->conn, arg); printf("\n"); b_echostr_s(); printf("Removed buddy %s.\n", arg); remove_from_list(arg); } /* PROTO */ void input_set_invisible(char *arg) { if (conn->isinvisible) { imcomm_set_invisible(conn->conn, 0); conn->isinvisible = 0; printf("\n"); b_echostr_s(); printf("You are now visible.\n"); } else { imcomm_set_invisible(conn->conn, 1); conn->isinvisible = 1; printf("\n"); b_echostr_s(); printf("You are now invisible.\n"); } } /* PROTO */ void input_set_away(char *arg) { if (conn->conn == NULL) return; if (conn->isaway) { conn->isaway = 0; free(conn->awaymsg); conn->awaymsg = NULL; imcomm_set_unaway(conn->conn); printf("\n"); b_echostr_s(); printf("You are no longer away.\n"); return; } else { printf("\n"); b_echostr_s(); printf("You are now away: %s\n", arg); conn->isaway = 1; imcomm_set_away(conn->conn, arg); conn->awaymsg = strdup(arg); return; } } /* PROTO */ void input_get_info(char *arg) { if (conn->conn == NULL) return; imcomm_request_awayprofile(conn->conn, arg); printf("\n"); } /* PROTO */ void input_get_away(char *arg) { if (conn->conn == NULL) return; imcomm_request_awaymsg(conn->conn, arg); printf("\n"); } /* PROTO */ void input_get_profile(char *arg) { if (conn->conn == NULL) return; imcomm_request_profile(conn->conn, arg); printf("\n"); } /* PROTO */ void input_set_predefaway(char *arg) { int msgnum = 0, count; struct AwayMessages *tv; if (conn->conn == NULL) return; if (conn->awaymsgs == NULL) { printf("\n"); b_echostr_s(); printf("No away messages defined.\n"); return; } if (arg[0] == 0) { printf("\n"); b_echostr_s(); printf("Defined messages:"); for (tv = conn->awaymsgs, count = 0; tv != NULL; tv = tv->next, count++) { printf("\n"); b_echostr_s(); printf("[%02d] \"%s\"", count, tv->message); } } else { msgnum = atoi(arg); for (tv = conn->awaymsgs, count = 0; tv != NULL; tv = tv->next, count++) { if (count == msgnum) { printf("\n"); b_echostr_s(); printf("You are now away: %s", tv->message); conn->isaway = 1; imcomm_set_away(conn->conn, tv->message); conn->awaymsg = strdup(tv->message); break; } } } printf("\n"); } /* PROTO */ ssize_t bsf_getline(char *str, int size) { size_t count = 0; char ch; while (count < size - 1) { #if defined(__MINGW32__) || defined(__DJGPP__) ch = getch(); #else read(fileno(stdin), &ch, 1); #endif if (ch == '\n' || ch == '\r') { break; } else if (ch == 24) { /* Ctrl-X */ return -1; } else if (ch == '\b' || ch == 127 || ch == 4) { count--; printf("\b \b"); fflush(stdout); } else { str[count] = ch; count++; putchar(ch); fflush(stdout); } } str[count] = 0; return count; } /* PROTO */ void input_reconnect(char *arg) { struct ConnPtr *temp, *trav; eraseline(); b_echostr_s(); if (conn->timestamps) { addts(); putchar(' '); } if (arg[0] != '\0') { if (conn->username) { free(conn->username); conn->username = NULL; } if (conn->password) { free(conn->password); conn->password = NULL; } printf("Reconnecting as %s...\n", arg); conn->username = strdup(arg); b_getpassword(); } else { printf("Reconnecting...\n"); } if (conn->conn != NULL) { delete_buddylist(buddylist); buddylist = NULL; conn->buddiesonline = 0; if (conn->clist->conn == conn->conn) { temp = conn->clist; conn->clist = conn->clist->next; if (temp->username) free(temp->username); free(temp); } else { for (trav = conn->clist; trav->next;) { if (trav->next->conn == conn->conn) { temp = trav->next; trav->next = trav->next->next; if (temp->username) free(temp->username); free(temp); } } } imcomm_delete_handle_now(conn->conn); conn->conn = NULL; } create_new_connection(); if (conn->proxytype != PROXY_TYPE_NONE) { imcomm_set_proxy(conn->clist->conn, conn->proxytype, conn->proxy, (uint16_t) conn->proxyport); } if (conn->oscarport != 0) { imcomm_set_oscar_port(conn->clist->conn, conn->oscarport); } imcomm_im_signon(conn->clist->conn, conn->username, conn->password); conn->conn = conn->clist->conn; if (conn->isaway) imcomm_set_away(conn->conn, conn->awaymsg); }