Mercurial > pidgin
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 |
