/* * nsimpleyahoo.c * very simple yahoo client * based on sample_client.c from libyahoo2 * stripped down version * plus some mods. * thanks to libyahoo2 and gaim/pidgin team * nop, 2007, GPL. * http://www.noprianto.com/code.php */ #include #include #include #include #include #include #include #include #include #include #include #include #define FREE(x) if(x) {free(x); x=NULL;} #define y_new0(type, n) (type *)calloc((n), sizeof(type)) #define print_message(x) { printf x; printf("\n"); } static char *local_host = NULL; typedef struct { char yahoo_id[255]; char password[255]; int id; int fd; int status; char *msg; } yahoo_local_account; typedef struct { char yahoo_id[255]; char name[255]; int status; int away; char *msg; char group[255]; } yahoo_account; static yahoo_local_account * ylad = NULL; static YList * buddies = NULL; struct connect_callback_data { yahoo_connect_callback callback; void * callback_data; int id; int tag; }; YList *connections = NULL; struct _conn { int tag; int fd; int id; yahoo_input_condition cond; void *data; int remove; }; static int connection_tags=0; static char * get_buddy_name(char * yid) { YList * b; for (b = buddies; b; b = b->next) { yahoo_account * ya = b->data; if(!strcmp(yid, ya->yahoo_id)) return ya->name&&*ya->name?ya->name:ya->yahoo_id; } return yid; } void ext_yahoo_status_changed(int id, char *who, int stat, char *msg, int away) { yahoo_account * ya=NULL; YList * b; for(b = buddies; b; b = b->next) { if(!strcmp(((yahoo_account *)b->data)->yahoo_id, who)) { ya = b->data; break; } } print_message(("%s (%s) [%d]", ya?ya->name:who, who, stat)) } void ext_yahoo_got_buddies(int id, YList * buds) { while(buddies) { FREE(buddies->data); buddies = buddies->next; if(buddies) FREE(buddies->prev); } for(; buds; buds = buds->next) { yahoo_account *ya = y_new0(yahoo_account, 1); struct yahoo_buddy *bud = buds->data; strncpy(ya->yahoo_id, bud->id, 255); if(bud->real_name) strncpy(ya->name, bud->real_name, 255); strncpy(ya->group, bud->group, 255); ya->status = YAHOO_STATUS_OFFLINE; buddies = y_list_append(buddies, ya); } } void ext_yahoo_got_im(int id, char *who, char *msg, long tm, int stat, int utf8) { char *umsg = msg; if(stat == 2) return; if(!msg) return; who = get_buddy_name(who); if(tm) { char timestr[255]; strncpy(timestr, ctime((time_t *)&tm), sizeof(timestr)); timestr[strlen(timestr) - 1] = '\0'; print_message(("[Offline message at %s from %s]: %s", timestr, who, umsg)) } else { if(!strcmp(umsg, "")) printf("\a"); print_message(("%s: %s", who, umsg)) } if(utf8) FREE(umsg); } void ext_yahoo_typing_notify(int id, char *who, int stat) { if(stat) print_message(("%s is typing...", who)); } void yahoo_logout() { if (ylad->id <= 0) return; yahoo_logoff(ylad->id); yahoo_close(ylad->id); ylad->status = YAHOO_STATUS_OFFLINE; ylad->id = 0; print_message(("logged out")); } void ext_yahoo_login(yahoo_local_account * ylad, int login_mode) { ylad->id = yahoo_init_with_attributes(ylad->yahoo_id, ylad->password, "local_host", local_host, "pager_port", 23, NULL); ylad->status = YAHOO_STATUS_OFFLINE; yahoo_login(ylad->id, login_mode); } void ext_yahoo_login_response(int id, int succ, char *url) { if (succ == YAHOO_LOGIN_OK) { ylad->status = yahoo_current_status(id); print_message(("Login OK.")); return; } else if(succ == YAHOO_LOGIN_PASSWD) { print_message (("Wrong password.")); } else if(succ == YAHOO_LOGIN_LOCK) { print_message (("Account locked. Please visit %s", url)); } else if(succ == YAHOO_LOGIN_DUPL) { print_message (("Duplicate login.")); } else if(succ == YAHOO_LOGIN_SOCK) { print_message (("Server closed the socket.")); } else { print_message (("General error.")); } ylad->status = YAHOO_STATUS_OFFLINE; yahoo_logout(); } void ext_yahoo_error(int id, char *err, int fatal) { fprintf(stdout, "Yahoo Error: "); fprintf(stdout, "%s", err); fprintf(stdout, "\n"); if(fatal) yahoo_logout(); } int ext_yahoo_add_handler(int id, int fd, yahoo_input_condition cond, void *data) { struct _conn *c = y_new0(struct _conn, 1); c->tag = ++connection_tags; c->id = id; c->fd = fd; c->cond = cond; c->data = data; connections = y_list_prepend(connections, c); return c->tag; } void ext_yahoo_remove_handler(int id, int tag) { YList *l; for(l = connections; l; l = y_list_next(l)) { struct _conn *c = l->data; if(c->tag == tag) { c->remove = 1; return; } } } static void connect_complete(void *data, int source, yahoo_input_condition condition) { struct connect_callback_data *ccd = data; int error, err_size = sizeof(error); ext_yahoo_remove_handler(0, ccd->tag); getsockopt(source, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&err_size); if(error) { close(source); source = -1; } ccd->callback(source, error, ccd->callback_data); FREE(ccd); } void yahoo_callback(struct _conn *c, yahoo_input_condition cond) { int ret=1; char buff[1024]={0}; if(c->id < 0) { connect_complete(c->data, c->fd, cond); } else { if(cond & YAHOO_INPUT_READ) ret = yahoo_read_ready(c->id, c->fd, c->data); if(ret>0 && cond & YAHOO_INPUT_WRITE) ret = yahoo_write_ready(c->id, c->fd, c->data); if(ret == -1) snprintf(buff, sizeof(buff), "Yahoo read error (%d): %s", errno, strerror(errno)); else if(ret == 0) snprintf(buff, sizeof(buff), "Yahoo read error: Server closed socket"); if(buff[0]) print_message((buff)); } } int ext_yahoo_connect_async(int id, char *host, int port, yahoo_connect_callback callback, void *data) { struct sockaddr_in serv_addr; static struct hostent *server; int servfd; struct connect_callback_data * ccd; int error; if(!(server = gethostbyname(host))) { errno=h_errno; return -1; } if((servfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memcpy(&serv_addr.sin_addr.s_addr, *server->h_addr_list, server->h_length); serv_addr.sin_port = htons(port); error = connect(servfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); if(!error) { callback(servfd, 0, data); return 0; } else if(error == -1 && errno == EINPROGRESS) { ccd = calloc(1, sizeof(struct connect_callback_data)); ccd->callback = callback; ccd->callback_data = data; ccd->id = id; ccd->tag = ext_yahoo_add_handler(-1, servfd, YAHOO_INPUT_WRITE, ccd); return ccd->tag; } else { if(error == -1) { } close(servfd); return -1; } } static void local_input_callback(int source) { char line[1024] = {0}; char cmd[64] = {0}; char data[960] = {0}; char yaccount[255] = {0}; char message[705] = {0}; int i,j, index; char c; i=0; c=0; do { if(read(source, &c, 1) <= 0) c='\0'; if(c == '\r') continue; if(c == '\n') break; if(c == '\b') { if(!i) continue; c = '\0'; i--; } if(c) { line[i++] = c; line[i]='\0'; } } while(i<1023 && c != '\n'); if(line[0]) { for (i=0; i> Sending keep alive command")); yahoo_keepalive(ylad->id); } else if (strcmp(cmd, "im") == 0) { for (i=0; i < strlen (data); i++) { if (data[i] != ' ') { yaccount[i] = data[i]; } else { index = i + 1 ; break; } } yaccount[i] = 0; for (i = index, j=0; i < strlen (data); i++, j++) { message[j] = data[i]; } message[j] = 0; print_message (("Sending IM to %s", yaccount)); yahoo_send_im(ylad -> id, NULL, yaccount, message, 0); } else { print_message (("Unknown command.")); } } } int main(int argc, char * argv[]) { int status; int log_level; int lfd=0; fd_set inp, outp; struct timeval tv; int fd_stdin = fileno(stdin); YList *l=connections; ylad = y_new0(yahoo_local_account, 1); printf("Yahoo Id: "); scanf("%s", ylad->yahoo_id); printf("Password: "); scanf("%s", ylad->password); printf("\n"); ext_yahoo_login(ylad, YAHOO_STATUS_AVAILABLE); while(1) { FD_ZERO(&inp); FD_ZERO(&outp); FD_SET(fd_stdin, &inp); tv.tv_sec=1; tv.tv_usec=0; lfd=0; for(l=connections; l; ) { struct _conn *c = l->data; if(c->remove) { YList *n = y_list_next(l); connections = y_list_remove_link(connections, l); y_list_free_1(l); free(c); l=n; } else { if(c->cond & YAHOO_INPUT_READ) FD_SET(c->fd, &inp); if(c->cond & YAHOO_INPUT_WRITE) FD_SET(c->fd, &outp); if(lfd < c->fd) lfd = c->fd; l = y_list_next(l); } } select(lfd + 1, &inp, &outp, NULL, &tv); if(FD_ISSET(fd_stdin, &inp)) local_input_callback(0); for(l = connections; l; l = y_list_next(l)) { struct _conn *c = l->data; if(c->remove) continue; if(FD_ISSET(c->fd, &inp)) yahoo_callback(c, YAHOO_INPUT_READ); if(FD_ISSET(c->fd, &outp)) yahoo_callback(c, YAHOO_INPUT_WRITE); } } while(connections) { YList *tmp = connections; struct _conn * c = connections->data; close(c->fd); FREE(c); connections = y_list_remove_link(connections, connections); y_list_free_1(tmp); } yahoo_logout(); FREE(ylad); return 0; } int ext_yahoo_log(char *fmt,...) { } int ext_yahoo_connect(char *host, int port) { } void ext_yahoo_got_cookies(int id) { } void ext_yahoo_got_ignore(int id, YList * igns) { } void ext_yahoo_rejected(int id, char *who, char *msg) { } void ext_yahoo_contact_added(int id, char *myid, char *who, char *msg) { } void ext_yahoo_game_notify(int id, char *who, int stat) { } void ext_yahoo_mail_notify(int id, char *from, char *subj, int cnt) { } void ext_yahoo_got_webcam_image(int id, const char *who, const unsigned char *image, unsigned int image_size, unsigned int real_size, unsigned int timestamp) { } void ext_yahoo_webcam_viewer(int id, char *who, int connect) { } void ext_yahoo_webcam_closed(int id, char *who, int reason) { } void ext_yahoo_webcam_data_request(int id, int send) { } void ext_yahoo_webcam_invite(int id, char *from) { } void ext_yahoo_webcam_invite_reply(int id, char *from, int accept) { } void ext_yahoo_system_message(int id, char *msg) { } void ext_yahoo_got_file(int id, char *who, char *url, long expires, char *msg, char *fname, unsigned long fesize) { } void ext_yahoo_got_identities(int id, YList * ids) { } void ext_yahoo_chat_yahoologout(int id) { } void ext_yahoo_chat_yahooerror(int id) { } void ext_yahoo_got_search_result(int id, int found, int start, int total, YList *contacts) { } void ext_yahoo_got_conf_invite(int id, char *who, char *room, char *msg, YList *members) { } void ext_yahoo_conf_userdecline(int id, char *who, char *room, char *msg) { } void ext_yahoo_conf_userjoin(int id, char *who, char *room) { } void ext_yahoo_conf_userleave(int id, char *who, char *room) { } void ext_yahoo_conf_message(int id, char *who, char *room, char *msg, int utf8) { } void ext_yahoo_chat_cat_xml(int id, char *xml) { } void ext_yahoo_chat_join(int id, char *room, char * topic, YList *members, int fd) { } void ext_yahoo_chat_userjoin(int id, char *room, struct yahoo_chat_member *who) { } void ext_yahoo_chat_userleave(int id, char *room, char *who) { } void ext_yahoo_chat_message(int id, char *who, char *room, char *msg, int msgtype, int utf8) { }