int CVkProto::SendMsg(MCONTACT hContact, int, const char *szMsg) { debugLogA("CVkProto::SendMsg"); if (!IsOnline()) return 0; bool bIsChat = isChatRoom(hContact); LONG iUserID = getDword(hContact, bIsChat ? "vk_chat_id" : "ID" , -1); if (iUserID == -1 || iUserID == VK_FEED_USER) { ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact)); return 0; } int StickerId = 0; ptrA pszRetMsg(GetStickerId(szMsg, StickerId)); ULONG uMsgId = ::InterlockedIncrement(&m_msgId); AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, bIsChat? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh) << INT_PARAM(bIsChat ? "chat_id" : "user_id", iUserID) << INT_PARAM("random_id", ((LONG) time(NULL)) * 100 + uMsgId % 100); pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); if (StickerId) pReq << INT_PARAM("sticker_id", StickerId); else { pReq << CHAR_PARAM("message", szMsg); if (m_vkOptions.bSendVKLinksAsAttachments) { CMStringA szAttachments = GetAttachmentsFromMessage(szMsg); if (!szAttachments.IsEmpty()) { debugLogA("CVkProto::SendMsg Attachments = %s", szAttachments); pReq << CHAR_PARAM("attachment", szAttachments); } } } if (!bIsChat) pReq->pUserInfo = new CVkSendMsgParam(hContact, uMsgId); Push(pReq); if (!m_bServerDelivery && !bIsChat) ForkThread(&CVkProto::SendMsgAck, new CVkSendMsgParam(hContact, uMsgId)); if (!IsEmpty(pszRetMsg)) SendMsg(hContact, 0, pszRetMsg); return uMsgId; }
void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnOAuthAuthorize %d", reply->resultCode); GrabCookies(reply); if (reply->resultCode == 302) { // manual redirect LPCSTR pszLocation = findHeader(reply, "Location"); if (pszLocation) { if (!_strnicmp(pszLocation, szBlankUrl, sizeof(szBlankUrl)-1)) { m_szAccessToken = NULL; LPCSTR p = strstr(pszLocation, VK_TOKEN_BEG); if (p) { p += sizeof(VK_TOKEN_BEG)-1; for (LPCSTR q = p+1; *q; q++) { if (*q == '&' || *q == '=' || *q == '\"') { m_szAccessToken = mir_strndup(p, q-p); break; } } if (m_szAccessToken == NULL) m_szAccessToken = mir_strdup(p); setString("AccessToken", m_szAccessToken); RetrieveMyInfo(); } else { delSetting("AccessToken"); ConnectionFailed(LOGINERR_NOSERVER); } } else { AsyncHttpRequest *pRedirectReq = new AsyncHttpRequest(); pRedirectReq->requestType = REQUEST_GET; pRedirectReq->flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; pRedirectReq->m_pFunc = &CVkProto::OnOAuthAuthorize; pRedirectReq->AddHeader("Referer", m_prevUrl); pRedirectReq->Redirect(reply); if (!pRedirectReq->m_szUrl.IsEmpty()) { if (pRedirectReq->m_szUrl[0] == '/') pRedirectReq->m_szUrl = VK_LOGIN_DOMAIN + pRedirectReq->m_szUrl; ApplyCookies(pRedirectReq); m_prevUrl = pRedirectReq->m_szUrl; } pRedirectReq->m_bApiReq = false; pRedirectReq->bIsMainConn = true; Push(pRedirectReq); } } else ConnectionFailed(LOGINERR_NOSERVER); return; } if (reply->resultCode != 200 || !strstr(reply->pData, "form method=\"post\"")) { // something went wrong ConnectionFailed(LOGINERR_NOSERVER); return; } if (strstr(reply->pData, "service_msg_warning")) { ConnectionFailed(LOGINERR_WRONGPASSWORD); return; } CMStringA szAction, szBody; bool bSuccess = AutoFillForm(reply->pData, szAction, szBody); if (!bSuccess || szAction.IsEmpty() || szBody.IsEmpty()) { if (m_prevError) { ConnectionFailed(LOGINERR_NOSERVER); return; } m_prevError = true; } pReq = new AsyncHttpRequest(); pReq->requestType = REQUEST_POST; pReq->flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; pReq->m_szParam = szBody; pReq->m_szUrl = szAction; if (!pReq->m_szUrl.IsEmpty() && pReq->m_szUrl[0] == '/') pReq->m_szUrl = VK_LOGIN_DOMAIN + pReq->m_szUrl; m_prevUrl = pReq->m_szUrl; pReq->m_pFunc = &CVkProto::OnOAuthAuthorize; pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); pReq->Redirect(reply); ApplyCookies(pReq); pReq->m_bApiReq = false; pReq->bIsMainConn = true; Push(pReq); }
void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { SendFileFiled(fup, VKERR_OFFLINE); return; } debugLogA("CVkProto::OnReciveUploadFile %d", reply->resultCode); if (reply->resultCode != 200) { SendFileFiled(fup, VKERR_FILE_NOT_UPLOADED); return; } JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse || pReq->m_iErrorCode) { SendFileFiled(fup, pReq->m_iErrorCode); return; } int id = fup->GetType() == CVkFileUploadParam::typeAudio ? jnResponse["id"].as_int() : (*jnResponse.begin())["id"].as_int(); int owner_id = fup->GetType() == CVkFileUploadParam::typeAudio ? jnResponse["owner_id"].as_int() : (*jnResponse.begin())["owner_id"].as_int(); if ((id == 0) || (owner_id == 0)) { SendFileFiled(fup, VKERR_INVALID_PARAMETERS); return; } CMString Attachment; switch (fup->GetType()) { case CVkFileUploadParam::typeImg: Attachment.AppendFormat(_T("photo%d_%d"), owner_id, id); break; case CVkFileUploadParam::typeAudio: Attachment.AppendFormat(_T("audio%d_%d"), owner_id, id); break; case CVkFileUploadParam::typeDoc: Attachment.AppendFormat(_T("doc%d_%d"), owner_id, id); break; default: SendFileFiled(fup, VKERR_FTYPE_NOT_SUPPORTED); return; } AsyncHttpRequest *pMsgReq; if (isChatRoom(fup->hContact)) { ptrT tszChatID(getTStringA(fup->hContact, "ChatRoomID")); if (!tszChatID) { SendFileFiled(fup, VKERR_INVALID_USER); return; } CVkChatInfo *cc = GetChatById(tszChatID); if (cc == NULL) { SendFileFiled(fup, VKERR_INVALID_USER); return; } pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh) << INT_PARAM("chat_id", cc->m_chatid); pMsgReq->pUserInfo = pReq->pUserInfo; } else { LONG userID = getDword(fup->hContact, "ID", -1); if (userID == -1 || userID == VK_FEED_USER) { SendFileFiled(fup, VKERR_INVALID_USER); return; } pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh) << INT_PARAM("user_id", userID); pMsgReq->pUserInfo = new CVkSendMsgParam(fup->hContact, fup); } pMsgReq << TCHAR_PARAM("message", fup->Desc) << TCHAR_PARAM("attachment", Attachment) << VER_API; pMsgReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); Push(pMsgReq); }
void CVkProto::OnReciveUploadServer(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { SendFileFiled(fup, VKERR_OFFLINE); return; } debugLogA("CVkProto::OnReciveUploadServer %d", reply->resultCode); if (reply->resultCode != 200) { SendFileFiled(fup, VKERR_INVALID_SERVER); return; } JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse || pReq->m_iErrorCode) { SendFileFiled(fup, pReq->m_iErrorCode); return; } CMStringA uri(jnResponse["upload_url"].as_mstring()); if (uri.IsEmpty()) { SendFileFiled(fup, VKERR_INVALID_URL); return; } FILE *pFile = _tfopen(fup->FileName, _T("rb")); if (pFile == NULL) { SendFileFiled(fup, VKERR_ERR_OPEN_FILE); return; } fseek(pFile, 0, SEEK_END); long iFileLen = ftell(pFile); //FileSize if (iFileLen < 1) { fclose(pFile); SendFileFiled(fup, VKERR_ERR_READ_FILE); return; } fseek(pFile, 0, SEEK_SET); ProtoBroadcastAck(fup->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)fup); AsyncHttpRequest *pUploadReq = new AsyncHttpRequest(this, REQUEST_POST, uri, false, &CVkProto::OnReciveUpload); pUploadReq->m_bApiReq = false; pUploadReq->m_szParam = ""; CMStringA boundary, header; CMStringA NamePart = fup->atrName(); CMStringA FNamePart = fup->fileName(); // Boundary int iboundary; Utils_GetRandom(&iboundary, sizeof(iboundary)); boundary.AppendFormat("Miranda%dNG%d", iboundary, time(NULL)); // Header header.AppendFormat("multipart/form-data; boundary=%s", boundary); pUploadReq->AddHeader("Content-Type", header); // Content-Disposition { CMStringA DataBegin = "--"; DataBegin += boundary; DataBegin += "\r\n"; DataBegin += "Content-Disposition: form-data; name=\""; DataBegin += NamePart; DataBegin += "\"; filename=\""; DataBegin += FNamePart; DataBegin += "\";\r\n\r\n"; // } Content-Disposition CMStringA DataEnd = "\r\n--"; DataEnd += boundary; DataEnd += "--\r\n"; // Body size long dataLength = iFileLen + DataBegin.GetLength() + DataEnd.GetLength(); // Body { char* pData = (char *)mir_alloc(dataLength); memcpy(pData, (void *)DataBegin.GetBuffer(), DataBegin.GetLength()); pUploadReq->pData = pData; pData += DataBegin.GetLength(); long lBytes = (long)fread(pData, 1, iFileLen, pFile); fclose(pFile); if (lBytes != iFileLen) { SendFileFiled(fup, VKERR_ERR_READ_FILE); mir_free(pUploadReq->pData); delete pUploadReq; return; } pData += iFileLen; memcpy(pData, (void *)DataEnd.GetBuffer(), DataEnd.GetLength()); // } Body pUploadReq->dataLength = (int)dataLength; pUploadReq->pUserInfo = pReq->pUserInfo; Push(pUploadReq); }