📄 odc.c
字号:
break; } size = atol(sizestr); g_datalist_clear(&attributes); if ((size > 0) && (tmp + size > dataend)) break; embedded_data = g_new(struct embedded_data, 1); embedded_data->size = size; embedded_data->data = (const guint8 *)tmp; tmp += size; /* Skip past the closing </data> tag */ if (strncasecmp(tmp, "</data>", 7)) { g_free(embedded_data); break; } tmp += 7; g_hash_table_insert(embedded_datas, GINT_TO_POINTER(id), embedded_data); } } /* * Loop through the message, replacing OSCAR img tags with the * equivalent Purple img tag. */ images = NULL; newmsg = g_string_new(""); tmp = msg; while (purple_markup_find_tag("img", tmp, &start, &end, &attributes)) { int imgid = 0; idstr = g_datalist_get_data(&attributes, "id"); src = g_datalist_get_data(&attributes, "src"); sizestr = g_datalist_get_data(&attributes, "datasize"); if ((idstr != NULL) && (src != NULL) && (sizestr!= NULL)) { unsigned int id; size_t size; id = atoi(idstr); size = atol(sizestr); embedded_data = g_hash_table_lookup(embedded_datas, GINT_TO_POINTER(id)); if ((embedded_data != NULL) && (embedded_data->size == size)) { imgid = purple_imgstore_add_with_id(g_memdup(embedded_data->data, size), size, src); /* Record the image number */ images = g_slist_append(images, GINT_TO_POINTER(imgid)); } } /* Delete the attribute list */ g_datalist_clear(&attributes); /* Append the message up to the tag */ utf8 = purple_plugin_oscar_decode_im_part(account, conn->sn, encoding, 0x0000, tmp, start - tmp); if (utf8 != NULL) { g_string_append(newmsg, utf8); g_free(utf8); } if (imgid != 0) { /* Write the new image tag */ g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid); } /* Continue from the end of the tag */ tmp = end + 1; } /* Append any remaining message data */ if (tmp <= msgend) { utf8 = purple_plugin_oscar_decode_im_part(account, conn->sn, encoding, 0x0000, tmp, msgend - tmp); if (utf8 != NULL) { g_string_append(newmsg, utf8); g_free(utf8); } } /* Send the message */ imflags = 0; if (images != NULL) imflags |= PURPLE_MESSAGE_IMAGES; if (autoreply) imflags |= PURPLE_MESSAGE_AUTO_RESP; serv_got_im(gc, conn->sn, newmsg->str, imflags, time(NULL)); g_string_free(newmsg, TRUE); /* unref any images we allocated */ if (images) { GSList *l; for (l = images; l != NULL; l = l->next) purple_imgstore_unref_by_id(GPOINTER_TO_INT(l->data)); g_slist_free(images); } /* Delete our list of pointers to embedded images */ g_hash_table_destroy(embedded_datas);}/** * This is a purple_input_add() watcher callback function for reading * direct IM payload data. "Payload data" is always an IM and * maybe some embedded images or files or something. The actual * ODC frame is read using peer_connection_recv_cb(). We temporarily * switch to this watcher callback ONLY to read the payload, and we * switch back once we're done. */static voidpeer_odc_recv_cb(gpointer data, gint source, PurpleInputCondition cond){ PeerConnection *conn; OdcFrame *frame; ByteStream *bs; ssize_t read; conn = data; frame = conn->frame; bs = &frame->payload; /* Read data into the temporary buffer until it is complete */ read = recv(conn->fd, &bs->data[bs->offset], bs->len - bs->offset, 0); /* Check if the remote user closed the connection */ if (read == 0) { peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL); return; } if (read < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) /* No worries */ return; peer_connection_destroy(conn, OSCAR_DISCONNECT_LOST_CONNECTION, strerror(errno)); return; } bs->offset += read; if (bs->offset < bs->len) /* Waiting for more data to arrive */ return; /* We have a complete ODC/OFT frame! Handle it and continue reading */ byte_stream_rewind(bs); peer_odc_handle_payload(conn, (const char *)bs->data, bs->len, frame->encoding, frame->flags & 0x0001); g_free(bs->data); bs->data = NULL; g_free(frame); conn->frame = NULL; purple_input_remove(conn->watcher_incoming); conn->watcher_incoming = purple_input_add(conn->fd, PURPLE_INPUT_READ, peer_connection_recv_cb, conn);}/** * Handle an incoming OdcFrame. If there is a payload associated * with this frame, then we remove the old watcher and add the * ODC watcher to read in the payload. */voidpeer_odc_recv_frame(PeerConnection *conn, ByteStream *bs){ PurpleConnection *gc; OdcFrame *frame; gc = conn->od->gc; frame = g_new0(OdcFrame, 1); frame->type = byte_stream_get16(bs); frame->subtype = byte_stream_get16(bs); byte_stream_advance(bs, 2); byte_stream_getrawbuf(bs, frame->cookie, 8); byte_stream_advance(bs, 8); frame->payload.len = byte_stream_get32(bs); frame->encoding = byte_stream_get16(bs); byte_stream_advance(bs, 4); frame->flags = byte_stream_get16(bs); byte_stream_advance(bs, 4); byte_stream_getrawbuf(bs, frame->sn, 32); purple_debug_info("oscar", "Incoming ODC frame from %s with " "type=0x%04x, flags=0x%04x, payload length=%u\n", frame->sn, frame->type, frame->flags, frame->payload.len); if (!conn->ready) { /* * We need to verify the cookie so that we know we are * connected to our friend and not a malicious middle man. */ PurpleAccount *account; PurpleConversation *conv; if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING) { if (memcmp(conn->cookie, frame->cookie, 8)) { /* * Oh no! The user that connected to us did not send * the correct cookie! They are not our friend. Go try * to accept another connection? */ purple_debug_info("oscar", "Received an incorrect cookie. " "Closing connection.\n"); peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL); g_free(frame); return; } /* * Ok, we know they are legit. Now be courteous and * send them our cookie. Note: This doesn't seem * to be necessary, but it also doesn't seem to hurt. */ peer_odc_send_cookie(conn); } conn->ready = TRUE; /* * If they connected to us then close the listener socket * and send them our cookie. */ if (conn->listenerfd != -1) { close(conn->listenerfd); conn->listenerfd = -1; } /* Tell the local user that we are connected */ account = purple_connection_get_account(gc); conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn); purple_conversation_write(conv, NULL, _("Direct IM established"), PURPLE_MESSAGE_SYSTEM, time(NULL)); } if ((frame->type != 0x0001) && (frame->subtype != 0x0006)) { purple_debug_info("oscar", "Unknown ODC frame type 0x%04hx, " "subtype 0x%04hx.\n", frame->type, frame->subtype); return; } if (frame->flags & 0x0008) { /* I had to leave this. It's just too funny. It reminds me of my sister. */ purple_debug_info("oscar", "ohmigod! %s has started typing " "(DirectIM). He's going to send you a message! " "*squeal*\n", conn->sn); serv_got_typing(gc, conn->sn, 0, PURPLE_TYPING); } else if (frame->flags & 0x0004) { serv_got_typing(gc, conn->sn, 0, PURPLE_TYPED); } else { serv_got_typing_stopped(gc, conn->sn); } if (frame->payload.len > 0) { /* We have payload data! Switch to the ODC watcher to read it. */ frame->payload.data = g_new(guint8, frame->payload.len); frame->payload.offset = 0; conn->frame = frame; purple_input_remove(conn->watcher_incoming); conn->watcher_incoming = purple_input_add(conn->fd, PURPLE_INPUT_READ, peer_odc_recv_cb, conn); return; } g_free(frame);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -