Mercurial > pidgin
comparison src/protocols/msn/msg.c @ 9158:c30d81b4dd22
[gaim-migrate @ 9942]
Patch from Felipe Contreras to sync our MSN prpl with what's in his tree.
He says this may fix a couple bugs, but the important thing is the
restructuring of how MsnMessages work. Lots of style changes and other
stuff as well.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Tue, 01 Jun 2004 06:42:20 +0000 |
| parents | 9e5a709c30a8 |
| children | 502707ca1836 |
comparison
equal
deleted
inserted
replaced
| 9157:bd1ea0a717d7 | 9158:c30d81b4dd22 |
|---|---|
| 52 (((*((buf)+1))<<16)&0x00ff0000) + \ | 52 (((*((buf)+1))<<16)&0x00ff0000) + \ |
| 53 (((*((buf)+2))<< 8)&0x0000ff00) + \ | 53 (((*((buf)+2))<< 8)&0x0000ff00) + \ |
| 54 (((*((buf)+3) )&0x000000ff))) | 54 (((*((buf)+3) )&0x000000ff))) |
| 55 | 55 |
| 56 | 56 |
| 57 /* | |
| 58 * "MIME-Version: 1.0\r\n" == 19 | |
| 59 * "Content-Type: " == 14 | |
| 60 * "\r\n" == 2 | |
| 61 * "\r\n" before body == 2 | |
| 62 * ---- | |
| 63 * 37 | |
| 64 * MATH PAYS OFF!! | |
| 65 */ | |
| 66 #define MSN_MESSAGE_BASE_SIZE 37 | |
| 67 | |
| 68 MsnMessage * | 57 MsnMessage * |
| 69 msn_message_new(void) | 58 msn_message_new(void) |
| 70 { | 59 { |
| 71 MsnMessage *msg; | 60 MsnMessage *msg; |
| 72 | 61 |
| 73 msg = g_new0(MsnMessage, 1); | 62 msg = g_new0(MsnMessage, 1); |
| 74 | 63 |
| 75 msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, | 64 msg->attr_table = g_hash_table_new_full(g_str_hash, g_str_equal, |
| 76 g_free, g_free); | 65 g_free, g_free); |
| 77 msg->size = MSN_MESSAGE_BASE_SIZE; | 66 |
| 78 | 67 msn_message_ref(msg); |
| 68 | |
| 69 return msg; | |
| 70 } | |
| 71 | |
| 72 MsnMessage * | |
| 73 msn_message_new_plain(const char *message) | |
| 74 { | |
| 75 MsnMessage *msg; | |
| 76 char *message_cr; | |
| 77 | |
| 78 msg = msn_message_new(); | |
| 79 msn_message_set_attr(msg, "User-Agent", "Gaim/" VERSION); | 79 msn_message_set_attr(msg, "User-Agent", "Gaim/" VERSION); |
| 80 msn_message_set_content_type(msg, "text/plain"); | 80 msn_message_set_content_type(msg, "text/plain"); |
| 81 msn_message_set_charset(msg, "UTF-8"); | 81 msn_message_set_charset(msg, "UTF-8"); |
| 82 msn_message_set_flag(msg, 'U'); | 82 msn_message_set_flag(msg, 'N'); |
| 83 | 83 msn_message_set_attr(msg, "X-MMS-IM-Format", |
| 84 msn_message_ref(msg); | 84 "FN=MS%20Sans%20Serif; EF=; CO=0; PF=0"); |
| 85 | |
| 86 message_cr = gaim_str_add_cr(message); | |
| 87 msn_message_set_bin_data(msg, message_cr, strlen(message_cr)); | |
| 88 g_free(message_cr); | |
| 85 | 89 |
| 86 return msg; | 90 return msg; |
| 87 } | 91 } |
| 88 | 92 |
| 89 MsnMessage * | 93 MsnMessage * |
| 94 msg = msn_message_new(); | 98 msg = msn_message_new(); |
| 95 | 99 |
| 96 msn_message_set_attr(msg, "User-Agent", NULL); | 100 msn_message_set_attr(msg, "User-Agent", NULL); |
| 97 | 101 |
| 98 msg->msnslp_message = TRUE; | 102 msg->msnslp_message = TRUE; |
| 99 msg->size += 52; | |
| 100 | 103 |
| 101 msn_message_set_flag(msg, 'D'); | 104 msn_message_set_flag(msg, 'D'); |
| 102 msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); | 105 msn_message_set_content_type(msg, "application/x-msnmsgrp2p"); |
| 103 msn_message_set_charset(msg, NULL); | |
| 104 | 106 |
| 105 return msg; | 107 return msg; |
| 106 } | 108 } |
| 107 | 109 |
| 108 MsnMessage * | 110 MsnMessage * |
| 116 msg = msn_message_new_msnslp(); | 118 msg = msn_message_new_msnslp(); |
| 117 | 119 |
| 118 msg->msnslp_ack_message = TRUE; | 120 msg->msnslp_ack_message = TRUE; |
| 119 msg->acked_msg = msn_message_ref(acked_msg); | 121 msg->acked_msg = msn_message_ref(acked_msg); |
| 120 | 122 |
| 121 msg->msnslp_header.session_id = acked_msg->msnslp_header.session_id; | 123 msg->msnslp_header.session_id = acked_msg->msnslp_header.session_id; |
| 122 msg->msnslp_header.total_size_1 = acked_msg->msnslp_header.total_size_1; | 124 msg->msnslp_header.total_size = acked_msg->msnslp_header.total_size; |
| 123 msg->msnslp_header.total_size_2 = acked_msg->msnslp_header.total_size_2; | 125 msg->msnslp_header.flags = 0x02; |
| 124 msg->msnslp_header.flags = 0x02; | 126 msg->msnslp_header.ack_id = acked_msg->msnslp_header.id; |
| 125 msg->msnslp_header.ack_session_id = acked_msg->msnslp_header.session_id; | 127 msg->msnslp_header.ack_sub_id = acked_msg->msnslp_header.ack_id; |
| 126 msg->msnslp_header.ack_unique_id = acked_msg->msnslp_header.ack_session_id; | 128 msg->msnslp_header.ack_size = acked_msg->msnslp_header.total_size; |
| 127 msg->msnslp_header.ack_length_1 = acked_msg->msnslp_header.total_size_1; | |
| 128 msg->msnslp_header.ack_length_2 = acked_msg->msnslp_header.total_size_2; | |
| 129 | 129 |
| 130 return msg; | 130 return msg; |
| 131 } | 131 } |
| 132 | 132 |
| 133 void | 133 void |
| 134 msn_message_parse_payload(MsnMessage *msg, const char *payload, | 134 msn_message_parse_payload(MsnMessage *msg, |
| 135 size_t payload_len) | 135 const char *payload, size_t payload_len) |
| 136 { | 136 { |
| 137 char *tmp_base, *tmp, *c; | 137 char *tmp_base, *tmp; |
| 138 const char *content_type; | 138 const char *content_type; |
| 139 | 139 |
| 140 tmp_base = g_malloc(payload_len + 1); | 140 g_return_if_fail(payload != NULL); |
| 141 memcpy(tmp_base, payload, payload_len); | 141 |
| 142 tmp_base[payload_len] = '\0'; | 142 tmp_base = tmp = g_memdup(payload, payload_len); |
| 143 | |
| 144 tmp = tmp_base; | |
| 145 | 143 |
| 146 /* Back to the parsination. */ | 144 /* Back to the parsination. */ |
| 147 while (*tmp != '\r') | 145 while (*tmp != '\r') |
| 148 { | 146 { |
| 149 char *key, *value; | 147 char *key, *value, *c; |
| 150 | 148 |
| 151 key = tmp; | 149 key = tmp; |
| 152 | 150 |
| 153 GET_NEXT(tmp); /* Key */ | 151 GET_NEXT(tmp); /* Key */ |
| 154 | 152 |
| 156 | 154 |
| 157 GET_NEXT_LINE(tmp); /* Value */ | 155 GET_NEXT_LINE(tmp); /* Value */ |
| 158 | 156 |
| 159 if ((c = strchr(key, ':')) != NULL) | 157 if ((c = strchr(key, ':')) != NULL) |
| 160 *c = '\0'; | 158 *c = '\0'; |
| 159 | |
| 160 if (!g_ascii_strcasecmp(key, "MIME-Version")) | |
| 161 continue; | |
| 161 | 162 |
| 162 if (!g_ascii_strcasecmp(key, "Content-Type")) | 163 if (!g_ascii_strcasecmp(key, "Content-Type")) |
| 163 { | 164 { |
| 164 char *charset; | 165 char *charset; |
| 165 | 166 |
| 187 content_type = msn_message_get_content_type(msg); | 188 content_type = msn_message_get_content_type(msg); |
| 188 | 189 |
| 189 if (content_type != NULL && | 190 if (content_type != NULL && |
| 190 !strcmp(content_type, "application/x-msnmsgrp2p")) | 191 !strcmp(content_type, "application/x-msnmsgrp2p")) |
| 191 { | 192 { |
| 192 char header[48]; | 193 MsnSlpHeader header; |
| 193 char footer[4]; | 194 MsnSlpFooter footer; |
| 194 size_t body_len; | |
| 195 char *tmp2; | |
| 196 | 195 |
| 197 msg->msnslp_message = TRUE; | 196 msg->msnslp_message = TRUE; |
| 198 | 197 |
| 199 memcpy(header, tmp, 48); | |
| 200 | |
| 201 tmp += 48; | |
| 202 | |
| 203 body_len = payload_len - (tmp - tmp_base) - 4; | |
| 204 | |
| 205 if (body_len > 0) | |
| 206 { | |
| 207 msg->body = g_malloc(body_len + 1); | |
| 208 memcpy(msg->body, tmp, body_len); | |
| 209 msg->body[body_len] = '\0'; | |
| 210 | |
| 211 tmp++; | |
| 212 } | |
| 213 else | |
| 214 msg->body = NULL; | |
| 215 | |
| 216 memcpy(footer, tmp, 4); | |
| 217 | |
| 218 tmp += 4; | |
| 219 | |
| 220 /* Import the header. */ | 198 /* Import the header. */ |
| 221 tmp2 = header; | 199 memcpy(&header, tmp, sizeof(header)); |
| 222 msg->msnslp_header.session_id = msn_get32(tmp2); tmp2 += 4; | 200 tmp += sizeof(header); |
| 223 msg->msnslp_header.id = msn_get32(tmp2); tmp2 += 4; | 201 |
| 224 msg->msnslp_header.offset_1 = msn_get32(tmp2); tmp2 += 4; | 202 msg->msnslp_header.session_id = GUINT32_FROM_LE(header.session_id); |
| 225 msg->msnslp_header.offset_2 = msn_get32(tmp2); tmp2 += 4; | 203 msg->msnslp_header.id = GUINT64_FROM_LE(header.id); |
| 226 msg->msnslp_header.total_size_1 = msn_get32(tmp2); tmp2 += 4; | 204 msg->msnslp_header.offset = GUINT64_FROM_LE(header.offset); |
| 227 msg->msnslp_header.total_size_2 = msn_get32(tmp2); tmp2 += 4; | 205 msg->msnslp_header.total_size = GUINT32_FROM_LE(header.total_size); |
| 228 msg->msnslp_header.length = msn_get32(tmp2); tmp2 += 4; | 206 msg->msnslp_header.length = GUINT32_FROM_LE(header.length); |
| 229 msg->msnslp_header.flags = msn_get32(tmp2); tmp2 += 4; | 207 msg->msnslp_header.flags = GUINT32_FROM_LE(header.flags); |
| 230 msg->msnslp_header.ack_session_id = msn_get32(tmp2); tmp2 += 4; | 208 msg->msnslp_header.ack_id = GUINT32_FROM_LE(header.ack_id); |
| 231 msg->msnslp_header.ack_unique_id = msn_get32(tmp2); tmp2 += 4; | 209 msg->msnslp_header.ack_sub_id = GUINT32_FROM_LE(header.ack_sub_id); |
| 232 msg->msnslp_header.ack_length_1 = msn_get32(tmp2); tmp2 += 4; | 210 msg->msnslp_header.ack_size = GUINT64_FROM_LE(header.ack_size); |
| 233 msg->msnslp_header.ack_length_2 = msn_get32(tmp2); tmp2 += 4; | 211 |
| 234 | 212 /* Import the body. */ |
| 235 /* Convert to the right endianness */ | 213 msg->body_len = payload_len - (tmp - tmp_base) - sizeof(footer); |
| 236 msg->msnslp_header.session_id = ntohl(msg->msnslp_header.session_id); | 214 |
| 237 msg->msnslp_header.id = ntohl(msg->msnslp_header.id); | 215 if (msg->body_len > 0) |
| 238 msg->msnslp_header.length = ntohl(msg->msnslp_header.length); | 216 msg->body = g_memdup(tmp, msg->body_len); |
| 239 msg->msnslp_header.flags = ntohl(msg->msnslp_header.flags); | 217 |
| 240 msg->msnslp_header.ack_length_1 = | 218 tmp += msg->body_len; |
| 241 ntohl(msg->msnslp_header.ack_length_1); | |
| 242 msg->msnslp_header.ack_length_2 = | |
| 243 ntohl(msg->msnslp_header.ack_length_2); | |
| 244 msg->msnslp_header.ack_session_id = | |
| 245 ntohl(msg->msnslp_header.ack_session_id); | |
| 246 msg->msnslp_header.ack_unique_id = | |
| 247 ntohl(msg->msnslp_header.ack_unique_id); | |
| 248 | 219 |
| 249 /* Import the footer. */ | 220 /* Import the footer. */ |
| 250 msg->msnslp_footer.app_id = (long)footer; | 221 memcpy(&footer, tmp, sizeof(footer)); |
| 222 tmp += sizeof(footer); | |
| 223 | |
| 224 msg->msnslp_footer.value = GUINT32_FROM_BE(footer.value); | |
| 251 } | 225 } |
| 252 else | 226 else |
| 253 { | 227 { |
| 254 char *tmp2; | 228 msg->body_len = payload_len - (tmp - tmp_base); |
| 255 size_t body_len; | 229 msg->body = g_memdup(tmp, msg->body_len); |
| 256 | |
| 257 body_len = payload_len - (tmp - tmp_base); | |
| 258 | |
| 259 tmp2 = g_malloc(body_len + 1); | |
| 260 | |
| 261 if (body_len > 0) | |
| 262 memcpy(tmp2, tmp, body_len); | |
| 263 | |
| 264 tmp2[body_len] = '\0'; | |
| 265 | |
| 266 msn_message_set_body(msg, tmp2); | |
| 267 | |
| 268 g_free(tmp2); | |
| 269 } | 230 } |
| 270 | 231 |
| 271 g_free(tmp_base); | 232 g_free(tmp_base); |
| 272 | 233 |
| 273 /* Done! */ | 234 /* Done! */ |
| 298 g_list_free(msg->attr_list); | 259 g_list_free(msg->attr_list); |
| 299 | 260 |
| 300 if (msg->msnslp_ack_message) | 261 if (msg->msnslp_ack_message) |
| 301 msn_message_unref(msg->acked_msg); | 262 msn_message_unref(msg->acked_msg); |
| 302 | 263 |
| 303 gaim_debug(GAIM_DEBUG_INFO, "msn", "Destroying message\n"); | |
| 304 g_free(msg); | 264 g_free(msg); |
| 305 } | 265 } |
| 306 | 266 |
| 307 MsnMessage * | 267 MsnMessage * |
| 308 msn_message_ref(MsnMessage *msg) | 268 msn_message_ref(MsnMessage *msg) |
| 335 | 295 |
| 336 char * | 296 char * |
| 337 msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size) | 297 msn_message_gen_payload(const MsnMessage *msg, size_t *ret_size) |
| 338 { | 298 { |
| 339 GList *l; | 299 GList *l; |
| 340 char *str; | 300 char *n, *base, *end; |
| 341 char buf[MSN_BUF_LEN]; | |
| 342 int len; | 301 int len; |
| 343 | 302 size_t body_len; |
| 344 /* | 303 const void *body; |
| 345 * Okay, how we do things here is just bad. I don't like writing to | 304 |
| 346 * a static buffer and then copying to the string. Unfortunately, | 305 g_return_val_if_fail(msg != NULL, NULL); |
| 347 * just trying to append to the string is causing issues.. Such as | 306 |
| 348 * the string you're appending to being erased. Ugh. So, this is | 307 len = MSN_BUF_LEN; |
| 349 * good enough for now. | 308 |
| 350 * | 309 base = n = end = g_malloc(len + 1); |
| 351 * -- ChipX86 | 310 end += len; |
| 352 */ | |
| 353 g_return_val_if_fail(msg != NULL, NULL); | |
| 354 | |
| 355 len = msg->size + 1; | |
| 356 | |
| 357 str = g_new0(char, len + 1); | |
| 358 | 311 |
| 359 /* Standard header. */ | 312 /* Standard header. */ |
| 360 if (msg->charset == NULL) | 313 if (msg->charset == NULL) |
| 361 { | 314 { |
| 362 g_snprintf(buf, sizeof(buf), | 315 g_snprintf(n, len, |
| 363 "MIME-Version: 1.0\r\n" | 316 "MIME-Version: 1.0\r\n" |
| 364 "Content-Type: %s\r\n", | 317 "Content-Type: %s\r\n", |
| 365 msg->content_type); | 318 msg->content_type); |
| 366 } | 319 } |
| 367 else | 320 else |
| 368 { | 321 { |
| 369 g_snprintf(buf, sizeof(buf), | 322 g_snprintf(n, len, |
| 370 "MIME-Version: 1.0\r\n" | 323 "MIME-Version: 1.0\r\n" |
| 371 "Content-Type: %s; charset=%s\r\n", | 324 "Content-Type: %s; charset=%s\r\n", |
| 372 msg->content_type, msg->charset); | 325 msg->content_type, msg->charset); |
| 373 } | 326 } |
| 374 | 327 |
| 375 g_strlcat(str, buf, len); | 328 n += strlen(n); |
| 376 | 329 |
| 377 for (l = msg->attr_list; l != NULL; l = l->next) | 330 for (l = msg->attr_list; l != NULL; l = l->next) |
| 378 { | 331 { |
| 379 const char *key = (char *)l->data; | 332 const char *key; |
| 380 const char *value; | 333 const char *value; |
| 381 | 334 |
| 335 key = l->data; | |
| 382 value = msn_message_get_attr(msg, key); | 336 value = msn_message_get_attr(msg, key); |
| 383 | 337 |
| 384 g_snprintf(buf, sizeof(buf), "%s: %s\r\n", key, value); | 338 g_snprintf(n, end - n, "%s: %s\r\n", key, value); |
| 385 | 339 n += strlen(n); |
| 386 g_strlcat(str, buf, len); | 340 } |
| 387 } | 341 |
| 388 | 342 n += g_strlcpy(n, "\r\n", end - n); |
| 389 g_strlcat(str, "\r\n", len); | 343 |
| 344 body = msn_message_get_bin_data(msg, &body_len); | |
| 390 | 345 |
| 391 if (msg->msnslp_message) | 346 if (msg->msnslp_message) |
| 392 { | 347 { |
| 393 char *c; | 348 MsnSlpHeader header; |
| 394 long session_id, id, offset_1, offset_2, total_size_1, total_size_2; | 349 MsnSlpFooter footer; |
| 395 long length, flags; | 350 |
| 396 long ack_session_id, ack_unique_id, ack_length_1, ack_length_2; | 351 header.session_id = GUINT32_TO_LE(msg->msnslp_header.session_id); |
| 397 | 352 header.id = GUINT64_TO_LE(msg->msnslp_header.id); |
| 398 c = str + strlen(str); | 353 header.offset = GUINT64_TO_LE(msg->msnslp_header.offset); |
| 399 | 354 header.total_size = GUINT32_TO_LE(msg->msnslp_header.total_size); |
| 400 session_id = htonl(msg->msnslp_header.session_id); | 355 header.length = GUINT32_TO_LE(msg->msnslp_header.length); |
| 401 id = htonl(msg->msnslp_header.id); | 356 header.flags = GUINT32_TO_LE(msg->msnslp_header.flags); |
| 402 offset_1 = htonl(msg->msnslp_header.offset_1); | 357 header.ack_id = GUINT32_TO_LE(msg->msnslp_header.ack_id); |
| 403 offset_2 = htonl(msg->msnslp_header.offset_2); | 358 header.ack_sub_id = GUINT32_TO_LE(msg->msnslp_header.ack_sub_id); |
| 404 total_size_1 = htonl(msg->msnslp_header.total_size_1); | 359 header.ack_size = GUINT64_TO_LE(msg->msnslp_header.ack_size); |
| 405 total_size_2 = htonl(msg->msnslp_header.total_size_2); | 360 |
| 406 length = htonl(msg->msnslp_header.length); | 361 memcpy(n, &header, 48); |
| 407 flags = htonl(msg->msnslp_header.flags); | 362 n += 48; |
| 408 ack_session_id = htonl(msg->msnslp_header.ack_session_id); | 363 |
| 409 ack_unique_id = htonl(msg->msnslp_header.ack_unique_id); | 364 if (body != NULL) |
| 410 ack_length_1 = htonl(msg->msnslp_header.ack_length_1); | |
| 411 ack_length_2 = htonl(msg->msnslp_header.ack_length_2); | |
| 412 | |
| 413 c += msn_put32(c, session_id); | |
| 414 c += msn_put32(c, id); | |
| 415 c += msn_put32(c, offset_1); | |
| 416 c += msn_put32(c, offset_2); | |
| 417 c += msn_put32(c, total_size_1); | |
| 418 c += msn_put32(c, total_size_2); | |
| 419 c += msn_put32(c, length); | |
| 420 c += msn_put32(c, flags); | |
| 421 c += msn_put32(c, ack_session_id); | |
| 422 c += msn_put32(c, ack_unique_id); | |
| 423 c += msn_put32(c, ack_length_1); | |
| 424 c += msn_put32(c, ack_length_2); | |
| 425 | |
| 426 if (msg->bin_content) | |
| 427 { | 365 { |
| 428 size_t bin_len; | 366 memcpy(n, body, body_len); |
| 429 const void *body = msn_message_get_bin_data(msg, &bin_len); | 367 n += body_len; |
| 430 | |
| 431 if (body != NULL) | |
| 432 { | |
| 433 memcpy(c, body, bin_len); | |
| 434 | |
| 435 c += bin_len; | |
| 436 } | |
| 437 } | 368 } |
| 438 else | 369 |
| 370 footer.value = GUINT32_TO_BE(msg->msnslp_footer.value); | |
| 371 | |
| 372 memcpy(n, &footer, 4); | |
| 373 n += 4; | |
| 374 } | |
| 375 else | |
| 376 { | |
| 377 if (body != NULL) | |
| 439 { | 378 { |
| 440 const char *body = msn_message_get_body(msg); | 379 memcpy(n, body, body_len); |
| 441 | 380 n += body_len; |
| 442 if (body != NULL) | |
| 443 { | |
| 444 g_strlcpy(c, body, msg->size - (c - str)); | |
| 445 | |
| 446 c += strlen(body); | |
| 447 | |
| 448 if (strlen(body) > 0) | |
| 449 *c++ = '\0'; | |
| 450 } | |
| 451 } | 381 } |
| 452 | |
| 453 c += msn_put32(c, msg->msnslp_footer.app_id); | |
| 454 | |
| 455 if (msg->size != (c - str)) | |
| 456 { | |
| 457 gaim_debug(GAIM_DEBUG_ERROR, "msn", | |
| 458 "Outgoing message size (%d) and data length (%d) " | |
| 459 "do not match!\n", msg->size, (c - str)); | |
| 460 } | |
| 461 } | |
| 462 else | |
| 463 { | |
| 464 const char *body = msn_message_get_body(msg); | |
| 465 | |
| 466 g_strlcat(str, body, len); | |
| 467 | |
| 468 if (msg->size != strlen(str)) | |
| 469 { | |
| 470 gaim_debug(GAIM_DEBUG_ERROR, "msn", | |
| 471 "Outgoing message size (%d) and string length (%d) " | |
| 472 "do not match!\n", msg->size, strlen(str)); | |
| 473 } | |
| 474 } | 382 } |
| 475 | 383 |
| 476 if (ret_size != NULL) | 384 if (ret_size != NULL) |
| 477 { | 385 { |
| 478 *ret_size = len - 1; | 386 *ret_size = n - base; |
| 479 | 387 |
| 480 if (*ret_size > 1664) | 388 if (*ret_size > 1664) |
| 481 *ret_size = 1664; | 389 *ret_size = 1664; |
| 482 } | 390 } |
| 483 | 391 |
| 484 return str; | 392 return base; |
| 485 } | 393 } |
| 486 | 394 |
| 487 void | 395 void |
| 488 msn_message_set_flag(MsnMessage *msg, char flag) | 396 msn_message_set_flag(MsnMessage *msg, char flag) |
| 489 { | 397 { |
| 500 | 408 |
| 501 return msg->flag; | 409 return msg->flag; |
| 502 } | 410 } |
| 503 | 411 |
| 504 void | 412 void |
| 505 msn_message_set_body(MsnMessage *msg, const char *body) | 413 msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len) |
| 506 { | 414 { |
| 507 const char *c; | 415 g_return_if_fail(msg != NULL); |
| 508 char *buf, *d; | 416 |
| 509 int newline_count = 0; | 417 /* There is no need to waste memory on data we cannot send anyway */ |
| 510 size_t new_len; | 418 if (len > 1664) |
| 511 | 419 len = 1664; |
| 512 g_return_if_fail(msg != NULL); | 420 |
| 513 | 421 if (msg->body != NULL) |
| 514 if (msg->bin_content) | |
| 515 { | |
| 516 msn_message_set_bin_data(msg, NULL, 0); | |
| 517 return; | |
| 518 } | |
| 519 | |
| 520 if (msg->body != NULL) { | |
| 521 msg->size -= strlen(msg->body); | |
| 522 g_free(msg->body); | 422 g_free(msg->body); |
| 523 | 423 |
| 524 if (msg->msnslp_message) | 424 if (data != NULL && len > 0) |
| 525 msg->size--; | 425 { |
| 526 } | 426 msg->body = g_memdup(data, len); |
| 527 | 427 msg->body_len = len; |
| 528 if (body != NULL) | |
| 529 { | |
| 530 for (c = body; *c != '\0'; c++) | |
| 531 { | |
| 532 if (*c == '\n' && (c == body || *(c - 1) != '\r')) | |
| 533 newline_count++; | |
| 534 } | |
| 535 | |
| 536 new_len = strlen(body) + newline_count; | |
| 537 | |
| 538 buf = g_new0(char, new_len + 1); | |
| 539 | |
| 540 for (c = body, d = buf; *c != '\0'; c++) { | |
| 541 if (*c == '\n' && (c == body || *(c - 1) != '\r')) { | |
| 542 *d++ = '\r'; | |
| 543 *d++ = '\n'; | |
| 544 } | |
| 545 else | |
| 546 *d++ = *c; | |
| 547 } | |
| 548 | |
| 549 msg->body = buf; | |
| 550 msg->size += new_len; | |
| 551 | |
| 552 msg->bin_content = FALSE; | |
| 553 | |
| 554 if (msg->msnslp_message) | |
| 555 msg->size++; | |
| 556 } | 428 } |
| 557 else | 429 else |
| 430 { | |
| 558 msg->body = NULL; | 431 msg->body = NULL; |
| 559 } | 432 msg->body_len = 0; |
| 560 | |
| 561 const char * | |
| 562 msn_message_get_body(const MsnMessage *msg) | |
| 563 { | |
| 564 g_return_val_if_fail(msg != NULL, NULL); | |
| 565 g_return_val_if_fail(!msg->bin_content, NULL); | |
| 566 | |
| 567 return msg->body; | |
| 568 } | |
| 569 | |
| 570 void | |
| 571 msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len) | |
| 572 { | |
| 573 g_return_if_fail(msg != NULL); | |
| 574 | |
| 575 if (!msg->bin_content) | |
| 576 msn_message_set_body(msg, NULL); | |
| 577 | |
| 578 msg->bin_content = TRUE; | |
| 579 | |
| 580 if (msg->body != NULL) | |
| 581 { | |
| 582 msg->size -= msg->bin_len; | |
| 583 g_free(msg->body); | |
| 584 } | |
| 585 | |
| 586 if (data != NULL && len > 0) | |
| 587 { | |
| 588 msg->body = g_memdup(data, len); | |
| 589 msg->bin_len = len; | |
| 590 | |
| 591 msg->size += len; | |
| 592 } | |
| 593 else | |
| 594 { | |
| 595 msg->body = NULL; | |
| 596 msg->bin_len = 0; | |
| 597 } | 433 } |
| 598 } | 434 } |
| 599 | 435 |
| 600 const void * | 436 const void * |
| 601 msn_message_get_bin_data(const MsnMessage *msg, size_t *len) | 437 msn_message_get_bin_data(const MsnMessage *msg, size_t *len) |
| 602 { | 438 { |
| 603 g_return_val_if_fail(msg != NULL, NULL); | 439 g_return_val_if_fail(msg != NULL, NULL); |
| 604 g_return_val_if_fail(len != NULL, NULL); | 440 |
| 605 g_return_val_if_fail(msg->bin_content, NULL); | 441 if (len) |
| 606 | 442 *len = msg->body_len; |
| 607 *len = msg->bin_len; | |
| 608 | 443 |
| 609 return msg->body; | 444 return msg->body; |
| 610 } | 445 } |
| 611 | 446 |
| 612 void | 447 void |
| 613 msn_message_set_content_type(MsnMessage *msg, const char *type) | 448 msn_message_set_content_type(MsnMessage *msg, const char *type) |
| 614 { | 449 { |
| 615 g_return_if_fail(msg != NULL); | 450 g_return_if_fail(msg != NULL); |
| 616 | 451 |
| 617 if (msg->content_type != NULL) { | 452 if (msg->content_type != NULL) |
| 618 msg->size -= strlen(msg->content_type); | |
| 619 g_free(msg->content_type); | 453 g_free(msg->content_type); |
| 620 } | 454 |
| 621 | 455 if (type != NULL) |
| 622 if (type != NULL) { | |
| 623 msg->content_type = g_strdup(type); | 456 msg->content_type = g_strdup(type); |
| 624 | |
| 625 msg->size += strlen(type); | |
| 626 } | |
| 627 else | 457 else |
| 628 msg->content_type = NULL; | 458 msg->content_type = NULL; |
| 629 } | 459 } |
| 630 | 460 |
| 631 const char * | 461 const char * |
| 639 void | 469 void |
| 640 msn_message_set_charset(MsnMessage *msg, const char *charset) | 470 msn_message_set_charset(MsnMessage *msg, const char *charset) |
| 641 { | 471 { |
| 642 g_return_if_fail(msg != NULL); | 472 g_return_if_fail(msg != NULL); |
| 643 | 473 |
| 644 if (msg->charset != NULL) { | 474 if (msg->charset != NULL) |
| 645 msg->size -= strlen(msg->charset) + strlen("; charset="); | |
| 646 g_free(msg->charset); | 475 g_free(msg->charset); |
| 647 } | 476 |
| 648 | 477 if (charset != NULL) |
| 649 if (charset != NULL) { | |
| 650 msg->charset = g_strdup(charset); | 478 msg->charset = g_strdup(charset); |
| 651 | |
| 652 msg->size += strlen(charset) + strlen("; charset="); | |
| 653 } | |
| 654 else | 479 else |
| 655 msg->charset = NULL; | 480 msg->charset = NULL; |
| 656 } | 481 } |
| 657 | 482 |
| 658 const char * | 483 const char * |
| 672 g_return_if_fail(msg != NULL); | 497 g_return_if_fail(msg != NULL); |
| 673 g_return_if_fail(attr != NULL); | 498 g_return_if_fail(attr != NULL); |
| 674 | 499 |
| 675 temp = msn_message_get_attr(msg, attr); | 500 temp = msn_message_get_attr(msg, attr); |
| 676 | 501 |
| 677 if (value == NULL) { | 502 if (value == NULL) |
| 678 if (temp != NULL) { | 503 { |
| 504 if (temp != NULL) | |
| 505 { | |
| 679 GList *l; | 506 GList *l; |
| 680 | 507 |
| 681 msg->size -= strlen(temp) + strlen(attr) + 4; | 508 for (l = msg->attr_list; l != NULL; l = l->next) |
| 682 | 509 { |
| 683 for (l = msg->attr_list; l != NULL; l = l->next) { | 510 if (!g_ascii_strcasecmp(l->data, attr)) |
| 684 if (!g_ascii_strcasecmp(l->data, attr)) { | 511 { |
| 685 msg->attr_list = g_list_remove(msg->attr_list, l->data); | 512 msg->attr_list = g_list_remove(msg->attr_list, l->data); |
| 686 | 513 |
| 687 break; | 514 break; |
| 688 } | 515 } |
| 689 } | 516 } |
| 696 | 523 |
| 697 new_attr = g_strdup(attr); | 524 new_attr = g_strdup(attr); |
| 698 | 525 |
| 699 g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value)); | 526 g_hash_table_insert(msg->attr_table, new_attr, g_strdup(value)); |
| 700 | 527 |
| 701 if (temp == NULL) { | 528 if (temp == NULL) |
| 702 msg->attr_list = g_list_append(msg->attr_list, new_attr); | 529 msg->attr_list = g_list_append(msg->attr_list, new_attr); |
| 703 msg->size += strlen(attr) + 4; | |
| 704 } | |
| 705 else | |
| 706 msg->size -= strlen(temp); | |
| 707 | |
| 708 msg->size += strlen(value); | |
| 709 } | 530 } |
| 710 | 531 |
| 711 const char * | 532 const char * |
| 712 msn_message_get_attr(const MsnMessage *msg, const char *attr) | 533 msn_message_get_attr(const MsnMessage *msg, const char *attr) |
| 713 { | 534 { |
| 722 { | 543 { |
| 723 GHashTable *table; | 544 GHashTable *table; |
| 724 char *body, *s, *c; | 545 char *body, *s, *c; |
| 725 | 546 |
| 726 g_return_val_if_fail(msg != NULL, NULL); | 547 g_return_val_if_fail(msg != NULL, NULL); |
| 727 g_return_val_if_fail(msn_message_get_body(msg) != NULL, NULL); | 548 |
| 728 | 549 s = body = g_strdup(msn_message_get_bin_data(msg, NULL)); |
| 729 s = body = g_strdup(msn_message_get_body(msg)); | 550 |
| 551 g_return_val_if_fail(body != NULL, NULL); | |
| 730 | 552 |
| 731 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | 553 table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); |
| 732 | 554 |
| 733 while (*s != '\r' && *s != '\0') { | 555 while (*s != '\r' && *s != '\0') |
| 556 { | |
| 734 char *key, *value; | 557 char *key, *value; |
| 735 | 558 |
| 736 key = s; | 559 key = s; |
| 737 | 560 |
| 738 GET_NEXT(s); | 561 GET_NEXT(s); |
| 739 | 562 |
| 740 value = s; | 563 value = s; |
| 741 | 564 |
| 742 GET_NEXT_LINE(s); | 565 GET_NEXT_LINE(s); |
| 743 | 566 |
| 744 if ((c = strchr(key, ':')) != NULL) { | 567 if ((c = strchr(key, ':')) != NULL) |
| 568 { | |
| 745 *c = '\0'; | 569 *c = '\0'; |
| 746 | 570 |
| 747 g_hash_table_insert(table, g_strdup(key), g_strdup(value)); | 571 g_hash_table_insert(table, g_strdup(key), g_strdup(value)); |
| 748 } | 572 } |
| 749 } | 573 } |
| 750 | 574 |
| 751 g_free(body); | 575 g_free(body); |
| 752 | 576 |
| 753 return table; | 577 return table; |
| 754 } | 578 } |
| 755 |
