/*
Copyright (c) 2015-18 Miranda NG team (https://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef _HTTP_REQUEST_H_
#define _HTTP_REQUEST_H_
class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
{
HttpRequest& operator=(const HttpRequest&); // to prevent copying;
va_list formatArgs;
CMStringA url;
protected:
enum HttpRequestUrlFormat { FORMAT };
class HttpRequestUrl
{
friend HttpRequest;
private:
HttpRequest & request;
HttpRequestUrl(HttpRequest &request, const char *url) : request(request)
{
request.url = url;
request.szUrl = request.url.GetBuffer();
}
HttpRequestUrl(HttpRequest &request, const char *urlFormat, va_list args) : request(request)
{
request.url.AppendFormatV(urlFormat, args);
request.szUrl = request.url.GetBuffer();
}
HttpRequestUrl& operator=(const HttpRequestUrl&); // to prevent copying;
public:
HttpRequestUrl& operator<<(const char *param)
{
if (param)
request.AddUrlParameter("%s", param);
return *this;
}
HttpRequestUrl& operator<<(const BOOL_PARAM ¶m)
{
request.AddUrlParameter("%s=%s", param.szName, param.bValue ? "true" : "false");
return *this;
}
HttpRequestUrl& operator<<(const INT_PARAM ¶m)
{
request.AddUrlParameter("%s=%i", param.szName, param.iValue);
return *this;
}
HttpRequestUrl& operator<<(const INT64_PARAM ¶m)
{
request.AddUrlParameter("%s=%lld", param.szName, param.iValue);
return *this;
}
HttpRequestUrl& operator<<(const CHAR_PARAM ¶m)
{
request.AddUrlParameter("%s=%s", param.szName, param.szValue);
return *this;
}
char* ToString()
{
return request.url.GetBuffer();
}
};
class HttpRequestHeaders
{
HttpRequestHeaders& operator=(const HttpRequestHeaders&); // to prevent copying;
HttpRequest &request;
void Add(LPCSTR szName)
{
Add(szName, "");
}
void Add(LPCSTR szName, LPCSTR szValue)
{
request.headers = (NETLIBHTTPHEADER*)mir_realloc(
request.headers, sizeof(NETLIBHTTPHEADER)* (request.headersCount + 1));
request.headers[request.headersCount].szName = mir_strdup(szName);
request.headers[request.headersCount].szValue = mir_strdup(szValue);
request.headersCount++;
}
public:
HttpRequestHeaders(HttpRequest &request) : request(request) {}
HttpRequestHeaders& operator<<(const CHAR_PARAM ¶m)
{
Add(param.szName, param.szValue);
return *this;
}
};
class HttpRequestBody
{
private:
CMStringA content;
void AppendSeparator()
{
if (!content.IsEmpty())
content.AppendChar('&');
}
public:
HttpRequestBody() {}
HttpRequestBody& operator<<(const char *str)
{
AppendSeparator();
if (str != nullptr)
content.Append(str);
return *this;
}
HttpRequestBody& operator<<(const BOOL_PARAM ¶m)
{
AppendSeparator();
content.AppendFormat("%s=%s", param.szName, param.bValue ? "true" : "false");
return *this;
}
HttpRequestBody& operator<<(const INT_PARAM ¶m)
{
AppendSeparator();
content.AppendFormat("%s=%i", param.szName, param.iValue);
return *this;
}
HttpRequestBody& operator<<(const INT64_PARAM ¶m)
{
AppendSeparator();
content.AppendFormat("%s=%lld", param.szName, param.iValue);
return *this;
}
HttpRequestBody& operator<<(const CHAR_PARAM ¶m)
{
AppendSeparator();
content.AppendFormat("%s=%s", param.szName, param.szValue);
return *this;
}
char* ToString()
{
return content.GetBuffer();
}
};
void AddUrlParameter(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
url += (url.Find('?') == -1) ? '?' : '&';
url.AppendFormatV(fmt, args);
va_end(args);
szUrl = url.GetBuffer();
}
public:
HttpRequestUrl Url;
HttpRequestHeaders Headers;
HttpRequestBody Body;
enum PersistentType { NONE, DEFAULT, CHANNEL, MESSAGES };
bool NotifyErrors;
PersistentType Persistent;
HttpRequest(int type, LPCSTR url)
: Url(*this, url), Headers(*this)
{
cbSize = sizeof(NETLIBHTTPREQUEST);
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_DUMPASTEXT;
requestType = type;
pData = nullptr;
timeout = 20 * 1000;
NotifyErrors = true;
Persistent = DEFAULT;
}
HttpRequest(int type, HttpRequestUrlFormat, LPCSTR urlFormat, ...)
: Url(*this, urlFormat, (va_start(formatArgs, urlFormat), formatArgs)), Headers(*this)
{
cbSize = sizeof(NETLIBHTTPREQUEST);
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_DUMPASTEXT;
requestType = type;
va_end(formatArgs);
pData = nullptr;
timeout = 20 * 1000;
NotifyErrors = true;
Persistent = DEFAULT;
}
virtual ~HttpRequest()
{
for (int i = 0; i < headersCount; i++) {
mir_free(headers[i].szName);
mir_free(headers[i].szValue);
}
mir_free(headers);
}
virtual NETLIBHTTPREQUEST* Send(HNETLIBUSER nlu)
{
if (url.Find("://") == -1)
url.Insert(0, ((flags & NLHRF_SSL) ? "https://" : "http://"));
szUrl = url.GetBuffer();
if (!pData) {
pData = Body.ToString();
dataLength = (int)mir_strlen(pData);
}
Netlib_Logf(nlu, "Send request to %s", szUrl);
return Netlib_HttpTransaction(nlu, this);
}
};
/////////////////////////////////////////////////////////////////////////////////////////
// channel.cpp
struct ChannelRequest : public HttpRequest
{
enum Type { PULL, PING };
ChannelRequest(facebook_client *fc, Type type);
};
//////////////////////////////////////////////////////////////////////////////////////////
// contact.cpp
// getting frienship requests (using mobile website)
struct GetFriendshipsRequest : public HttpRequest
{
GetFriendshipsRequest(bool mobileBasicWorks) :
HttpRequest(REQUEST_GET, FORMAT, "%s/friends/center/requests/", mobileBasicWorks ? FACEBOOK_SERVER_MBASIC : FACEBOOK_SERVER_MOBILE)
{
flags |= NLHRF_REDIRECT;
}
};
// getting info about particular friend
struct UserInfoRequest : public HttpRequest
{ UserInfoRequest(facebook_client *fc, const LIST &userIds);
};
// getting info about all friends
struct UserInfoAllRequest : public HttpRequest
{ UserInfoAllRequest(facebook_client *fc);
};
// requesting friendships
struct AddFriendRequest : public HttpRequest
{ AddFriendRequest(facebook_client *fc, const char *userId);
};
// deleting friendships
struct DeleteFriendRequest : public HttpRequest
{ DeleteFriendRequest(facebook_client *fc, const char *userId);
};
// canceling (our) friendship request
struct CancelFriendshipRequest : public HttpRequest
{ CancelFriendshipRequest(facebook_client *fc, const char *userId);
};
// approving or ignoring friendship requests
struct AnswerFriendshipRequest : public HttpRequest
{
enum Answer { CONFIRM, REJECT };
AnswerFriendshipRequest(facebook_client *fc, const char *userId, Answer answer);
};
//////////////////////////////////////////////////////////////////////////////////////////
// feeds.cpp
// getting newsfeed posts
struct NewsfeedRequest : public HttpRequest
{ NewsfeedRequest(facebook_client *fc);
};
// getting memories ("on this day") posts
struct MemoriesRequest : public HttpRequest
{ MemoriesRequest(facebook_client *fc);
};
//////////////////////////////////////////////////////////////////////////////////////////
// history.cpp
// getting thread info and messages
class ThreadInfoRequest : public HttpRequest
{
void setCommonBody(facebook_client *fc);
public:
// Request only messages history
ThreadInfoRequest(facebook_client *fc, bool isChat, const char *id, const char* timestamp = nullptr, int limit = -1);
ThreadInfoRequest(facebook_client *fc, const LIST &ids, int offset, int limit);
};
// getting unread threads
struct UnreadThreadsRequest : public HttpRequest
{ UnreadThreadsRequest(facebook_client *fc);
};
//////////////////////////////////////////////////////////////////////////////////////////
// login.cpp
// connecting physically
struct LoginRequest : public HttpRequest
{
LoginRequest();
LoginRequest(const char *username, const char *password, const char *urlData, const char *bodyData);
};
// disconnecting physically
struct LogoutRequest : public HttpRequest
{ LogoutRequest(const char *dtsg, const char *logoutHash);
};
// request to receive login code via SMS
struct LoginSmsRequest : public HttpRequest
{ LoginSmsRequest(facebook_client *fc, const char *dtsg);
};
// setting machine name
struct SetupMachineRequest : public HttpRequest
{
SetupMachineRequest();
SetupMachineRequest(const char *dtsg, const char *nh, const char *submit);
};
//////////////////////////////////////////////////////////////////////////////////////////
// messages.cpp
// sending messages
struct SendMessageRequest : public HttpRequest
{ SendMessageRequest(facebook_client *fc, const char *userId, const char *threadId, const char *messageId, const char *messageText, bool isChat, const char *captcha, const char *captchaPersistData);
};
// sending typing notification
struct SendTypingRequest : public HttpRequest
{ SendTypingRequest(facebook_client *fc, const char *userId, bool isChat, bool isTyping);
};
struct MarkMessageReadRequest : public HttpRequest
{ MarkMessageReadRequest(facebook_client *fc, const LIST &ids);
};
//////////////////////////////////////////////////////////////////////////////////////////
// notifications.cpp
// getting notifications
struct GetNotificationsRequest : public HttpRequest
{ GetNotificationsRequest(facebook_client *fc, int count);
};
// marking notifications read
struct MarkNotificationReadRequest : public HttpRequest
{ MarkNotificationReadRequest(facebook_client *fc, const char *id);
};
//////////////////////////////////////////////////////////////////////////////////////////
// profile.cpp
// getting own name, avatar, ...
struct HomeRequest : public HttpRequest
{ HomeRequest();
};
// getting fb_dtsg
struct DtsgRequest : public HttpRequest
{ DtsgRequest();
};
// request mobile page containing profile picture
struct ProfilePictureRequest : public HttpRequest
{ ProfilePictureRequest(bool mobileBasicWorks, const char *userId);
};
// request mobile page containing user profile
struct ProfileRequest : public HttpRequest
{ ProfileRequest(bool mobileBasicWorks, const char *data);
};
// request mobile page containing user profile by his id, and in english language (for parsing data)
struct ProfileInfoRequest : public HttpRequest
{ ProfileInfoRequest(bool mobileBasicWorks, const char *userId);
};
//////////////////////////////////////////////////////////////////////////////////////////
// search.cpp
// searching
struct SearchRequest : public HttpRequest
{ SearchRequest(bool mobileBasicWorks, const char *query, int s, int pn, const char *ssid);
};
//////////////////////////////////////////////////////////////////////////////////////////
// status.cpp
// getting info about channel and connecting to it
struct ReconnectRequest : public HttpRequest
{ ReconnectRequest(facebook_client *fc);
};
// setting chat visibility
struct SetVisibilityRequest : public HttpRequest
{ SetVisibilityRequest(facebook_client *fc, bool online);
};
//////////////////////////////////////////////////////////////////////////////////////////
// utils.cpp
// getting data for given url (for sending/posting reasons)
struct LinkScraperRequest : public HttpRequest
{ LinkScraperRequest(facebook_client *fc, status_data *status);
};
// refreshing captcha dialog (changing captcha type)
struct RefreshCaptchaRequest : public HttpRequest
{ RefreshCaptchaRequest(facebook_client *fc, const char *captchaPersistData);
};
// getting owned/admined pages list
struct GetPagesRequest : public HttpRequest
{
GetPagesRequest() :
HttpRequest(REQUEST_GET, FACEBOOK_SERVER_REGULAR "/bookmarks/pages")
{}
};
// changing identity to post status for pages
struct SwitchIdentityRequest : public HttpRequest
{ SwitchIdentityRequest(const char *dtsg, const char *userId);
};
// posting status to our or friends's wall
struct SharePostRequest : public HttpRequest
{ SharePostRequest(facebook_client *fc, status_data *status, const char *linkData);
};
// sending pokes
struct SendPokeRequest : public HttpRequest
{ SendPokeRequest(facebook_client *fc, const char *userId);
};
#endif //_HTTP_REQUEST_H_