# HG changeset patch # User Eric Warmenhoven # Date 969617800 0 # Node ID 5e6ca3dd4d02082b5d6654c09ddcf16472d6cf15 # Parent e5da96def4bd183a048c956e496600813a70a281 [gaim-migrate @ 945] yay. thanks bmiller committer: Tailor Script diff -r e5da96def4bd -r 5e6ca3dd4d02 libfaim/CHANGES --- a/libfaim/CHANGES Thu Sep 21 19:21:35 2000 +0000 +++ b/libfaim/CHANGES Fri Sep 22 10:16:40 2000 +0000 @@ -1,6 +1,11 @@ No release numbers ------------------ + - Thu Sep 21 00:24:36 UTC 2000 + - Add socks5 proxy support (not tested real well, worked the + few times a tried). + - Added proxy support to faimtest. + - Tue Sep 19 03:10:07 UTC 2000 - Add aim_setuserinterests() and aim_setdirectoryinfo() - Add ICQ away status diff -r e5da96def4bd -r 5e6ca3dd4d02 libfaim/CHANGES.gaim --- a/libfaim/CHANGES.gaim Thu Sep 21 19:21:35 2000 +0000 +++ b/libfaim/CHANGES.gaim Fri Sep 22 10:16:40 2000 +0000 @@ -1,3 +1,8 @@ + +Fri Sep 22 10:12:37 UTC 2000 EWarmenhoven + - yeah, libfaim does socks 5 proxying now. it may be fragile though, + and the necessary call in gaim to get it to work isn't there yet. + be patient. i just don't want to write the UI for it yet. Wed Sep 20 23:30:32 UTC 2000 EWarmenhoven - libfaim does dir info now diff -r e5da96def4bd -r 5e6ca3dd4d02 libfaim/aim_conn.c --- a/libfaim/aim_conn.c Thu Sep 21 19:21:35 2000 +0000 +++ b/libfaim/aim_conn.c Fri Sep 22 10:16:40 2000 +0000 @@ -162,6 +162,154 @@ } /* + * An extrememly quick and dirty SOCKS5 interface. + */ +static int aim_proxyconnect(struct aim_session_t *sess, + char *host, unsigned short port, + int *statusret) +{ + int fd = -1; + + if (strlen(sess->socksproxy.server)) { /* connecting via proxy */ + int i; + unsigned char buf[512]; + struct sockaddr_in sa; + struct hostent *hp; + char *proxy; + unsigned short proxyport = 1080; + + for(i=0;i<(int)strlen(sess->socksproxy.server);i++) { + if (sess->socksproxy.server[i] == ':') { + proxyport = atoi(&(sess->socksproxy.server[i+1])); + break; + } + } + proxy = (char *)malloc(i+1); + strncpy(proxy, sess->socksproxy.server, i); + proxy[i] = '\0'; + + if (!(hp = gethostbyname(proxy))) { + printf("proxyconnect: unable to resolve proxy name\n"); + *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); + return -1; + } + free(proxy); + + memset(&sa.sin_zero, 0, 8); + sa.sin_port = htons(proxyport); + memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); + sa.sin_family = hp->h_addrtype; + + fd = socket(hp->h_addrtype, SOCK_STREAM, 0); + if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { + printf("proxyconnect: unable to connect to proxy\n"); + close(fd); + return -1; + } + + i = 0; + buf[0] = 0x05; /* SOCKS version 5 */ + if (strlen(sess->socksproxy.username)) { + buf[1] = 0x02; /* two methods */ + buf[2] = 0x00; /* no authentication */ + buf[3] = 0x02; /* username/password authentication */ + i = 4; + } else { + buf[1] = 0x01; + buf[2] = 0x00; + i = 3; + } + + if (write(fd, buf, i) < i) { + *statusret = errno; + close(fd); + return -1; + } + + if (read(fd, buf, 2) < 2) { + *statusret = errno; + close(fd); + return -1; + } + + if ((buf[0] != 0x05) || (buf[1] == 0xff)) { + *statusret = EINVAL; + close(fd); + return -1; + } + + /* check if we're doing username authentication */ + if (buf[1] == 0x02) { + i = aimutil_put8(buf, 0x01); /* version 1 */ + i += aimutil_put8(buf+i, strlen(sess->socksproxy.username)); + i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username)); + i += aimutil_put8(buf+i, strlen(sess->socksproxy.password)); + i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password)); + if (write(fd, buf, i) < i) { + *statusret = errno; + close(fd); + return -1; + } + if (read(fd, buf, 2) < 2) { + *statusret = errno; + close(fd); + return -1; + } + if ((buf[0] != 0x01) || (buf[1] != 0x00)) { + *statusret = EINVAL; + close(fd); + return -1; + } + } + + i = aimutil_put8(buf, 0x05); + i += aimutil_put8(buf+i, 0x01); /* CONNECT */ + i += aimutil_put8(buf+i, 0x00); /* reserved */ + i += aimutil_put8(buf+i, 0x03); /* address type: host name */ + i += aimutil_put8(buf+i, strlen(host)); + i += aimutil_putstr(buf+i, host, strlen(host)); + i += aimutil_put16(buf+i, port); + + if (write(fd, buf, i) < i) { + *statusret = errno; + close(fd); + return -1; + } + if (read(fd, buf, 10) < 10) { + *statusret = errno; + close(fd); + return -1; + } + if ((buf[0] != 0x05) || (buf[1] != 0x00)) { + *statusret = EINVAL; + close(fd); + return -1; + } + + } else { /* connecting directly */ + struct sockaddr_in sa; + struct hostent *hp; + + if (!(hp = gethostbyname(host))) { + *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); + return -1; + } + + memset(&sa.sin_zero, 0, 8); + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); + sa.sin_family = hp->h_addrtype; + + fd = socket(hp->h_addrtype, SOCK_STREAM, 0); + if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { + close(fd); + fd = -1; + } + } + return fd; +} + +/* * aim_newconn(type, dest) * * Opens a new connection to the specified dest host of type type. @@ -214,31 +362,19 @@ strncpy(host, dest, i); host[i] = '\0'; - hp = gethostbyname(host); - free(host); - - if (hp == NULL) { - connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR); + if ((ret = aim_proxyconnect(sess, host, port, &connstruct->status)) < 0) { + connstruct->fd = -1; + connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); + free(host); faim_mutex_unlock(&connstruct->active); return connstruct; - } - - memset(&sa.sin_zero, 0, 8); - sa.sin_port = htons(port); - memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); - sa.sin_family = hp->h_addrtype; - - connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0); - ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)); - if(ret < 0) { - connstruct->fd = -1; - connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); - faim_mutex_unlock(&connstruct->active); - return connstruct; - } + } else + connstruct->fd = ret; faim_mutex_unlock(&connstruct->active); + free(host); + return connstruct; } @@ -372,6 +508,32 @@ return 0; } +/* + * Call this with your SOCKS5 proxy server parameters before + * the first call to aim_newconn(). If called with all NULL + * args, it will clear out a previously set proxy. + * + * Set username and password to NULL if not applicable. + * + */ +faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password) +{ + /* clear out the proxy info */ + if (!server || !strlen(server)) { + memset(sess->socksproxy.server, 0, sizeof(sess->socksproxy.server)); + memset(sess->socksproxy.username, 0, sizeof(sess->socksproxy.username)); + memset(sess->socksproxy.password, 0, sizeof(sess->socksproxy.password)); + return; + } + + strncpy(sess->socksproxy.server, server, sizeof(sess->socksproxy.server)); + if (username && strlen(username)) + strncpy(sess->socksproxy.username, username, sizeof(sess->socksproxy.username)); + if (password && strlen(password)) + strncpy(sess->socksproxy.password, password, sizeof(sess->socksproxy.password)); + return; +} + faim_export void aim_session_init(struct aim_session_t *sess) { if (!sess) diff -r e5da96def4bd -r 5e6ca3dd4d02 libfaim/faim/aim.h --- a/libfaim/faim/aim.h Thu Sep 21 19:21:35 2000 +0000 +++ b/libfaim/faim/aim.h Fri Sep 22 10:16:40 2000 +0000 @@ -331,6 +331,12 @@ faim_mutex_t snac_hash_locks[FAIM_SNAC_HASH_SIZE]; u_long snac_nextid; + struct { + char server[128]; + char username[128]; + char password[128]; + } socksproxy; + struct aim_msgcookie_t *msgcookies; }; @@ -492,6 +498,7 @@ faim_export int aim_conn_isready(struct aim_conn_t *); faim_export int aim_conn_setstatus(struct aim_conn_t *, int); faim_export void aim_session_init(struct aim_session_t *); +faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password); /* aim_misc.c */ diff -r e5da96def4bd -r 5e6ca3dd4d02 src/buddy.c --- a/src/buddy.c Thu Sep 21 19:21:35 2000 +0000 +++ b/src/buddy.c Fri Sep 22 10:16:40 2000 +0000 @@ -1045,6 +1045,30 @@ show_add_group(); } +static void im_callback(GtkWidget *widget, GtkTree *tree) +{ + GList *i; + struct buddy *b = NULL; + struct conversation *c; + i = GTK_TREE_SELECTION(tree); + if (i) { + b = gtk_object_get_user_data(GTK_OBJECT(i->data)); + } else { + show_im_dialog(); + return; + } + if (!b->name) + return; + + c = find_conversation(b->name); + if (c == NULL) { + c = new_conversation(b->name); + } else { + gdk_window_raise(c->window->window); + } +} + + static void info_callback(GtkWidget *widget, GtkTree *tree) { GList *i; @@ -1053,6 +1077,7 @@ if (i) { b = gtk_object_get_user_data(GTK_OBJECT(i->data)); } else { + show_info_dialog(); return; } if (!b->name) @@ -1771,7 +1796,7 @@ gtk_box_pack_start(GTK_BOX(imchatbox), chatbutton, TRUE, TRUE, 0); gtk_container_border_width(GTK_CONTAINER(imchatbox), 10); - gtk_signal_connect(GTK_OBJECT(imbutton), "clicked", GTK_SIGNAL_FUNC(show_im_dialog), buddies); + gtk_signal_connect(GTK_OBJECT(imbutton), "clicked", GTK_SIGNAL_FUNC(im_callback), buddies); gtk_signal_connect(GTK_OBJECT(infobutton), "clicked", GTK_SIGNAL_FUNC(info_callback), buddies); gtk_signal_connect(GTK_OBJECT(chatbutton), "clicked", GTK_SIGNAL_FUNC(chat_callback), buddies); diff -r e5da96def4bd -r 5e6ca3dd4d02 src/dialogs.c --- a/src/dialogs.c Thu Sep 21 19:21:35 2000 +0000 +++ b/src/dialogs.c Fri Sep 22 10:16:40 2000 +0000 @@ -71,6 +71,7 @@ GdkColor fgcolor; static GtkWidget *imdialog = NULL; /*I only want ONE of these :) */ +static GtkWidget *infodialog = NULL; static GList *dialogwindows = NULL; static GtkWidget *exportdialog, *importdialog; static GtkWidget *aliasdlg = NULL; @@ -332,6 +333,9 @@ if (dest == imdialog) imdialog = NULL; + if (dest == infodialog) + infodialog = NULL; + if (dest == exportdialog) exportdialog = NULL; @@ -369,6 +373,11 @@ destroy_dialog(NULL, imdialog); imdialog = NULL; } + + if (infodialog) { + destroy_dialog(NULL, infodialog); + infodialog = NULL; + } if (exportdialog) { destroy_dialog(NULL, exportdialog); @@ -639,6 +648,24 @@ g_free(who); } +static void do_info(GtkWidget *widget, GtkWidget *infoentry) +{ + char *who; + + who = g_strdup(normalize(gtk_entry_get_text(GTK_ENTRY(infoentry)))); + destroy_dialog(NULL, infodialog); + infodialog = NULL; + + if (!strcasecmp(who, "")) { + g_free(who); + return; + } + + serv_get_info(who); + + g_free(who); +} + void show_ee_dialog(int ee) { GtkWidget *ok; @@ -682,7 +709,7 @@ gtk_widget_show(eedialog); } -void show_im_dialog(GtkWidget *w, GtkWidget *w2) +void show_im_dialog() { GtkWidget *button; GtkWidget *imentry; @@ -722,7 +749,7 @@ gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(destroy_dialog), imdialog); - label = gtk_label_new(_("IM who: ")); + label = gtk_label_new(_("IM who:")); gtk_box_pack_start(GTK_BOX(ebox), label, TRUE, TRUE, 10); gtk_widget_show(label); @@ -757,6 +784,81 @@ gtk_widget_show(imdialog); } +void show_info_dialog() +{ + GtkWidget *button; + GtkWidget *infoentry; + GtkWidget *vbox; + GtkWidget *ebox; + GtkWidget *bbox; + GtkWidget *label; + GtkWidget *frame; + GtkWidget *fbox; + + if (!infodialog) { + + infodialog = gtk_window_new(GTK_WINDOW_DIALOG); + gtk_window_set_wmclass(GTK_WINDOW(infodialog), "infodialog", + "Gaim"); + gtk_widget_set_usize(infodialog, 255, 105); + gtk_container_border_width(GTK_CONTAINER(infodialog), 5); + gtk_window_set_policy(GTK_WINDOW(infodialog), FALSE, FALSE, TRUE); + gtk_widget_show(infodialog); + + bbox = gtk_hbox_new(TRUE, 10); + vbox = gtk_vbox_new(FALSE, 5); + ebox = gtk_hbox_new(FALSE, 2); + fbox = gtk_vbox_new(TRUE, 10); + + frame = gtk_frame_new(_("Get User Info")); + + infoentry = gtk_entry_new(); + + button = picture_button(infodialog, _("OK"), ok_xpm); + gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 5); + gtk_signal_connect(GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC(do_info), infoentry); + + button = picture_button(infodialog, _("Cancel"), cancel_xpm); + gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 5); + gtk_signal_connect(GTK_OBJECT(button), "clicked", + GTK_SIGNAL_FUNC(destroy_dialog), infodialog); + + label = gtk_label_new(_("User:")); + gtk_box_pack_start(GTK_BOX(ebox), label, TRUE, TRUE, 10); + gtk_widget_show(label); + + gtk_box_pack_start(GTK_BOX(ebox), infoentry, TRUE, TRUE, 10); + + gtk_box_pack_start(GTK_BOX(vbox), ebox, FALSE, FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 5); + + /* Handle closes right */ + gtk_signal_connect(GTK_OBJECT(infoentry), "activate", + GTK_SIGNAL_FUNC(do_info), infoentry); + gtk_signal_connect(GTK_OBJECT(infodialog), "destroy", + GTK_SIGNAL_FUNC(destroy_dialog), infodialog); + + /* Finish up */ + gtk_widget_show(ebox); + gtk_widget_show(infoentry); + gtk_widget_show(bbox); + gtk_widget_show(vbox); + gtk_widget_show(fbox); + gtk_widget_show(frame); + gtk_container_add(GTK_CONTAINER(frame), vbox); + gtk_box_pack_start(GTK_BOX(fbox), frame, FALSE, FALSE, 5); + gtk_window_set_title(GTK_WINDOW(infodialog), _("Gaim - Get User Info")); + gtk_container_add(GTK_CONTAINER(infodialog), fbox); + gtk_widget_grab_focus(infoentry); + gtk_widget_realize(infodialog); + + aol_icon(infodialog->window); + + } + gtk_widget_show(infodialog); +} + /*------------------------------------------------------------------------*/ /* The dialog for adding buddies */ diff -r e5da96def4bd -r 5e6ca3dd4d02 src/gaim.h --- a/src/gaim.h Thu Sep 21 19:21:35 2000 +0000 +++ b/src/gaim.h Fri Sep 22 10:16:40 2000 +0000 @@ -414,7 +414,7 @@ #define TYPE_SIGNOFF 4 #define TYPE_KEEPALIVE 5 -#define REVISION "gaim:$Revision: 940 $" +#define REVISION "gaim:$Revision: 945 $" #define FLAPON "FLAPON\r\n\r\n" #define ROAST "Tic/Toc" @@ -808,7 +808,8 @@ extern void show_warn_dialog(char *); extern void do_error_dialog(char *, char *); extern void show_error_dialog(char *); -extern void show_im_dialog(GtkWidget *, GtkWidget *); +extern void show_im_dialog(); +extern void show_info_dialog(); extern void show_add_buddy(char *, char *); extern void show_add_group(); extern void show_add_perm();