00001
00023
00024
00025 #include "debug.h"
00026 #include "notify.h"
00027 #include "request.h"
00028 #include "server.h"
00029
00030 #include "buddy_opt.h"
00031 #include "char_conv.h"
00032 #include "group_conv.h"
00033 #include "group_find.h"
00034 #include "group_free.h"
00035 #include "group_hash.h"
00036 #include "group_info.h"
00037 #include "group_join.h"
00038 #include "group_opt.h"
00039 #include "group_network.h"
00040
00041 enum {
00042 QQ_GROUP_JOIN_OK = 0x01,
00043 QQ_GROUP_JOIN_NEED_AUTH = 0x02,
00044 };
00045
00046
00047 void _qq_group_exit_with_gc_and_id(gc_and_uid * g)
00048 {
00049 GaimConnection *gc;
00050 guint32 internal_group_id;
00051 qq_group *group;
00052
00053 g_return_if_fail(g != NULL && g->gc != NULL && g->uid > 0);
00054 gc = g->gc;
00055 internal_group_id = g->uid;
00056
00057 group = qq_group_find_by_internal_group_id(gc, internal_group_id);
00058 g_return_if_fail(group != NULL);
00059
00060 qq_send_cmd_group_exit_group(gc, group);
00061 }
00062
00063
00064
00065 void _qq_send_cmd_group_join_group(GaimConnection * gc, qq_group * group)
00066 {
00067 guint8 *raw_data, *cursor;
00068 gint bytes, data_len;
00069
00070 g_return_if_fail(gc != NULL && group != NULL);
00071 if (group->my_status == QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) {
00072 group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING;
00073 qq_group_refresh(gc, group);
00074 }
00075
00076 data_len = 5;
00077 raw_data = g_newa(guint8, data_len);
00078 cursor = raw_data;
00079
00080 bytes = 0;
00081 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP);
00082 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
00083
00084 if (bytes != data_len)
00085 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00086 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP));
00087 else
00088 qq_send_group_cmd(gc, group, raw_data, data_len);
00089 }
00090
00091
00092 void _qq_group_join_auth_with_gc_and_id(gc_and_uid * g, const gchar * reason_utf8)
00093 {
00094 GaimConnection *gc;
00095 qq_group *group;
00096 guint32 internal_group_id;
00097
00098 g_return_if_fail(g != NULL && g->gc != NULL && g->uid > 0);
00099 gc = g->gc;
00100 internal_group_id = g->uid;
00101
00102 group = qq_group_find_by_internal_group_id(gc, internal_group_id);
00103 if (group == NULL) {
00104 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", internal_group_id);
00105 return;
00106 } else
00107 qq_send_cmd_group_auth(gc, group, QQ_GROUP_AUTH_REQUEST_APPLY, 0, reason_utf8);
00108
00109 }
00110
00111
00112 void _qq_group_join_auth(GaimConnection * gc, qq_group * group)
00113 {
00114 gchar *msg;
00115 gc_and_uid *g;
00116 g_return_if_fail(gc != NULL && group != NULL);
00117
00118 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group (internal id: %d) needs authentication\n", group->internal_group_id);
00119
00120 msg = g_strdup_printf("Group \"%s\" needs authentication\n", group->group_name_utf8);
00121 g = g_new0(gc_and_uid, 1);
00122 g->gc = gc;
00123 g->uid = group->internal_group_id;
00124 gaim_request_input(gc, NULL, msg,
00125 _("Input request here"),
00126 _("Would you be my friend?"), TRUE, FALSE, NULL,
00127 _("Send"),
00128 G_CALLBACK(_qq_group_join_auth_with_gc_and_id),
00129 _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), g);
00130 g_free(msg);
00131 }
00132
00133
00134 unsigned char unknown32[32] = {0x68, 0x12, 0x8c, 0xf1, 0x95, 0xdd, 0xbb, 0x47,
00135 0xf6, 0xb1, 0xb0, 0xf6, 0x86, 0xd7, 0x26, 0x6d,
00136 0x47, 0xe9, 0x22, 0x57, 0xc2, 0xde, 0x68, 0xa5,
00137 0xd7, 0x0b, 0x3b, 0xa8, 0x90, 0x2c, 0xca, 0x1c
00138 };
00139 void qq_send_cmd_group_auth(GaimConnection * gc, qq_group * group, guint8 opt, guint32 uid, const gchar * reason_utf8) {
00140 guint8 *raw_data, *cursor;
00141 gchar *reason_qq;
00142 gint bytes, data_len;
00143
00144 g_return_if_fail(gc != NULL && group != NULL);
00145
00146 if (reason_utf8 == NULL || strlen(reason_utf8) == 0)
00147 reason_qq = g_strdup("");
00148 else
00149 reason_qq = utf8_to_qq(reason_utf8, QQ_CHARSET_DEFAULT);
00150
00151 if (opt == QQ_GROUP_AUTH_REQUEST_APPLY) {
00152 group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING;
00153 qq_group_refresh(gc, group);
00154 uid = 0;
00155 }
00156
00157 data_len = 44 + strlen(reason_qq) + 1;
00158 raw_data = g_newa(guint8, data_len);
00159 cursor = raw_data;
00160
00161 bytes = 0;
00162 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_JOIN_GROUP_AUTH);
00163 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
00164 bytes += create_packet_b(raw_data, &cursor, opt);
00165 bytes += create_packet_b(raw_data, &cursor, 0);
00166 bytes += create_packet_b(raw_data, &cursor, 32);
00167 bytes += create_packet_data(raw_data, &cursor, unknown32, 32);
00168 bytes += create_packet_dw(raw_data, &cursor, uid);
00169 bytes += create_packet_b(raw_data, &cursor, strlen(reason_qq));
00170 bytes += create_packet_data(raw_data, &cursor, reason_qq, strlen(reason_qq));
00171
00172 if (bytes != data_len)
00173 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00174 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_JOIN_GROUP_AUTH));
00175 else
00176 qq_send_group_cmd(gc, group, raw_data, data_len);
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 void qq_send_cmd_group_exit_group(GaimConnection * gc, qq_group * group)
00190 {
00191 guint8 *raw_data, *cursor;
00192 gint bytes, data_len;
00193
00194 g_return_if_fail(gc != NULL && group != NULL);
00195
00196 data_len = 5;
00197 raw_data = g_newa(guint8, data_len);
00198 cursor = raw_data;
00199
00200 bytes = 0;
00201 bytes += create_packet_b(raw_data, &cursor, QQ_GROUP_CMD_EXIT_GROUP);
00202 bytes += create_packet_dw(raw_data, &cursor, group->internal_group_id);
00203
00204 if (bytes != data_len)
00205 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00206 "Fail create packet for %s\n", qq_group_cmd_get_desc(QQ_GROUP_CMD_EXIT_GROUP));
00207 else
00208 qq_send_group_cmd(gc, group, raw_data, data_len);
00209 }
00210
00211
00212
00213 void qq_process_group_cmd_exit_group(guint8 * data, guint8 ** cursor, gint len, GaimConnection * gc) {
00214 gint bytes, expected_bytes;
00215 guint32 internal_group_id;
00216 GaimChat *chat;
00217 qq_group *group;
00218 qq_data *qd;
00219
00220 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00221 g_return_if_fail(data != NULL && len > 0);
00222 qd = (qq_data *) gc->proto_data;
00223
00224 bytes = 0;
00225 expected_bytes = 4;
00226 bytes += read_packet_dw(data, cursor, len, &internal_group_id);
00227
00228 if (bytes == expected_bytes) {
00229 group = qq_group_find_by_internal_group_id(gc, internal_group_id);
00230 if (group != NULL) {
00231 chat =
00232 gaim_blist_find_chat
00233 (gaim_connection_get_account(gc), g_strdup_printf("%d", group->external_group_id));
00234 if (chat != NULL)
00235 gaim_blist_remove_chat(chat);
00236 qq_group_remove_by_internal_group_id(qd, internal_group_id);
00237 }
00238 gaim_notify_info(gc, _("QQ Qun Operation"), _("You have successfully exit group"), NULL);
00239 } else
00240 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00241 "Invalid exit group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
00242
00243 }
00244
00245
00246
00247 void qq_process_group_cmd_join_group_auth(guint8 * data, guint8 ** cursor, gint len, GaimConnection * gc) {
00248 gint bytes, expected_bytes;
00249 guint32 internal_group_id;
00250 qq_data *qd;
00251
00252 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00253 g_return_if_fail(data != NULL && len > 0);
00254 qd = (qq_data *) gc->proto_data;
00255
00256 bytes = 0;
00257 expected_bytes = 4;
00258 bytes += read_packet_dw(data, cursor, len, &internal_group_id);
00259 g_return_if_fail(internal_group_id > 0);
00260
00261 if (bytes == expected_bytes)
00262 gaim_notify_info
00263 (gc, _("QQ Group Auth"), _("You authorization operation has been accepted by QQ server"), NULL);
00264 else
00265 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00266 "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
00267
00268 }
00269
00270
00271
00272 void qq_process_group_cmd_join_group(guint8 * data, guint8 ** cursor, gint len, GaimConnection * gc) {
00273 gint bytes, expected_bytes;
00274 guint32 internal_group_id;
00275 guint8 reply;
00276 qq_group *group;
00277
00278 g_return_if_fail(gc != NULL && data != NULL && len > 0);
00279
00280 bytes = 0;
00281 expected_bytes = 5;
00282 bytes += read_packet_dw(data, cursor, len, &internal_group_id);
00283 bytes += read_packet_b(data, cursor, len, &reply);
00284
00285 if (bytes != expected_bytes) {
00286 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00287 "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes);
00288 return;
00289 } else {
00290 group = qq_group_find_by_internal_group_id(gc, internal_group_id);
00291
00292 g_return_if_fail(group != NULL);
00293 switch (reply) {
00294 case QQ_GROUP_JOIN_OK:
00295 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8);
00296 group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER;
00297 qq_group_refresh(gc, group);
00298
00299 qq_group_conv_show_window(gc, group);
00300 qq_send_cmd_group_get_group_info(gc, group);
00301 break;
00302 case QQ_GROUP_JOIN_NEED_AUTH:
00303 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00304 "Fail joining group [%d] %s, needs authentication\n",
00305 group->external_group_id, group->group_name_utf8);
00306 group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER;
00307 qq_group_refresh(gc, group);
00308 _qq_group_join_auth(gc, group);
00309 break;
00310 default:
00311 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00312 "Error joining group [%d] %s, unknown reply: 0x%02x\n",
00313 group->external_group_id, group->group_name_utf8, reply);
00314 }
00315 }
00316 }
00317
00318
00319
00320 void qq_group_join(GaimConnection * gc, GHashTable * data)
00321 {
00322 gchar *internal_group_id_ptr;
00323 guint32 internal_group_id;
00324 qq_group *group;
00325
00326 g_return_if_fail(gc != NULL && data != NULL);
00327
00328 internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id");
00329 internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
00330
00331 g_return_if_fail(internal_group_id > 0);
00332
00333
00334
00335 group = qq_group_find_by_internal_group_id(gc, internal_group_id);
00336 if (group == NULL)
00337 group = qq_group_from_hashtable(gc, data);
00338
00339 g_return_if_fail(group != NULL);
00340
00341 switch (group->auth_type) {
00342 case QQ_GROUP_AUTH_TYPE_NO_AUTH:
00343 case QQ_GROUP_AUTH_TYPE_NEED_AUTH:
00344 _qq_send_cmd_group_join_group(gc, group);
00345 break;
00346 case QQ_GROUP_AUTH_TYPE_NO_ADD:
00347 gaim_notify_warning(gc, NULL, _("This group does not allow others to join"), NULL);
00348 break;
00349 default:
00350 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unknown group auth type: %d\n", group->auth_type);
00351 }
00352 }
00353
00354
00355 void qq_group_exit(GaimConnection * gc, GHashTable * data)
00356 {
00357 gchar *internal_group_id_ptr;
00358 guint32 internal_group_id;
00359 gc_and_uid *g;
00360
00361 g_return_if_fail(gc != NULL && data != NULL);
00362
00363 internal_group_id_ptr = g_hash_table_lookup(data, "internal_group_id");
00364 internal_group_id = strtol(internal_group_id_ptr, NULL, 10);
00365
00366 g_return_if_fail(internal_group_id > 0);
00367
00368 g = g_new0(gc_and_uid, 1);
00369 g->gc = gc;
00370 g->uid = internal_group_id;
00371
00372 gaim_request_action(gc, _("QQ Qun Operation"),
00373 _("Are you sure to exit this Qun?"),
00374 _
00375 ("Note, if you are the creator, \nthis operation will eventually remove this Qun."),
00376 1, g, 2, _("Cancel"),
00377 G_CALLBACK(qq_do_nothing_with_gc_and_uid),
00378 _("Go ahead"), G_CALLBACK(_qq_group_exit_with_gc_and_id));
00379
00380 }
00381
00382
00383