static void qq_modify_buddy_memo_from_menu_cb(PurpleBlistNode *node, gpointer data) { PurpleBuddy *buddy; qq_buddy_data *bd; PurpleConnection *gc; guint32 bd_uid; g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; g_return_if_fail(NULL != buddy); gc = purple_account_get_connection(purple_buddy_get_account(buddy)); g_return_if_fail(NULL != gc); bd = (qq_buddy_data *)purple_buddy_get_protocol_data(buddy); g_return_if_fail(NULL != bd); bd_uid = bd->uid; /* param: gc, uid, update_class, action * here, update_class is set to bd_uid. because some memo packages returned * without uid, which will make us confused */ qq_request_buddy_memo(gc, bd_uid, 0, QQ_BUDDY_MEMO_MODIFY); }
qq_buddy_data *qq_buddy_data_find(PurpleConnection *gc, guint32 uid) { gchar *who; PurpleBuddy *buddy; qq_buddy_data *bd; g_return_val_if_fail(gc != NULL, NULL); who = uid_to_purple_name(uid); if (who == NULL) return NULL; buddy = purple_find_buddy(purple_connection_get_account(gc), who); g_free(who); if (buddy == NULL) { purple_debug_error("QQ", "Can not find purple buddy of %u\n", uid); return NULL; } if ((bd = purple_buddy_get_protocol_data(buddy)) == NULL) { purple_debug_error("QQ", "Can not find buddy data of %u\n", uid); return NULL; } return bd; }
static void plainprpl_login(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); purple_debug_info("plainprpl", "logging in %s\n", account->username); purple_connection_update_progress(gc, _("Connecting"), 0, 2); purple_connection_update_progress(gc, _("Connected"), 1, 2); purple_connection_set_state(gc, PURPLE_CONNECTED); /* Setup plugin data */ plain_plugin_state *pstate = g_new0(plain_plugin_state, 1); /* General account data */ const char *listen_af = purple_account_get_string(account, "listen_af", NULL); const char *listen_port = purple_account_get_string(account, "listen_port", NULL); //check port if (listen_port == NULL || atoi(listen_port) < 1 || atoi(listen_port) >= 65535) { listen_port = PLAIN_DEFAULT_PORT_STR; purple_account_set_string(account, "listen_port", listen_port); } //check protocol if (listen_af == NULL || (strcmp(listen_af, "ipv4") && strcmp(listen_af, "ipv6"))) { listen_af = "ipv4"; purple_account_set_string(account, "listen_port", listen_af); } /* Select the address to listen on */ const char *listen_addr = (strcmp(listen_af, "ipv4") == 0) ? "0.0.0.0" : "::1"; pstate->sockaf = str_to_af(listen_af); pstate->sockfd = net_bind("plainprpl", listen_addr, listen_port, NULL, IPPROTO_UDP, pstate->sockaf); if (pstate->sockfd < 0) { purple_debug_info("plainprpl", "Failed to bind to %s\n", listen_addr); g_free(pstate); //TODO: diable plugin return; } else { purple_debug_info("plainprpl", "Bind to %s\n", listen_addr); } pstate->receive_timer = purple_timeout_add(80, plain_receive, gc); purple_connection_set_protocol_data(gc, pstate); /* Attach buddy data to each buddy */ GSList *list = purple_find_buddies(account, NULL); purple_debug_info("plainprpl", "Buddies to load: %d\n", g_slist_length(list)); GSList *iter = list; while (iter) { PurpleBuddy *buddy = iter->data; //purple_debug_info("plainprpl", "#plainprpl_login: attach custom data to buddy: %s\n", buddy->name); assert(purple_buddy_get_protocol_data(buddy) == NULL); const char *addr_str = purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "addr_str"); if (addr_str != NULL && strlen(addr_str)) { add_buddy_sdata(buddy, pstate); } else { purple_debug_info("plainprpl", "Empty address for buddy: %s\n", buddy->name); } /* Set offline by default */ purple_prpl_got_user_status(account, buddy->name, PLAIN_STATUS_OFFLINE, NULL); iter = iter->next; } g_slist_free(list); /* Call the on_login script - if it is set */ const char *on_login = purple_account_get_string(account, "on_login", NULL); exec_process(on_login, NULL, NULL, gc, NULL); }
static gboolean plain_receive(gpointer data) { purple_debug_info("plainprpl", "plain_receive called\n"); char msgbuf[MAX_MESSAGE_SIZE]; int msgbuf_len; IP addr; const char *status; PurpleConnection *gc; PurpleAccount *account; PurpleBuddy *buddy; plain_plugin_state *pstate; plain_buddy_state *bstate; /* Get time in seconds since 1970 */ time_t now = time(NULL); gc = (PurpleConnection *) data; account = purple_connection_get_account(gc); pstate = purple_connection_get_protocol_data(gc); /* Check if we need to ping any buddy */ ping_buddies(gc, now); msgbuf_len = sizeof(msgbuf); buddy = receive_msg(pstate, &addr, msgbuf, &msgbuf_len); /* Nothing to receive or error */ if (msgbuf_len <= 0) { return TRUE; } if (!g_utf8_validate(msgbuf, -1, NULL)) { purple_debug_info("plainprpl", "Received invalid UTF8 message from %s - ignore.\n", str_addr(&addr)); return TRUE; } /* We got a message and identified the sender */ purple_debug_info("plainprpl", "Received message from %s (%d Bytes): %s\n", str_addr(&addr), strlen(msgbuf), msgbuf); /* We got a message from a source we don't know */ gboolean allow_unknown = purple_account_get_bool(account, "allow_unknown", FALSE); if (buddy == NULL) { purple_debug_info("plainprpl", "Packet from unknown buddy from address %s.\n", str_addr(&addr)); if (allow_unknown && !pstate->block_unknown) { //temporary disable the setting pstate->block_unknown = TRUE; plainprpl_add_buddy_by_contact_request(gc, str_addr(&addr), msgbuf); } return TRUE; } bstate = purple_buddy_get_protocol_data(buddy); if (bstate == NULL) { purple_debug_info("plainprpl", "bstate of buddy %s is NULL.\n", buddy->name); return TRUE; } status = PLAIN_STATUS_ONLINE; if (strcmp(msgbuf, "/ping") == 0) { /* Received a ping from a buddy */ if ((bstate->time_recv + 5) < now) { /* Send pong at most every 5 seconds */ send_msg(pstate, bstate, "/pong"); } else { /* Ignore ping */ } } else if (strcmp(msgbuf, "/pong") == 0) { /* Nothing to do */ } else if (strcmp(msgbuf, "/bye") == 0) { status = PLAIN_STATUS_OFFLINE; } else if (msgbuf[0] != '/') { /* Display message */ serv_got_im(gc, bstate->name, msgbuf, PURPLE_MESSAGE_RECV, now); } else { /* Unknown command - ignore */ } bstate->time_recv = now; /* Set buddy status to online */ purple_prpl_got_user_status(account, bstate->name, status, NULL); return TRUE; //continue loop }
/* Ping buddies a ping every 5 minutes if there is no traffic */ void ping_buddies(PurpleConnection *gc, time_t now) { PurpleBuddy *buddy; PurpleAccount *account; plain_buddy_state *bstate; plain_plugin_state *pstate; time_t time_next; GSList *iter; account = purple_connection_get_account(gc); pstate = purple_connection_get_protocol_data(gc); if(pstate->time_next > now) { return; } time_next = now + (60*5); //max time we wait for another round const char *on_lookup = purple_account_get_string(account, "on_lookup", NULL); iter = pstate->all_buddies; while (iter) { buddy = iter->data; bstate = purple_buddy_get_protocol_data(buddy); //uninitialized buddy if(bstate == NULL) { purple_debug_info("plainprpl", "Buddy %s has no state set.\n", buddy->name); goto next; } //printf("Do ping_buddies for %s\n", buddy->name); int state = bstate->state; int state_step = bstate->state_step; time_t state_next = bstate->state_next; if(state == BUDDY_STATE_RESOLVE) { const char *addr_str = purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "addr_str"); if(exec_process(on_lookup, addr_str, on_lookup_handle, gc, buddy) == 0) { /* Script was called - wait for answer some other time */ purple_debug_info("plainprpl", "Lookup by SCRIPT succeded. Start to ping %s\n", str_addr(&bstate->addr)); state = BUDDY_STATE_PING; state_step = 1; state_next = now + 1; } else if(addr_parse_full(&bstate->addr, addr_str, PLAIN_DEFAULT_PORT_STR, pstate->sockaf) == 0) { purple_debug_info("plainprpl", "Lookup by DNS succeded (%s). Start to ping %s\n", addr_str, str_addr(&bstate->addr)); //switch to ping state state = BUDDY_STATE_PING; state_step = 1; state_next = now + 1; } else { if(state_step == 0) { state_step = 4; } else if(state_step < (5*60)) { state_step *= 2; } purple_debug_info("plainprpl", "Resolve failed. Try again in %d seconds.\n", state_step); state_next = now + state_step; } } else if(state == BUDDY_STATE_PING) { //send ping if(bstate->time_recv < (now - (5*60))) { if(state_step < (5*60)) { state_step *= 2; state_next = now + state_step; send_msg(pstate, bstate, "/ping"); /* Set buddy status to online */ purple_prpl_got_user_status(account, bstate->name, PLAIN_STATUS_OFFLINE, NULL); } else { state = BUDDY_STATE_RESOLVE; state_step = 1; state_next = now + 1; } } else { state_step = 1; state_next = now + (5*60); } } else { purple_debug_info("plainprpl", "Invalid state: %d\n", state); } bstate->state = state; bstate->state_step = state_step; bstate->state_next = state_next; /* Get next time we need to do something here */ if (state_next < time_next) { time_next = state_next; } next: iter = iter->next; } pstate->time_next = time_next; purple_debug_info("plainprpl", "Next iteration in %d seconds.\n", (int)(time_next - now)); }
void qq_process_add_buddy_no_auth(PurpleConnection *gc, guint8 *data, gint data_len, guint32 uid) { qq_data *qd; gchar **segments; gchar *dest_uid, *reply; PurpleBuddy *buddy; qq_buddy_data *bd; g_return_if_fail(data != NULL && data_len != 0); g_return_if_fail(uid != 0); qd = (qq_data *) gc->proto_data; purple_debug_info("QQ", "Process buddy add for id [%u]\n", uid); qq_show_packet("buddy_add_no_auth", data, data_len); if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) return; dest_uid = segments[0]; reply = segments[1]; if (strtoul(dest_uid, NULL, 10) != qd->uid) { /* should not happen */ purple_debug_error("QQ", "Add buddy reply is to [%s], not me!\n", dest_uid); g_strfreev(segments); return; } if (strtol(reply, NULL, 10) == 0) { /* add OK */ qq_buddy_find_or_new(gc, uid); qq_request_buddy_info(gc, uid, 0, 0); if (qd->client_version >= 2007) { qq_request_get_level_2007(gc, uid); } else { qq_request_get_level(gc, uid); } qq_request_get_buddies_online(gc, 0, 0); purple_debug_info("QQ", "Successed adding into %u's buddy list\n", uid); g_strfreev(segments); return; } /* need auth */ purple_debug_warning("QQ", "Failed adding buddy, need authorize\n"); buddy = qq_buddy_find(gc, uid); if (buddy == NULL) { buddy = qq_buddy_new(gc, uid); } if (buddy != NULL && (bd = purple_buddy_get_protocol_data(buddy)) != NULL) { /* Not authorized now, free buddy data */ qq_buddy_data_free(bd); purple_buddy_set_protocol_data(buddy, NULL); } add_buddy_authorize_input(gc, uid, NULL, 0); g_strfreev(segments); }
/* a floating text when mouse is on the icon, show connection status here */ static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { qq_buddy_data *bd; gchar *tmp; GString *str; PurplePresence *presence; PurpleStatus *status; gchar *moodtext; g_return_if_fail(b != NULL); presence = purple_buddy_get_presence(b); bd = purple_buddy_get_protocol_data(b); if (bd == NULL) return; if (bd->level == NULL) qq_request_get_level(purple_account_get_connection(purple_buddy_get_account(b)), bd->uid); /* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */ if (bd->ip.s_addr != 0) { str = g_string_new(NULL); g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port); if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append(str, " TCP"); } else { g_string_append(str, " UDP"); } g_string_free(str, TRUE); } tmp = g_strdup_printf("%d", bd->age); purple_notify_user_info_add_pair(user_info, _("Age"), tmp); g_free(tmp); switch (bd->gender) { case QQ_BUDDY_GENDER_GG: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male")); break; case QQ_BUDDY_GENDER_MM: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Female")); break; default: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown")); } if (bd->level) { tmp = g_strdup_printf("%d", bd->level); purple_notify_user_info_add_pair(user_info, _("Level"), tmp); g_free(tmp); } str = g_string_new(NULL); if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { g_string_append( str, _("Member") ); } if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) { g_string_append( str, _(" VIP") ); } if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append( str, _(" TCP") ); } if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) { g_string_append( str, _(" FromMobile") ); } if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { g_string_append( str, _(" BindMobile") ); } if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) { g_string_append( str, _(" Video") ); } if (bd->ext_flag & QQ_EXT_FLAG_ZONE) { g_string_append( str, _(" Zone") ); } purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); g_string_free(str, TRUE); status = purple_presence_get_status(presence, PURPLE_MOOD_NAME); moodtext = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT); if (moodtext) { purple_notify_user_info_add_pair(user_info, _("Signature"), moodtext); } #ifdef DEBUG tmp = g_strdup_printf( "%s (%04X)", qq_get_ver_desc(bd->client_tag), bd->client_tag ); purple_notify_user_info_add_pair(user_info, _("Ver"), tmp); g_free(tmp); tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X", bd->ext_flag, bd->comm_flag ); purple_notify_user_info_add_pair(user_info, _("Flag"), tmp); g_free(tmp); #endif }
static void _browser_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { PurpleAccount *account = userdata; PurpleBuddy *pb = NULL; switch (event) { case AVAHI_BROWSER_FAILURE: purple_debug_error("bonjour", "_browser_callback - Failure: %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); /* TODO: This is an error that should be handled. */ break; case AVAHI_BROWSER_NEW: /* A new peer has joined the network and uses iChat bonjour */ purple_debug_info("bonjour", "_browser_callback - new service\n"); /* Make sure it isn't us */ if (purple_utf8_strcasecmp(name, bonjour_get_jid(account)) != 0) { if (!avahi_service_resolver_new(avahi_service_browser_get_client(b), interface, protocol, name, type, domain, protocol, 0, _resolver_callback, account)) { purple_debug_warning("bonjour", "_browser_callback -- Error initiating resolver: %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); } } break; case AVAHI_BROWSER_REMOVE: purple_debug_info("bonjour", "_browser_callback - Remove service\n"); pb = purple_find_buddy(account, name); if (pb != NULL) { BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); AvahiBuddyImplData *b_impl; GSList *l; AvahiSvcResolverData *rd_search; g_return_if_fail(bb != NULL); b_impl = bb->mdns_impl_data; /* There may be multiple presences, we should only get rid of this one */ rd_search = g_new0(AvahiSvcResolverData, 1); rd_search->interface = interface; rd_search->protocol = protocol; rd_search->name = (gchar *) name; rd_search->type = (gchar *) type; rd_search->domain = (gchar *) domain; l = g_slist_find_custom(b_impl->resolvers, rd_search, _find_resolver_data); g_free(rd_search); if (l != NULL) { AvahiSvcResolverData *rd = l->data; b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd); /* This IP is no longer available */ if (rd->ip != NULL) { bb->ips = g_slist_remove(bb->ips, rd->ip); g_free((gchar *) rd->ip); } _cleanup_resolver_data(rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) bonjour_buddy_signed_off(pb); } } break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: break; default: purple_debug_info("bonjour", "Unrecognized Service browser event: %d.\n", event); } }
static void _resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { PurpleBuddy *pb; BonjourBuddy *bb; PurpleAccount *account = userdata; AvahiStringList *l; size_t size; char *key, *value; char ip[AVAHI_ADDRESS_STR_MAX]; AvahiBuddyImplData *b_impl; AvahiSvcResolverData *rd; GSList *res; g_return_if_fail(r != NULL); pb = purple_find_buddy(account, name); bb = (pb != NULL) ? purple_buddy_get_protocol_data(pb) : NULL; switch (event) { case AVAHI_RESOLVER_FAILURE: purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n", avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); avahi_service_resolver_free(r); if (bb != NULL) { b_impl = bb->mdns_impl_data; res = g_slist_find_custom(b_impl->resolvers, r, _find_resolver_data_by_resolver); if (res != NULL) { rd = res->data; b_impl->resolvers = g_slist_remove_link(b_impl->resolvers, res); /* We've already freed the resolver */ rd->resolver = NULL; _cleanup_resolver_data(rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) bonjour_buddy_signed_off(pb); } } break; case AVAHI_RESOLVER_FOUND: purple_debug_info("bonjour", "_resolve_callback - name:%s account:%p bb:%p\n", name, account, bb); /* create a buddy record */ if (bb == NULL) bb = bonjour_buddy_new(name, account); b_impl = bb->mdns_impl_data; /* If we're reusing an existing buddy, it may be a new resolver or an existing one. */ res = g_slist_find_custom(b_impl->resolvers, r, _find_resolver_data_by_resolver); if (res != NULL) rd = res->data; else { rd = g_new0(AvahiSvcResolverData, 1); rd->resolver = r; rd->interface = interface; rd->protocol = protocol; rd->name = g_strdup(name); rd->type = g_strdup(type); rd->domain = g_strdup(domain); b_impl->resolvers = g_slist_prepend(b_impl->resolvers, rd); } /* Get the ip as a string */ ip[0] = '\0'; avahi_address_snprint(ip, AVAHI_ADDRESS_STR_MAX, a); purple_debug_info("bonjour", "_resolve_callback - name:%s ip:%s prev_ip:%s\n", name, ip, rd->ip); if (rd->ip == NULL || strcmp(rd->ip, ip) != 0) { /* We store duplicates in bb->ips, so we always remove the one */ if (rd->ip != NULL) { bb->ips = g_slist_remove(bb->ips, rd->ip); g_free((gchar *) rd->ip); } /* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */ if (protocol == AVAHI_PROTO_INET6) { rd->ip = g_strdup_printf("%s%%%d", ip, interface); bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip); } else { rd->ip = g_strdup(ip); bb->ips = g_slist_append(bb->ips, (gchar *) rd->ip); } } bb->port_p2pj = port; /* Obtain the parameters from the text_record */ clear_bonjour_buddy_values(bb); for(l = txt; l != NULL; l = l->next) { if (avahi_string_list_get_pair(l, &key, &value, &size) < 0) continue; set_bonjour_buddy_value(bb, key, value, size); /* TODO: Since we're using the glib allocator, I think we * can use the values instead of re-copying them */ avahi_free(key); avahi_free(value); } if (!bonjour_buddy_check(bb)) { b_impl->resolvers = g_slist_remove(b_impl->resolvers, rd); _cleanup_resolver_data(rd); /* If this was the last resolver, remove the buddy */ if (b_impl->resolvers == NULL) { if (pb != NULL) bonjour_buddy_signed_off(pb); else bonjour_buddy_delete(bb); } } else /* Add or update the buddy in our buddy list */ bonjour_buddy_add_to_purple(bb, pb); break; default: purple_debug_info("bonjour", "Unrecognized Service Resolver event: %d.\n", event); } }
static void skypeweb_got_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) { gchar *username = user_data; PurpleNotifyUserInfo *user_info; JsonObject *userobj; PurpleBuddy *buddy; SkypeWebBuddy *sbuddy; const gchar *new_avatar; if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) return; userobj = json_node_get_object(node); user_info = purple_notify_user_info_new(); #define _SKYPE_USER_INFO(prop, key) if (prop && json_object_has_member(userobj, (prop)) && !json_object_get_null_member(userobj, (prop))) \ purple_notify_user_info_add_pair_html(user_info, _(key), json_object_get_string_member(userobj, (prop))); _SKYPE_USER_INFO("firstname", "First Name"); _SKYPE_USER_INFO("lastname", "Last Name"); _SKYPE_USER_INFO("birthday", "Birthday"); //_SKYPE_USER_INFO("gender", "Gender"); if (json_object_has_member(userobj, "gender") && !json_object_get_null_member(userobj, "gender")) { const gchar *gender = json_object_get_string_member(userobj, "gender"); const gchar *gender_output; if (*gender == '1') { gender_output = _("Male"); } else if (*gender == '2') { gender_output = _("Female"); } else { gender_output = _("Unknown"); } purple_notify_user_info_add_pair_html(user_info, _("Gender"), gender_output); } _SKYPE_USER_INFO("language", "Language"); _SKYPE_USER_INFO("country", "Country"); _SKYPE_USER_INFO("province", "Province"); _SKYPE_USER_INFO("city", "City"); _SKYPE_USER_INFO("homepage", "Homepage"); _SKYPE_USER_INFO("about", "About"); _SKYPE_USER_INFO("jobtitle", "Job Title"); _SKYPE_USER_INFO("phoneMobile", "Phone - Mobile"); _SKYPE_USER_INFO("phoneHome", "Phone - Home"); _SKYPE_USER_INFO("phoneOffice", "Phone - Office"); //_SKYPE_USER_INFO("mood", "Mood"); //_SKYPE_USER_INFO("richMood", "Mood"); //_SKYPE_USER_INFO("avatarUrl", "Avatar"); buddy = purple_find_buddy(sa->account, username); if (buddy) { sbuddy = purple_buddy_get_protocol_data(buddy); if (sbuddy == NULL) { sbuddy = g_new0(SkypeWebBuddy, 1); purple_buddy_set_protocol_data(buddy, sbuddy); sbuddy->skypename = g_strdup(username); sbuddy->sa = sa; } new_avatar = json_object_get_string_member(userobj, "avatarUrl"); if (new_avatar && (!sbuddy->avatar_url || !g_str_equal(sbuddy->avatar_url, new_avatar))) { g_free(sbuddy->avatar_url); sbuddy->avatar_url = g_strdup(new_avatar); skypeweb_get_icon(buddy); } g_free(sbuddy->mood); sbuddy->mood = g_strdup(json_object_get_string_member(userobj, "mood")); } purple_notify_userinfo(sa->pc, username, user_info, NULL, NULL); g_free(username); }
/* process received extended (2007) text IM */ static void process_extend_im_text(PurpleConnection *gc, guint8 *data, gint len, qq_im_header *im_header) { qq_data *qd; guint16 purple_msg_type; gchar *who; gchar *msg_smiley, *msg_fmt, *msg_utf8; PurpleBuddy *buddy; qq_buddy_data *bd; gint bytes, tail_len; qq_im_format *fmt = NULL; struct { /* now comes the part for text only */ guint16 msg_seq; guint32 send_time; guint16 sender_icon; guint32 has_font_attr; guint8 unknown1[8]; guint8 fragment_count; guint8 fragment_index; guint8 msg_id; guint8 unknown2; guint8 msg_type; gchar *msg; /* no fixed length, ends with 0x00 */ guint8 fromMobileQQ; } im_text; g_return_if_fail (data != NULL && len > 0); g_return_if_fail(im_header != NULL); qd = (qq_data *) gc->proto_data; memset(&im_text, 0, sizeof(im_text)); /* qq_show_packet("Extend IM text", data, len); */ bytes = 0; bytes += qq_get16(&(im_text.msg_seq), data + bytes); bytes += qq_get32(&(im_text.send_time), data + bytes); bytes += qq_get16(&(im_text.sender_icon), data + bytes); bytes += qq_get32(&(im_text.has_font_attr), data + bytes); bytes += qq_getdata(im_text.unknown1, sizeof(im_text.unknown1), data + bytes); bytes += qq_get8(&(im_text.fragment_count), data + bytes); bytes += qq_get8(&(im_text.fragment_index), data + bytes); bytes += qq_get8(&(im_text.msg_id), data + bytes); bytes += 1; /* skip 0x00 */ bytes += qq_get8(&(im_text.msg_type), data + bytes); purple_debug_info("QQ", "IM Seq %u, id %04X, fragment %d-%d, type %d, %s\n", im_text.msg_seq, im_text.msg_id, im_text.fragment_count, im_text.fragment_index, im_text.msg_type, im_text.has_font_attr ? "exist font atrr" : ""); if (im_text.has_font_attr) { fmt = qq_im_fmt_new(); tail_len = qq_get_im_tail(fmt, data + bytes, len - bytes); im_text.msg = g_strndup((gchar *)(data + bytes), len - tail_len); } else { im_text.msg = g_strndup((gchar *)(data + bytes), len - bytes); } /* qq_show_packet("IM text", (guint8 *)im_text.msg , strlen(im_text.msg)); */ if(im_text.fragment_count == 0) im_text.fragment_count = 1; who = uid_to_purple_name(im_header->uid_from); buddy = purple_find_buddy(gc->account, who); if (buddy == NULL) { /* create no-auth buddy */ buddy = qq_buddy_new(gc, im_header->uid_from); } bd = (buddy == NULL) ? NULL : purple_buddy_get_protocol_data(buddy); if (bd != NULL) { bd->client_tag = im_header->version_from; bd->face = im_text.sender_icon; qq_update_buddy_icon(gc->account, who, bd->face); } purple_msg_type = 0; msg_smiley = qq_emoticon_to_purple(im_text.msg); if (fmt != NULL) { msg_fmt = qq_im_fmt_to_purple(fmt, msg_smiley); msg_utf8 = qq_to_utf8(msg_fmt, QQ_CHARSET_DEFAULT); g_free(msg_fmt); qq_im_fmt_free(fmt); } else { msg_utf8 = qq_to_utf8(msg_smiley, QQ_CHARSET_DEFAULT); } g_free(msg_smiley); /* send encoded to purple, note that we use im_text.send_time, * not the time we receive the message * as it may have been delayed when I am not online. */ serv_got_im(gc, who, msg_utf8, purple_msg_type, (time_t) im_text.send_time); g_free(msg_utf8); g_free(who); g_free(im_text.msg); }
/* a floating text when mouse is on the icon, show connection status here */ static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { qq_buddy_data *bd; gchar *tmp; GString *str; g_return_if_fail(b != NULL); bd = purple_buddy_get_protocol_data(b); if (bd == NULL) return; /* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */ if (bd->ip.s_addr != 0) { str = g_string_new(NULL); g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port); if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append(str, " TCP"); } else { g_string_append(str, " UDP"); } g_string_free(str, TRUE); } tmp = g_strdup_printf("%d", bd->age); purple_notify_user_info_add_pair(user_info, _("Age"), tmp); g_free(tmp); switch (bd->gender) { case QQ_BUDDY_GENDER_GG: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male")); break; case QQ_BUDDY_GENDER_MM: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Female")); break; case QQ_BUDDY_GENDER_UNKNOWN: purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown")); break; default: tmp = g_strdup_printf("Error (%d)", bd->gender); purple_notify_user_info_add_pair(user_info, _("Gender"), tmp); g_free(tmp); } if (bd->level) { tmp = g_strdup_printf("%d", bd->level); purple_notify_user_info_add_pair(user_info, _("Level"), tmp); g_free(tmp); } str = g_string_new(NULL); if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) { g_string_append( str, _("Member") ); } if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) { g_string_append( str, _(" VIP") ); } if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) { g_string_append( str, _(" TCP") ); } if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) { g_string_append( str, _(" FromMobile") ); } if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) { g_string_append( str, _(" BindMobile") ); } if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) { g_string_append( str, _(" Video") ); } if (bd->ext_flag & QQ_EXT_FLAG_ZONE) { g_string_append( str, _(" Zone") ); } purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); g_string_free(str, TRUE); #ifdef DEBUG tmp = g_strdup_printf( "%s (%04X)", qq_get_ver_desc(bd->client_tag), bd->client_tag ); purple_notify_user_info_add_pair(user_info, _("Ver"), tmp); g_free(tmp); tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X", bd->ext_flag, bd->comm_flag ); purple_notify_user_info_add_pair(user_info, _("Flag"), tmp); g_free(tmp); #endif }