Mon, 24 Jun 2013 01:38:51 +0530
Refactored novell and oscar protocols to use GObject conversation API
| 13593 | 1 | /* |
| 15884 | 2 | * Purple's oscar protocol plugin |
| 13593 | 3 | * This file is the legal property of its developers. |
| 4 | * Please see the AUTHORS file distributed alongside this file. | |
| 5 | * | |
| 6 | * This library is free software; you can redistribute it and/or | |
| 7 | * modify it under the terms of the GNU Lesser General Public | |
| 8 | * License as published by the Free Software Foundation; either | |
| 9 | * version 2 of the License, or (at your option) any later version. | |
| 10 | * | |
| 11 | * This library is distributed in the hope that it will be useful, | |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | * Lesser General Public License for more details. | |
| 15 | * | |
| 16 | * You should have received a copy of the GNU Lesser General Public | |
| 17 | * License along with this library; if not, write to the Free Software | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
18552
diff
changeset
|
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 13593 | 19 | */ |
| 20 | ||
| 21 | /* From the oscar PRPL */ | |
|
30656
846b66ef678b
Moved encoding-related functions to a separate file, renamed some of them,
Ivan Komarov <ivan.komarov@pidgin.im>
parents:
28944
diff
changeset
|
22 | #include "encoding.h" |
| 13593 | 23 | #include "oscar.h" |
| 24 | #include "peer.h" | |
| 25 | ||
| 15884 | 26 | /* From Purple */ |
| 13593 | 27 | #include "conversation.h" |
| 28 | #include "imgstore.h" | |
| 29 | #include "util.h" | |
| 30 | ||
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
31 | #define DIRECTIM_MAX_FILESIZE 52428800 |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
32 | |
| 13593 | 33 | /** |
| 34 | * Free any ODC related data and print a message to the conversation | |
| 35 | * window based on conn->disconnect_reason. | |
| 36 | */ | |
| 37 | void | |
| 38 | peer_odc_close(PeerConnection *conn) | |
| 39 | { | |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
40 | gchar *tmp; |
| 13593 | 41 | |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
42 | if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED) |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
43 | tmp = g_strdup(_("The remote user has closed the connection.")); |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
44 | else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED) |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
45 | tmp = g_strdup(_("The remote user has declined your request.")); |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
46 | else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION) |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
47 | tmp = g_strdup_printf(_("Lost connection with the remote user:<br>%s"), |
|
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
48 | conn->error_message); |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
49 | else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA) |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
50 | tmp = g_strdup(_("Received invalid data on connection with remote user.")); |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
51 | else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT) |
|
27635
0cd19038c417
More uniformity among disconnect error messages
Mark Doliner <markdoliner@pidgin.im>
parents:
25889
diff
changeset
|
52 | tmp = g_strdup(_("Unable to establish a connection with the remote user.")); |
| 13593 | 53 | else |
| 54 | /* | |
| 55 | * We shouldn't print a message for some disconnect_reasons. | |
|
13609
a6fbfad454b6
[gaim-migrate @ 15994]
Mark Doliner <markdoliner@pidgin.im>
parents:
13601
diff
changeset
|
56 | * Like OSCAR_DISCONNECT_LOCAL_CLOSED. |
| 13593 | 57 | */ |
| 58 | tmp = NULL; | |
| 59 | ||
| 60 | if (tmp != NULL) | |
| 61 | { | |
| 15884 | 62 | PurpleAccount *account; |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
63 | PurpleIMConversation *im; |
| 13593 | 64 | |
| 15884 | 65 | account = purple_connection_get_account(conn->od->gc); |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
66 | im = purple_im_conversation_new(account, conn->bn); |
|
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
67 | purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, |
|
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
68 | PURPLE_MESSAGE_SYSTEM, time(NULL)); |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
69 | g_free(tmp); |
| 13593 | 70 | } |
| 71 | ||
| 72 | if (conn->frame != NULL) | |
| 73 | { | |
| 74 | OdcFrame *frame; | |
| 75 | frame = conn->frame; | |
| 76 | g_free(frame->payload.data); | |
| 77 | g_free(frame); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | /** | |
| 82 | * Write the given OdcFrame to a ByteStream and send it out | |
| 83 | * on the established PeerConnection. | |
| 84 | */ | |
| 85 | static void | |
| 86 | peer_odc_send(PeerConnection *conn, OdcFrame *frame) | |
| 87 | { | |
| 15884 | 88 | PurpleAccount *account; |
| 13593 | 89 | const char *username; |
| 90 | size_t length; | |
| 91 | ByteStream bs; | |
| 92 | ||
| 15884 | 93 | purple_debug_info("oscar", "Outgoing ODC frame to %s with " |
|
30689
d7ebbdb28650
Change the "length of bstream" data type to be a gsize, since it represents
Mark Doliner <markdoliner@pidgin.im>
parents:
30666
diff
changeset
|
94 | "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n", |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
95 | conn->bn, frame->type, frame->flags, frame->payload.len); |
| 13593 | 96 | |
| 15884 | 97 | account = purple_connection_get_account(conn->od->gc); |
| 98 | username = purple_account_get_username(account); | |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
99 | memcpy(frame->bn, username, strlen(username)); |
| 13593 | 100 | memcpy(frame->cookie, conn->cookie, 8); |
| 101 | ||
| 102 | length = 76; | |
|
15151
bb985812fefa
[gaim-migrate @ 17875]
Mark Doliner <markdoliner@pidgin.im>
parents:
14464
diff
changeset
|
103 | byte_stream_new(&bs, length + frame->payload.len); |
| 13593 | 104 | byte_stream_putraw(&bs, conn->magic, 4); |
| 105 | byte_stream_put16(&bs, length); | |
| 106 | byte_stream_put16(&bs, frame->type); | |
| 107 | byte_stream_put16(&bs, frame->subtype); | |
| 108 | byte_stream_put16(&bs, 0x0000); | |
| 109 | byte_stream_putraw(&bs, frame->cookie, 8); | |
| 110 | byte_stream_put16(&bs, 0x0000); | |
| 111 | byte_stream_put16(&bs, 0x0000); | |
| 112 | byte_stream_put16(&bs, 0x0000); | |
| 113 | byte_stream_put16(&bs, 0x0000); | |
| 114 | byte_stream_put32(&bs, frame->payload.len); | |
| 115 | byte_stream_put16(&bs, frame->encoding); | |
|
31294
73607ab89c6f
Remove trailing whitespace
Richard Laager <rlaager@pidgin.im>
parents:
30689
diff
changeset
|
116 | byte_stream_put16(&bs, 0x0000); |
| 13593 | 117 | byte_stream_put16(&bs, 0x0000); |
| 118 | byte_stream_put16(&bs, frame->flags); | |
| 119 | byte_stream_put16(&bs, 0x0000); | |
| 120 | byte_stream_put16(&bs, 0x0000); | |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
121 | byte_stream_putraw(&bs, frame->bn, 32); |
| 13593 | 122 | byte_stream_putraw(&bs, frame->payload.data, frame->payload.len); |
| 123 | ||
| 124 | peer_connection_send(conn, &bs); | |
| 125 | ||
|
22862
24f8ae1208ca
Fixed the final stragglers in need of byte_stream_destroy()
Evan Schoenberg <evands@pidgin.im>
parents:
21389
diff
changeset
|
126 | byte_stream_destroy(&bs); |
| 13593 | 127 | } |
| 128 | ||
| 129 | /** | |
| 130 | * Send a very basic ODC frame (which contains the cookie) so that the | |
| 131 | * remote user can verify that we are the person they were expecting. | |
| 132 | * If we made an outgoing connection to then remote user, then we send | |
| 133 | * this immediately. If the remote user connected to us, then we wait | |
| 134 | * for the other person to send this to us, then we send one to them. | |
| 135 | */ | |
| 136 | void | |
| 137 | peer_odc_send_cookie(PeerConnection *conn) | |
| 138 | { | |
| 139 | OdcFrame frame; | |
| 140 | ||
| 141 | memset(&frame, 0, sizeof(OdcFrame)); | |
| 142 | frame.type = 0x0001; | |
| 143 | frame.subtype = 0x0006; | |
| 144 | frame.flags = 0x0060; /* Maybe this means "we're sending the cookie"? */ | |
| 145 | ||
| 146 | peer_odc_send(conn, &frame); | |
| 147 | } | |
| 148 | ||
| 149 | /** | |
| 150 | * Send client-to-client typing notification over an established direct connection. | |
| 151 | */ | |
| 152 | void | |
|
34622
753f46dd000f
Global replace - renamed functions and types according to GObject-based PurpleConversation API
Ankit Vani <a@nevitus.org>
parents:
33768
diff
changeset
|
153 | peer_odc_send_typing(PeerConnection *conn, PurpleIMConversationTypingState typing) |
| 13593 | 154 | { |
| 155 | OdcFrame frame; | |
| 156 | ||
| 157 | memset(&frame, 0, sizeof(OdcFrame)); | |
| 158 | frame.type = 0x0001; | |
| 159 | frame.subtype = 0x0006; | |
|
34622
753f46dd000f
Global replace - renamed functions and types according to GObject-based PurpleConversation API
Ankit Vani <a@nevitus.org>
parents:
33768
diff
changeset
|
160 | if (typing == PURPLE_IM_CONVERSATION_TYPING) |
| 13593 | 161 | frame.flags = 0x0002 | 0x0008; |
|
34622
753f46dd000f
Global replace - renamed functions and types according to GObject-based PurpleConversation API
Ankit Vani <a@nevitus.org>
parents:
33768
diff
changeset
|
162 | else if (typing == PURPLE_IM_CONVERSATION_TYPED) |
| 13593 | 163 | frame.flags = 0x0002 | 0x0004; |
| 164 | else | |
| 165 | frame.flags = 0x0002; | |
| 166 | ||
| 167 | peer_odc_send(conn, &frame); | |
| 168 | } | |
| 169 | ||
| 170 | /** | |
| 171 | * Send client-to-client IM over an established direct connection. | |
| 172 | * To send a direct IM, call this just like you would aim_send_im. | |
| 173 | * | |
| 174 | * @param conn The already-connected ODC connection. | |
| 175 | * @param msg Null-terminated string to send. | |
| 176 | * @param len The length of the message to send, including binary data. | |
| 177 | * @param encoding See the AIM_CHARSET_* defines in oscar.h | |
| 178 | * @param autoreply TRUE if this is any auto-reply. | |
| 179 | */ | |
| 180 | void | |
| 181 | peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply) | |
| 182 | { | |
| 183 | OdcFrame frame; | |
| 184 | ||
| 185 | g_return_if_fail(msg != NULL); | |
| 186 | g_return_if_fail(len > 0); | |
| 187 | ||
| 188 | memset(&frame, 0, sizeof(OdcFrame)); | |
| 189 | frame.type = 0x0001; | |
| 190 | frame.subtype = 0x0006; | |
| 191 | frame.payload.len = len; | |
| 192 | frame.encoding = encoding; | |
| 193 | frame.flags = autoreply; | |
|
15151
bb985812fefa
[gaim-migrate @ 17875]
Mark Doliner <markdoliner@pidgin.im>
parents:
14464
diff
changeset
|
194 | byte_stream_new(&frame.payload, len); |
| 13593 | 195 | byte_stream_putraw(&frame.payload, (guint8 *)msg, len); |
| 196 | ||
| 197 | peer_odc_send(conn, &frame); | |
| 198 | ||
| 199 | g_free(frame.payload.data); | |
| 200 | } | |
| 201 | ||
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
202 | struct embedded_data |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
203 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
204 | size_t size; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
205 | const guint8 *data; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
206 | }; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
207 | |
| 13593 | 208 | /** |
| 209 | * This is called after a direct IM has been received in its entirety. This | |
| 210 | * function is passed a long chunk of data which contains the IM with any | |
| 211 | * data chunks (images) appended to it. | |
| 212 | * | |
| 213 | * This function rips out all the data chunks and creates an imgstore for | |
| 214 | * each one. In order to do this, it first goes through the IM and takes | |
| 215 | * out all the IMG tags. When doing so, it rewrites the original IMG tag | |
| 15884 | 216 | * with one compatible with the imgstore Purple core code. For each one, we |
| 13593 | 217 | * then read in chunks of data from the end of the message and actually |
| 218 | * create the img store using the given data. | |
| 219 | * | |
| 220 | * For somewhat easy reference, here's a sample message | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
221 | * (with added whitespace): |
| 13593 | 222 | * |
| 223 | * <HTML><BODY BGCOLOR="#ffffff"> | |
| 224 | * <FONT LANG="0"> | |
| 225 | * This is a really stupid picture:<BR> | |
| 226 | * <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR> | |
| 227 | * Yeah it is<BR> | |
| 228 | * Here is another one:<BR> | |
| 229 | * <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978"> | |
| 230 | * </FONT> | |
| 231 | * </BODY></HTML> | |
| 232 | * <BINARY> | |
| 233 | * <DATA ID="1" SIZE="9894">datadatadatadata</DATA> | |
| 234 | * <DATA ID="2" SIZE="65978">datadatadatadata</DATA> | |
| 235 | * </BINARY> | |
| 236 | */ | |
| 237 | static void | |
| 238 | peer_odc_handle_payload(PeerConnection *conn, const char *msg, size_t len, int encoding, gboolean autoreply) | |
| 239 | { | |
| 15884 | 240 | PurpleConnection *gc; |
| 241 | PurpleAccount *account; | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
242 | const char *msgend, *binary_start, *dataend; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
243 | const char *tmp, *start, *end, *idstr, *src, *sizestr; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
244 | GData *attributes; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
245 | GHashTable *embedded_datas; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
246 | struct embedded_data *embedded_data; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
247 | GSList *images; |
| 13593 | 248 | gchar *utf8; |
| 249 | GString *newmsg; | |
| 15884 | 250 | PurpleMessageFlags imflags; |
| 13593 | 251 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
252 | gc = conn->od->gc; |
| 15884 | 253 | account = purple_connection_get_account(gc); |
| 13593 | 254 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
255 | dataend = msg + len; |
| 13593 | 256 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
257 | /* |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
258 | * Create a hash table containing references to each embedded |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
259 | * data chunk. The key is the "ID" and the value is an |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
260 | * embedded_data struct. |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
261 | */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
262 | embedded_datas = g_hash_table_new_full(g_direct_hash, |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
263 | g_direct_equal, NULL, g_free); |
| 13593 | 264 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
265 | /* |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
266 | * Create an index of any binary chunks. If we run into any |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
267 | * problems while parsing the binary data section then we stop |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
268 | * parsing it, and the local user will see broken image icons. |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
269 | */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
270 | /* TODO: Use a length argument when looking for the <binary> tag! */ |
| 15884 | 271 | binary_start = purple_strcasestr(msg, "<binary>"); |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
272 | if (binary_start == NULL) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
273 | msgend = dataend; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
274 | else |
| 13593 | 275 | { |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
276 | msgend = binary_start; |
| 13593 | 277 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
278 | /* Move our pointer to immediately after the <binary> tag */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
279 | tmp = binary_start + 8; |
| 13593 | 280 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
281 | /* The embedded binary markup has a mimimum length of 29 bytes */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
282 | /* TODO: Use a length argument when looking for the <data> tag! */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
283 | while ((tmp + 29 <= dataend) && |
| 15884 | 284 | purple_markup_find_tag("data", tmp, &start, &tmp, &attributes)) |
| 13593 | 285 | { |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
286 | unsigned int id; |
| 13593 | 287 | size_t size; |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
288 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
289 | /* Move the binary pointer from ">" to the start of the data */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
290 | tmp++; |
| 13593 | 291 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
292 | /* Get the ID */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
293 | idstr = g_datalist_get_data(&attributes, "id"); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
294 | if (idstr == NULL) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
295 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
296 | g_datalist_clear(&attributes); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
297 | break; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
298 | } |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
299 | id = atoi(idstr); |
| 13593 | 300 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
301 | /* Get the size */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
302 | sizestr = g_datalist_get_data(&attributes, "size"); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
303 | if (sizestr == NULL) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
304 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
305 | g_datalist_clear(&attributes); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
306 | break; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
307 | } |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
308 | size = atol(sizestr); |
| 13593 | 309 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
310 | g_datalist_clear(&attributes); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
311 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
312 | if ((size > 0) && (tmp + size > dataend)) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
313 | break; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
314 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
315 | embedded_data = g_new(struct embedded_data, 1); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
316 | embedded_data->size = size; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
317 | embedded_data->data = (const guint8 *)tmp; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
318 | tmp += size; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
319 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
320 | /* Skip past the closing </data> tag */ |
|
18552
810a338ef085
Use the glib strcasecmp functions everywhere, as we've had reports of
Richard Laager <rlaager@pidgin.im>
parents:
17539
diff
changeset
|
321 | if (g_ascii_strncasecmp(tmp, "</data>", 7)) |
|
13600
4f436279a21c
[gaim-migrate @ 15985]
Mark Doliner <markdoliner@pidgin.im>
parents:
13593
diff
changeset
|
322 | { |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
323 | g_free(embedded_data); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
324 | break; |
|
13600
4f436279a21c
[gaim-migrate @ 15985]
Mark Doliner <markdoliner@pidgin.im>
parents:
13593
diff
changeset
|
325 | } |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
326 | tmp += 7; |
| 13593 | 327 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
328 | g_hash_table_insert(embedded_datas, |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
329 | GINT_TO_POINTER(id), embedded_data); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
330 | } |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
331 | } |
| 13593 | 332 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
333 | /* |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
334 | * Loop through the message, replacing OSCAR img tags with the |
| 15884 | 335 | * equivalent Purple img tag. |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
336 | */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
337 | images = NULL; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
338 | newmsg = g_string_new(""); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
339 | tmp = msg; |
| 15884 | 340 | while (purple_markup_find_tag("img", tmp, &start, &end, &attributes)) |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
341 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
342 | int imgid = 0; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
343 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
344 | idstr = g_datalist_get_data(&attributes, "id"); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
345 | src = g_datalist_get_data(&attributes, "src"); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
346 | sizestr = g_datalist_get_data(&attributes, "datasize"); |
| 13593 | 347 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
348 | if ((idstr != NULL) && (src != NULL) && (sizestr!= NULL)) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
349 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
350 | unsigned int id; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
351 | size_t size; |
| 13593 | 352 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
353 | id = atoi(idstr); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
354 | size = atol(sizestr); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
355 | embedded_data = g_hash_table_lookup(embedded_datas, |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
356 | GINT_TO_POINTER(id)); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
357 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
358 | if ((embedded_data != NULL) && (embedded_data->size == size)) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
359 | { |
|
33768
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
360 | char *basename; |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
361 | char *escaped; |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
362 | basename = g_path_get_basename(src); |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
363 | escaped = g_strdup(purple_escape_filename(basename)); |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
364 | g_free(basename); |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
365 | imgid = purple_imgstore_new_with_id(g_memdup(embedded_data->data, size), size, escaped); |
|
20d5c960d48f
Use an escaped basename as the filename for incoming IM images
Mark Doliner <mark@kingant.net>
parents:
33661
diff
changeset
|
366 | g_free(escaped); |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
367 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
368 | /* Record the image number */ |
| 13593 | 369 | images = g_slist_append(images, GINT_TO_POINTER(imgid)); |
| 370 | } | |
| 371 | } | |
| 372 | ||
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
373 | /* Delete the attribute list */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
374 | g_datalist_clear(&attributes); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
375 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
376 | /* Append the message up to the tag */ |
|
30666
ff138d6c7bc4
Got rid of receiving multipart messages over channel 1, which simplified the code
Ivan Komarov <ivan.komarov@pidgin.im>
parents:
30656
diff
changeset
|
377 | utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, start - tmp); |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
378 | if (utf8 != NULL) { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
379 | g_string_append(newmsg, utf8); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
380 | g_free(utf8); |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
381 | } |
| 13593 | 382 | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
383 | if (imgid != 0) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
384 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
385 | /* Write the new image tag */ |
|
33052
df92c3d93904
From now on, prpls must specify images using SRC instead of ID.
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
31294
diff
changeset
|
386 | g_string_append_printf(newmsg, |
|
df92c3d93904
From now on, prpls must specify images using SRC instead of ID.
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
31294
diff
changeset
|
387 | "<IMG SRC=\"" PURPLE_STORED_IMAGE_PROTOCOL "%d\">", |
|
df92c3d93904
From now on, prpls must specify images using SRC instead of ID.
Elliott Sales de Andrade <qulogic@pidgin.im>
parents:
31294
diff
changeset
|
388 | imgid); |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
389 | } |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
390 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
391 | /* Continue from the end of the tag */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
392 | tmp = end + 1; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
393 | } |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
394 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
395 | /* Append any remaining message data */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
396 | if (tmp <= msgend) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
397 | { |
|
30666
ff138d6c7bc4
Got rid of receiving multipart messages over channel 1, which simplified the code
Ivan Komarov <ivan.komarov@pidgin.im>
parents:
30656
diff
changeset
|
398 | utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, msgend - tmp); |
| 13593 | 399 | if (utf8 != NULL) { |
| 400 | g_string_append(newmsg, utf8); | |
| 401 | g_free(utf8); | |
| 402 | } | |
| 403 | } | |
| 404 | ||
|
25426
71bd2a5b4eab
Fixed an errant comment
Evan Schoenberg <evands@pidgin.im>
parents:
25296
diff
changeset
|
405 | /* Display the message we received */ |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
406 | imflags = 0; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
407 | if (images != NULL) |
| 15884 | 408 | imflags |= PURPLE_MESSAGE_IMAGES; |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
409 | if (autoreply) |
| 15884 | 410 | imflags |= PURPLE_MESSAGE_AUTO_RESP; |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
411 | serv_got_im(gc, conn->bn, newmsg->str, imflags, time(NULL)); |
| 13593 | 412 | g_string_free(newmsg, TRUE); |
| 413 | ||
| 414 | /* unref any images we allocated */ | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
415 | if (images) |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
416 | { |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
417 | GSList *l; |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
418 | for (l = images; l != NULL; l = l->next) |
|
16437
7ff7c3405ea2
Rework the buddy icon subsystem to use the imgstore subsystem, and modify the
Richard Laager <rlaager@pidgin.im>
parents:
15884
diff
changeset
|
419 | purple_imgstore_unref_by_id(GPOINTER_TO_INT(l->data)); |
| 13593 | 420 | g_slist_free(images); |
| 421 | } | |
|
13601
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
422 | |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
423 | /* Delete our list of pointers to embedded images */ |
|
d22aea27e7e6
[gaim-migrate @ 15986]
Mark Doliner <markdoliner@pidgin.im>
parents:
13600
diff
changeset
|
424 | g_hash_table_destroy(embedded_datas); |
| 13593 | 425 | } |
| 426 | ||
| 427 | /** | |
| 15884 | 428 | * This is a purple_input_add() watcher callback function for reading |
| 13593 | 429 | * direct IM payload data. "Payload data" is always an IM and |
| 430 | * maybe some embedded images or files or something. The actual | |
| 431 | * ODC frame is read using peer_connection_recv_cb(). We temporarily | |
| 432 | * switch to this watcher callback ONLY to read the payload, and we | |
| 433 | * switch back once we're done. | |
| 434 | */ | |
| 435 | static void | |
| 15884 | 436 | peer_odc_recv_cb(gpointer data, gint source, PurpleInputCondition cond) |
| 13593 | 437 | { |
| 438 | PeerConnection *conn; | |
| 439 | OdcFrame *frame; | |
| 440 | ByteStream *bs; | |
|
23079
b887906eed60
More s/ssize_t/gssize/
Daniel Atallah <datallah@pidgin.im>
parents:
22862
diff
changeset
|
441 | gssize read; |
| 13593 | 442 | |
| 443 | conn = data; | |
| 444 | frame = conn->frame; | |
| 445 | bs = &frame->payload; | |
| 446 | ||
| 447 | /* Read data into the temporary buffer until it is complete */ | |
| 448 | read = recv(conn->fd, | |
| 449 | &bs->data[bs->offset], | |
| 450 | bs->len - bs->offset, | |
| 451 | 0); | |
| 452 | ||
| 453 | /* Check if the remote user closed the connection */ | |
| 454 | if (read == 0) | |
| 455 | { | |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
456 | peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL); |
| 13593 | 457 | return; |
| 458 | } | |
| 459 | ||
|
17539
0fd875385856
Only check for EAGAIN if send returns -1, not when it returns 0
Mark Doliner <markdoliner@pidgin.im>
parents:
16539
diff
changeset
|
460 | if (read < 0) |
| 13593 | 461 | { |
| 462 | if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | |
| 463 | /* No worries */ | |
| 464 | return; | |
| 465 | ||
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
466 | peer_connection_destroy(conn, |
|
21389
e1dd8142bb87
replace most calls to strerror with calls to g_strerror. strerror will return
Nathan Walp <nwalp@pidgin.im>
parents:
20192
diff
changeset
|
467 | OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno)); |
| 13593 | 468 | return; |
| 469 | } | |
| 470 | ||
| 471 | bs->offset += read; | |
| 472 | if (bs->offset < bs->len) | |
| 473 | /* Waiting for more data to arrive */ | |
| 474 | return; | |
| 475 | ||
| 476 | /* We have a complete ODC/OFT frame! Handle it and continue reading */ | |
| 477 | byte_stream_rewind(bs); | |
| 478 | peer_odc_handle_payload(conn, (const char *)bs->data, | |
| 479 | bs->len, frame->encoding, frame->flags & 0x0001); | |
| 480 | g_free(bs->data); | |
| 481 | bs->data = NULL; | |
| 482 | g_free(frame); | |
| 483 | conn->frame = NULL; | |
| 484 | ||
| 15884 | 485 | purple_input_remove(conn->watcher_incoming); |
| 486 | conn->watcher_incoming = purple_input_add(conn->fd, | |
| 487 | PURPLE_INPUT_READ, peer_connection_recv_cb, conn); | |
| 13593 | 488 | } |
| 489 | ||
| 490 | /** | |
| 491 | * Handle an incoming OdcFrame. If there is a payload associated | |
| 492 | * with this frame, then we remove the old watcher and add the | |
| 493 | * ODC watcher to read in the payload. | |
| 494 | */ | |
| 495 | void | |
| 496 | peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs) | |
| 497 | { | |
| 15884 | 498 | PurpleConnection *gc; |
| 13593 | 499 | OdcFrame *frame; |
| 500 | ||
| 501 | gc = conn->od->gc; | |
| 502 | ||
| 503 | frame = g_new0(OdcFrame, 1); | |
| 504 | frame->type = byte_stream_get16(bs); | |
| 505 | frame->subtype = byte_stream_get16(bs); | |
| 506 | byte_stream_advance(bs, 2); | |
| 507 | byte_stream_getrawbuf(bs, frame->cookie, 8); | |
| 508 | byte_stream_advance(bs, 8); | |
| 509 | frame->payload.len = byte_stream_get32(bs); | |
| 510 | frame->encoding = byte_stream_get16(bs); | |
| 511 | byte_stream_advance(bs, 4); | |
| 512 | frame->flags = byte_stream_get16(bs); | |
| 513 | byte_stream_advance(bs, 4); | |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
514 | byte_stream_getrawbuf(bs, frame->bn, 32); |
| 13593 | 515 | |
| 15884 | 516 | purple_debug_info("oscar", "Incoming ODC frame from %s with " |
|
30689
d7ebbdb28650
Change the "length of bstream" data type to be a gsize, since it represents
Mark Doliner <markdoliner@pidgin.im>
parents:
30666
diff
changeset
|
517 | "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n", |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
518 | frame->bn, frame->type, frame->flags, frame->payload.len); |
| 13593 | 519 | |
| 520 | if (!conn->ready) | |
| 521 | { | |
| 522 | /* | |
| 523 | * We need to verify the cookie so that we know we are | |
| 524 | * connected to our friend and not a malicious middle man. | |
| 525 | */ | |
| 526 | ||
| 15884 | 527 | PurpleAccount *account; |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
528 | PurpleIMConversation *im; |
| 13593 | 529 | |
| 530 | if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING) | |
| 531 | { | |
| 532 | if (memcmp(conn->cookie, frame->cookie, 8)) | |
| 533 | { | |
| 534 | /* | |
| 535 | * Oh no! The user that connected to us did not send | |
| 536 | * the correct cookie! They are not our friend. Go try | |
| 537 | * to accept another connection? | |
| 538 | */ | |
| 15884 | 539 | purple_debug_info("oscar", "Received an incorrect cookie. " |
| 13593 | 540 | "Closing connection.\n"); |
|
14464
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
541 | peer_connection_destroy(conn, |
|
b7bca43f75b3
[gaim-migrate @ 17110]
Mark Doliner <markdoliner@pidgin.im>
parents:
14254
diff
changeset
|
542 | OSCAR_DISCONNECT_INVALID_DATA, NULL); |
| 13593 | 543 | g_free(frame); |
| 544 | return; | |
| 545 | } | |
| 546 | ||
| 547 | /* | |
| 548 | * Ok, we know they are legit. Now be courteous and | |
| 549 | * send them our cookie. Note: This doesn't seem | |
| 550 | * to be necessary, but it also doesn't seem to hurt. | |
| 551 | */ | |
| 552 | peer_odc_send_cookie(conn); | |
| 553 | } | |
| 554 | ||
| 555 | conn->ready = TRUE; | |
| 556 | ||
| 557 | /* | |
| 558 | * If they connected to us then close the listener socket | |
| 559 | * and send them our cookie. | |
| 560 | */ | |
| 561 | if (conn->listenerfd != -1) | |
| 562 | { | |
| 563 | close(conn->listenerfd); | |
| 564 | conn->listenerfd = -1; | |
| 565 | } | |
| 566 | ||
| 567 | /* Tell the local user that we are connected */ | |
| 15884 | 568 | account = purple_connection_get_account(gc); |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
569 | im = purple_im_conversation_new(account, conn->bn); |
|
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
570 | purple_conversation_write(PURPLE_CONVERSATION(im), NULL, _("Direct IM established"), |
| 15884 | 571 | PURPLE_MESSAGE_SYSTEM, time(NULL)); |
| 13593 | 572 | } |
| 573 | ||
| 574 | if ((frame->type != 0x0001) && (frame->subtype != 0x0006)) | |
| 575 | { | |
| 15884 | 576 | purple_debug_info("oscar", "Unknown ODC frame type 0x%04hx, " |
| 13593 | 577 | "subtype 0x%04hx.\n", frame->type, frame->subtype); |
|
25296
0450df777754
Fix a leak "KuSh" discovered using "cppcheck". Fixes #7857.
Daniel Atallah <datallah@pidgin.im>
parents:
23079
diff
changeset
|
578 | g_free(frame); |
| 13593 | 579 | return; |
| 580 | } | |
| 581 | ||
| 582 | if (frame->flags & 0x0008) | |
| 583 | { | |
| 584 | /* I had to leave this. It's just too funny. It reminds me of my sister. */ | |
| 15884 | 585 | purple_debug_info("oscar", "ohmigod! %s has started typing " |
| 13593 | 586 | "(DirectIM). He's going to send you a message! " |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
587 | "*squeal*\n", conn->bn); |
|
34622
753f46dd000f
Global replace - renamed functions and types according to GObject-based PurpleConversation API
Ankit Vani <a@nevitus.org>
parents:
33768
diff
changeset
|
588 | serv_got_typing(gc, conn->bn, 0, PURPLE_IM_CONVERSATION_TYPING); |
| 13593 | 589 | } |
| 590 | else if (frame->flags & 0x0004) | |
| 591 | { | |
|
34622
753f46dd000f
Global replace - renamed functions and types according to GObject-based PurpleConversation API
Ankit Vani <a@nevitus.org>
parents:
33768
diff
changeset
|
592 | serv_got_typing(gc, conn->bn, 0, PURPLE_IM_CONVERSATION_TYPED); |
| 13593 | 593 | } |
| 594 | else | |
| 595 | { | |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
596 | serv_got_typing_stopped(gc, conn->bn); |
| 13593 | 597 | } |
| 598 | ||
| 599 | if (frame->payload.len > 0) | |
| 600 | { | |
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
601 | if (frame->payload.len > DIRECTIM_MAX_FILESIZE) |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
602 | { |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
603 | gchar *tmp, *size1, *size2; |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
604 | PurpleAccount *account; |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
605 | PurpleIMConversation *im; |
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
606 | |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
607 | size1 = purple_str_size_to_units(frame->payload.len); |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
608 | size2 = purple_str_size_to_units(DIRECTIM_MAX_FILESIZE); |
|
25889
26d9ca30335c
Change "screen name" to "username" or "buddy name" in a whole bunch of
Mark Doliner <markdoliner@pidgin.im>
parents:
25426
diff
changeset
|
609 | tmp = g_strdup_printf(_("%s tried to send you a %s file, but we only allow files up to %s over Direct IM. Try using file transfer instead.\n"), conn->bn, size1, size2); |
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
610 | g_free(size1); |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
611 | g_free(size2); |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
612 | |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
613 | account = purple_connection_get_account(conn->od->gc); |
|
34639
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
614 | im = purple_im_conversation_new(account, conn->bn); |
|
53b5e1b31031
Refactored novell and oscar protocols to use GObject conversation API
Ankit Vani <a@nevitus.org>
parents:
34627
diff
changeset
|
615 | purple_conversation_write(PURPLE_CONVERSATION(im), NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); |
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
616 | g_free(tmp); |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
617 | |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
618 | peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL); |
|
25296
0450df777754
Fix a leak "KuSh" discovered using "cppcheck". Fixes #7857.
Daniel Atallah <datallah@pidgin.im>
parents:
23079
diff
changeset
|
619 | g_free(frame); |
|
20192
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
620 | return; |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
621 | } |
|
162883eb3251
applied changes from 2ab75e32c52e94c674d0b5a396d224da7e9d509e
Luke Schierer <lschiere@pidgin.im>
parents:
19859
diff
changeset
|
622 | |
| 13593 | 623 | /* We have payload data! Switch to the ODC watcher to read it. */ |
| 624 | frame->payload.data = g_new(guint8, frame->payload.len); | |
| 625 | frame->payload.offset = 0; | |
| 626 | conn->frame = frame; | |
| 15884 | 627 | purple_input_remove(conn->watcher_incoming); |
| 628 | conn->watcher_incoming = purple_input_add(conn->fd, | |
| 629 | PURPLE_INPUT_READ, peer_odc_recv_cb, conn); | |
| 13593 | 630 | return; |
| 631 | } | |
| 632 | ||
| 633 | g_free(frame); | |
| 634 | } |