From 46fd8bbce689895bfbaaa08d9bad73b879e17172 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 19 Feb 2020 12:31:20 +0300 Subject: Twitter: - fixes #2218 (add support for private messages); - code optimization; - support for JSON requests; - fixed base url; --- protocols/Twitter/src/chat.cpp | 14 ++++-------- protocols/Twitter/src/connection.cpp | 18 ++++------------ protocols/Twitter/src/contacts.cpp | 8 +++---- protocols/Twitter/src/http.h | 2 ++ protocols/Twitter/src/oauth.cpp | 16 ++++++-------- protocols/Twitter/src/proto.cpp | 10 +++------ protocols/Twitter/src/proto.h | 3 +-- protocols/Twitter/src/resource.h | 6 ++---- protocols/Twitter/src/stdafx.h | 1 - protocols/Twitter/src/twitter.cpp | 21 +++++++++++------- protocols/Twitter/src/ui.cpp | 37 +------------------------------ protocols/Twitter/src/utility.cpp | 42 +++++++++++++++++++++--------------- 12 files changed, 65 insertions(+), 113 deletions(-) (limited to 'protocols/Twitter/src') diff --git a/protocols/Twitter/src/chat.cpp b/protocols/Twitter/src/chat.cpp index 72705dd926..733e4aacee 100644 --- a/protocols/Twitter/src/chat.cpp +++ b/protocols/Twitter/src/chat.cpp @@ -23,17 +23,15 @@ along with this program. If not, see . void CTwitterProto::UpdateChat(const twitter_user &update) { + CMStringA chatText = update.status.text.c_str(); + chatText.Replace("%", "%%"); + GCEVENT gce = { m_szModuleName, m_szChatId, GC_EVENT_MESSAGE }; gce.dwFlags = GCEF_UTF8 + GCEF_ADDTOLOG; gce.bIsMe = (update.username.c_str() == m_szUserName); gce.pszUID.a = update.username.c_str(); - //TODO: write code here to replace % with %% in update.status.text (which is a CMStringA) - - CMStringA chatText = update.status.text.c_str(); - chatText.Replace("%", "%%"); - gce.pszText.a = chatText.c_str(); - gce.time = static_cast(update.status.time); + gce.time = (DWORD)update.status.time; MCONTACT hContact = UsernameToHContact(update.username.c_str()); CMStringA szNick = db_get_sm(hContact, "CList", "MyHandle"); @@ -43,10 +41,6 @@ void CTwitterProto::UpdateChat(const twitter_user &update) gce.pszNick.a = update.username.c_str(); Chat_Event(&gce); - - mir_free(const_cast(gce.pszNick.w)); - mir_free(const_cast(gce.pszUID.w)); - mir_free(const_cast(gce.pszText.w)); } int CTwitterProto::OnChatOutgoing(WPARAM, LPARAM lParam) diff --git a/protocols/Twitter/src/connection.cpp b/protocols/Twitter/src/connection.cpp index b927de5c4d..6995fe942c 100644 --- a/protocols/Twitter/src/connection.cpp +++ b/protocols/Twitter/src/connection.cpp @@ -93,14 +93,6 @@ bool CTwitterProto::NegotiateConnection() if (m_szUserName.IsEmpty()) m_szUserName = getMStringA(TWITTER_KEY_UN); - // CTwitterProto changed the base URL in v1.1 of the API, I don't think users will need to modify it, so - // i'll be forcing it to the new API URL here. After a while I can get rid of this as users will - // have either had this run at least once, or have reset their miranda profile. 14/10/2012 - if (getByte("UpgradeBaseURL", 1)) { - setString(TWITTER_KEY_BASEURL, "https://api.twitter.com/"); - setByte("UpgradeBaseURL", 0); - } - if (szOauthToken.IsEmpty() || szOauthTokenSecret.IsEmpty()) { // first, reset all the keys so we can start fresh debugLogA("**NegotiateConnection - Reset OAuth Keys"); @@ -196,8 +188,6 @@ bool CTwitterProto::NegotiateConnection() m_szAccessTokenSecret = szOauthTokenSecret; } - m_szBaseUrl = getMStringA(TWITTER_KEY_BASEURL); - debugLogA("**NegotiateConnection - Setting Consumer Keys and verifying creds..."); if (m_szUserName.IsEmpty()) { @@ -205,7 +195,7 @@ bool CTwitterProto::NegotiateConnection() debugLogA("**NegotiateConnection - Missing the Nick key in the database. Everything will still work, but it's nice to have"); } - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/account/verify_credentials.json"); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/account/verify_credentials.json"); if (Execute(req).code != 200) { debugLogA("**NegotiateConnection - Verifying credentials failed! No internet maybe?"); @@ -355,7 +345,7 @@ void CTwitterProto::UpdateAvatar(MCONTACT hContact, const CMStringA &url, bool f void CTwitterProto::UpdateFriends() { - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/friends/list.json"); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/friends/list.json"); http::response resp = Execute(req); if (resp.code != 200) { debugLogA("Friend list reading failed"); @@ -448,7 +438,7 @@ void CTwitterProto::ShowContactPopup(MCONTACT hContact, const CMStringA &text, c void CTwitterProto::UpdateStatuses(bool pre_read, bool popups, bool tweetToMsg) { - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/statuses/home_timeline.json"); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/statuses/home_timeline.json"); req << INT_PARAM("count", 200); if (since_id_ != 0) req << INT64_PARAM("since_id", since_id_); @@ -545,7 +535,7 @@ void CTwitterProto::UpdateStatuses(bool pre_read, bool popups, bool tweetToMsg) void CTwitterProto::UpdateMessages(bool pre_read) { - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/direct_messages/events/list.json"); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/direct_messages/events/list.json"); req << INT_PARAM("count", 50); if (dm_since_id_ != 0) req << INT64_PARAM("since_id", dm_since_id_); diff --git a/protocols/Twitter/src/contacts.cpp b/protocols/Twitter/src/contacts.cpp index 01524b6a12..cd8fb08162 100644 --- a/protocols/Twitter/src/contacts.cpp +++ b/protocols/Twitter/src/contacts.cpp @@ -43,7 +43,7 @@ MCONTACT CTwitterProto::AddToList(int, PROTOSEARCHRESULT *psr) return AddToClientList(_T2A(psr->nick.w), ""); } -// ************************* +///////////////////////////////////////////////////////////////////////////////////////// void CTwitterProto::UpdateInfoWorker(void *arg) { @@ -79,7 +79,7 @@ int CTwitterProto::GetInfo(MCONTACT hContact, int info_type) return 1; } -// ************************* +///////////////////////////////////////////////////////////////////////////////////////// struct search_query { @@ -136,7 +136,7 @@ HANDLE CTwitterProto::SearchByEmail(const wchar_t *email) return (HANDLE)1; } -// ************************* +///////////////////////////////////////////////////////////////////////////////////////// void CTwitterProto::GetAwayMsgWorker(void *arg) { @@ -195,7 +195,7 @@ int CTwitterProto::OnMarkedRead(WPARAM, LPARAM hDbEvent) return 0; } -// ************************* +///////////////////////////////////////////////////////////////////////////////////////// bool CTwitterProto::IsMyContact(MCONTACT hContact, bool include_chat) { diff --git a/protocols/Twitter/src/http.h b/protocols/Twitter/src/http.h index 0522fa53ab..ab91b177a7 100644 --- a/protocols/Twitter/src/http.h +++ b/protocols/Twitter/src/http.h @@ -19,6 +19,8 @@ along with this program. If not, see . #pragma once +#define TWITTER_BASE_URL "https://api.twitter.com/1.1" + namespace http { struct response diff --git a/protocols/Twitter/src/oauth.cpp b/protocols/Twitter/src/oauth.cpp index ee42730b47..bb4ba506e2 100644 --- a/protocols/Twitter/src/oauth.cpp +++ b/protocols/Twitter/src/oauth.cpp @@ -62,17 +62,13 @@ static CMStringA OAuthNormalizeRequestParameters(const CMStringA &requestParamet return res; } -CMStringA CTwitterProto::BuildSignedOAuthParameters( - const CMStringA &requestParameters, - const CMStringA &url, - const CMStringA &httpMethod, - const CMStringA &postData) +CMStringA CTwitterProto::BuildSignedOAuthParameters(const CMStringA &request, const CMStringA &url, const char *httpMethod, const char *postData) { CMStringA timestamp(FORMAT, "%lld", _time64(0)); CMStringA nonce = OAuthCreateNonce(); // create oauth requestParameters - auto *req = new AsyncHttpRequest(httpMethod == "GET" ? REQUEST_GET : REQUEST_POST, url); + auto *req = new AsyncHttpRequest(!mir_strcmp(httpMethod, "GET") ? REQUEST_GET : REQUEST_POST, url); req << CHAR_PARAM("oauth_timestamp", timestamp) << CHAR_PARAM("oauth_nonce", nonce) << CHAR_PARAM("oauth_version", "1.0") << CHAR_PARAM("oauth_signature_method", "HMAC-SHA1") << CHAR_PARAM("oauth_consumer_key", OAUTH_CONSUMER_KEY) << CHAR_PARAM("oauth_callback", "oob"); @@ -86,12 +82,12 @@ CMStringA CTwitterProto::BuildSignedOAuthParameters( // create a parameter list containing both oauth and original parameters // this will be used to create the parameter signature - if (!requestParameters.IsEmpty()) { + if (!request.IsEmpty()) { req->m_szParam.AppendChar('&'); - req->m_szParam.Append(requestParameters); + req->m_szParam.Append(request); } - if (!postData.IsEmpty()) { + if (!mir_strlen(postData)) { req->m_szParam.AppendChar('&'); req->m_szParam.Append(postData); } @@ -100,7 +96,7 @@ CMStringA CTwitterProto::BuildSignedOAuthParameters( // all of the necessary information needed to generate a valid signature CMStringA normalUrl = OAuthNormalizeUrl(url); CMStringA normalizedParameters = OAuthNormalizeRequestParameters(req->m_szParam, true); - CMStringA signatureBase = httpMethod + "&" + mir_urlEncode(normalUrl) + "&" + mir_urlEncode(normalizedParameters); + CMStringA signatureBase = CMStringA(httpMethod) + "&" + mir_urlEncode(normalUrl) + "&" + mir_urlEncode(normalizedParameters); // obtain a signature and add it to header requestParameters CMStringA signature = OAuthCreateSignature(signatureBase, OAUTH_CONSUMER_SECRET, m_szAccessTokenSecret); diff --git a/protocols/Twitter/src/proto.cpp b/protocols/Twitter/src/proto.cpp index 01da0ec206..8ab85237b1 100644 --- a/protocols/Twitter/src/proto.cpp +++ b/protocols/Twitter/src/proto.cpp @@ -26,7 +26,6 @@ static volatile LONG g_msgid = 1; CTwitterProto::CTwitterProto(const char *proto_name, const wchar_t *username) : PROTO(proto_name, username), m_szChatId(mir_utf8encodeW(username)), - m_szBaseUrl("https://api.twitter.com/"), m_arChatMarks(10, NumericKeySortT) { CreateProtoService(PS_CREATEACCMGRUI, &CTwitterProto::SvcCreateAccMgrUI); @@ -138,13 +137,10 @@ void CTwitterProto::SendSuccess(void *p) auto *data = (TSendDirect*)p; - DBVARIANT dbv; - if (!db_get_s(data->hContact, m_szModuleName, TWITTER_KEY_UN, &dbv)) { - mir_cslock s(twitter_lock_); - send_direct(dbv.pszVal, data->msg); - + CMStringA id(getMStringA(data->hContact, TWITTER_KEY_ID)); + if (!id.IsEmpty()) { + send_direct(id, data->msg); ProtoBroadcastAck(data->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)data->msgid, 0); - db_free(&dbv); } delete data; diff --git a/protocols/Twitter/src/proto.h b/protocols/Twitter/src/proto.h index 6067841973..498925ff4a 100644 --- a/protocols/Twitter/src/proto.h +++ b/protocols/Twitter/src/proto.h @@ -78,7 +78,6 @@ class CTwitterProto : public PROTO CMStringA m_szUserName; CMStringA m_szPassword; - CMStringA m_szBaseUrl; CMStringA m_szConsumerKey; CMStringA m_szConsumerSecret; CMStringA m_szAccessToken; @@ -113,7 +112,7 @@ class CTwitterProto : public PROTO CMStringA UrlGetQuery(const CMStringA &url); - CMStringA BuildSignedOAuthParameters(const CMStringA &requestParameters, const CMStringA &url, const CMStringA &httpMethod, const CMStringA &postData); + CMStringA BuildSignedOAuthParameters(const CMStringA &requestParameters, const CMStringA &url, const char *httpMethod, const char *postData); CMStringA OAuthCreateNonce(); CMStringA OAuthCreateSignature(const CMStringA &signatureBase, const CMStringA &consumerSecret, const CMStringA &requestTokenSecret); diff --git a/protocols/Twitter/src/resource.h b/protocols/Twitter/src/resource.h index ffbfaaa57c..7add011e15 100644 --- a/protocols/Twitter/src/resource.h +++ b/protocols/Twitter/src/resource.h @@ -1,6 +1,6 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. -// Used by CTwitterProto.rc +// Used by w:\miranda-ng\protocols\Twitter\res\twitter.rc // #define IDD_TWITTERACCOUNT 101 #define IDI_TWITTER 102 @@ -16,7 +16,6 @@ #define IDC_USERDETAILS 1006 #define IDC_MISC 1007 #define IDC_CHATFEED 1008 -#define IDC_BASEURL 1009 #define IDC_POLLRATE 1010 #define IDC_COLBACK 1011 #define IDC_COLTEXT 1012 @@ -32,7 +31,6 @@ #define IDC_PREVIEW 1022 #define IDC_NOSIGNONPOPUPS 1023 #define IDC_RECONNECT 1024 -#define IDC_SERVER 1025 #define IDC_PIN 1026 #define IDC_GROUP 1027 #define IDC_USERNAME 1028 @@ -42,7 +40,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 110 +#define _APS_NEXT_RESOURCE_VALUE 111 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1030 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/protocols/Twitter/src/stdafx.h b/protocols/Twitter/src/stdafx.h index f7bc9d7241..239dbcb540 100644 --- a/protocols/Twitter/src/stdafx.h +++ b/protocols/Twitter/src/stdafx.h @@ -69,7 +69,6 @@ using std::map; #define TWITTER_KEY_OAUTH_TOK_SEC "OAuthTokenSecret" #define TWITTER_KEY_OAUTH_ACCESS_TOK "OAuthAccessToken" #define TWITTER_KEY_OAUTH_ACCESS_SEC "OAuthAccessTokenSecret" -#define TWITTER_KEY_BASEURL "BaseURL" #define TWITTER_KEY_CHATFEED "ChatFeed" #define TWITTER_KEY_POLLRATE "PollRate" #define TWITTER_KEY_GROUP "DefaultGroup" diff --git a/protocols/Twitter/src/twitter.cpp b/protocols/Twitter/src/twitter.cpp index 16b105ab67..2baa2110b6 100644 --- a/protocols/Twitter/src/twitter.cpp +++ b/protocols/Twitter/src/twitter.cpp @@ -37,7 +37,7 @@ bool CTwitterProto::get_info(const CMStringA &name, twitter_user *info) if (!info) return false; - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/users/show/" + mir_urlEncode(name.c_str()).c_str() + ".json"); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/users/show/" + mir_urlEncode(name) + ".json"); http::response resp = Execute(req); if (resp.code != 200) return false; @@ -60,7 +60,7 @@ bool CTwitterProto::get_info_by_email(const CMStringA &email, twitter_user *info if (!info) return false; - auto *req = new AsyncHttpRequest(REQUEST_GET, m_szBaseUrl + "1.1/users/show.json?email=" + mir_urlEncode(email)); + auto *req = new AsyncHttpRequest(REQUEST_GET, "/users/show.json?email=" + mir_urlEncode(email)); http::response resp = Execute(req); if (resp.code != 200) return false; @@ -80,7 +80,7 @@ bool CTwitterProto::get_info_by_email(const CMStringA &email, twitter_user *info bool CTwitterProto::add_friend(const CMStringA &name, twitter_user &ret) { - auto *req = new AsyncHttpRequest(REQUEST_POST, m_szBaseUrl + "1.1/friendships/create/" + mir_urlEncode(name) + ".json"); + auto *req = new AsyncHttpRequest(REQUEST_POST, "/friendships/create/" + mir_urlEncode(name) + ".json"); http::response resp = Execute(req); if (resp.code != 200) return false; @@ -104,7 +104,7 @@ bool CTwitterProto::add_friend(const CMStringA &name, twitter_user &ret) void CTwitterProto::remove_friend(const CMStringA &name) { - auto *req = new AsyncHttpRequest(REQUEST_POST, m_szBaseUrl + "1.1/friendships/destroy/" + mir_urlEncode(name) + ".json"); + auto *req = new AsyncHttpRequest(REQUEST_POST, "/friendships/destroy/" + mir_urlEncode(name) + ".json"); Execute(req); } @@ -114,7 +114,7 @@ void CTwitterProto::mark_read(MCONTACT hContact, const CMStringA &msgId) if (id.IsEmpty()) return; - auto *req = new AsyncHttpRequest(REQUEST_POST, m_szBaseUrl + "1.1/direct_messages/mark_read.json"); + auto *req = new AsyncHttpRequest(REQUEST_POST, "/direct_messages/mark_read.json"); req << CHAR_PARAM("recipient_id", id) << CHAR_PARAM("last_read_event_id", msgId); Execute(req); } @@ -124,15 +124,20 @@ void CTwitterProto::set_status(const CMStringA &text) if (text.IsEmpty()) return; - auto *req = new AsyncHttpRequest(REQUEST_POST, m_szBaseUrl + "1.1/statuses/update.json"); + auto *req = new AsyncHttpRequest(REQUEST_POST, "/statuses/update.json"); req << CHAR_PARAM("status", text); Execute(req); } void CTwitterProto::send_direct(const CMStringA &name, const CMStringA &text) { - auto *req = new AsyncHttpRequest(REQUEST_POST, m_szBaseUrl + "1.1/direct_messages/events/new.json"); - req << CHAR_PARAM("text", text) << CHAR_PARAM("screen_name", name); + auto *req = new AsyncHttpRequest(REQUEST_POST, "/direct_messages/events/new.json"); + JSONNode target; target.set_name("target"); target << CHAR_PARAM("recipient_id", name); + JSONNode msgData; msgData.set_name("message_data"); msgData << CHAR_PARAM("text", text); + JSONNode msgCreate; msgCreate.set_name("message_create"); msgCreate << msgData << target; + JSONNode event; event.set_name("event"); event << CHAR_PARAM("type", "message_create") << msgCreate; + JSONNode body; body << event; + req->m_szParam = body.write().c_str(); Execute(req); } diff --git a/protocols/Twitter/src/ui.cpp b/protocols/Twitter/src/ui.cpp index 405faaa5c5..713b90b2a0 100644 --- a/protocols/Twitter/src/ui.cpp +++ b/protocols/Twitter/src/ui.cpp @@ -19,11 +19,6 @@ along with this program. If not, see . #include "stdafx.h" #include "ui.h" -static const wchar_t *sites[] = { - L"https://api.twitter.com/", - L"https://identi.ca/api/" -}; - INT_PTR CALLBACK first_run_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { CTwitterProto *proto; @@ -46,15 +41,6 @@ INT_PTR CALLBACK first_run_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM SetDlgItemTextA(hwndDlg, IDC_USERNAME, dbv.pszVal); db_free(&dbv); } - - for (auto &it : sites) - SendDlgItemMessage(hwndDlg, IDC_SERVER, CB_ADDSTRING, 0, reinterpret_cast(it)); - - if (!proto->getString(TWITTER_KEY_BASEURL, &dbv)) { - SetDlgItemTextA(hwndDlg, IDC_SERVER, dbv.pszVal); - db_free(&dbv); - } - else SendDlgItemMessage(hwndDlg, IDC_SERVER, CB_SETCURSEL, 0, 0); return true; case WM_COMMAND: @@ -76,14 +62,8 @@ INT_PTR CALLBACK first_run_dialog(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM case WM_NOTIFY: // might be able to get rid of this bit? if (reinterpret_cast(lParam)->code == PSN_APPLY) { proto = reinterpret_cast(GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); - char str[128]; - wchar_t tstr[128]; - - GetDlgItemTextA(hwndDlg, IDC_SERVER, str, _countof(str) - 1); - if (str[mir_strlen(str) - 1] != '/') - mir_strncat(str, "/", _countof(str) - mir_strlen(str)); - proto->setString(TWITTER_KEY_BASEURL, str); + wchar_t tstr[128]; GetDlgItemText(hwndDlg, IDC_GROUP, tstr, _countof(tstr)); proto->setWString(TWITTER_KEY_GROUP, tstr); @@ -177,15 +157,6 @@ INT_PTR CALLBACK options_proc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPar CheckDlgButton(hwndDlg, IDC_CHATFEED, proto->getByte(TWITTER_KEY_CHATFEED) ? BST_CHECKED : BST_UNCHECKED); - for (auto &it : sites) - SendDlgItemMessage(hwndDlg, IDC_BASEURL, CB_ADDSTRING, 0, reinterpret_cast(it)); - - if (!proto->getString(TWITTER_KEY_BASEURL, &dbv)) { - SetDlgItemTextA(hwndDlg, IDC_BASEURL, dbv.pszVal); - db_free(&dbv); - } - else SendDlgItemMessage(hwndDlg, IDC_BASEURL, CB_SETCURSEL, 0, 0); - char pollrate_str[32]; mir_snprintf(pollrate_str, "%d", proto->getDword(TWITTER_KEY_POLLRATE, 80)); SetDlgItemTextA(hwndDlg, IDC_POLLRATE, pollrate_str); @@ -208,7 +179,6 @@ INT_PTR CALLBACK options_proc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPar switch (LOWORD(wParam)) { case IDC_UN: case IDC_PW: - case IDC_BASEURL: ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECT), SW_SHOW); } SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); @@ -224,11 +194,6 @@ INT_PTR CALLBACK options_proc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPar GetDlgItemTextA(hwndDlg, IDC_UN, str, _countof(str)); proto->setString(TWITTER_KEY_UN, str); - GetDlgItemTextA(hwndDlg, IDC_BASEURL, str, _countof(str) - 1); - if (str[mir_strlen(str) - 1] != '/') - mir_strncat(str, "/", _countof(str) - mir_strlen(str)); - proto->setString(TWITTER_KEY_BASEURL, str); - proto->setByte(TWITTER_KEY_CHATFEED, IsDlgButtonChecked(hwndDlg, IDC_CHATFEED) != 0); GetDlgItemTextA(hwndDlg, IDC_POLLRATE, str, _countof(str)); diff --git a/protocols/Twitter/src/utility.cpp b/protocols/Twitter/src/utility.cpp index 38452f9608..3abe268171 100644 --- a/protocols/Twitter/src/utility.cpp +++ b/protocols/Twitter/src/utility.cpp @@ -22,13 +22,21 @@ along with this program. If not, see . http::response CTwitterProto::Execute(AsyncHttpRequest *pReq) { + if (pReq->m_szUrl[0] == '/') + pReq->m_szUrl.Insert(0, TWITTER_BASE_URL); + + bool bIsJson = false; if (!pReq->m_szParam.IsEmpty()) { if (pReq->requestType == REQUEST_POST) { - pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); + if (pReq->m_szParam[0] == '{') { + bIsJson = true; + pReq->AddHeader("Content-Type", "application/json"); + } + else pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); pReq->AddHeader("Cache-Control", "no-cache"); pReq->dataLength = (int)pReq->m_szParam.GetLength(); - pReq->pData = pReq->m_szParam.GetBuffer(); + pReq->pData = pReq->m_szParam.Detach(); } else { pReq->m_szUrl.AppendChar('?'); @@ -40,7 +48,7 @@ http::response CTwitterProto::Execute(AsyncHttpRequest *pReq) if (pReq->requestType == REQUEST_GET) auth = OAuthWebRequestSubmit(pReq->m_szUrl, "GET", ""); else - auth = OAuthWebRequestSubmit(pReq->m_szUrl, "POST", pReq->m_szParam); + auth = OAuthWebRequestSubmit(pReq->m_szUrl, "POST", (bIsJson) ? "" : pReq->pData); pReq->AddHeader("Authorization", auth); pReq->szUrl = pReq->m_szUrl.GetBuffer(); @@ -73,19 +81,19 @@ bool save_url(HNETLIBUSER hNetlib, const CMStringA &url, const CMStringW &filena req.szUrl = const_cast(url.c_str()); NLHR_PTR resp(Netlib_HttpTransaction(hNetlib, &req)); - if (resp) { - bool success = (resp->resultCode == 200); - if (success) { - // Create folder if necessary - CreatePathToFileW(filename); - - // Write to file - FILE *f = _wfopen(filename, L"wb"); - fwrite(resp->pData, 1, resp->dataLength, f); - fclose(f); - } - return success; - } + if (!resp) + return false; + + if (resp->resultCode != 200) + return false; + + // Create folder if necessary + CreatePathToFileW(filename); - return false; + // Write to file + FILE *f = _wfopen(filename, L"wb"); + fwrite(resp->pData, 1, resp->dataLength, f); + fclose(f); + + return true; } -- cgit v1.2.3