人人网需要天天登陆,才能获得持续的登录奖励,但是每次都登录啥的,感觉非常没意思,于是派生出用软件来自动登陆,这样既省时省事,又能获得奖励。 登录过程非常简单,就是模拟浏览器发送请求,如果你需要更新状态,需要从返回的请求包中提取出get_check,然后在发送的时候使用这个值就ok了。 当然服务器返回的数据中,使用的是gzip编码,需要进行响应的解码才能得到数据。 别的不多说了,贴C++代码。 环境 Win7 +VS2010, MFC+ zlib。 以下是登录代码: C++代码 // 模拟FireFox4.0 登陆网页 bool CLoginDlg::OnPcWebLogin(const CString &email, // username : email const CString &password) // password: { bool ret = false; CInternetSession session; CHttpConnection* pServer; CHttpFile* pf; m_check = ""; try { CString ServerName = "www.renren.com"; INTERNET_PORT nPort = 80; //port CString suffix = "autoLogin=false&origURL=http%3A%2F%2Fwww.renren.com%2Fhome&domain=renren.com"; CString data = "email=" + email + "&password=" + password + "&" + suffix; pServer = session.GetHttpConnection(ServerName, nPort); //拼接头部 pf = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,"/PLogin.do"); pf->AddRequestHeaders("Host: www.renren.com"); pf->AddRequestHeaders("User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20100101 Firefox/4.0"); pf->AddRequestHeaders("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); pf->AddRequestHeaders("Accept-Language: zh-cn,zh;q=0.5"); pf->AddRequestHeaders("Accept-Encoding: gzip, deflate"); pf->AddRequestHeaders("Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7"); // pf->AddRequestHeaders("Keep-Alive: 115"); // pf->AddRequestHeaders("DNT: 1"); // pf->AddRequestHeaders("Connection:Keep-Alive"); pf->AddRequestHeaders("Referer: http://www.renren.com/SysHome.do"); pf->AddRequestHeaders("Content-Type: application/x-www-form-urlencoded"); pf->SendRequest(NULL, 0, data.GetBuffer(0), data.GetLength()); DWORD statusCode = 0; if(!pf->QueryInfoStatusCode(statusCode) || statusCode != HTTP_STATUS_OK) { CString e; e.Format("PC WEB Login failed, Pls Check. status code = %d/n", statusCode); throw exception(e.GetBuffer()); } DWORD ptrLen = 100 * 1024; // 以下为读取数据 LPSTR ptr = new CHAR[ptrLen]; ZeroMemory(ptr, ptrLen); DWORD len = 0, len2 = 0; do { len = pf->Read(ptr + len2, ptrLen); len2 += len; }while(len != 0); LPSTR ptr2 = new CHAR[ptrLen]; ZeroMemory(ptr2, ptrLen); // 由gzip解压 httpgzdecompress((Byte *)ptr, len2, (Byte *)ptr2, &ptrLen); delete ptr; ptr = NULL; // 寻找校验码 LPSTR checkBeginPos = strstr(ptr2, "get_check:/'"); if(checkBeginPos != NULL) { checkBeginPos += strlen("get_check:/'"); LPSTR checkEndPos = strstr(checkBeginPos, "/'"); if(checkEndPos != NULL) { *checkEndPos = '/0'; m_check = checkBeginPos; ret = true; } } delete ptr2; ptr2 = NULL; } catch(exception e) { TRACE("[ERROR]:%s/n", e.what()); } if(pf != NULL) { pf->Close(); delete pf; pf = NULL; } if(pServer != NULL) { pServer->Close(); delete pServer; pServer = NULL; } session.Close(); return ret; }
以下是发送状态的代码。 这里面的状态要求是utf8编码,务必请自己转换。 C++代码 bool CLoginDlg::OnPcWebStatus(const CString &status) // status for update { bool ret = false; if(m_check == "") { TRACE("Pls Login First!/n"); return ret; } CInternetSession session; CHttpConnection* pServer; CHttpFile* pf; CString ServerName = "status.renren.com"; INTERNET_PORT nPort = 80; //port CString data = "c=" + status + "&raw=" + status + "&isAtHome=1&publisher_form_ticket=" + m_check + "&requestToken=" + m_check; pServer = session.GetHttpConnection(ServerName,nPort);
//拼接头部 pf = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST,"/doing/update.do?"); pf->AddRequestHeaders("Host: status.renren.com"); pf->AddRequestHeaders("User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0) Gecko/20100101 Firefox/4.0"); pf->AddRequestHeaders("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); pf->AddRequestHeaders("Accept-Language: zh-cn,zh;q=0.5"); pf->AddRequestHeaders("Accept-Encoding: gzip, deflate"); pf->AddRequestHeaders("Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7"); // pf->AddRequestHeaders("Keep-Alive: 115"); // pf->AddRequestHeaders("DNT: 1"); // pf->AddRequestHeaders("Connection:Keep-Alive"); pf->AddRequestHeaders("Content-Type: application/x-www-form-urlencoded; charset=UTF-8"); pf->AddRequestHeaders("Referer: http://status.renren.com/ajaxproxy.htm");
pf->SendRequest(NULL,0,data.GetBuffer(0), data.GetLength()); ret = true; DWORD statusCode = 0; if(!pf->QueryInfoStatusCode(statusCode) || statusCode != HTTP_STATUS_OK) { TRACE("Fuck for error %d/n", statusCode); ret = false; } if(pf != NULL) { pf->Close(); delete pf; pf = NULL; } if(pServer != NULL) { pServer->Close(); delete pServer; pServer = NULL; } session.Close(); return ret; }
转换代码如下: C++代码 DWORD ucs2Len = MultiByteToWideChar(CP_ACP, 0, status.GetBuffer(0), status.GetLength(), NULL, 0); PWCHAR ucs2 = new WCHAR[ucs2Len + 1]; ZeroMemory(ucs2, (ucs2Len + 1) * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, status.GetBuffer(0), status.GetLength(), ucs2, ucs2Len + 1); DWORD utf8Len = WideCharToMultiByte(CP_UTF8, 0, ucs2, ucs2Len, NULL, 0, 0, 0); PCHAR utf8 = new CHAR[utf8Len + 1]; ZeroMemory(utf8, (utf8Len + 1) * sizeof(CHAR)); WideCharToMultiByte(CP_UTF8, 0, ucs2, ucs2Len, utf8, utf8Len, 0, 0); CString newStatus = utf8; delete [] utf8; utf8 = NULL; delete [] ucs2; ucs2 = NULL;
最后还有最重要的是,gzip解码代码,这部分代码时参考某位大神提供的gzip的测试代码,具体是哪位大神,没有记录下来,非常的不好意思。 C++代码 /* HTTP gzip decompress */ int httpgzdecompress(Byte *zdata, uLong nzdata, Byte *data, uLong *ndata) { int err = 0; z_stream d_stream = {0}; /* decompression stream */ static char dummy_head[2] = { 0x8 + 0x7 * 0x10, (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, }; d_stream.zalloc = (alloc_func)0; d_stream.zfree = (free_func)0; d_stream.opaque = (voidpf)0; d_stream.next_in = zdata; d_stream.avail_in = 0; d_stream.next_out = data; if(inflateInit2(&d_stream, 47) != Z_OK) return -1; while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) { d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break; if(err != Z_OK ) { if(err == Z_DATA_ERROR) { d_stream.next_in = (Bytef*) dummy_head; d_stream.avail_in = sizeof(dummy_head); if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) { return -1; } } else return -1; } } if(inflateEnd(&d_stream) != Z_OK) return -1; *ndata = d_stream.total_out; return 0; }
|