json_t *lwqq__parse_retcode_result(json_t *json,int* retcode) { //{"retcode":0,"result":......} /** * Frist, we parse retcode that indicate whether we get * correct response from server */ char* value = json_parse_simple_value(json, "retcode"); if(!value){ *retcode = LWQQ_EC_ERROR; return NULL; } *retcode = s_atoi(value,LWQQ_EC_ERROR); /** * Second, Check whether there is a "result" key in json object * if success it would return result; * if failed it would return NULL; */ json_t* result = json_find_first_label_all(json, "result"); if(result == NULL) return NULL; return result->child; }
/** * Parse value from json object whose value is a simle string * Caller dont need to free the returned string. * * @param json Json object setup by json_parse_document() * @param key the key you want to search * * @return Key whose value will be searched */ char *json_parse_simple_value(json_t *json, const char *key) { json_t *val; if (!json || !key) return NULL; val = json_find_first_label_all(json, key); if (val && val->child && val->child->text) { return val->child->text; } return NULL; }
json_t *json_find_first_label_all (const json_t * json, const char *text_label) { json_t *cur, *tmp; assert (json != NULL); assert (text_label != NULL); if(json -> text != NULL && strcmp(json -> text, text_label) == 0){ return (json_t *)json; } for(cur = json -> child; cur != NULL; cur = cur -> next){ tmp = json_find_first_label_all(cur, text_label); if(tmp != NULL){ return tmp; } } return NULL; }
static gint do_send_buddy_msg(QQInfo *info, QQSendMsg *msg, GError **err) { GString *uin = msg -> to_uin; gint ret_code = 0; gint res = 0; gchar params[3000]; g_debug("Send msg to %s!(%s, %d)", uin -> str, __FILE__, __LINE__); Request *req = request_new(); Response *rps = NULL; request_set_method(req, "POST"); request_set_version(req, "HTTP/1.1"); request_set_uri(req, MSGFRIPATH); request_set_default_headers(req); request_add_header(req, "Host", MSGHOST); request_add_header(req, "Cookie", info -> cookie -> str); request_add_header(req, "Origin", "http://d.web2.qq.com"); request_add_header(req, "Content-Type", "application/x-www-form-urlencoded"); request_add_header(req, "Referer" , "http://"MSGHOST"/proxy.html?v=20110331002&callback=2"); GString *content; content = qq_sendmsg_contents_tostring(msg); g_snprintf(params, 3000, "r={\"to\":%s,\"face\":%s," "%s,\"msg_id\":%s," "\"clientid\":\"%s\",\"psessionid\":\"%s\"}" , uin -> str, msg -> face -> str , content -> str , msg -> msg_id -> str , info -> clientid -> str , info -> psessionid -> str); g_string_free(content, TRUE); gchar *euri = g_uri_escape_string(params, "=", FALSE); request_append_msg(req, euri, strlen(euri)); g_free(euri); g_snprintf(params, 3000, "%u", (unsigned int)strlen(req -> msg -> str)); request_add_header(req, "Content-Length", params); Connection *con = connect_to_host(MSGHOST, 80); if(con == NULL){ g_warning("Can NOT connect to server!(%s, %d)" , __FILE__, __LINE__); request_del(req); return -1; } send_request(con, req); res = rcv_response(con, &rps); close_con(con); connection_free(con); if (-1 == res || !rps) { g_warning("Null point access (%s, %d)\n", __FILE__, __LINE__); ret_code = -1; goto error; } const gchar *retstatus = rps -> status -> str; json_t *json = NULL; if(g_strstr_len(retstatus, -1, "200") == NULL){ /* * Maybe some error occured. */ g_warning("Resoponse status is NOT 200, but %s (%s, %d)" , retstatus, __FILE__, __LINE__); ret_code = -1; goto error; } switch(json_parse_document(&json, rps -> msg -> str)) { case JSON_OK: break; default: g_warning("json_parser_document: syntax error. (%s, %d)" , __FILE__, __LINE__); } json_t *val = json_find_first_label_all(json, "result"); if(val != NULL){ val = val -> child; if(g_strstr_len(val -> text, -1, "ok") == NULL){ g_warning("Server return error. %s (%s, %d)" , val -> text, __FILE__, __LINE__); } }else{ g_warning("Server return: (%s, %d)%s", __FILE__, __LINE__ , rps -> msg -> str); } json_free_value(&json); error: request_del(req); response_del(rps); return ret_code; }
static gint do_logout(QQInfo *info, GError **err) { gint ret_code = 0; gint res = 0; g_debug("Logout... (%s, %d)", __FILE__, __LINE__); if(info -> psessionid == NULL || info -> psessionid -> len <= 0){ g_warning("Need psessionid !!(%s, %d)", __FILE__, __LINE__); return -1; } gchar params[300]; Request *req = request_new(); Response *rps = NULL; request_set_method(req, "GET"); request_set_version(req, "HTTP/1.1"); g_sprintf(params, LOGOUTPATH"?clientid=%s&psessionid=%s&t=%ld" , info -> clientid -> str , info -> psessionid -> str, get_now_millisecond()); request_set_uri(req, params); request_set_default_headers(req); request_add_header(req, "Host", LOGOUTHOST); request_add_header(req, "Cookie", info -> cookie -> str); request_add_header(req, "Referer", REFERER); Connection *con = connect_to_host(LOGOUTHOST, 80); if(con == NULL){ g_warning("Can NOT connect to server!(%s, %d)" , __FILE__, __LINE__); request_del(req); return -1; } send_request(con, req); res = rcv_response(con, &rps); close_con(con); connection_free(con); if (-1 == res || !rps) { g_warning("Null point access (%s, %d)\n", __FILE__, __LINE__); ret_code = -1; goto error; } const gchar *retstatus = rps -> status -> str; if(g_strstr_len(retstatus, -1, "200") == NULL){ /* * Maybe some error occured. */ g_warning("Resoponse status is NOT 200, but %s (%s, %d)" , retstatus, __FILE__, __LINE__); ret_code = -1; goto error; } json_t *json = NULL; switch(json_parse_document(&json, rps -> msg -> str)) { case JSON_OK: break; default: g_warning("json_parser_document: syntax error. (%s, %d)" , __FILE__, __LINE__); ret_code = -1; goto error; } json_t *retcode, *result; retcode = json_find_first_label_all(json, "retcode"); result = json_find_first_label_all(json, "result"); if(retcode != NULL && result != NULL){ if(g_strstr_len(result -> child -> text, -1, "ok") != NULL){ g_debug("Logout ok!(%s, %d)", __FILE__, __LINE__); ret_code = 0; } }else{ g_debug("(%s, %d)%s", __FILE__, __LINE__, rps -> msg -> str); } json_free_value(&json); error: request_del(req); response_del(rps); return ret_code; }
/* * Get the psessionid. * * This function is the last step of loginning */ static int get_psessionid(QQInfo *info) { int ret = NO_ERR; gint res = 0; if(info -> ptwebqq == NULL || info -> ptwebqq -> len <= 0){ g_warning("Need ptwebqq!!(%s, %d)", __FILE__, __LINE__); return PARAMETER_ERR; } Request *req = request_new(); Response *rps = NULL; request_set_method(req, "POST"); request_set_version(req, "HTTP/1.1"); request_set_uri(req, PSIDPATH); request_set_default_headers(req); request_add_header(req, "Host", PSIDHOST); request_add_header(req, "Cookie2", "$Version=1"); request_add_header(req, "Referer" , "http://d.web2.qq.com/proxy.html?v=20101025002"); GString *clientid = generate_clientid(); info -> clientid = clientid; g_debug("clientid: %s", clientid -> str); gchar* msg = g_malloc(500); g_snprintf(msg, 500, "{\"status\":\"%s\",\"ptwebqq\":\"%s\"," "\"passwd_sig\":""\"\",\"clientid\":\"%s\"" ", \"psessionid\":null}" , info -> me -> status -> str, info -> ptwebqq -> str , clientid -> str); gchar *escape = g_uri_escape_string(msg, NULL, FALSE); g_snprintf(msg, 500, "r=%s", escape); g_free(escape); request_append_msg(req, msg, strlen(msg)); gchar cl[10]; g_sprintf(cl, "%u", (unsigned int)strlen(msg)); request_add_header(req, "Content-Length", cl); request_add_header(req, "Content-Type" , "application/x-www-form-urlencoded"); g_free(msg); gchar *cookie = g_malloc(2000); gint idx = 0; if(info -> ptvfsession != NULL){ idx += g_snprintf(cookie + idx, 2000 - idx, "ptvfsession=%s; " , info -> ptvfsession -> str); } idx += g_snprintf(cookie + idx, 2000 - idx, "%s" , info -> cookie -> str); request_add_header(req, "Cookie", cookie); g_free(cookie); Connection *con = connect_to_host(PSIDHOST, 80); if(con == NULL){ g_warning("Can NOT connect to server!(%s, %d)" , __FILE__, __LINE__); request_del(req); return NETWORK_ERR; } send_request(con, req); res = rcv_response(con, &rps); if (-1 == res || !rps) { g_warning("Null point access (%s, %d)\n", __FILE__, __LINE__); ret = -1; goto error; } const gchar *retstatus = rps -> status -> str; if(g_strstr_len(retstatus, -1, "200") == NULL){ g_warning("Server status %s (%s, %d)", retstatus , __FILE__, __LINE__); ret = NETWORK_ERR; goto error; } json_t *json = NULL; switch(json_parse_document(&json, rps -> msg -> str)) { case JSON_OK: break; default: g_warning("json_parser_document: syntax error. (%s, %d)" , __FILE__, __LINE__); ret = NETWORK_ERR; goto error; } json_t *val; val = json_find_first_label_all(json, "retcode"); if(val -> child -> text[0] != '0'){ g_warning("Server return code %s(%s, %d)", val -> child -> text , __FILE__, __LINE__); ret = NETWORK_ERR; goto error; } val = json_find_first_label_all(json, "seskey"); if(val != NULL){ g_debug("seskey: %s (%s, %d)", val -> child -> text , __FILE__, __LINE__); info -> seskey = g_string_new(val -> child -> text); } val = json_find_first_label_all(json, "cip"); if(val != NULL){ info -> cip = g_string_new(val -> child -> text); } val = json_find_first_label_all(json, "index"); if(val != NULL){ info -> index = g_string_new(val -> child -> text); } val = json_find_first_label_all(json, "port"); if(val != NULL){ info -> port = g_string_new(val -> child -> text); } val = json_find_first_label_all(json, "status"); { g_debug("status: %s (%s, %d)", val -> child -> text , __FILE__, __LINE__); } val = json_find_first_label_all(json, "vfwebqq"); if(val != NULL){ g_debug("vfwebqq: %s (%s, %d)", val -> child -> text , __FILE__, __LINE__); info -> vfwebqq = g_string_new(val -> child -> text); } val = json_find_first_label_all(json, "psessionid"); if(val != NULL){ g_debug("psessionid: %s (%s, %d)", val -> child -> text , __FILE__, __LINE__); info -> psessionid = g_string_new(val -> child -> text); }else{ g_debug("Can not find pesssionid!(%s, %d): %s" , __FILE__, __LINE__, rps -> msg -> str); } error: json_free_value(&json); close_con(con); connection_free(con); request_del(req); response_del(rps); return ret; }