comparison src/protocols/sametime/sametime.c @ 12105:d4cd7d443795

[gaim-migrate @ 14402] trying not to fall behind on sametime fixes committer: Tailor Script <tailor@pidgin.im>
author Christopher O'Brien <siege@pidgin.im>
date Tue, 15 Nov 2005 06:06:47 +0000
parents 980c877bd238
children 40724851e95e
comparison
equal deleted inserted replaced
12104:3db14853d9ae 12105:d4cd7d443795
3690 } 3690 }
3691 3691
3692 3692
3693 /** determine content type from extension. Not so happy about this, 3693 /** determine content type from extension. Not so happy about this,
3694 but I don't want to actually write image type detection */ 3694 but I don't want to actually write image type detection */
3695 static const char *im_mime_img_content_type(GaimStoredImage *img) { 3695 static char *im_mime_img_content_type(GaimStoredImage *img) {
3696 const char *fn = gaim_imgstore_get_filename(img); 3696 const char *fn = gaim_imgstore_get_filename(img);
3697 3697 const char *ct = NULL;
3698 fn = strrchr(fn, '.'); 3698
3699 if(! fn) { 3699 ct = strrchr(fn, '.');
3700 return "image"; 3700 if(! ct) {
3701 3701 ct = "image";
3702 } else if(! strcmp(".png", fn)) { 3702
3703 return "image/png"; 3703 } else if(! strcmp(".png", ct)) {
3704 3704 ct = "image/png";
3705 } else if(! strcmp(".jpg", fn)) { 3705
3706 return "image/jpeg"; 3706 } else if(! strcmp(".jpg", ct)) {
3707 3707 ct = "image/jpeg";
3708 } else if(! strcmp(".jpeg", fn)) { 3708
3709 return "image/jpeg"; 3709 } else if(! strcmp(".jpeg", ct)) {
3710 3710 ct = "image/jpeg";
3711 } else if(! strcmp(".gif", fn)) { 3711
3712 return "image/gif"; 3712 } else if(! strcmp(".gif", ct)) {
3713 ct = "image/gif";
3713 3714
3714 } else { 3715 } else {
3715 return "image"; 3716 ct = "image";
3716 } 3717 }
3718
3719 return g_strdup_printf("%s; name=\"%s\"", ct, fn);
3717 } 3720 }
3718 3721
3719 3722
3720 static char *im_mime_img_content_disp(GaimStoredImage *img) { 3723 static char *im_mime_img_content_disp(GaimStoredImage *img) {
3721 const char *fn = gaim_imgstore_get_filename(img); 3724 const char *fn = gaim_imgstore_get_filename(img);
3722 return g_strdup_printf("attachment; filename=\"%s\"", fn); 3725 return g_strdup_printf("attachment; filename=\"%s\"", fn);
3723 } 3726 }
3724 3727
3725 3728
3729 static char *nb_im_encode(GaimConnection *gc, const char *message) {
3730 GaimAccount *acct;
3731 const char *enc;
3732 char *ret;
3733 GError *error = NULL;
3734
3735 acct = gaim_connection_get_account(gc);
3736 g_return_val_if_fail(acct != NULL, NULL);
3737
3738 enc = gaim_account_get_string(acct, MW_KEY_ENCODING,
3739 MW_PLUGIN_DEFAULT_ENCODING);
3740 g_return_val_if_fail(enc != NULL, NULL);
3741
3742 ret = g_convert_with_fallback(message, strlen(message),
3743 enc, "UTF-8", "?",
3744 NULL, NULL, &error);
3745
3746 if(error) {
3747 DEBUG_INFO("problem converting to %s: %s\n",
3748 enc, NSTR(error->message));
3749 g_error_free(error);
3750 }
3751
3752 /* something went so wrong that not even the fallback worked */
3753 if(! ret) ret = g_strdup(message);
3754
3755 return ret;
3756 }
3757
3758
3759 static gboolean is_nb(struct mwConversation *conv) {
3760 struct mwLoginInfo *info;
3761
3762 info = mwConversation_getTargetInfo(conv);
3763 if(! info) return FALSE;
3764
3765 /* NotesBuddy can be at least three different type IDs (all in the
3766 0x1400 range), or it can show up as 0x1002. However, if we're
3767 calling this check, then we're already in HTML or MIME mode, so
3768 we can discount the real 0x1002 */
3769 /* I tried to avoid having any client-type-dependant code in here, I
3770 really did. Oh well. CURSE YOU NOTESBUDDY */
3771 return ((info->type == 0x1002) || ((info->type & 0xff00) == 0x1400));
3772 }
3773
3774
3726 /** turn an IM with embedded images into a multi-part mime document */ 3775 /** turn an IM with embedded images into a multi-part mime document */
3727 static char *im_mime_convert(const char *message) { 3776 static char *im_mime_convert(GaimConnection *gc,
3777 struct mwConversation *conv,
3778 const char *message) {
3728 GString *str; 3779 GString *str;
3729 GaimMimeDocument *doc; 3780 GaimMimeDocument *doc;
3730 GaimMimePart *part; 3781 GaimMimePart *part;
3731 3782
3732 GData *attr; 3783 GData *attr;
3768 3819
3769 data = im_mime_img_content_disp(img); 3820 data = im_mime_img_content_disp(img);
3770 gaim_mime_part_set_field(part, "Content-Disposition", data); 3821 gaim_mime_part_set_field(part, "Content-Disposition", data);
3771 g_free(data); 3822 g_free(data);
3772 3823
3824 data = im_mime_img_content_type(img);
3825 gaim_mime_part_set_field(part, "Content-Type", data);
3826 g_free(data);
3827
3773 cid = im_mime_content_id(); 3828 cid = im_mime_content_id();
3774 data = g_strdup_printf("<%s>", cid); 3829 data = g_strdup_printf("<%s>", cid);
3775 gaim_mime_part_set_field(part, "Content-ID", data); 3830 gaim_mime_part_set_field(part, "Content-ID", data);
3776 g_free(data); 3831 g_free(data);
3777 3832
3778 gaim_mime_part_set_field(part, "Content-transfer-encoding", "base64"); 3833 gaim_mime_part_set_field(part, "Content-transfer-encoding", "base64");
3779 gaim_mime_part_set_field(part, "Content-Type",
3780 im_mime_img_content_type(img));
3781
3782 3834
3783 /* obtain and base64 encode the image data, and put it in the 3835 /* obtain and base64 encode the image data, and put it in the
3784 mime part */ 3836 mime part */
3785 data = gaim_imgstore_get_data(img); 3837 data = gaim_imgstore_get_data(img);
3786 size = gaim_imgstore_get_size(img); 3838 size = gaim_imgstore_get_size(img);
3804 } 3856 }
3805 3857
3806 /* append left-overs */ 3858 /* append left-overs */
3807 g_string_append(str, tmp); 3859 g_string_append(str, tmp);
3808 3860
3861 /* add the text/html part */
3809 part = gaim_mime_part_new(doc); 3862 part = gaim_mime_part_new(doc);
3810 gaim_mime_part_set_field(part, "Content-Type", "text/html");
3811 gaim_mime_part_set_field(part, "Content-Disposition", "inline"); 3863 gaim_mime_part_set_field(part, "Content-Disposition", "inline");
3812 gaim_mime_part_set_field(part, "Content-Transfer-Encoding", "8bit"); 3864
3813 3865 if(is_nb(conv)) {
3814 gaim_mime_part_set_data(part, str->str); 3866 GaimAccount *acct = gaim_connection_get_account(gc);
3867
3868 tmp = (char *) gaim_account_get_string(acct, MW_KEY_ENCODING,
3869 MW_PLUGIN_DEFAULT_ENCODING);
3870 tmp = g_strdup_printf("text/html; charset=\"%s\"", tmp);
3871 gaim_mime_part_set_field(part, "Content-Type", tmp);
3872 g_free(tmp);
3873
3874 gaim_mime_part_set_field(part, "Content-Transfer-Encoding", "7bit");
3875
3876 tmp = nb_im_encode(gc, str->str);
3877 gaim_mime_part_set_data(part, tmp);
3878 g_free(tmp);
3879
3880 } else {
3881 gaim_mime_part_set_field(part, "Content-Type", "text/html");
3882 gaim_mime_part_set_field(part, "Content-Transfer-Encoding", "8bit");
3883 gaim_mime_part_set_data(part, str->str);
3884 }
3885
3815 g_string_free(str, TRUE); 3886 g_string_free(str, TRUE);
3816 3887
3817 str = g_string_new(NULL); 3888 str = g_string_new(NULL);
3818 gaim_mime_document_write(doc, str); 3889 gaim_mime_document_write(doc, str);
3819 tmp = str->str; 3890 tmp = str->str;
3821 3892
3822 return tmp; 3893 return tmp;
3823 } 3894 }
3824 3895
3825 3896
3826 static char *nb_im_encode(GaimConnection *gc, const char *message) {
3827 GaimAccount *acct;
3828 const char *enc;
3829 char *ret;
3830 GError *error = NULL;
3831
3832 acct = gaim_connection_get_account(gc);
3833 g_return_val_if_fail(acct != NULL, NULL);
3834
3835 enc = gaim_account_get_string(acct, MW_KEY_ENCODING,
3836 MW_PLUGIN_DEFAULT_ENCODING);
3837 g_return_val_if_fail(enc != NULL, NULL);
3838
3839 ret = g_convert_with_fallback(message, -1, enc, "UTF-8",
3840 "?", NULL, NULL, &error);
3841 if(error) {
3842 DEBUG_INFO("problem converting to %s: %s\n",
3843 enc, NSTR(error->message));
3844 g_error_free(error);
3845 }
3846 return ret;
3847 }
3848
3849
3850 static gboolean is_nb(struct mwConversation *conv) {
3851 struct mwLoginInfo *info;
3852
3853 info = mwConversation_getTargetInfo(conv);
3854 if(! info) return FALSE;
3855
3856 /* NotesBuddy can be at least three different type IDs (all in the
3857 0x1400 range), or it can show up as 0x1002. However, if we're
3858 calling this check, then we're already in HTML or MIME mode, so
3859 we can discount the real 0x1002 */
3860 /* I tried to avoid having any client-type-dependant code in here, I
3861 really did. Oh well. CURSE YOU NOTESBUDDY */
3862 return ((info->type == 0x1002) || ((info->type & 0xff00) == 0x1400));
3863 }
3864
3865
3866 static int mw_prpl_send_im(GaimConnection *gc, 3897 static int mw_prpl_send_im(GaimConnection *gc,
3867 const char *name, 3898 const char *name,
3868 const char *message, 3899 const char *message,
3869 GaimConvImFlags flags) { 3900 GaimConvImFlags flags) {
3870 3901
3871 struct mwGaimPluginData *pd; 3902 struct mwGaimPluginData *pd;
3872 struct mwIdBlock who = { (char *) name, NULL }; 3903 struct mwIdBlock who = { (char *) name, NULL };
3873 struct mwConversation *conv; 3904 struct mwConversation *conv;
3874 char *msg = NULL;
3875 3905
3876 g_return_val_if_fail(gc != NULL, 0); 3906 g_return_val_if_fail(gc != NULL, 0);
3877 pd = gc->proto_data; 3907 pd = gc->proto_data;
3878 3908
3879 g_return_val_if_fail(pd != NULL, 0); 3909 g_return_val_if_fail(pd != NULL, 0);
3880
3881 msg = g_strdup(message);
3882 3910
3883 conv = mwServiceIm_getConversation(pd->srvc_im, &who); 3911 conv = mwServiceIm_getConversation(pd->srvc_im, &who);
3884 3912
3885 /* this detection of features to determine how to send the message 3913 /* this detection of features to determine how to send the message
3886 (plain, html, or mime) is flawed because the other end of the 3914 (plain, html, or mime) is flawed because the other end of the
3888 existing formatting in an outgoing message innapropriate. The end 3916 existing formatting in an outgoing message innapropriate. The end
3889 result is that it may be possible that the other side of the 3917 result is that it may be possible that the other side of the
3890 conversation will receive a plaintext message with html contents, 3918 conversation will receive a plaintext message with html contents,
3891 which is bad. I'm not sure how to fix this correctly. */ 3919 which is bad. I'm not sure how to fix this correctly. */
3892 3920
3893 if(strstr(msg, "<img ") || strstr(msg, "<IMG ")) 3921 if(strstr(message, "<img ") || strstr(message, "<IMG "))
3894 flags |= GAIM_CONV_IM_IMAGES; 3922 flags |= GAIM_CONV_IM_IMAGES;
3895 3923
3896 if(mwConversation_isOpen(conv)) { 3924 if(mwConversation_isOpen(conv)) {
3897 char *tmp; 3925 char *tmp;
3898 int ret; 3926 int ret;
3899 3927
3900 if((flags & GAIM_CONV_IM_IMAGES) && 3928 if((flags & GAIM_CONV_IM_IMAGES) &&
3901 mwConversation_supports(conv, mwImSend_MIME)) { 3929 mwConversation_supports(conv, mwImSend_MIME)) {
3902 /* send a MIME message */ 3930 /* send a MIME message */
3903 3931
3904 /* mime messages need the notesbuddy hack */ 3932 tmp = im_mime_convert(gc, conv, message);
3905 if(is_nb(conv)) {
3906 g_free(msg);
3907 msg = nb_im_encode(gc, message);
3908 }
3909
3910 tmp = im_mime_convert(msg);
3911 g_free(msg);
3912
3913 ret = mwConversation_send(conv, mwImSend_MIME, tmp); 3933 ret = mwConversation_send(conv, mwImSend_MIME, tmp);
3914 g_free(tmp); 3934 g_free(tmp);
3915 3935
3916 } else if(mwConversation_supports(conv, mwImSend_HTML)) { 3936 } else if(mwConversation_supports(conv, mwImSend_HTML)) {
3917 /* send an HTML message */ 3937 /* send an HTML message */
3918 3938
3919 /* html messages need the notesbuddy hack */ 3939 /* need to do this to get the \n to <br> conversion */
3920 if(is_nb(conv)) { 3940 if(is_nb(conv)) {
3941
3942 /* html messages need the notesbuddy hack */
3943 char *msg = nb_im_encode(gc, message);
3944 tmp = gaim_strdup_withhtml(msg);
3921 g_free(msg); 3945 g_free(msg);
3922 msg = nb_im_encode(gc, message); 3946
3947 } else {
3948 tmp = gaim_strdup_withhtml(message);
3923 } 3949 }
3924
3925 /* need to do this to get the \n to <br> conversion */
3926 tmp = gaim_strdup_withhtml(msg);
3927 g_free(msg);
3928 3950
3929 ret = mwConversation_send(conv, mwImSend_HTML, tmp); 3951 ret = mwConversation_send(conv, mwImSend_HTML, tmp);
3930 g_free(tmp); 3952 g_free(tmp);
3931 3953
3932 } else { 3954 } else {
3933 /* default to text */ 3955 /* default to text */
3934 ret = mwConversation_send(conv, mwImSend_PLAIN, msg); 3956 ret = mwConversation_send(conv, mwImSend_PLAIN, message);
3935 g_free(msg);
3936 } 3957 }
3937 3958
3938 return !ret; 3959 return !ret;
3939 3960
3940 } else { 3961 } else {
3941 3962
3942 /* queue up the message safely as plain text */ 3963 /* queue up the message safely as plain text */
3943 char *tmp = gaim_markup_strip_html(msg); 3964 char *tmp = gaim_markup_strip_html(message);
3944 g_free(msg);
3945
3946 convo_queue(conv, mwImSend_PLAIN, tmp); 3965 convo_queue(conv, mwImSend_PLAIN, tmp);
3947 g_free(tmp); 3966 g_free(tmp);
3948 3967
3949 if(! mwConversation_isPending(conv)) 3968 if(! mwConversation_isPending(conv))
3950 mwConversation_open(conv); 3969 mwConversation_open(conv);
4074 g_return_if_fail(acct != NULL); 4093 g_return_if_fail(acct != NULL);
4075 gc = gaim_account_get_connection(acct); 4094 gc = gaim_account_get_connection(acct);
4076 4095
4077 state = gaim_status_get_id(status); 4096 state = gaim_status_get_id(status);
4078 4097
4079 gaim_debug_info("meanwhile", "Set status to %s\n", 4098 DEBUG_INFO("Set status to %s\n", gaim_status_get_name(status));
4080 gaim_status_get_name(status));
4081 4099
4082 g_return_if_fail(gc != NULL); 4100 g_return_if_fail(gc != NULL);
4083 4101
4084 session = gc_to_session(gc); 4102 session = gc_to_session(gc);
4085 g_return_if_fail(session != NULL); 4103 g_return_if_fail(session != NULL);
4097 } else if(! strcmp(state, MW_STATE_BUSY)) { 4115 } else if(! strcmp(state, MW_STATE_BUSY)) {
4098 stat.status = mwStatus_BUSY; 4116 stat.status = mwStatus_BUSY;
4099 } 4117 }
4100 4118
4101 /* determine the message */ 4119 /* determine the message */
4102 switch(stat.status) { 4120 message = (char *) gaim_status_get_attr_string(status, MW_STATE_MESSAGE);
4103 case mwStatus_ACTIVE:
4104 stat.time = 0;
4105 case mwStatus_AWAY:
4106 case mwStatus_BUSY:
4107 message = (char *)gaim_status_get_attr_string(status, MW_STATE_MESSAGE);
4108 break;
4109 }
4110 4121
4111 if(message) { 4122 if(message) {
4112 /* all the possible non-NULL values of message up to this point 4123 /* all the possible non-NULL values of message up to this point
4113 are const, so we don't need to free them */ 4124 are const, so we don't need to free them */
4114 message = gaim_markup_strip_html(message); 4125 message = gaim_markup_strip_html(message);
4126 4137
4127 4138
4128 static void mw_prpl_set_idle(GaimConnection *gc, int t) { 4139 static void mw_prpl_set_idle(GaimConnection *gc, int t) {
4129 struct mwSession *session; 4140 struct mwSession *session;
4130 struct mwUserStatus stat; 4141 struct mwUserStatus stat;
4131 4142
4143
4132 session = gc_to_session(gc); 4144 session = gc_to_session(gc);
4133 g_return_if_fail(session != NULL); 4145 g_return_if_fail(session != NULL);
4134 4146
4135 mwUserStatus_clone(&stat, mwSession_getUserStatus(session)); 4147 mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
4136 4148
4137 if(t > 0 && stat.status == mwStatus_ACTIVE) { 4149 if(t) {
4138 time_t now = time(NULL); 4150 time_t now = time(NULL);
4139 stat.time = now - t; 4151 stat.time = now - t;
4152
4153 } else {
4154 stat.time = 0;
4155 }
4156
4157 if(t > 0 && stat.status == mwStatus_ACTIVE) {
4158 /* we were active and went idle, so change the status to IDLE. */
4140 stat.status = mwStatus_IDLE; 4159 stat.status = mwStatus_IDLE;
4141 4160
4142 } else if(t == 0 && stat.status == mwStatus_IDLE) { 4161 } else if(t == 0 && stat.status == mwStatus_IDLE) {
4143 stat.time = 0; 4162 /* we only become idle automatically, so change back to ACTIVE */
4144 stat.status = mwStatus_ACTIVE; 4163 stat.status = mwStatus_ACTIVE;
4145 } 4164 }
4146 4165
4147 mwSession_setUserStatus(session, &stat); 4166 mwSession_setUserStatus(session, &stat);
4148 mwUserStatus_clear(&stat); 4167 mwUserStatus_clear(&stat);
4149 } 4168 }
4150 4169
4151 4170