Mercurial > pidgin.yaz
diff libpurple/protocols/qq/buddy_memo.c @ 25148:59ed7712be5e
2009.02.21 - flos <lonicerae(at)gmail.com>
* Rewrite whole buddy memo part
* Remove 'qq_to_utf8_len' and 'utf8_to_qq_len' functions in char_conv.c
* Update ChangeLog, AUTHORS
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Fri, 20 Feb 2009 18:00:32 +0000 |
parents | 8bc9f89f305e |
children | 7da3cf2530b7 |
line wrap: on
line diff
--- a/libpurple/protocols/qq/buddy_memo.c Mon Feb 09 15:52:13 2009 +0000 +++ b/libpurple/protocols/qq/buddy_memo.c Fri Feb 20 18:00:32 2009 +0000 @@ -1,10 +1,9 @@ - -#include "buddy_memo.h" #include "internal.h" #include "debug.h" #include "notify.h" #include "request.h" +#include "buddy_memo.h" #include "utils.h" #include "packet_parse.h" #include "buddy_list.h" @@ -14,314 +13,344 @@ #include "qq_define.h" #include "qq_base.h" #include "qq_network.h" -#include "../../blist.h" +#include "qq.h" -#include<string.h> -#include<stdlib.h> -#include<stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> #include <stdlib.h> #include <stdio.h> -static const gchar* buddy_memo_txt[] = { - "Name", - "Mobile", - "Telephone", - "Address", - "Email", - "ZipCode", - "Note" -};/* 备注信息的名称 */ - -/** - * 打印出好友备注信息 - * - * @param memo - */ -static void buddy_memo_debug( gchar* memo[] ); - -/** - * 好友备注对话框中上传按钮的响应函数 - * - * @param info_request - * @param fields - */ -static void buddy_memo_on_upload(void *info_request, PurpleRequestFields *fields); - - -static gchar** buddy_memo_init_data( ); +/* memo index */ +enum { + QQ_MEMO_ALIAS = 0, + QQ_MEMO_MOBILD, + QQ_MEMO_TELEPHONE, + QQ_MEMO_ADDRESS, + QQ_MEMO_EMAIL, + QQ_MEMO_ZIPCODE, + QQ_MEMO_NOTE, + QQ_MEMO_SIZE +}; - - -/** - * 弹出窗口显示好友备注信息 - * - * @param node - * @param buddy_data - */ -static void qq_show_buddy_memo( void* node, void* buddy_data ); - - - - +/* memo id */ +static const gchar *memo_id[] = { + N_("mm_alias"), + N_("mm_mobile"), + N_("mm_telephone"), + N_("mm_address"), + N_("mm_email"), + N_("mm_zipcode"), + N_("mm_note") +}; -/** - * 向服务器发送更新好友信息请求 - * - * @param gc - * @param buddy_data - */ -static void qq_request_buddy_memo_upload( PurpleBuddy * buddy ); +/* memo text */ +static const gchar *memo_txt[] = { + N_("Alias"), + N_("Mobile"), + N_("Telephone"), + N_("Address"), + N_("Email"), + N_("ZipCode"), + N_("Note") +}; - - -/*********************************************************************************************/ - - - +typedef struct _modify_memo_request { + PurpleConnection *gc; + guint32 bd_uid; + gchar **segments; +} modify_memo_request; -void buddy_memo_on_upload(void *bd, PurpleRequestFields *fields) +static void memo_debug(gchar **segments) { - int index; - PurpleBuddy *buddy; - qq_buddy_data* buddy_data; - int memoChanged; - const char *utf8_str; - buddy = ( PurpleBuddy* )bd; - buddy_data = ( qq_buddy_data* )( buddy->proto_data ); - - - purple_debug_info("QQ", "update memo\n"); - memoChanged = 0; - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - utf8_str = purple_request_fields_get_string(fields, buddy_memo_txt[index]); - if( utf8_str == NULL ){ - if( buddy_data->memo[index] != NULL ){ - g_free( buddy_data->memo[index] ); - memoChanged = 1; - } - buddy_data->memo[index] = g_new0( gchar,1 ); - } - else if( buddy_data->memo[index] == NULL || - strcmp( utf8_str, buddy_data->memo[index] ) != 0 ) - { - if( buddy_data->memo[index] != NULL ) - g_free( buddy_data->memo[index] ); - buddy_data->memo[index] = g_new( gchar,strlen(utf8_str)+2 ); - strcpy( buddy_data->memo[index], utf8_str ); - memoChanged = 1; - purple_debug_info( "QQ","%s=%s\n",buddy_memo_txt[index],utf8_str ); - } - - } - if( memoChanged == 1 ){ - qq_request_buddy_memo_upload( buddy ); - purple_blist_alias_buddy( buddy,buddy_data->memo[QQ_BUDDY_MEMO_NAME] ); - } - return; -} - -void qq_request_buddy_memo_upload( PurpleBuddy * buddy ) -{ - PurpleConnection* gc; - qq_buddy_data* buddy_data; - guint8* rawData; - gint bytes; - int rawDataSize; - int index; - int memoItemSize[QQ_BUDDY_MEMO_SIZE]; - gchar* qqCharSetTxt[QQ_BUDDY_MEMO_SIZE]; - - gc = buddy->account->gc; - buddy_data = ( qq_buddy_data* )buddy->proto_data; - purple_debug_info( "QQ","call qq_request_buddy_memo_download_upload\n" ); - rawDataSize = 7; - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - qqCharSetTxt[index] = utf8_to_qq( buddy_data->memo[index], QQ_CHARSET_DEFAULT ); - memoItemSize[index] = strlen( qqCharSetTxt[index] ); - rawDataSize += memoItemSize[index]+1; - } - rawData = g_new0( guint8,rawDataSize ); - bytes = 0; - bytes += qq_put8( rawData+bytes,QQ_BUDDY_MEMO_UPLOAD ); - bytes += qq_put8( rawData+bytes,0 ); - bytes += qq_put32( rawData+bytes, buddy_data->uid ); - bytes += qq_put8( rawData+bytes,0 ); - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - bytes += qq_put8( rawData+bytes,0xff&memoItemSize[index] ); //TODO: 0xff? - bytes += qq_putdata( rawData+bytes, (const guint8 *)qqCharSetTxt[index], memoItemSize[index] ); - } - - qq_send_cmd( gc, QQ_CMD_BUDDY_MEMO, rawData, rawDataSize ); - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - g_free( qqCharSetTxt[index] ); + gint index; + g_return_if_fail(NULL != segments); + for (index = 0; index < QQ_MEMO_SIZE; index++) { + purple_debug_info("QQ","memo[%i]=%s\n", index, segments[index]); } } - - -void qq_request_buddy_memo_download(PurpleConnection *gc, guint32 uid) +static void memo_free(gchar **segments) { - guint8 raw_data[16] = {0}; - //unsigned int tmp; - gint bytes; - - purple_debug_info("QQ", "Call qq_request_buddy_memo_download! qq number =%u\n", uid); - g_return_if_fail(uid != 0); - bytes = 0; - bytes += qq_put8( raw_data+bytes, QQ_BUDDY_MEMO_GET ); - bytes += qq_put32( raw_data+bytes, uid ); - - qq_send_cmd(gc, QQ_CMD_BUDDY_MEMO, (guint8*)raw_data, bytes); + gint index; + g_return_if_fail(NULL != segments); + for (index = 0; index < QQ_MEMO_SIZE; index++) { + g_free(segments[index]); + } + purple_debug_info("QQ", "memo freed\n"); } - -void qq_process_get_buddy_memo( PurpleConnection *gc, guint8* data, gint len ) +static void update_buddy_memo(PurpleConnection *gc, guint32 bd_uid, gchar *alias) { - qq_data *qd; + PurpleAccount *account; PurpleBuddy *buddy; gchar *who; - qq_buddy_data* bd; + g_return_if_fail(NULL != gc && NULL != alias); + + account = (PurpleAccount *)gc->account; + g_return_if_fail(NULL != account); + + who = uid_to_purple_name(bd_uid); + buddy = purple_find_buddy(account, who); + if (buddy == NULL || buddy->proto_data == NULL) { + g_free(who); + purple_debug_info("QQ", "Error Can not find %d!\n", bd_uid); + return; + } + purple_blist_alias_buddy(buddy, (const char*)alias); +} + +static void request_change_memo(PurpleConnection *gc, guint32 bd_uid, gchar **segments) +{ gint bytes; - guint8 lenth; - guint32 qq_number; - guint8 receive_cmd; - guint8 receive_data; - int k; + /* Attention, length of each segment must be guint8(0~255), + * so length of memo string is limited. + * convert it to guint8 first before put data */ + guint seg_len; + gint index; + guint8 raw_data[MAX_PACKET_SIZE - 16] = {0}; + + purple_debug_info( "QQ", "request_change_memo\n" ); + g_return_if_fail(NULL != gc && NULL != segments); bytes = 0; - bytes += qq_get8( &receive_cmd, data+bytes ); - switch( receive_cmd ){ - case QQ_BUDDY_MEMO_UPLOAD : - case QQ_BUDDY_MEMO_REMOVE : - bytes += qq_get8( &receive_data, data+bytes ); - if( receive_data == QQ_BUDDY_MEMO_REQUEST_SUCCESS ){//显示服务器接受请求对话框 - purple_debug_info( "QQ","服务器接受了请求\n" ); - purple_notify_message( gc, - PURPLE_NOTIFY_MSG_INFO, - _( "Your request was accepted" ), - _( "Your request was accepted" ), - _( "Your request was accepted" ), - NULL, - NULL); - } - else{ - purple_debug_info( "QQ","服务器拒绝了请求\n" ); - purple_notify_message( gc, - PURPLE_NOTIFY_MSG_INFO, - _( "Your request was rejected" ), - _( "Your request was rejected" ), - _( "Your request was rejected" ), - NULL, - NULL); - } - break; - case QQ_BUDDY_MEMO_GET: - qd = (qq_data *) gc->proto_data; - bytes += qq_get32( &qq_number, data+bytes ); - bytes ++;//qq号后面有一个字节不知道什么作用 - who = uid_to_purple_name( qq_number ); - buddy = purple_find_buddy( gc->account, who ); - if (buddy == NULL || buddy->proto_data == NULL) { - g_free(who); - purple_debug_info("QQ", "Error Can not find %d!\n", qq_number); - return; - } - bd = (qq_buddy_data *)buddy->proto_data; - - if( bd->memo == NULL ){ - bd->memo = g_new0( gchar*,QQ_BUDDY_MEMO_SIZE ); - } - for( k=0; k<QQ_BUDDY_MEMO_SIZE; k++ ){ - bytes += qq_get8( &lenth, data+bytes ); - if( bd->memo[k] != NULL ) - g_free( bd->memo[k] ); - bd->memo[k] = qq_to_utf8_len( (gchar*)(data+bytes), lenth, QQ_CHARSET_DEFAULT ); - bytes += lenth; - } - buddy_memo_debug( bd->memo ); - purple_blist_alias_buddy( buddy, - (const char*)bd->memo[QQ_BUDDY_MEMO_NAME] );//改名 - break; - default: - purple_debug_info( "QQ","error: unknown memo cmd \n" ); - break; + bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_MODIFY); + bytes += qq_put8(raw_data+bytes, 0x00); + bytes += qq_put32(raw_data+bytes, (guint32)bd_uid); + bytes += qq_put8(raw_data+bytes, 0x00); + for (index = 0; index < QQ_MEMO_SIZE; index++) { + seg_len = strlen(segments[index]); + seg_len = seg_len & 0xff; + bytes += qq_put8(raw_data+bytes, (guint8)seg_len); + bytes += qq_putdata(raw_data+bytes, (const guint8 *)segments[index], (guint8)seg_len); } - - + + /* debug */ + /* + qq_show_packet("MEMO MODIFY", raw_data, bytes); + */ + + qq_send_cmd(gc, QQ_CMD_BUDDY_MEMO, raw_data, bytes); +} + +static void memo_modify_cancle_cb(modify_memo_request *memo_request, PurpleRequestFields *fields) +{ + memo_free(memo_request->segments); + g_free(memo_request); } -void buddy_memo_debug( gchar* memo[] ) +/* prepare segments to be sent, string all convert to qq charset */ +static void memo_modify_ok_cb(modify_memo_request *memo_request, PurpleRequestFields *fields) { - gint k=0; - for( k=0; k<QQ_BUDDY_MEMO_SIZE; k++ ){ - purple_debug_info( "QQ","备注: %s=%s\n",buddy_memo_txt[k],memo[k] ); + PurpleConnection *gc; + guint32 bd_uid; + gchar **segments; + const gchar *utf8_str; + gchar *value = NULL; + gint index; + + g_return_if_fail(NULL != memo_request); + gc = (PurpleConnection *)memo_request->gc; + segments = (gchar **)memo_request->segments; + g_return_if_fail(NULL != gc && NULL != segments); + bd_uid = (guint32)memo_request->bd_uid; + + + for (index = 0; index < QQ_MEMO_SIZE; index++) { + utf8_str = purple_request_fields_get_string(fields, memo_id[index]); + /* update alias */ + if (QQ_MEMO_ALIAS == index) { + update_buddy_memo(gc, bd_uid, segments[QQ_MEMO_ALIAS]); + } + if (NULL == utf8_str) { + value = g_strdup(""); + } + else { + value = utf8_to_qq(utf8_str, QQ_CHARSET_DEFAULT); + /* Warnning: value will be string "(NULL)" instead of NULL */ + if (!g_strcmp0("(NULL)", value)) { + value = g_strdup(""); + } + } + g_free(segments[index]); + segments[index] = value; } + + memo_debug(segments); + /* send segments */ + request_change_memo(gc, bd_uid, segments); + + /* free segments */ + memo_free(segments); + g_free(memo_request); } -void qq_show_buddy_memo( void* node, void* buddy_data ) +/* memo modify dialogue */ +static void memo_modify_dialogue(PurpleConnection *gc, guint32 bd_uid, gchar **segments, gint iclass) { - qq_buddy_data* data; + modify_memo_request *memo_request; PurpleRequestField *field; PurpleRequestFields *fields; PurpleRequestFieldGroup *group; int index; - - data = ( qq_buddy_data* )buddy_data; - - fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); + gchar *utf8_title; + gchar *utf8_primary; + + g_return_if_fail(NULL != gc && NULL != segments); + + switch (iclass) { + case QQ_BUDDY_MEMO_GET: + break; + case QQ_BUDDY_MEMO_MODIFY: + /* Keep one dialog once a time */ + purple_request_close_with_handle(gc); + /* show dialog */ + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); + + for(index = 0; index < QQ_MEMO_SIZE; index++) { + /* + purple_debug_info("QQ", "id:%s txt:%s segment:%s\n", + memo_id[index], memo_txt[index], segments[index]); + */ - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - if( data->memo == NULL ){ - data->memo = buddy_memo_init_data( ); - } - field = purple_request_field_string_new(buddy_memo_txt[index], - buddy_memo_txt[index], - data->memo[index], - FALSE); - purple_request_field_group_add_field(group, field); + field = purple_request_field_string_new(memo_id[index], memo_txt[index], + segments[index], FALSE); + purple_request_field_group_add_field(group, field); + } + + /* for upload cb */ + memo_request = g_new0(modify_memo_request, 1); + memo_request->gc = gc; + memo_request->bd_uid = bd_uid; + memo_request->segments = segments; + /* callback */ + utf8_title = g_strdup(_("Buddy Memo")); + utf8_primary = g_strdup(_("Change his/her memo as you like")); + + purple_request_fields(gc, utf8_title, utf8_primary, NULL, + fields, + _("_Modify"), G_CALLBACK(memo_modify_ok_cb), + _("_Cancel"), G_CALLBACK(memo_modify_cancle_cb), + purple_connection_get_account(gc), NULL, NULL, + memo_request); + + g_free(utf8_title); + g_free(utf8_primary); + break; + default: + purple_debug_info("QQ", "unknown memo action\n"); + break; } - - purple_request_fields(node, - _( "Buddy_memo" ), - "", - NULL, - fields, - _("_Upload"), G_CALLBACK(buddy_memo_on_upload), - _("_Cancel"), NULL, - ((PurpleBuddy *)node)->account, ((PurpleBuddy *)node)->name, NULL, - node); } - +/* process reply to get_memo packet */ +void qq_process_get_buddy_memo(PurpleConnection *gc, guint8* data, gint data_len, guint32 action) +{ + gchar **segments; + gint bytes; + gint index; + guint8 rcv_cmd; + guint32 rcv_uid; + guint8 unk1_8; + guint8 is_success; -void qq_on_show_memo(PurpleBlistNode *node, gpointer data) -{ + g_return_if_fail(data != NULL && data_len != 0); + /* + qq_show_packet("MEMO REACH", data, data_len); + */ + purple_debug_info("QQ", "action:0x%x\n", action); + + bytes = 0; - PurpleBuddy *buddy; + /* TX looks a bit clever than before... :) */ + bytes += qq_get8(&rcv_cmd, data+bytes); + purple_debug_info("QQ", "rcv_cmd:0x%x\n", rcv_cmd); + /* it's possible that no buddy uid and no memo!!! */ + if (1 == data_len) { + purple_debug_info("QQ", "memo packet contains no buddy uid and memo...\n"); + return; + } - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; + switch (rcv_cmd) { + case QQ_BUDDY_MEMO_MODIFY: + case QQ_BUDDY_MEMO_REMOVE: + bytes += qq_get8(&is_success, data+bytes); + if (QQ_BUDDY_MEMO_REQUEST_SUCCESS == is_success) { + purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, + _("Memo Modify"), _("Your request was accepted."), NULL, + NULL, NULL); + purple_debug_info("QQ", "memo change succeessfully!"); + } + else { + purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO, + _("Memo Modify"), _("Your request was rejected."), NULL, + NULL, NULL); + purple_debug_info("QQ", "memo change failed"); + } + break; + case QQ_BUDDY_MEMO_GET: + bytes += qq_get32(&rcv_uid, data+bytes); + purple_debug_info("QQ", "rcv_uid:%u\n", rcv_uid); + bytes += qq_get8(&unk1_8, data+bytes); + purple_debug_info("QQ", "unk1_8:0x%x\n", unk1_8); + segments = g_new0(gchar*, QQ_MEMO_SIZE); + for (index = 0; index < QQ_MEMO_SIZE; index++) { + /* get utf8 string */ + bytes += qq_get_vstr(&segments[index], QQ_CHARSET_DEFAULT, data+bytes); + /* + purple_debug_info("QQ", "bytes:%d, seg:%s\n", bytes, segments[index]); + */ + } - qq_show_buddy_memo( node, buddy->proto_data ); + /* common action, update buddy memo */ + update_buddy_memo(gc, rcv_uid, segments[QQ_MEMO_ALIAS]); + + /* memo is thing that we regard our buddy as, so we need one more buddy_uid */ + memo_modify_dialogue(gc, rcv_uid, segments, action); - - purple_debug_info( "QQ","show memo" ); + break; + default: + purple_debug_info("QQ", "received an UNKNOWN memo cmd!!!"); + break; + } } - -gchar** buddy_memo_init_data( ) +/* request buddy memo */ +void qq_request_buddy_memo(PurpleConnection *gc, guint32 bd_uid, gint update_class, int action) { - gchar** pmemo; - int index; - pmemo = g_new0( gchar*,QQ_BUDDY_MEMO_SIZE ); - for( index=0; index<QQ_BUDDY_MEMO_SIZE; index++ ){ - pmemo[index] = g_new0( gchar,1 ); + guint8 raw_data[16] = {0}; + gint bytes; + + purple_debug_info("QQ", "qq_request_buddy_memo, buddy uid=%u\n", bd_uid); + g_return_if_fail(NULL != gc); + /* '0' is ok + g_return_if_fail(uid != 0); + */ + bytes = 0; + bytes += qq_put8(raw_data+bytes, QQ_BUDDY_MEMO_GET); + bytes += qq_put32(raw_data+bytes, bd_uid); + /* + qq_show_packet("MEMO REQUEST", raw_data, bytes); + */ + + qq_send_cmd_mess(gc, QQ_CMD_BUDDY_MEMO, (guint8*)raw_data, bytes, update_class, action); +} + +void qq_create_buddy_memo(PurpleConnection *gc, guint32 bd_uid, int action) +{ + gchar **segments; + gint index; + g_return_if_fail(NULL != gc); + + segments = g_new0(gchar*, QQ_MEMO_SIZE); + for (index = 0; index < QQ_MEMO_SIZE; index++) { + segments[index] = g_strdup("");; } - return pmemo; + memo_modify_dialogue(gc, bd_uid, segments, action); } +