/* * ImageIM (tm) Gaim plugin. * * Copyright (C) 2005 Will Gorman (willgorman@hotmail.com) * * License: GNU General Public License (GPL) * * This plugin allows a gaim client to send images to any other im client. * */ #define IMAGE_IM_PLUGIN_ID "image-im" #include #include #include #include "internal.h" #include "connection.h" #include "conversation.h" #include "core.h" #include "debug.h" #include "signals.h" #include "version.h" #include "notify.h" #include "imgstore.h" #include "util.h" #include "gtkutils.h" #include "gtkconv.h" #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" #include "gtkplugin.h" /******************************************************************/ /* PLUGIN GTK PREFS ITEMS */ /******************************************************************/ static GtkWidget *username_entry; static GtkWidget *password_entry; void imageim_auth_cb(void *user_data, const char *data, size_t len) { gaim_prefs_set_string("/plugins/imageim/auth", data); } static void apply_prefs() { /* SAVE PREFERENCE */ gaim_prefs_set_string("/plugins/imageim/username", gtk_entry_get_text(GTK_ENTRY(username_entry))); gaim_prefs_set_string("/plugins/imageim/password", gtk_entry_get_text(GTK_ENTRY(password_entry))); /* check for authentication. */ GString * url = g_string_new(""); g_string_sprintf(url, "http://www.imageim.com/auth.jsp?username=%s&password=%s", gaim_prefs_get_string("/plugins/imageim/username"),gaim_prefs_get_string("/plugins/imageim/password")); gaim_prefs_set_string("/plugins/imageim/auth", "FALSE"); gaim_url_fetch(url->str, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, imageim_auth_cb, NULL); g_string_free(url, TRUE); } static GtkWidget * get_config_frame(GaimPlugin *plugin) { gaim_debug_misc("imageim", "get_config_frame\n"); GtkWidget *frame; GtkWidget *vbox, *hbox; GtkWidget *label, *button, *infolabel; GtkWidget *pwlabel; frame = gtk_vbox_new(FALSE, 18); gtk_container_set_border_width(GTK_CONTAINER(frame), 12); vbox = gaim_gtk_make_frame(frame, _("ImageIM User Configuration")); hbox = gtk_hbox_new(FALSE, 18); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); infolabel = gtk_label_new_with_mnemonic(_("Visit http://www.imageim.com to register")); gtk_box_pack_start(GTK_BOX(hbox), infolabel, FALSE, FALSE, 0); gtk_widget_show(infolabel); hbox = gtk_hbox_new(FALSE, 18); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic(_("_Username:")); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); username_entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(username_entry), 40); gtk_entry_set_text(GTK_ENTRY(username_entry), gaim_prefs_get_string("/plugins/imageim/username")); gtk_box_pack_start(GTK_BOX(hbox), username_entry, TRUE, TRUE, 0); gtk_label_set_mnemonic_widget(GTK_LABEL(label), username_entry); gtk_widget_show(username_entry); hbox = gtk_hbox_new(FALSE, 18); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); pwlabel = gtk_label_new_with_mnemonic(_("_Password:")); gtk_box_pack_start(GTK_BOX(hbox), pwlabel, FALSE, FALSE, 0); gtk_widget_show(pwlabel); password_entry = gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE); gtk_entry_set_max_length(GTK_ENTRY(password_entry), 40); gtk_entry_set_text(GTK_ENTRY(password_entry), gaim_prefs_get_string("/plugins/imageim/password")); gtk_box_pack_start(GTK_BOX(hbox), password_entry, TRUE, TRUE, 0); gtk_label_set_mnemonic_widget(GTK_LABEL(pwlabel), password_entry); gtk_widget_show(password_entry); hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); hbox = gtk_hbutton_box_new(); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); button = gtk_button_new_from_stock(GTK_STOCK_APPLY); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(apply_prefs), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); gtk_widget_show_all(frame); return frame; } static GaimGtkPluginUiInfo ui_info = { get_config_frame }; /******************************************************************/ /* HTTP POST ITEMS */ /* (sending im, etc) */ /******************************************************************/ struct imageim_http { GString * filename; char * buddyname; char * recipient; char * account; gpointer imgdata; unsigned long size; int inpa; }; static void http_results(gpointer data, gint source, GaimInputCondition cond) { struct imageim_http *hdata = data; gaim_debug_misc("imageim", "http_results : Data Recovered \n"); char *webdata; int len; char read_data; webdata = NULL; len = 0; while (read(source, &read_data, 1) > 0 || errno == EWOULDBLOCK) { if (errno == EWOULDBLOCK) { errno = 0; continue; } if (!read_data) continue; len++; webdata = g_realloc(webdata, len); webdata[len - 1] = read_data; } webdata = g_realloc(webdata, len + 1); webdata[len] = 0; g_free(hdata->recipient); g_free(hdata->account); g_free(hdata->buddyname); g_string_free(hdata->filename, TRUE); gaim_input_remove(hdata->inpa); close(source); gaim_debug_misc("imageim", "http_results : Data Recovered (%s)\n", webdata); g_free(webdata); g_free(hdata); } static void http_req_callback(gpointer data, gint source, GaimInputCondition cond) { struct imageim_http *http = data; GString *content = g_string_new(""); GString *prepend = g_string_new(""); if (source == 0) { g_string_free(http->filename, TRUE); g_free(http->buddyname); g_free(http->recipient); g_free(http->account); g_free(http); return; } g_string_printf(content, "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"imageimversion\"\r\n\r\n" "0.9b\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"buddyname\"\r\n\r\n" "%s\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"recipient\"\r\n\r\n" "%s\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"account\"\r\n\r\n" "%s\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"username\"\r\n\r\n" "%s\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"password\"\r\n\r\n" "%s\r\n" "------------------------------7c633d5c27ce\r\n" "Content-Disposition: form-data; name=\"fileupload\"; filename=\"%s.jpg\"\r\n" "Content-Type: application/octet-stream\r\n\r\n", http->buddyname, http->recipient, http->account, gaim_prefs_get_string("/plugins/imageim/username"), gaim_prefs_get_string("/plugins/imageim/password"), http->filename->str); content = g_string_append_len(content, http->imgdata, http->size); content = g_string_append(content, "------------------------------7c633d5c27ce--\r\n" "\r\n"); g_string_printf(prepend,"POST /upload.jsp HTTP/1.0\r\n" "Host: %s\r\n" "Pragma: no-cache\r\n" "User-Agent: Mozilla/4.0\r\n" "Content-Length: %d\r\n" "Content-Type: multipart/form-data; boundary=----------------------------7c633d5c27ce\r\n" "\r\n", "www.imageim.com", content->len); gaim_debug_misc("imageim", "content length = %d\n",content->len); content = g_string_prepend(content, prepend->str); if (write(source, content->str, content->len) < content->len) { g_string_free(prepend, TRUE); g_string_free(content, TRUE); g_string_free(http->filename, TRUE); g_free(http->recipient); g_free(http->account); g_free(http->buddyname); g_free(http); close(source); gaim_notify_error(NULL, NULL, _("Error communicating with server"), _("Gaim was unable to complete your request due " "to a problem communicating with the " "HTTP server. Please try again later.")); return; } g_string_free(prepend, TRUE); g_string_free(content, TRUE); http->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_results, data); } /* * if image tag present, upload image to specified http server * replace image tag with href tag to image on server */ static void sending_im_msg_cb(GaimAccount *account, char *recipient, char **buffer, void *data) { if (strcmp(gaim_prefs_get_string("/plugins/imageim/auth"), "TRUE") != 0) { return; } gaim_debug_misc("imageim", "sending-im-msg (%s, %s, %s)\n", gaim_account_get_username(account), recipient, *buffer); int imageid = 0; /* check to see if image tag is present. */ GData *attribs; const char *start, *end, *last; GString *temp1 = NULL; GString *temp2 = NULL; GString *msg = g_string_new(""); last = *buffer; /* for each valid IMG tag... */ while (last && *last && gaim_markup_find_tag("img", last, &start, &end, &attribs)) { gaim_debug_misc("imageim", "sending-im-msg located image tag\n"); GaimStoredImage *image = NULL; const char *id; if (start - last) { g_string_append_len(msg, last, start - last); } id = g_datalist_get_data(&attribs, "id"); /* ... if it refers to a valid gaim image ... */ if (id && (image = gaim_imgstore_get(atoi(id)))) { /* ... append the message from start to the tag ... */ gaim_debug_misc("imageim", "sending-im-msg creating imageim_http struct\n"); struct imageim_http *http = g_new0(struct imageim_http, 1); http->size = gaim_imgstore_get_size(image); char date[80]; time_t tme; time(&tme); strftime(date, sizeof(date), "%Y%m%d%H%M%S", localtime(&tme)); http->filename = g_string_new(""); http->buddyname = g_strdup(account->username); http->recipient = g_strdup(recipient); http->account = g_strdup(gaim_account_get_protocol_name(account)); temp1 = g_string_new(account->username); temp2 = g_string_new(recipient); char * ch; ch = strchr(temp1->str,' '); while (ch != NULL) { *ch = '_'; ch = strchr(temp1->str,' '); gaim_debug_misc("imageim", "sending-im-msg temp1 = (%s)\n", temp1->str); } ch = strchr(temp2->str,' '); while (ch != NULL) { *ch = '_'; ch = strchr(temp2->str,' '); gaim_debug_misc("imageim", "sending-im-msg temp1 = (%s)\n", temp2->str); } g_string_printf(http->filename, "%s_%s_%s%d", temp1->str,temp2->str,date,imageid++); g_string_free(temp1, TRUE); g_string_free(temp2, TRUE); http->imgdata = gaim_imgstore_get_data(image); gaim_debug_misc("imageim", "sending-im-msg made it this far !(2)\n"); /* send message, wait till completed. */ if (gaim_proxy_connect(account, "www.imageim.com", 80, http_req_callback, http) < 0) { gaim_notify_error(NULL, NULL, _("Error connecting to ImageIM server"), _("Error connecting to ImageIM server")); g_string_free(http->filename, TRUE); g_free(http->recipient); g_free(http->account); g_free(http->buddyname); g_free(http); } else { g_string_append_printf(msg, " http://www.imageim.com/imageim.jsp?img=%s ", http->filename->str, http->filename->str); } } /* If the tag is invalid, skip it, thus no else here */ g_datalist_clear(&attribs); /* continue from the end of the tag */ last = end + 1; } /* append any remaining message data (without the > :-) */ if (last && *last) msg = g_string_append(msg, last); g_free(*buffer); /* WRITE TO NEW LOCATION */ *buffer = msg->str; g_string_free(msg, FALSE); } /******************************************************************/ /* Fetching Code */ /* conversation_created_cb */ /******************************************************************/ void imageim_fetch_jpg_cb(void *user_data, const char *pic_data, size_t len); static gboolean imageim_find_url(const char * str, const char ** start, const char ** end, char ** url) { char *lower, *loc, *locend, *href, *astart, *aend, *altlocend; const char * tmp; g_return_val_if_fail( str != NULL, FALSE); g_return_val_if_fail( *str != '\0', FALSE); g_return_val_if_fail( start != NULL, FALSE); g_return_val_if_fail( end != NULL, FALSE); g_return_val_if_fail( url != NULL, FALSE); gaim_debug_misc("imageim", "imageim_find_url NEW (%s)\n", str); lower = g_ascii_strdown(str, -1); gaim_debug_misc("imageim", "imageim_find_url lower(%s)\n",lower); char data[100]; g_sprintf(data, "http://www.imageim.com/imageim.jsp"); loc = strstr(lower, data); if (loc) { /* see if regular or wrapped within html tag. */ if ((loc - 1 > lower) && (*(loc-1) == '"')) { /* we possibly have an ... senario */ href = strstr(lower,"href=\"http://www.imageim.com/imageim.jsp"); if (href) { astart = NULL; while ((href >= lower) && (astart == NULL)) { if (*(href) == '<') astart = href; href--; } if (astart) { aend = strstr(astart,""); if (aend) { locend = strchr(loc, '"'); if (locend != NULL) { *start = str + (astart-lower); *end = str + (aend-lower+3); tmp = str + (loc-lower); *url = g_strndup(tmp, locend-loc); gaim_debug_misc("imageim", "imageim_find_url (http) url = (%s)\n",*url); g_free(lower); return TRUE; } } } } } /* see if regular or wrapped within html tag. */ if ((loc - 1 > lower) && (*(loc-1) == '\'')) { /* we possibly have an ... senario */ href = strstr(lower,"href='http://www.imageim.com/imageim.jsp"); if (href) { astart = NULL; while ((href >= lower) && (astart == NULL)) { if (*(href) == '<') astart = href; href--; } if (astart) { aend = strstr(astart,""); if (aend) { locend = strchr(loc, '\''); if (locend != NULL) { *start = str + (astart-lower); *end = str + (aend-lower+3); tmp = str + (loc-lower); *url = g_strndup(tmp, locend-loc); gaim_debug_misc("imageim", "imageim_find_url (href, sq) url = (%s)\n",*url); g_free(lower); return TRUE; } } } } } /* see if wrapped in '<A HREF"' '">' */ if ((loc - 6 > lower) && (*(loc-1) == ';') && (*(loc-2) == 't') && (*(loc-3) == 'o') && (*(loc-4) == 'u') && (*(loc-5) == 'q') && (*(loc-6) == '&')) { /* we possibly have an ... senario */ href = strstr(lower,"href="http://www.imageim.com/imageim.jsp"); if (href) { astart = NULL; while ((href >= lower) && (astart == NULL)) { if ((*(href) == '&') && (*(href+1) == 'l') && (*(href+2) == 't') && (*(href+3) == ';')) astart = href; href--; } if (astart) { aend = strstr(astart,"</a>"); if (aend) { locend = strstr(loc, """); if (locend != NULL) { *start = str + (astart-lower); *end = str + (aend-lower+9); tmp = str + (loc-lower); *url = g_strndup(tmp, locend-loc); gaim_debug_misc("imageim", "imageim_find_url (&&&) url = (%s)\n",*url); g_free(lower); return TRUE; } } } } } locend = strchr(loc, ' '); altlocend = strchr(loc, '<'); if (locend == NULL) { if (altlocend != NULL) { locend = altlocend - 1; } else { locend = lower + strlen(lower) - 1; } } else { if (altlocend != NULL && altlocend < locend) { locend = altlocend; } locend = locend - 1; } *start = str + (loc-lower); *end = str + (locend-lower); *url = g_strndup(*start, (*end)-(*start) + 1); gaim_debug_misc("imageim", "imageim_find_url (normal) url = (%s)\n",*url); g_free(lower); return TRUE; } else { gaim_debug_misc("imageim", "imageim_find_url loc(NULL)\n"); g_free(lower); return FALSE; } } struct imageim_fetch_img_data { char * sender; char * url; int attempts; GaimAccount *account; }; gboolean retry_fetch(gpointer data) { struct imageim_fetch_img_data *imgdata = data; gaim_url_fetch(imgdata->url, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, imageim_fetch_jpg_cb, imgdata); return FALSE; } void imageim_fetch_jpg_cb(void *user_data, const char *pic_data, size_t len) { struct imageim_fetch_img_data *imgdata = user_data; int id; GaimConversation *cnv; GaimGtkConversation *gtkconv; char * firstpart = g_strndup(pic_data, 10); int datapoint1 = (int)firstpart[0]; int datapoint2 = (int)firstpart[1]; int datapoint3 = (int)firstpart[2]; int datapoint4 = (int)firstpart[3]; gaim_debug_misc("imageim", "imageim_fetch_jpg_cb (%d %d %d %d)\n", firstpart[0], firstpart[1], firstpart[2], firstpart[3]); g_free(firstpart); /* BEFORE CREATING IMAGESTORE_ADD, TEST DATA TO VERIFY JPG IF NOT JPG, SLEEP FOR A SEC AND TRY AGAIN (X TIMES UNTIL COMPLETED) ff d8 ff e0 I'm not proud of this. please help. */ if ((datapoint1 == -1) && (datapoint2 == -40) && (datapoint3 == -1) && (datapoint4 == -32)) { gaim_debug_misc("imageim", "imageim_fetch_jpg_cb : JPG DETECTED\n"); id = gaim_imgstore_add(pic_data, len, "test.jpg"); GString *str = g_string_new(""); g_string_printf(str, "", id); cnv = gaim_find_conversation_with_account(imgdata->sender, imgdata->account); gtkconv = GAIM_GTK_CONVERSATION(cnv); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), str->str, 0); g_string_free(str, TRUE); gaim_imgstore_unref(id); g_free(imgdata->url); g_free(imgdata->sender); g_free(imgdata); } else { gaim_debug_misc("imageim", "imageim_fetch_jpg_cb : NO JPG DETECTED.\n"); if (imgdata->attempts < 10) { imgdata->attempts++; gaim_debug_misc("imageim", "imageim_fetch_jpg_cb : attempt #%d\n",(imgdata->attempts+1)); g_timeout_add(5000, retry_fetch, imgdata); } else { cnv = gaim_find_conversation_with_account(imgdata->sender, imgdata->account); gtkconv = GAIM_GTK_CONVERSATION(cnv); gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), " Error: failed to retrieve imageim image. ", 0); g_free(imgdata->url); g_free(imgdata->sender); g_free(imgdata); } } } static gboolean receiving_im_msg_cb(GaimAccount *account, char **sender, char **buffer, int *flags, void *data) { gaim_debug_misc("imageim", "receiving-im-msg (%s, %s, %s, %d)\n", gaim_account_get_username(account), *sender, *buffer, *flags); /* IF AUTH FALSE, RETURN */ if (strcmp(gaim_prefs_get_string("/plugins/imageim/auth"), "TRUE") != 0) { return FALSE; } const gchar *start, *end, *last; gchar *url; GString *msg = g_string_new(""); last = *buffer; /* for each valid IMG tag... */ while (last && *last && imageim_find_url(last, &start, &end, &url)) { if (start - last) { g_string_append_len(msg, last, start - last); } /* we have a match. now we need to swap it out. */ gaim_debug_misc("imageim", "gaim_url_fetch starting.\n"); struct imageim_fetch_img_data *img_data = g_new0(struct imageim_fetch_img_data, 1); img_data->account = account; img_data->sender = g_strdup(*sender); /* URL is http://www.imageim.com/imageim.jsp?img=XXX */ char * ch; ch = strchr(url,'='); ch++; GString *tmp = g_string_new(""); g_string_sprintf(tmp, "http://www.imageim.com/images/%s.jpg", ch); /* Needs to be http://www.imageim.com/images/XXX.jpg */ img_data->url = tmp->str; g_string_free(tmp, FALSE); img_data->attempts = 0; gaim_url_fetch(img_data->url, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, imageim_fetch_jpg_cb, img_data); gaim_debug_misc("imageim", "gaim_url_fetch done.\n"); gaim_debug_misc("imageim", "receiving-im-msg - href matches:%s\n", url); g_free(url); last = end + 1; } gaim_debug_misc("imageim", "receiving-im-msg - done while\n"); /* append any remaining message data (without the > :-) */ if (last && *last) msg = g_string_append(msg, last); gaim_debug_misc("imageim", "receiving-im-msg - done msg append\n"); g_free(*buffer); gaim_debug_misc("imageim", "receiving-im-msg - done freeing buffer\n"); *buffer = msg->str; g_string_free(msg, FALSE); return FALSE; } /* static gboolean sending_chat_msg_cb(GaimAccount *account, char **buffer, int id, void *data) { gaim_debug_misc("imageim", "sending-chat-msg (%s, %s, %d)\n", gaim_account_get_username(account), *buffer, id); return FALSE; } static gboolean receiving_chat_msg_cb(GaimAccount *account, char **sender, char **buffer, GaimConversation *chat, void *data) { gaim_debug_misc("imageim", "receiving-chat-msg (%s, %s, %s, %s)\n", gaim_account_get_username(account), *sender, *buffer, gaim_conversation_get_name(chat)); return FALSE; } */ /******************************************************************/ /* Screenshot Section */ /* receiving_im_msg_cb */ /******************************************************************/ struct img_event_data { GdkPixbuf *screenshot; GaimConversation *conv; }; static void screenshot_event_cb( GtkWidget *widget, GdkEvent *event, gpointer rdata) { GtkTextIter iter; GtkTextMark *ins; GaimGtkConversation *gtkconv; GtkIMHtmlToolbar *toolbar; GdkScreen * cur_screen2 = gdk_screen_get_default (); struct img_event_data *imgdata = (struct img_event_data *) rdata; gtkconv = GAIM_GTK_CONVERSATION(imgdata->conv); toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar); GdkPixbuf * data = imgdata->screenshot; GdkPixbuf * subdata = NULL; int id; gchar * buffer; gsize buffer_size; gint screen_width = gdk_screen_get_width(cur_screen2); gint screen_height = gdk_screen_get_height(cur_screen2); GError * error = NULL; gdouble x, y; gdouble x1, x2, y1,y2; static gdouble ix = 0.0; static gdouble iy = 0.0; static gdouble ex = 0.0; static gdouble ey = 0.0; static gboolean dragging = FALSE; gdk_draw_pixbuf (widget->window, NULL, data, 0,0,0,0,screen_width, screen_height, GDK_RGB_DITHER_NONE,0,0); char errmsg[100]; switch((gint)event->type) { case GDK_MOTION_NOTIFY: if (dragging) { x = ((GdkEventMotion*)event)->x; y = ((GdkEventMotion*)event)->y; if (x > ix) { x1 = ix; x2 = ex = x; } else { x1 = ex = x; x2 = ix; } if (y > iy) { y1 = iy; y2 = ey = y; } else { y1 = ey = y; y2 = iy; } gdk_draw_rectangle(widget->window, widget->style->black_gc, FALSE, (gint)x1, (gint)y1, (gint)(x2 - x1), (gint)(y2 - y1)); } break; case GDK_BUTTON_PRESS: dragging = TRUE; ex = ix = ((GdkEventButton*)event)->x; ey = iy = ((GdkEventButton*)event)->y; gdk_display_beep (gdk_screen_get_display (cur_screen2)); break; case GDK_BUTTON_RELEASE: dragging = FALSE; if (ix < ex) { x1 = ix; x2 = ex; } else { x1 = ex; x2 = ix; } if (iy < ey) { y1 = iy; y2 = ey; } else { y1 = ey; y2 = iy; } if (x2-x1 == 0 || y2-y1 == 0) { g_free(buffer); gdk_pixbuf_unref(data); gtk_widget_destroy(widget); return; } subdata = gdk_pixbuf_new_subpixbuf(data, x1, y1, x2-x1, y2-y1); if (subdata != NULL) { gdk_pixbuf_save_to_buffer(subdata, &buffer, &buffer_size, "jpeg", &error, NULL); } if (error){ gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving image: %s"), error->message); g_error_free(error); } id = gaim_imgstore_add(buffer, buffer_size, "test.jpg"); ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml))); gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins); gtk_imhtml_insert_image_at_iter(GTK_IMHTML(toolbar->imhtml), id, &iter); gaim_imgstore_unref(id); gdk_pixbuf_unref(subdata); gdk_pixbuf_unref(data); g_free(buffer); g_free(imgdata); /* Restore video mode and delete the FSImg */ gtk_widget_destroy(widget); break; case GDK_CONFIGURE: case GDK_EXPOSE: break; default: snprintf(errmsg, BUFSIZ, "uncaptured event type = %d", event->type); gaim_notify_error(NULL, NULL, _("Error"), _(errmsg)); break; } return; } static GdkPixbuf * shoot (void) { GdkWindow *window; GdkPixbuf *screenshot; GdkRectangle rect; GdkRectangle screen_rect; gint x, y; GdkScreen *cur_screen = NULL; cur_screen = gdk_screen_get_default (); screen_rect.x = 0; screen_rect.y = 0; screen_rect.width = gdk_screen_get_width (cur_screen); screen_rect.height = gdk_screen_get_height (cur_screen); window = gdk_screen_get_root_window (cur_screen); if (!window) { g_message (_("Specified window not found")); return NULL; } gdk_window_get_origin (window, &x, &y); rect.x = x; rect.y = y; gdk_drawable_get_size (GDK_DRAWABLE (window), &rect.width, &rect.height); if (!gdk_rectangle_intersect (&rect, &screen_rect, &rect)) return NULL; screenshot = gdk_pixbuf_get_from_drawable (NULL, window, NULL, rect.x - x, rect.y - y, 0, 0, rect.width, rect.height); gdk_flush (); if (!screenshot) { g_message (_("Error obtaining Screen Shot")); return NULL; } return screenshot; } void insert_screenshot_cb(GtkWidget *save, GaimConversation *conv) { if (strcmp(gaim_prefs_get_string("/plugins/imageim/auth"), "TRUE") != 0) { gaim_notify_error(NULL, NULL, _("ImageIM Authentication Error"), _("Username and password for ImageIM are invalid. You may adjust these settings in Preferences -> Plugins -> ImageIM.")); return; } GdkPixbuf * screenshot = shoot(); GdkCursor *grab_cursor; GdkScreen * screen = gdk_screen_get_default (); gint screen_width = gdk_screen_get_width(screen); gint screen_height = gdk_screen_get_height(screen); GtkWidget * top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_add_events(GTK_WIDGET(top_window), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); gtk_window_set_decorated(GTK_WINDOW(top_window), FALSE); struct img_event_data *img_data = g_new0(struct img_event_data, 1); img_data->screenshot = screenshot; img_data->conv = conv; g_signal_connect_after( GTK_OBJECT(top_window), "button_press_event", GTK_SIGNAL_FUNC(screenshot_event_cb), img_data ); g_signal_connect_after (GTK_OBJECT (top_window), "expose_event", GTK_SIGNAL_FUNC(screenshot_event_cb), img_data); g_signal_connect_after (GTK_OBJECT (top_window), "configure_event", GTK_SIGNAL_FUNC(screenshot_event_cb), img_data); g_signal_connect_after( GTK_OBJECT(top_window), "button_release_event", GTK_SIGNAL_FUNC(screenshot_event_cb), img_data ); g_signal_connect_after( GTK_OBJECT(top_window), "motion_notify_event", GTK_SIGNAL_FUNC(screenshot_event_cb), img_data ); /* Move and resize the FSImg window to display the image */ gtk_widget_set_uposition(top_window, 0, 0); gtk_widget_set_usize(top_window, screen_width, screen_height); /* Map and raise the FSImg window */ gdk_window_raise(top_window->window); gtk_widget_show(top_window); /* Grab focus and add grab to receive key events */ /* DRAW IMAGE */ grab_cursor = gdk_cursor_new(GDK_CROSSHAIR); gdk_window_set_cursor(top_window->window, grab_cursor); } static void conversation_created_cb(GaimConversation *conv, void *data) { gaim_debug_misc("imageim", "conversation-created (%s)\n", gaim_conversation_get_name(conv)); GaimGtkConversation *gtkconv; GtkWidget *imageimbutton; gtkconv = GAIM_GTK_CONVERSATION(conv); if (gtkconv != NULL) { /* Info button */ imageimbutton = gaim_gtkconv_button_new(GTK_STOCK_SELECT_COLOR, _("ImageIM"), _("Send screenshot to buddy"), gtkconv->tooltips, insert_screenshot_cb, conv); gtk_box_pack_start(GTK_BOX(gtkconv->bbox), imageimbutton, TRUE, TRUE, 0); gtk_size_group_add_widget(gtkconv->sg, imageimbutton); gtk_widget_show(imageimbutton); } } static void deleting_conversation_cb(GaimConversation *conv, void *data) { gaim_debug_misc("imageim", "deleting-conversation (%s)\n", gaim_conversation_get_name(conv)); /* REMOVE IMAGEIM AND DELETE BUTTON */ /*GList *children; GaimGtkConversation *gtkconv; gtkconv = GAIM_GTK_CONVERSATION(conv); */ /* Remove anything else in our parent */ /*children = gtk_container_get_children(GTK_CONTAINER(gtkconv->bbox)); while (children != NULL) { IF child is GTK_BUTTON and is called ImageIM, REMOVE children = g_list_next(children); } */ } /************************************************************************** * Plugin stuff **************************************************************************/ static gboolean plugin_load(GaimPlugin *plugin) { void *conv_handle = gaim_conversations_get_handle(); GString * url = g_string_new(""); g_string_sprintf(url, "http://www.imageim.com/auth.jsp?username=%s&password=%s", gaim_prefs_get_string("/plugins/imageim/username"),gaim_prefs_get_string("/plugins/imageim/password")); gaim_prefs_set_string("/plugins/imageim/auth", "FALSE"); gaim_url_fetch(url->str, FALSE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, imageim_auth_cb, NULL); g_string_free(url, TRUE); /* Conversations subsystem signals */ gaim_signal_connect(conv_handle, "sending-im-msg", plugin, GAIM_CALLBACK(sending_im_msg_cb), NULL); gaim_signal_connect(conv_handle, "receiving-im-msg", plugin, GAIM_CALLBACK(receiving_im_msg_cb), NULL); /* gaim_signal_connect(conv_handle, "sending-chat-msg", plugin, GAIM_CALLBACK(sending_chat_msg_cb), NULL); gaim_signal_connect(conv_handle, "receiving-chat-msg", plugin, GAIM_CALLBACK(receiving_chat_msg_cb), NULL); */ gaim_signal_connect(conv_handle, "conversation-created", plugin, GAIM_CALLBACK(conversation_created_cb), NULL); gaim_signal_connect(conv_handle, "deleting-conversation", plugin, GAIM_CALLBACK(deleting_conversation_cb), NULL); return TRUE; } static GaimPluginInfo info = { GAIM_PLUGIN_MAGIC, GAIM_MAJOR_VERSION, GAIM_MINOR_VERSION, GAIM_PLUGIN_STANDARD, /**< type */ GAIM_GTK_PLUGIN_TYPE, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ GAIM_PRIORITY_DEFAULT, /**< priority */ IMAGE_IM_PLUGIN_ID, /**< id */ N_("ImageIM (tm)"), /**< name */ N_("0.9b"), /**< version */ /** summary */ N_("Sending Screenshots Instantly."), /** description */ N_("This plugin allows one to quickly send a screenshot to a buddy."), N_("Will Gorman "), /**< author */ N_("http://www.imageim.com"), /**< homepage */ plugin_load, /**< load */ NULL, /**< unload */ NULL, /**< destroy */ &ui_info, /**< ui_info */ NULL, /**< extra_info */ NULL, NULL }; static void init_plugin(GaimPlugin *plugin) { gaim_debug_misc("imageim", "init_plugin\n"); gaim_prefs_add_none("/plugins/imageim"); gaim_prefs_add_string("/plugins/imageim/username", ""); gaim_prefs_add_string("/plugins/imageim/password", ""); gaim_prefs_add_string("/plugins/imageim/auth", "FALSE"); } GAIM_INIT_PLUGIN(imageim, init_plugin, info)