Compare commits
10
Commits
962a3b2bff
...
6effb195e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6effb195e7 | ||
|
|
f32ec710ff | ||
|
|
271121ec07 | ||
|
|
28208e58c9 | ||
|
|
e91fca0be6 | ||
|
|
346738835a | ||
|
|
d7221c7227 | ||
|
|
ed98242af8 | ||
|
|
ffde1ca33d | ||
|
|
48f91c0912 |
@@ -0,0 +1,29 @@
|
|||||||
|
# TODO
|
||||||
|
- [X] Backportation of OpenSSL
|
||||||
|
- [X] HTTP implementation
|
||||||
|
- [X] WS implementation
|
||||||
|
- [X] Working gateway
|
||||||
|
- [X] Sending and receiving messages
|
||||||
|
- [X] Listing Guilds
|
||||||
|
- [X] Listing channels
|
||||||
|
- [X] DMs support
|
||||||
|
- [X] ChatView with proper message alignment
|
||||||
|
- [X] Showing mention counts
|
||||||
|
- [X] Keep-Alive HTTP implementation
|
||||||
|
- [X] Switch to keep-alive HTTP use
|
||||||
|
- [ ] Add support for GCs
|
||||||
|
- [ ] Rendering replies
|
||||||
|
- [ ] Add support for guild folders
|
||||||
|
- [ ] Use the root guild folder to order the guilds properly
|
||||||
|
- [ ] File uploading
|
||||||
|
- [ ] Marking unread messages as read
|
||||||
|
- [ ] Editing & Deleting messages
|
||||||
|
- [ ] NT3.51 shims
|
||||||
|
- [ ] Attachements
|
||||||
|
- [ ] Polls
|
||||||
|
- [ ] Embeds & GIFs
|
||||||
|
- [ ] Emojis
|
||||||
|
- [ ] Pins
|
||||||
|
- [ ] User profiles
|
||||||
|
- [ ] Markdown & Links
|
||||||
|
- [ ] Threads & Implementation of the Forum channels
|
||||||
+12
-7
@@ -50,6 +50,11 @@ void ChatView_SetUserPfp(char *path, char *user) {
|
|||||||
PngBuffer pngbuf = {buf, file_size, 0};
|
PngBuffer pngbuf = {buf, file_size, 0};
|
||||||
|
|
||||||
png_set_read_fn(png, &pngbuf, PngReadBufCB);
|
png_set_read_fn(png, &pngbuf, PngReadBufCB);
|
||||||
|
if (setjmp(png_jmpbuf(png))) {
|
||||||
|
png_destroy_read_struct(&png, &info, NULL);
|
||||||
|
// err
|
||||||
|
MessageBoxA(NULL, "zzzzzzzz", "zzzzzzzzz", 0);
|
||||||
|
}
|
||||||
png_read_info(png, info);
|
png_read_info(png, info);
|
||||||
|
|
||||||
BITMAPINFO bmi = {0};
|
BITMAPINFO bmi = {0};
|
||||||
@@ -59,11 +64,6 @@ void ChatView_SetUserPfp(char *path, char *user) {
|
|||||||
bmi.bmiHeader.biPlanes = 1;
|
bmi.bmiHeader.biPlanes = 1;
|
||||||
bmi.bmiHeader.biBitCount = 32;
|
bmi.bmiHeader.biBitCount = 32;
|
||||||
bmi.bmiHeader.biCompression = BI_RGB; // THIS IS RAW - gordon ramsey
|
bmi.bmiHeader.biCompression = BI_RGB; // THIS IS RAW - gordon ramsey
|
||||||
if (setjmp(png_jmpbuf(png))) {
|
|
||||||
png_destroy_read_struct(&png, &info, NULL);
|
|
||||||
// err
|
|
||||||
MessageBoxA(NULL, "zzzzzzzz", "zzzzzzzzz", 0);
|
|
||||||
}
|
|
||||||
png_set_expand(png);
|
png_set_expand(png);
|
||||||
png_set_strip_16(png);
|
png_set_strip_16(png);
|
||||||
png_set_filler(png, 0xFF,
|
png_set_filler(png, 0xFF,
|
||||||
@@ -156,7 +156,7 @@ static int pfp_compare(const void *a, const void *b, void *udata) {
|
|||||||
}
|
}
|
||||||
static void pfp_free(void *pfpitem) {
|
static void pfp_free(void *pfpitem) {
|
||||||
IntPfpTableItem *item = pfpitem;
|
IntPfpTableItem *item = pfpitem;
|
||||||
free(item->bmp);
|
DeleteDC(item->bmp);
|
||||||
free(item->key);
|
free(item->key);
|
||||||
}
|
}
|
||||||
#define UsernameFieldHeight 15
|
#define UsernameFieldHeight 15
|
||||||
@@ -234,11 +234,16 @@ LRESULT CALLBACK ChatWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
for (int i = 0; i < cwnd->uimsgcnt; i++) {
|
for (int i = 0; i < cwnd->uimsgcnt; i++) {
|
||||||
RECT contr = {0, 0, clientRect.right - clientRect.left - 6 - 6 - 40,
|
RECT contr = {0, 0, clientRect.right - clientRect.left - 6 - 6 - 40,
|
||||||
0};
|
0};
|
||||||
|
if (strlen(cwnd->uimsgs[i].msg.content) == 0) {
|
||||||
|
msgdet[i].TextContentHeight = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
DrawTextA(hdc, cwnd->uimsgs[i].msg.content,
|
DrawTextA(hdc, cwnd->uimsgs[i].msg.content,
|
||||||
strlen(cwnd->uimsgs[i].msg.content), &contr,
|
strlen(cwnd->uimsgs[i].msg.content), &contr,
|
||||||
DT_CALCRECT | DT_WORDBREAK);
|
DT_CALCRECT | DT_WORDBREAK);
|
||||||
// printf("%i | %i\n", i, contr.bottom - contr.top);
|
|
||||||
msgdet[i].TextContentHeight = contr.bottom - contr.top;
|
msgdet[i].TextContentHeight = contr.bottom - contr.top;
|
||||||
|
}
|
||||||
|
// printf("%i | %i\n", i, contr.bottom - contr.top);
|
||||||
msgdet[i].StartMsg = IsStartMsg(cwnd, i);
|
msgdet[i].StartMsg = IsStartMsg(cwnd, i);
|
||||||
if (msgdet[i].StartMsg) {
|
if (msgdet[i].StartMsg) {
|
||||||
|
|
||||||
|
|||||||
@@ -228,8 +228,8 @@ LRESULT CALLBACK GuildWndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
nm.pt.x = x;
|
nm.pt.x = x;
|
||||||
nm.pt.y = y;
|
nm.pt.y = y;
|
||||||
|
|
||||||
SendMessage(GetParent(hwnd), WM_NOTIFY, nm.hdr.idFrom, (LPARAM)&nm);
|
|
||||||
InvalidateRect(hwnd, NULL, true);
|
InvalidateRect(hwnd, NULL, true);
|
||||||
|
SendMessage(GetParent(hwnd), WM_NOTIFY, nm.hdr.idFrom, (LPARAM)&nm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-8
@@ -1,6 +1,7 @@
|
|||||||
#include "discordtypes.h"
|
#include "discordtypes.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include <openssl/core.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
@@ -12,6 +13,8 @@
|
|||||||
hmap GuildsTable = NULL;
|
hmap GuildsTable = NULL;
|
||||||
hmap ChannelsTable = NULL;
|
hmap ChannelsTable = NULL;
|
||||||
DiscordChannel *PrivateChannels = NULL;
|
DiscordChannel *PrivateChannels = NULL;
|
||||||
|
HTTPConnection* maincon;
|
||||||
|
HTTPConnection* cdncon;
|
||||||
int PrivateChannelCount = 0;
|
int PrivateChannelCount = 0;
|
||||||
static uint64_t GuildHash(const void *item, uint64_t seed0, uint64_t seed1) {
|
static uint64_t GuildHash(const void *item, uint64_t seed0, uint64_t seed1) {
|
||||||
const DiscordGuild *e = item;
|
const DiscordGuild *e = item;
|
||||||
@@ -33,6 +36,15 @@ static void ChannelFree(void *item) {}
|
|||||||
extern void onDiscordGuildLoad(DiscordGuild *guild, char *id);
|
extern void onDiscordGuildLoad(DiscordGuild *guild, char *id);
|
||||||
extern void onDiscordUpdatedGuildReadState(DiscordGuild gld);
|
extern void onDiscordUpdatedGuildReadState(DiscordGuild gld);
|
||||||
extern void onDiscordReady(DiscordUser user, DiscordGuild *guilds, int guildscount);
|
extern void onDiscordReady(DiscordUser user, DiscordGuild *guilds, int guildscount);
|
||||||
|
int DiscordHTTPConnect(){
|
||||||
|
maincon=HTTPConnect("discord.com");
|
||||||
|
cdncon=HTTPConnect("cdn.discordapp.com");
|
||||||
|
return maincon->connected && cdncon->connected;
|
||||||
|
}
|
||||||
|
void DiscordHTTPClose(){
|
||||||
|
CloseHTTPConnection(maincon);
|
||||||
|
CloseHTTPConnection(cdncon);
|
||||||
|
}
|
||||||
int DiscordSendMessage(const char *channelID, const char *content) {
|
int DiscordSendMessage(const char *channelID, const char *content) {
|
||||||
cJSON *payload = cJSON_CreateObject();
|
cJSON *payload = cJSON_CreateObject();
|
||||||
cJSON *name = cJSON_CreateString(content);
|
cJSON *name = cJSON_CreateString(content);
|
||||||
@@ -46,8 +58,8 @@ int DiscordSendMessage(const char *channelID, const char *content) {
|
|||||||
char *payld = cJSON_Print(payload);
|
char *payld = cJSON_Print(payload);
|
||||||
long resplen;
|
long resplen;
|
||||||
char headers[17 + strlen(token) + 1];
|
char headers[17 + strlen(token) + 1];
|
||||||
wsprintf(headers, "Authorization: %s\r\n", token);
|
wsprintf(headers, "Authorization: %s", token);
|
||||||
SendShortHTTPReq("discord.com", "POST", endpoint, headers, user_agent,
|
SendHTTPRequest(maincon,"POST", endpoint, headers, user_agent,
|
||||||
"application/json", payld, strlen(payld), &forNothingGng,
|
"application/json", payld, strlen(payld), &forNothingGng,
|
||||||
&resplen);
|
&resplen);
|
||||||
free(payld);
|
free(payld);
|
||||||
@@ -74,8 +86,8 @@ char *DiscordFetchTmpPfp(char *userID, char *hash) {
|
|||||||
char *HTTPResp;
|
char *HTTPResp;
|
||||||
long resplen;
|
long resplen;
|
||||||
char headers[17 + strlen(token) + 1];
|
char headers[17 + strlen(token) + 1];
|
||||||
wsprintf(headers, "Authorization: %s\r\n", token);
|
wsprintf(headers, "Authorization: %s", token);
|
||||||
SendShortHTTPReq("cdn.discordapp.com", "GET", endpoint, headers, user_agent,
|
SendHTTPRequest(cdncon, "GET", endpoint, headers, user_agent,
|
||||||
"application/json", NULL, 0, &HTTPResp, &resplen);
|
"application/json", NULL, 0, &HTTPResp, &resplen);
|
||||||
free(endpoint);
|
free(endpoint);
|
||||||
|
|
||||||
@@ -105,8 +117,8 @@ char *DiscordFetchTmpGuildIcon(char *guildID, char *hash) {
|
|||||||
char *HTTPResp;
|
char *HTTPResp;
|
||||||
long resplen;
|
long resplen;
|
||||||
char headers[17 + strlen(token) + 1];
|
char headers[17 + strlen(token) + 1];
|
||||||
wsprintf(headers, "Authorization: %s\r\n", token);
|
wsprintf(headers, "Authorization: %s", token);
|
||||||
SendShortHTTPReq("cdn.discordapp.com", "GET", endpoint, headers, user_agent,
|
SendHTTPRequest(cdncon, "GET", endpoint, headers, user_agent,
|
||||||
"application/json", NULL, 0, &HTTPResp, &resplen);
|
"application/json", NULL, 0, &HTTPResp, &resplen);
|
||||||
free(endpoint);
|
free(endpoint);
|
||||||
|
|
||||||
@@ -146,9 +158,9 @@ int DiscordGetChannelHistory(const char *channelID, unsigned int amount,
|
|||||||
long resplen;
|
long resplen;
|
||||||
|
|
||||||
char headers[17 + strlen(token) + 1];
|
char headers[17 + strlen(token) + 1];
|
||||||
wsprintf(headers, "Authorization: %s\r\n", token);
|
wsprintf(headers, "Authorization: %s", token);
|
||||||
|
|
||||||
SendShortHTTPReq("discord.com", "GET", endpoint, headers, user_agent,
|
SendHTTPRequest(maincon, "GET", endpoint, headers, user_agent,
|
||||||
"application/json", NULL, 0, &HTTPResp, &resplen);
|
"application/json", NULL, 0, &HTTPResp, &resplen);
|
||||||
cJSON *resp = cJSON_Parse(HTTPResp);
|
cJSON *resp = cJSON_Parse(HTTPResp);
|
||||||
if (!resp)
|
if (!resp)
|
||||||
|
|||||||
+6
-3
@@ -3,12 +3,15 @@
|
|||||||
int DiscordSendMessage(const char *channelID, const char* content);
|
int DiscordSendMessage(const char *channelID, const char* content);
|
||||||
int DiscordListGuildChannels(char* guildID, DiscordChannel** out);
|
int DiscordListGuildChannels(char* guildID, DiscordChannel** out);
|
||||||
#define GUILD_TEXT 0
|
#define GUILD_TEXT 0
|
||||||
#define CHANNEL_TYPE_DM 1
|
#define CHANNEL_DM 1
|
||||||
#define GUILD_VOICE 2
|
#define GUILD_VOICE 2
|
||||||
#define GROUPCHAT 3
|
#define CHANNEL_GC 3
|
||||||
#define GUILD_CATEGORY 4
|
#define GUILD_CATEGORY 4
|
||||||
#define GUILD_ANNOUNCEMENT 5
|
#define GUILD_ANNOUNCEMENT 5
|
||||||
|
#define GUILD_FORUM 15
|
||||||
int DiscordGetChannelHistory(const char* channelID, unsigned int amount, DiscordMessage** msgs);
|
int DiscordGetChannelHistory(const char* channelID, unsigned int amount, DiscordMessage** msgs);
|
||||||
char *DiscordFetchTmpPfp(char *userID, char *hash);
|
char *DiscordFetchTmpPfp(char *userID, char *hash);
|
||||||
char *DiscordFetchTmpGuildIcon(char *guildID, char *hash);
|
char *DiscordFetchTmpGuildIcon(char *guildID, char *hash);
|
||||||
int DiscordListPrivateChannels(DiscordChannel** out);
|
int DiscordListPrivateChannels(DiscordChannel** out);
|
||||||
|
int DiscordHTTPConnect();
|
||||||
|
void DiscordHTTPClose();
|
||||||
@@ -7,378 +7,465 @@
|
|||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
// keepalive state
|
static void AppendHeader(char *buf, const char *key, const char *value) {
|
||||||
typedef struct {
|
strcat(buf, key);
|
||||||
SOCKET sock;
|
strcat(buf, ": ");
|
||||||
SSL* ssl;
|
strcat(buf, value);
|
||||||
SSL_CTX* ctx;
|
strcat(buf, "\r\n");
|
||||||
char hostname[256];
|
|
||||||
int connected;
|
|
||||||
} HTTPConnection;
|
|
||||||
|
|
||||||
static void AppendHeader(char* buf,
|
|
||||||
const char* key, const char* value)
|
|
||||||
{
|
|
||||||
strcat(buf, key);
|
|
||||||
strcat(buf, ": ");
|
|
||||||
strcat(buf, value);
|
|
||||||
strcat(buf, "\r\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ProcessChunkedTransfer(char* chunked, size_t chunked_len, size_t *out_len) {
|
char *ProcessChunkedTransfer(char *chunked, size_t chunked_len,
|
||||||
char* result = malloc(chunked_len);
|
size_t *out_len) {
|
||||||
size_t written = 0;
|
char *result = malloc(chunked_len);
|
||||||
char* curpos = chunked;
|
size_t written = 0;
|
||||||
|
char *curpos = chunked;
|
||||||
|
|
||||||
while(1) {
|
while (1) {
|
||||||
char* crlf = strstr(curpos, "\r\n");
|
char *crlf = strstr(curpos, "\r\n");
|
||||||
if(!crlf) break;
|
if (!crlf)
|
||||||
|
break;
|
||||||
|
|
||||||
int chunklen = (int)strtol(curpos, NULL, 16);
|
int chunklen = (int)strtol(curpos, NULL, 16);
|
||||||
if(chunklen == 0) break;
|
if (chunklen == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
char* data = crlf + 2;
|
char *data = crlf + 2;
|
||||||
memcpy(result + written, data, chunklen);
|
memcpy(result + written, data, chunklen);
|
||||||
written += chunklen;
|
written += chunklen;
|
||||||
curpos = data + chunklen + 2;
|
curpos = data + chunklen + 2;
|
||||||
}
|
|
||||||
|
|
||||||
*out_len = written;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPConnection* ConnectOverHTTP(const char* hostname) {
|
|
||||||
HTTPConnection* conn = malloc(sizeof(HTTPConnection));
|
|
||||||
RtlZeroMemory(conn, sizeof(HTTPConnection));
|
|
||||||
|
|
||||||
strncpy(conn->hostname, hostname, 255);
|
|
||||||
conn->hostname[255] = '\0';
|
|
||||||
|
|
||||||
conn->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
|
|
||||||
if (conn->sock == INVALID_SOCKET) {
|
|
||||||
MessageBoxA(NULL, "socket failed :(", "sad http announcement", 0);
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in server;
|
|
||||||
RtlZeroMemory(&server, sizeof(server));
|
|
||||||
server.sin_family = AF_INET;
|
|
||||||
server.sin_port = htons(443);
|
|
||||||
server.sin_addr = **(struct in_addr**)gethostbyname(hostname)->h_addr_list; // why is a part of this in bold
|
|
||||||
|
|
||||||
if (connect(conn->sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
|
|
||||||
MessageBoxA(NULL, "connect failed :(", "sad http announcement", 0);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->ctx = SSL_CTX_new(TLS_client_method());
|
|
||||||
|
|
||||||
if (!conn->ctx) {
|
|
||||||
MessageBoxA(NULL, "SSL_CTX_new failed :(", "sad http announcement", 0);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->ssl = SSL_new(conn->ctx);
|
|
||||||
|
|
||||||
if (!conn->ssl) {
|
|
||||||
MessageBoxA(NULL, "SSL_new failed :(", "sad http announcement", 0);
|
|
||||||
SSL_CTX_free(conn->ctx);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_set_fd(conn->ssl, (int)conn->sock);
|
|
||||||
SSL_set_tlsext_host_name(conn->ssl, hostname);
|
|
||||||
|
|
||||||
if (SSL_connect(conn->ssl) <= 0) {
|
|
||||||
MessageBoxA(NULL, "SSL_connect failed :(", "sad http announcement", 0);
|
|
||||||
SSL_free(conn->ssl);
|
|
||||||
SSL_CTX_free(conn->ctx);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
free(conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->connected = 1;
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
int SendHTTPRequest(HTTPConnection* conn, const char* method, const char* endpoint,
|
|
||||||
const char* user_agent, const char* content_type, void* payload,
|
|
||||||
unsigned long payload_size, char** response, long* responselen)
|
|
||||||
{
|
|
||||||
if (!conn || !conn->connected) {
|
|
||||||
MessageBoxA(NULL, "connection not established :(", "sad http announcement", 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char headerbuf[2048];
|
|
||||||
RtlZeroMemory(headerbuf, sizeof(headerbuf));
|
|
||||||
|
|
||||||
wsprintfA(headerbuf, "%s %s HTTP/1.1\r\n", method, endpoint);
|
|
||||||
strcat(headerbuf, "Host: ");
|
|
||||||
strcat(headerbuf, conn->hostname);
|
|
||||||
strcat(headerbuf, "\r\n");
|
|
||||||
strcat(headerbuf, "User-Agent: ");
|
|
||||||
strcat(headerbuf, user_agent);
|
|
||||||
strcat(headerbuf, "\r\n");
|
|
||||||
|
|
||||||
if (payload) {
|
|
||||||
strcat(headerbuf, "Content-Type: ");
|
|
||||||
strcat(headerbuf, content_type);
|
|
||||||
strcat(headerbuf, "\r\n");
|
|
||||||
|
|
||||||
char contentlen[128];
|
|
||||||
RtlZeroMemory(contentlen, sizeof(contentlen));
|
|
||||||
wsprintfA(contentlen, "Content-Length: %lu\r\n", payload_size);
|
|
||||||
strcat(headerbuf, contentlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
strcat(headerbuf, "Connection: keep-alive\r\n");
|
|
||||||
strcat(headerbuf, "\r\n");
|
|
||||||
|
|
||||||
if (SSL_write(conn->ssl, headerbuf, (int)strlen(headerbuf)) <= 0) {
|
|
||||||
MessageBoxA(NULL, "SSL_write headers failed :(", "sad http announcement", 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload && payload_size > 0) {
|
|
||||||
if (SSL_write(conn->ssl, payload, (int)payload_size) <= 0) {
|
|
||||||
MessageBoxA(NULL, "SSL_write payload failed :(", "sad http announcement", 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char* buffer = malloc(8192);
|
|
||||||
size_t sizeofbuf = 8192;
|
|
||||||
size_t total_bytes = 0;
|
|
||||||
int bytes_read;
|
|
||||||
|
|
||||||
while ((bytes_read = SSL_read(conn->ssl, buffer + total_bytes, (int)(sizeofbuf - total_bytes - 1))) > 0) {
|
|
||||||
total_bytes += bytes_read;
|
|
||||||
|
|
||||||
if (total_bytes + 1 >= sizeofbuf) {
|
|
||||||
sizeofbuf += 8192;
|
|
||||||
char* newbuf = realloc(buffer, sizeofbuf);
|
|
||||||
|
|
||||||
if (!newbuf) {
|
|
||||||
MessageBoxA(NULL, "realloc failed :(", "sad http announcement", 0);
|
|
||||||
free(buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = newbuf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[total_bytes] = '\0';
|
|
||||||
|
|
||||||
char* endofhdr = strstr(buffer, "\r\n\r\n");
|
|
||||||
|
|
||||||
if (!endofhdr) {
|
|
||||||
MessageBoxA(NULL, "malformed response :(", "sad http announcement", 0);
|
|
||||||
free(buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* body_start = endofhdr + 4;
|
|
||||||
size_t body_len = total_bytes - (body_start - buffer);
|
|
||||||
|
|
||||||
if (strstr(buffer, "Transfer-Encoding: chunked")) {
|
|
||||||
size_t outlen;
|
|
||||||
*response = ProcessChunkedTransfer(body_start, body_len, &outlen);
|
|
||||||
*responselen = (long)outlen;
|
|
||||||
free(buffer);
|
|
||||||
} else {
|
|
||||||
char* copy = malloc(body_len + 1);
|
|
||||||
memcpy(copy, body_start, body_len);
|
|
||||||
copy[body_len] = '\0';
|
|
||||||
*response = copy;
|
|
||||||
*responselen = (long)body_len;
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int CloseHTTPConnection(HTTPConnection* conn) {
|
|
||||||
if (!conn) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->ssl) {
|
|
||||||
SSL_shutdown(conn->ssl);
|
|
||||||
SSL_free(conn->ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->ctx) {
|
|
||||||
SSL_CTX_free(conn->ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn->sock != INVALID_SOCKET) {
|
|
||||||
closesocket(conn->sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(conn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int SendShortHTTPReq(const char* hostname,const char* reqtype, const char* endpoint, const char* extra_headers, const char* user_agent, const char* content_type, void* payload, unsigned long payload_size, char** response, long* responselen)
|
|
||||||
{
|
|
||||||
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (sock == INVALID_SOCKET) {
|
|
||||||
MessageBoxA(NULL, "socket failed", "Aa", 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr_in server;
|
|
||||||
RtlZeroMemory(&server, sizeof(server));
|
|
||||||
server.sin_family = AF_INET;
|
|
||||||
server.sin_port = htons(443); // HTTPS brotatochippiee
|
|
||||||
server.sin_addr = **(struct in_addr**)gethostbyname(hostname)->h_addr_list;
|
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
|
|
||||||
MessageBoxA(NULL, "connect failed", "Aa", 0);
|
|
||||||
closesocket(sock);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this debugging thing served us well yall MessageBoxA(NULL, "onto ze ctx", "Aa", 0);
|
*out_len = written;
|
||||||
SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
|
return result;
|
||||||
if (!ctx) {
|
}
|
||||||
|
|
||||||
|
HTTPConnection *HTTPConnect(const char *hostname) {
|
||||||
|
HTTPConnection *conn = malloc(sizeof(HTTPConnection));
|
||||||
|
RtlZeroMemory(conn, sizeof(HTTPConnection));
|
||||||
|
|
||||||
|
strncpy(conn->hostname, hostname, 255);
|
||||||
|
conn->hostname[255] = '\0';
|
||||||
|
|
||||||
|
conn->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (conn->sock == INVALID_SOCKET) {
|
||||||
|
char msg[128];
|
||||||
|
wsprintfA(msg, "socket failed: WSAGetLastError=%d", WSAGetLastError());
|
||||||
|
MessageBoxA(NULL, msg, "sad http announcement", 0);
|
||||||
|
free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in server;
|
||||||
|
RtlZeroMemory(&server, sizeof(server));
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons(443);
|
||||||
|
server.sin_addr = **(struct in_addr **)gethostbyname(hostname)
|
||||||
|
->h_addr_list; // why is a part of this in bold
|
||||||
|
|
||||||
|
if (connect(conn->sock, (struct sockaddr *)&server, sizeof(server)) ==
|
||||||
|
SOCKET_ERROR) {
|
||||||
|
MessageBoxA(NULL, "connect failed :(", "sad http announcement", 0);
|
||||||
|
closesocket(conn->sock);
|
||||||
|
free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->ctx = SSL_CTX_new(TLS_client_method());
|
||||||
|
|
||||||
|
if (!conn->ctx) {
|
||||||
|
MessageBoxA(NULL, "SSL_CTX_new failed :(", "sad http announcement", 0);
|
||||||
|
closesocket(conn->sock);
|
||||||
|
free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->ssl = SSL_new(conn->ctx);
|
||||||
|
|
||||||
|
if (!conn->ssl) {
|
||||||
|
MessageBoxA(NULL, "SSL_new failed :(", "sad http announcement", 0);
|
||||||
|
SSL_CTX_free(conn->ctx);
|
||||||
|
closesocket(conn->sock);
|
||||||
|
free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_set_fd(conn->ssl, (int)conn->sock);
|
||||||
|
SSL_set_tlsext_host_name(conn->ssl, hostname);
|
||||||
|
|
||||||
|
if (SSL_connect(conn->ssl) <= 0) {
|
||||||
|
MessageBoxA(NULL, "SSL_connect failed :(", "sad http announcement", 0);
|
||||||
|
SSL_free(conn->ssl);
|
||||||
|
SSL_CTX_free(conn->ctx);
|
||||||
|
closesocket(conn->sock);
|
||||||
|
free(conn);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->connected = 1;
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
char *GetHeaderValue(char *source, char *field) {
|
||||||
|
size_t flen = strlen(field);
|
||||||
|
for (char *curs = source; curs; curs = strstr(curs + 1, "\r\n")
|
||||||
|
? strstr(curs + 1, "\r\n") + 2
|
||||||
|
: NULL) {
|
||||||
|
if (strncmp(field, curs, flen) == 0 && curs[flen] == ':') {
|
||||||
|
char *dat = curs + flen + 1;
|
||||||
|
while (*dat == ' ')
|
||||||
|
dat++;
|
||||||
|
char *end = strstr(curs + 1, "\r\n");
|
||||||
|
char *ret = malloc(end - dat + 1);
|
||||||
|
memcpy(ret, dat, end - dat);
|
||||||
|
ret[end - dat] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int SendHTTPRequest(HTTPConnection *conn, const char *method,
|
||||||
|
const char *endpoint, const char *extra_headers,
|
||||||
|
const char *user_agent, const char *content_type,
|
||||||
|
void *payload, unsigned long payload_size, char **response,
|
||||||
|
long *responselen) {
|
||||||
|
if (!conn || !conn->connected) {
|
||||||
|
MessageBoxA(NULL, "connection not established :(",
|
||||||
|
"sad http announcement", 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char headerbuf[4096];
|
||||||
|
RtlZeroMemory(headerbuf, sizeof(headerbuf));
|
||||||
|
|
||||||
|
wsprintfA(headerbuf, "%s %s HTTP/1.1\r\n", method, endpoint);
|
||||||
|
strcat(headerbuf, "Host: ");
|
||||||
|
strcat(headerbuf, conn->hostname);
|
||||||
|
strcat(headerbuf, "\r\n");
|
||||||
|
strcat(headerbuf, extra_headers);
|
||||||
|
strcat(headerbuf, "\r\n");
|
||||||
|
strcat(headerbuf, "User-Agent: ");
|
||||||
|
strcat(headerbuf, user_agent);
|
||||||
|
strcat(headerbuf, "\r\n");
|
||||||
|
|
||||||
|
if (payload) {
|
||||||
|
strcat(headerbuf, "Content-Type: ");
|
||||||
|
strcat(headerbuf, content_type);
|
||||||
|
strcat(headerbuf, "\r\n");
|
||||||
|
|
||||||
|
char contentlen[128];
|
||||||
|
RtlZeroMemory(contentlen, sizeof(contentlen));
|
||||||
|
wsprintfA(contentlen, "Content-Length: %lu\r\n", payload_size);
|
||||||
|
strcat(headerbuf, contentlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(headerbuf, "Connection: keep-alive\r\n");
|
||||||
|
strcat(headerbuf, "\r\n");
|
||||||
|
//char dbg[64];
|
||||||
|
//wsprintfA(dbg, "headerbuf len: %d", (int)strlen(headerbuf));
|
||||||
|
//MessageBoxA(NULL, dbg, "debug", 0);
|
||||||
|
if (SSL_write(conn->ssl, headerbuf, (int)strlen(headerbuf)) <= 0) {
|
||||||
|
MessageBoxA(NULL, "SSL_write headers failed :(",
|
||||||
|
"sad http announcement", 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload && payload_size > 0) {
|
||||||
|
if (SSL_write(conn->ssl, payload, (int)payload_size) <= 0) {
|
||||||
|
MessageBoxA(NULL, "SSL_write payload failed :(",
|
||||||
|
"sad http announcement", 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buffer = malloc(8192);
|
||||||
|
memset(buffer, 0, 8192);
|
||||||
|
size_t sizeofbuf = 8192;
|
||||||
|
size_t total_bytes = 0;
|
||||||
|
int bytes_read;
|
||||||
|
int headerlen;
|
||||||
|
while (strstr(buffer, "\r\n\r\n") == NULL) {
|
||||||
|
bytes_read = SSL_read(conn->ssl, buffer + total_bytes,
|
||||||
|
(int)(sizeofbuf - total_bytes - 1));
|
||||||
|
total_bytes += bytes_read;
|
||||||
|
|
||||||
|
if (total_bytes + 1 >= sizeofbuf) {
|
||||||
|
sizeofbuf += 8192;
|
||||||
|
char *newbuf = realloc(buffer, sizeofbuf);
|
||||||
|
|
||||||
|
if (!newbuf) {
|
||||||
|
MessageBoxA(NULL, "realloc failed :(", "sad http announcement",
|
||||||
|
0);
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = newbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *endofhdr = strstr(buffer, "\r\n\r\n");
|
||||||
|
headerlen = endofhdr - buffer;
|
||||||
|
char *headers = malloc(headerlen + 1);
|
||||||
|
memcpy(headers, buffer, headerlen);
|
||||||
|
headers[headerlen] = '\0';
|
||||||
|
|
||||||
|
char *cclen = GetHeaderValue(headers, "Content-Length");
|
||||||
|
unsigned long long clen = cclen ? strtoull(cclen, NULL, 10) : 0;
|
||||||
|
free(cclen);
|
||||||
|
|
||||||
|
char *body_start = buffer + headerlen + 4;
|
||||||
|
size_t body_have =
|
||||||
|
total_bytes - (body_start - buffer); // body bytes already buffered
|
||||||
|
|
||||||
|
int is_chunked = 0;
|
||||||
|
char *cte = GetHeaderValue(headers, "Transfer-Encoding");
|
||||||
|
if (cte) {
|
||||||
|
if (strstr(cte, "chunked"))
|
||||||
|
is_chunked = 1;
|
||||||
|
free(cte);
|
||||||
|
}
|
||||||
|
free(headers);
|
||||||
|
if (is_chunked) {
|
||||||
|
while (!strstr(body_start, "0\r\n\r\n")) {
|
||||||
|
if (total_bytes + 1 >= sizeofbuf) {
|
||||||
|
sizeofbuf += 8192;
|
||||||
|
char *newbuf = realloc(buffer, sizeofbuf);
|
||||||
|
if (!newbuf) {
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buffer = newbuf;
|
||||||
|
body_start = buffer + headerlen + 4;
|
||||||
|
}
|
||||||
|
int n = SSL_read(conn->ssl, buffer + total_bytes,
|
||||||
|
(int)(sizeofbuf - total_bytes - 1));
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
total_bytes += n;
|
||||||
|
buffer[total_bytes] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (body_have < clen) {
|
||||||
|
if (total_bytes + 1 >= sizeofbuf) {
|
||||||
|
sizeofbuf += 8192;
|
||||||
|
char *newbuf = realloc(buffer, sizeofbuf);
|
||||||
|
if (!newbuf) {
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buffer = newbuf;
|
||||||
|
body_start = buffer + headerlen + 4;
|
||||||
|
}
|
||||||
|
int n = SSL_read(conn->ssl, buffer + total_bytes,
|
||||||
|
(int)(sizeofbuf - total_bytes - 1));
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
total_bytes += n;
|
||||||
|
body_have += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[total_bytes] = '\0';
|
||||||
|
|
||||||
|
if (!endofhdr) {
|
||||||
|
MessageBoxA(NULL, "malformed response :(", "sad http announcement", 0);
|
||||||
|
free(buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t body_len = total_bytes - (body_start - buffer);
|
||||||
|
|
||||||
|
if (is_chunked) {
|
||||||
|
size_t outlen;
|
||||||
|
*response = ProcessChunkedTransfer(body_start, body_len, &outlen);
|
||||||
|
*responselen = (long)outlen;
|
||||||
|
free(buffer);
|
||||||
|
} else {
|
||||||
|
char *copy = malloc(body_len + 1);
|
||||||
|
memcpy(copy, body_start, body_len);
|
||||||
|
copy[body_len] = '\0';
|
||||||
|
*response = copy;
|
||||||
|
*responselen = (long)body_len;
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int CloseHTTPConnection(HTTPConnection *conn) {
|
||||||
|
if (!conn) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->ssl) {
|
||||||
|
SSL_shutdown(conn->ssl);
|
||||||
|
SSL_free(conn->ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->ctx) {
|
||||||
|
SSL_CTX_free(conn->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn->sock != INVALID_SOCKET) {
|
||||||
|
closesocket(conn->sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int SendShortHTTPReq(const char *hostname, const char *reqtype,
|
||||||
|
const char *endpoint, const char *extra_headers,
|
||||||
|
const char *user_agent, const char *content_type,
|
||||||
|
void *payload, unsigned long payload_size, char **response,
|
||||||
|
long *responselen) {
|
||||||
|
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
MessageBoxA(NULL, "socket failed", "Aa", 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in server;
|
||||||
|
RtlZeroMemory(&server, sizeof(server));
|
||||||
|
server.sin_family = AF_INET;
|
||||||
|
server.sin_port = htons(443); // HTTPS brotatochippiee
|
||||||
|
server.sin_addr = **(struct in_addr **)gethostbyname(hostname)->h_addr_list;
|
||||||
|
|
||||||
|
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) ==
|
||||||
|
SOCKET_ERROR) {
|
||||||
|
MessageBoxA(NULL, "connect failed", "Aa", 0);
|
||||||
|
closesocket(sock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this debugging thing served us well yall MessageBoxA(NULL, "onto ze ctx",
|
||||||
|
// "Aa", 0);
|
||||||
|
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
|
||||||
|
if (!ctx) {
|
||||||
MessageBoxA(NULL, "SSL_CTX_new failed", "Aa", 0);
|
MessageBoxA(NULL, "SSL_CTX_new failed", "Aa", 0);
|
||||||
unsigned long err = ERR_get_error();
|
unsigned long err = ERR_get_error();
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
MessageBoxA(NULL, "unknown OpenSSL error", "title", MB_ICONERROR);
|
MessageBoxA(NULL, "unknown OpenSSL error", "title", MB_ICONERROR);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
ERR_error_string_n(err, buf, sizeof(buf));
|
ERR_error_string_n(err, buf, sizeof(buf));
|
||||||
|
|
||||||
MessageBoxA(NULL, buf, "title", MB_ICONERROR);
|
MessageBoxA(NULL, buf, "title", MB_ICONERROR);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL* ssl = SSL_new(ctx);
|
SSL *ssl = SSL_new(ctx);
|
||||||
if (!ssl) {
|
if (!ssl) {
|
||||||
MessageBoxA(NULL, "SSL_new failed qwq", "Aa", 0);
|
MessageBoxA(NULL, "SSL_new failed qwq", "Aa", 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach socket to SSL
|
// Attach socket to SSL
|
||||||
SSL_set_fd(ssl, (int)sock);
|
SSL_set_fd(ssl, (int)sock);
|
||||||
|
|
||||||
// SNI (importante shi)
|
// SNI (importante shi)
|
||||||
SSL_set_tlsext_host_name(ssl, hostname);
|
SSL_set_tlsext_host_name(ssl, hostname);
|
||||||
|
|
||||||
if (SSL_connect(ssl) <= 0) {
|
if (SSL_connect(ssl) <= 0) {
|
||||||
MessageBoxA(NULL, "SSL_connect failed", "Aa", 0);
|
MessageBoxA(NULL, "SSL_connect failed", "Aa", 0);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSL_write(ssl, reqtype, (int)strlen(reqtype)); // Sends request type
|
||||||
SSL_write(ssl, reqtype, (int)strlen(reqtype)); // Sends request type
|
SSL_write(ssl, " ", 1); // stupid fuckass space
|
||||||
SSL_write(ssl, " ", 1); // stupid fuckass space
|
|
||||||
SSL_write(ssl, endpoint, (int)strlen(endpoint)); // endpoint
|
SSL_write(ssl, endpoint, (int)strlen(endpoint)); // endpoint
|
||||||
SSL_write(ssl, " HTTP/1.1\r\n", 11); // the protocol thing.. ykw i will be more formal
|
SSL_write(ssl, " HTTP/1.1\r\n",
|
||||||
SSL_write(ssl, "Host: ", 6); // Host beginning
|
11); // the protocol thing.. ykw i will be more formal
|
||||||
|
SSL_write(ssl, "Host: ", 6); // Host beginning
|
||||||
SSL_write(ssl, hostname, (int)(strlen(hostname))); // Host data
|
SSL_write(ssl, hostname, (int)(strlen(hostname))); // Host data
|
||||||
SSL_write(ssl, "\r\n", 2); // Host end
|
SSL_write(ssl, "\r\n", 2); // Host end
|
||||||
SSL_write(ssl, "User-Agent: ", 12); // User Agent beginning
|
SSL_write(ssl, "User-Agent: ", 12); // User Agent beginning
|
||||||
SSL_write(ssl, user_agent, (int)(strlen(user_agent))); // User Agent data
|
SSL_write(ssl, user_agent, (int)(strlen(user_agent))); // User Agent data
|
||||||
SSL_write(ssl, "\r\n", 2); // User Agent end
|
SSL_write(ssl, "\r\n", 2); // User Agent end
|
||||||
|
|
||||||
|
|
||||||
if (payload != 0) {
|
if (payload != 0) {
|
||||||
SSL_write(ssl, "Content-Type: ", 14); // Content Type beginning
|
SSL_write(ssl, "Content-Type: ", 14); // Content Type beginning
|
||||||
SSL_write(ssl, content_type, (int)strlen(content_type));
|
SSL_write(ssl, content_type, (int)strlen(content_type));
|
||||||
SSL_write(ssl, "\r\n", 2); // Content Type end
|
SSL_write(ssl, "\r\n", 2); // Content Type end
|
||||||
|
|
||||||
SSL_write(ssl, "Content-Length: ", 16); // Content Length beginning
|
|
||||||
char lenstr[64];
|
|
||||||
RtlZeroMemory(lenstr,64);
|
|
||||||
wsprintfA(lenstr,"%d",payload_size);
|
|
||||||
SSL_write(ssl, lenstr, (int)(strlen(lenstr))); // Content Length data
|
|
||||||
SSL_write(ssl, "\r\n", 2); // Content Length end
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SSL_write(ssl, "Content-Length: ", 16); // Content Length beginning
|
||||||
|
char lenstr[64];
|
||||||
|
RtlZeroMemory(lenstr, 64);
|
||||||
|
wsprintfA(lenstr, "%d", payload_size);
|
||||||
|
SSL_write(ssl, lenstr, (int)(strlen(lenstr))); // Content Length data
|
||||||
|
SSL_write(ssl, "\r\n", 2); // Content Length end
|
||||||
|
}
|
||||||
|
|
||||||
SSL_write(ssl, extra_headers, (int)(strlen(extra_headers))); // Extra Header
|
SSL_write(ssl, extra_headers, (int)(strlen(extra_headers))); // Extra Header
|
||||||
SSL_write(ssl, "Connection: close\r\n", 19); //Short-term connection
|
SSL_write(ssl, "\r\n", 2);
|
||||||
SSL_write(ssl, "\r\n", 2); //Ends the header
|
SSL_write(ssl, "Connection: close\r\n", 19); // Short-term connection
|
||||||
if(payload)
|
SSL_write(ssl, "\r\n", 2); // Ends the header
|
||||||
SSL_write(ssl, payload, (int)payload_size); //Payload
|
if (payload)
|
||||||
|
SSL_write(ssl, payload, (int)payload_size); // Payload
|
||||||
|
|
||||||
char* buffer = malloc(4096);
|
char *buffer = malloc(4096);
|
||||||
size_t sizeofbuf = 4096;
|
size_t sizeofbuf = 4096;
|
||||||
size_t total_bytes = 0;
|
size_t total_bytes = 0;
|
||||||
int bytes_read;
|
int bytes_read;
|
||||||
|
|
||||||
while ((bytes_read = SSL_read(ssl, buffer + total_bytes, (int)(sizeofbuf - total_bytes - 1))) > 0) {
|
while ((bytes_read = SSL_read(ssl, buffer + total_bytes,
|
||||||
total_bytes += bytes_read;
|
(int)(sizeofbuf - total_bytes - 1))) > 0) {
|
||||||
|
total_bytes += bytes_read;
|
||||||
|
|
||||||
if (total_bytes + 1 >= sizeofbuf) {
|
if (total_bytes + 1 >= sizeofbuf) {
|
||||||
sizeofbuf += 4096;
|
sizeofbuf += 4096;
|
||||||
char* newbuf = realloc(buffer, sizeofbuf);
|
char *newbuf = realloc(buffer, sizeofbuf);
|
||||||
if (!newbuf) {
|
if (!newbuf) {
|
||||||
//what the fuck had possibly happened on bros pc :sob:
|
// what the fuck had possibly happened on bros pc :sob:
|
||||||
free(buffer);
|
free(buffer);
|
||||||
SSL_shutdown(ssl);
|
SSL_shutdown(ssl);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buffer = newbuf;
|
buffer = newbuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer[total_bytes] = '\0';
|
buffer[total_bytes] = '\0';
|
||||||
|
|
||||||
char *endofhdr = strstr(buffer, "\r\n\r\n");
|
char *endofhdr = strstr(buffer, "\r\n\r\n");
|
||||||
if (!endofhdr) {
|
if (!endofhdr) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx);
|
SSL_shutdown(ssl);
|
||||||
closesocket(sock);
|
SSL_free(ssl);
|
||||||
return -1;
|
SSL_CTX_free(ctx);
|
||||||
}
|
closesocket(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
char *body_start = endofhdr + 4;
|
char *body_start = endofhdr + 4;
|
||||||
size_t body_len = total_bytes - (body_start - buffer);
|
size_t body_len = total_bytes - (body_start - buffer);
|
||||||
if (strstr(buffer, "Transfer-Encoding: chunked")) {
|
if (strstr(buffer, "Transfer-Encoding: chunked")) {
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
*response = ProcessChunkedTransfer(body_start,body_len,&outlen);
|
*response = ProcessChunkedTransfer(body_start, body_len, &outlen);
|
||||||
*responselen = (long)outlen;
|
*responselen = (long)outlen;
|
||||||
free(buffer);
|
free(buffer);
|
||||||
} else {
|
} else {
|
||||||
char *copy = malloc(body_len + 1);
|
char *copy = malloc(body_len + 1);
|
||||||
memcpy(copy, body_start, body_len);
|
memcpy(copy, body_start, body_len);
|
||||||
copy[body_len] = '\0';
|
copy[body_len] = '\0';
|
||||||
*response = copy;
|
*response = copy;
|
||||||
*responselen = (long)body_len;
|
*responselen = (long)body_len;
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_shutdown(ssl);
|
SSL_shutdown(ssl);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
SSL_CTX_free(ctx);
|
SSL_CTX_free(ctx);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int InitHTTP() {
|
int InitHTTP() {
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
WSAStartup(MAKEWORD(2,2), &wsaData); //me when macros
|
WSAStartup(MAKEWORD(2, 2), &wsaData); // me when macros
|
||||||
}
|
|
||||||
int CleanupHTTP() {
|
|
||||||
WSACleanup();
|
|
||||||
}
|
}
|
||||||
|
int CleanupHTTP() { WSACleanup(); }
|
||||||
|
|||||||
@@ -1,10 +1,26 @@
|
|||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
// keepalive state
|
||||||
|
typedef struct {
|
||||||
|
SOCKET sock;
|
||||||
|
SSL* ssl;
|
||||||
|
SSL_CTX* ctx;
|
||||||
|
char hostname[256];
|
||||||
|
int connected;
|
||||||
|
} HTTPConnection;
|
||||||
void InitSockets();
|
void InitSockets();
|
||||||
int SendShortHTTPReq(const char *hostname, const char *reqtype,
|
int SendShortHTTPReq(const char *hostname, const char *reqtype,
|
||||||
const char *endpoint, const char *extra_headers,
|
const char *endpoint, const char *extra_headers,
|
||||||
const char *user_agent, const char *content_type,
|
const char *user_agent, const char *content_type,
|
||||||
void *payload, unsigned long payload_size, char** response, long* responselen);
|
void *payload, unsigned long payload_size, char** response, long* responselen);
|
||||||
|
|
||||||
|
HTTPConnection* HTTPConnect(const char* hostname);
|
||||||
|
int SendHTTPRequest(HTTPConnection* conn, const char* method, const char* endpoint, const char* extra_headers,
|
||||||
|
const char* user_agent, const char* content_type, void* payload,
|
||||||
|
unsigned long payload_size, char** response, long* responselen);
|
||||||
|
int CloseHTTPConnection(HTTPConnection* conn);
|
||||||
static void AppendHeader(char *buf, const char *key, const char *value);
|
static void AppendHeader(char *buf, const char *key, const char *value);
|
||||||
|
|
||||||
int InitHTTP();
|
int InitHTTP();
|
||||||
|
|||||||
@@ -72,8 +72,23 @@ int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, PSTR pCmdLine,
|
|||||||
InitSnowsControls();
|
InitSnowsControls();
|
||||||
hSidePfps = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 12, 1);
|
hSidePfps = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 12, 1);
|
||||||
hChannelImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 8, 1);
|
hChannelImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 8, 1);
|
||||||
ImageList_AddMasked(hChannelImgList,LoadBitmap(hinstance,MAKEINTRESOURCE(IDI_CHANNEL_VC)),RGB(255,0,255));
|
ImageList_AddMasked(
|
||||||
ImageList_AddMasked(hChannelImgList,LoadBitmap(hinstance,MAKEINTRESOURCE(IDI_CHANNEL_ANC)),RGB(255,0,255));
|
hChannelImgList,
|
||||||
|
LoadBitmap(hinstance, MAKEINTRESOURCE(IDI_CHANNEL_CATEGORY)),
|
||||||
|
RGB(255, 0, 255));
|
||||||
|
ImageList_AddMasked(hChannelImgList,
|
||||||
|
LoadBitmap(hinstance, MAKEINTRESOURCE(IDI_CHANNEL_TC)),
|
||||||
|
RGB(255, 0, 255));
|
||||||
|
ImageList_AddMasked(hChannelImgList,
|
||||||
|
LoadBitmap(hinstance, MAKEINTRESOURCE(IDI_CHANNEL_VC)),
|
||||||
|
RGB(255, 0, 255));
|
||||||
|
ImageList_AddMasked(hChannelImgList,
|
||||||
|
LoadBitmap(hinstance, MAKEINTRESOURCE(IDI_CHANNEL_ANC)),
|
||||||
|
RGB(255, 0, 255));
|
||||||
|
ImageList_AddMasked(
|
||||||
|
hChannelImgList,
|
||||||
|
LoadBitmap(hinstance, MAKEINTRESOURCE(IDI_CHANNEL_FORUM)),
|
||||||
|
RGB(255, 0, 255));
|
||||||
hInstance = hinstance;
|
hInstance = hinstance;
|
||||||
// register the window claws
|
// register the window claws
|
||||||
const char CLASS_NAME[] = "BackcordMain";
|
const char CLASS_NAME[] = "BackcordMain";
|
||||||
@@ -130,7 +145,7 @@ void onDiscordGuildLoad(DiscordGuild *guild, char *id) {
|
|||||||
wsprintfA(path, "%s%s.png", tempPath, guild->IconHash);
|
wsprintfA(path, "%s%s.png", tempPath, guild->IconHash);
|
||||||
if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) {
|
if (GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES) {
|
||||||
path = DiscordFetchTmpGuildIcon(guild->id,
|
path = DiscordFetchTmpGuildIcon(guild->id,
|
||||||
guild->IconHash); // testing
|
guild->IconHash); // testing
|
||||||
}
|
}
|
||||||
GuildView_SetIcon(hGSel, LoadPNGImage(path), id);
|
GuildView_SetIcon(hGSel, LoadPNGImage(path), id);
|
||||||
free(path);
|
free(path);
|
||||||
@@ -179,7 +194,7 @@ void onDiscordReady(DiscordUser user, DiscordGuild *guilds, int guildscount) {
|
|||||||
int DestH = ClientRect.bottom - ClientRect.top;
|
int DestH = ClientRect.bottom - ClientRect.top;
|
||||||
|
|
||||||
SendMessage(hPfpAreaPfp, STM_SETIMAGE, IMAGE_BITMAP,
|
SendMessage(hPfpAreaPfp, STM_SETIMAGE, IMAGE_BITMAP,
|
||||||
(LPARAM)ResizeBitmap(LoadPNGBitmap(path),DestW,DestH));
|
(LPARAM)ResizeBitmap(LoadPNGBitmap(path), DestW, DestH));
|
||||||
|
|
||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
@@ -249,6 +264,15 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
HFONT BoldSysFont = CreateFontIndirect(&ncm.lfMessageFont);
|
HFONT BoldSysFont = CreateFontIndirect(&ncm.lfMessageFont);
|
||||||
|
|
||||||
InitHTTP();
|
InitHTTP();
|
||||||
|
/* HTTPConnection* hc = HTTPConnect("httpbin.org");
|
||||||
|
long responselen;
|
||||||
|
char* response;
|
||||||
|
SendHTTPRequest(hc, "GET", "/get", "", user_agent, NULL, NULL, 0, &response, &responselen);
|
||||||
|
MessageBoxA(NULL,response,"HTTP Test",0);
|
||||||
|
if(responselen==strlen(response)){
|
||||||
|
MessageBoxA(NULL,"pass","HTTP Test",0);
|
||||||
|
}*/
|
||||||
|
DiscordHTTPConnect();
|
||||||
|
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetClientRect(hwnd, &rc);
|
GetClientRect(hwnd, &rc);
|
||||||
@@ -272,9 +296,17 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
TVS_LINESATROOT | TVS_HASBUTTONS,
|
TVS_LINESATROOT | TVS_HASBUTTONS,
|
||||||
90, 0, 128, rc.bottom - rc.top - 80, hwnd,
|
90, 0, 128, rc.bottom - rc.top - 80, hwnd,
|
||||||
(HMENU)103, hInstance, NULL);
|
(HMENU)103, hInstance, NULL);
|
||||||
hDMsList = CreateWindowExA(
|
TreeView_SetImageList(hChTree, hChannelImgList, 0);
|
||||||
WS_EX_CLIENTEDGE, WC_LISTVIEWA, NULL, WS_CHILD | WS_VISIBLE, 90, 0,
|
hDMsList = CreateWindowExA(WS_EX_CLIENTEDGE, WC_LISTVIEWA, NULL,
|
||||||
128, rc.bottom - rc.top - 80, hwnd, (HMENU)103, hInstance, NULL);
|
WS_CHILD | WS_VISIBLE | LVS_REPORT, 90, 0,
|
||||||
|
128, rc.bottom - rc.top - 80, hwnd,
|
||||||
|
(HMENU)106, hInstance, NULL);
|
||||||
|
LVCOLUMN lvc = {0};
|
||||||
|
lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
||||||
|
lvc.cx = 128;
|
||||||
|
lvc.pszText = "Direct Messages";
|
||||||
|
lvc.iSubItem = 0;
|
||||||
|
ListView_InsertColumn(hDMsList, 0, &lvc);
|
||||||
ShowWindow(hDMsList, SW_HIDE);
|
ShowWindow(hDMsList, SW_HIDE);
|
||||||
hMsgList = CreateWindowEx(0, // Optional window styles.
|
hMsgList = CreateWindowEx(0, // Optional window styles.
|
||||||
"BackcordChat", // Window class
|
"BackcordChat", // Window class
|
||||||
@@ -305,8 +337,8 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
NULL // Additional application data
|
NULL // Additional application data
|
||||||
);
|
);
|
||||||
hPfpAreaPfp = CreateWindowExA(
|
hPfpAreaPfp = CreateWindowExA(
|
||||||
0, "STATIC", "", SS_BITMAP | WS_CHILD | WS_VISIBLE,
|
0, "STATIC", "", SS_BITMAP | WS_CHILD | WS_VISIBLE, 12, 24, 36, 36,
|
||||||
12, 24, 36, 36, hPfpArea, NULL, GetModuleHandle(NULL), NULL);
|
hPfpArea, NULL, GetModuleHandle(NULL), NULL);
|
||||||
hPfpAreaDispName = CreateWindowExA(
|
hPfpAreaDispName = CreateWindowExA(
|
||||||
0, "STATIC", "Display Name", WS_CHILD | WS_VISIBLE, 54, 24, 144, 16,
|
0, "STATIC", "Display Name", WS_CHILD | WS_VISIBLE, 54, 24, 144, 16,
|
||||||
hPfpArea, NULL, GetModuleHandle(NULL), NULL);
|
hPfpArea, NULL, GetModuleHandle(NULL), NULL);
|
||||||
@@ -381,15 +413,16 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
if (pNMHDR.hwndFrom == hGSel) {
|
if (pNMHDR.hwndFrom == hGSel) {
|
||||||
LPNMGUILDVIEW pnmv = (LPNMGUILDVIEW)lParam;
|
LPNMGUILDVIEW pnmv = (LPNMGUILDVIEW)lParam;
|
||||||
if (pnmv->index == GUILDVIEW_DMS) {
|
if (pnmv->index == GUILDVIEW_DMS) {
|
||||||
|
ShowWindow(hChTree, HIDE_WINDOW);
|
||||||
|
ShowWindow(hDMsList, 1);
|
||||||
DiscordChannel *dms;
|
DiscordChannel *dms;
|
||||||
int cnt = DiscordListPrivateChannels(&dms);
|
int cnt = DiscordListPrivateChannels(&dms);
|
||||||
TreeView_DeleteAllItems(hChTree);
|
ListView_DeleteAllItems(hDMsList);
|
||||||
TreeView_SetImageList(hChTree, hSidePfps, TVSIL_NORMAL);
|
ListView_SetImageList(hDMsList, hSidePfps, LVSIL_SMALL);
|
||||||
TVINSERTSTRUCT tvInsert = {0};
|
LVITEM lvItem = {0};
|
||||||
HTREEITEM hParent = TVI_ROOT;
|
|
||||||
int pfpidx = 0;
|
int pfpidx = 0;
|
||||||
for (int i = 0; i < cnt; i++) {
|
for (int i = 0; i < cnt; i++) {
|
||||||
if (dms[i].type == CHANNEL_TYPE_DM) {
|
if (dms[i].type == CHANNEL_DM) {
|
||||||
printf("%s\n", dms[i].receipents[0].Username);
|
printf("%s\n", dms[i].receipents[0].Username);
|
||||||
|
|
||||||
if (dms[i].receipents[0].avatar) {
|
if (dms[i].receipents[0].avatar) {
|
||||||
@@ -420,51 +453,83 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tvInsert.hParent = hParent; // Parent is the root item
|
lvItem.mask =
|
||||||
tvInsert.hInsertAfter = TVI_LAST;
|
LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
|
||||||
tvInsert.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE |
|
lvItem.pszText = dms[i].receipents[0].DisplayName
|
||||||
TVIF_IMAGE;
|
? dms[i].receipents[0].DisplayName
|
||||||
tvInsert.item.pszText =
|
: dms[i].receipents[0].Username;
|
||||||
dms[i].receipents[0].DisplayName
|
lvItem.lParam = (LPARAM) & (dms[i]);
|
||||||
? dms[i].receipents[0].DisplayName
|
lvItem.iImage =
|
||||||
: dms[i].receipents[0].Username;
|
|
||||||
tvInsert.item.lParam = (LPARAM) & (dms[i]);
|
|
||||||
tvInsert.item.state = TVIS_EXPANDED;
|
|
||||||
tvInsert.item.stateMask = TVIS_EXPANDED;
|
|
||||||
tvInsert.item.iImage =
|
|
||||||
dms[i].receipents[0].avatar ? pfpidx : 0;
|
dms[i].receipents[0].avatar ? pfpidx : 0;
|
||||||
tvInsert.item.iSelectedImage =
|
ListView_InsertItem(hDMsList, &lvItem);
|
||||||
|
if (dms[i].receipents[0].avatar) {
|
||||||
|
pfpidx++;
|
||||||
|
}
|
||||||
|
} else if(dms[i].type==CHANNEL_GC){
|
||||||
|
printf("%s\n", dms[i].receipents[0].Username);
|
||||||
|
|
||||||
|
if (dms[i].receipents[0].avatar) {
|
||||||
|
|
||||||
|
char tempPath[MAX_PATH];
|
||||||
|
DWORD len = GetTempPathA(MAX_PATH, tempPath);
|
||||||
|
char path[MAX_PATH +
|
||||||
|
strlen(dms[i].receipents[0].avatar) + 1];
|
||||||
|
wsprintfA(path, "%s%s.png", tempPath,
|
||||||
|
dms[i].receipents[0].avatar);
|
||||||
|
|
||||||
|
if (GetFileAttributesA(path) ==
|
||||||
|
INVALID_FILE_ATTRIBUTES) {
|
||||||
|
char *path2 = DiscordFetchTmpPfp(
|
||||||
|
dms[i].receipents[0].id,
|
||||||
|
dms[i].receipents[0].avatar); // testing
|
||||||
|
ImageList_Add(
|
||||||
|
hSidePfps,
|
||||||
|
ResizeBitmap(LoadPNGBitmap(path2), 32, 32),
|
||||||
|
NULL);
|
||||||
|
free(path2);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ImageList_Add(
|
||||||
|
hSidePfps,
|
||||||
|
ResizeBitmap(LoadPNGBitmap(path), 32, 32),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lvItem.mask =
|
||||||
|
LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
|
||||||
|
lvItem.pszText = dms[i].name ? dms[i].name : (dms[i].receipents[0].DisplayName
|
||||||
|
? dms[i].receipents[0].DisplayName
|
||||||
|
: dms[i].receipents[0].Username);
|
||||||
|
lvItem.lParam = (LPARAM) & (dms[i]);
|
||||||
|
lvItem.iImage =
|
||||||
dms[i].receipents[0].avatar ? pfpidx : 0;
|
dms[i].receipents[0].avatar ? pfpidx : 0;
|
||||||
HTREEITEM lres = (HTREEITEM)SendMessage(
|
ListView_InsertItem(hDMsList, &lvItem);
|
||||||
hChTree, TVM_INSERTITEM, 0, (LPARAM)&tvInsert);
|
|
||||||
if (dms[i].receipents[0].avatar) {
|
if (dms[i].receipents[0].avatar) {
|
||||||
pfpidx++;
|
pfpidx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
ShowWindow(hChTree, 1);
|
||||||
|
ShowWindow(hDMsList, HIDE_WINDOW);
|
||||||
DiscordGuild *guild;
|
DiscordGuild *guild;
|
||||||
guild = pnmv->guild.data;
|
guild = pnmv->guild.data;
|
||||||
|
|
||||||
DiscordChannel *Channels;
|
DiscordChannel *Channels;
|
||||||
int ChannelCount =
|
int ChannelCount =
|
||||||
DiscordListGuildChannels(guild->id, &Channels);
|
DiscordListGuildChannels(guild->id, &Channels);
|
||||||
|
TreeView_SelectItem(hChTree, NULL);
|
||||||
TreeView_DeleteAllItems(hChTree);
|
TreeView_DeleteAllItems(hChTree);
|
||||||
//TreeView_SetImageList(hChTree, hChannelImgList, TVSIL_NORMAL);
|
// TreeView_SetImageList(hChTree, hChannelImgList,
|
||||||
|
// TVSIL_NORMAL);
|
||||||
struct hashmap *ChannelUITable =
|
struct hashmap *ChannelUITable =
|
||||||
hashmap_new(sizeof(ChannelUIEntry), 0, 0, 0, channel_hash,
|
hashmap_new(sizeof(ChannelUIEntry), 0, 0, 0, channel_hash,
|
||||||
channel_compare, NULL, NULL);
|
channel_compare, NULL, NULL);
|
||||||
for (int i = 0; i < ChannelCount; i++) {
|
for (int i = 0; i < ChannelCount; i++) {
|
||||||
char *VisualName;
|
char *VisualName;
|
||||||
if (Channels[i].type == GUILD_TEXT) {
|
VisualName = malloc(strlen(Channels[i].name) + 1);
|
||||||
VisualName = malloc(strlen(Channels[i].name) + 2);
|
strcpy(VisualName, Channels[i].name);
|
||||||
*VisualName = '#';
|
|
||||||
strcpy(VisualName + 1, Channels[i].name);
|
|
||||||
} else {
|
|
||||||
VisualName = malloc(strlen(Channels[i].name) + 1);
|
|
||||||
strcpy(VisualName, Channels[i].name);
|
|
||||||
}
|
|
||||||
TVINSERTSTRUCT tvInsert = {0};
|
TVINSERTSTRUCT tvInsert = {0};
|
||||||
HTREEITEM hParent = TVI_ROOT;
|
HTREEITEM hParent = TVI_ROOT;
|
||||||
if (Channels[i].parentID) {
|
if (Channels[i].parentID) {
|
||||||
@@ -480,12 +545,22 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
tvInsert.hParent = hParent; // Parent is the root item
|
tvInsert.hParent = hParent; // Parent is the root item
|
||||||
tvInsert.hInsertAfter = TVI_LAST;
|
tvInsert.hInsertAfter = TVI_LAST;
|
||||||
tvInsert.item.mask =
|
tvInsert.item.mask =
|
||||||
TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
|
TVIF_TEXT | TVIF_PARAM | TVIF_STATE | TVIF_IMAGE;
|
||||||
tvInsert.item.pszText = (VisualName);
|
tvInsert.item.pszText = (VisualName);
|
||||||
tvInsert.item.lParam = (LPARAM) & (Channels[i]);
|
tvInsert.item.lParam = (LPARAM) & (Channels[i]);
|
||||||
tvInsert.item.state = TVIS_EXPANDED;
|
tvInsert.item.state = TVIS_EXPANDED;
|
||||||
tvInsert.item.stateMask = TVIS_EXPANDED;
|
tvInsert.item.stateMask = TVIS_EXPANDED;
|
||||||
|
if (Channels[i].type == GUILD_CATEGORY) {
|
||||||
|
tvInsert.item.iImage = 0;
|
||||||
|
} else if (Channels[i].type == GUILD_VOICE) {
|
||||||
|
tvInsert.item.iImage = 2;
|
||||||
|
} else if (Channels[i].type == GUILD_ANNOUNCEMENT) {
|
||||||
|
tvInsert.item.iImage = 3;
|
||||||
|
} else if (Channels[i].type == GUILD_FORUM) {
|
||||||
|
tvInsert.item.iImage = 4;
|
||||||
|
} else {
|
||||||
|
tvInsert.item.iImage = 1;
|
||||||
|
}
|
||||||
HTREEITEM lres = (HTREEITEM)SendMessage(
|
HTREEITEM lres = (HTREEITEM)SendMessage(
|
||||||
hChTree, TVM_INSERTITEM, 0, (LPARAM)&tvInsert);
|
hChTree, TVM_INSERTITEM, 0, (LPARAM)&tvInsert);
|
||||||
if (Channels[i].type == GUILD_CATEGORY) {
|
if (Channels[i].type == GUILD_CATEGORY) {
|
||||||
@@ -494,51 +569,21 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
chnl->id = strdup(Channels[i].id);
|
chnl->id = strdup(Channels[i].id);
|
||||||
hashmap_set(ChannelUITable, chnl);
|
hashmap_set(ChannelUITable, chnl);
|
||||||
}
|
}
|
||||||
free(VisualName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pNMHDR.hwndFrom == hChTree) {
|
} else if (pNMHDR.hwndFrom == hChTree) {
|
||||||
LPNMTREEVIEW pnmv = (LPNMTREEVIEW)lParam;
|
LPNMTREEVIEW pnmv = (LPNMTREEVIEW)lParam;
|
||||||
if (pNMHDR.code == NM_CUSTOMDRAW) {
|
|
||||||
LPNMTVCUSTOMDRAW pcd = (LPNMTVCUSTOMDRAW)lParam;
|
|
||||||
switch (pcd->nmcd.dwDrawStage) {
|
|
||||||
case CDDS_PREPAINT:
|
|
||||||
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
|
|
||||||
return CDRF_NOTIFYITEMDRAW;
|
|
||||||
case CDDS_ITEMPREPAINT:
|
|
||||||
return CDRF_NOTIFYPOSTPAINT;
|
|
||||||
case CDDS_ITEMPOSTPAINT: {
|
|
||||||
DiscordChannel *chnl = (DiscordChannel *)pcd->nmcd.lItemlParam;
|
|
||||||
if (chnl && chnl->type == GUILD_VOICE) {
|
|
||||||
RECT rc;
|
|
||||||
TreeView_GetItemRect(hChTree, (HTREEITEM)pcd->nmcd.dwItemSpec, &rc, TRUE);
|
|
||||||
// draw icon to the left of the label rect
|
|
||||||
ImageList_Draw(hChannelImgList, 0, pcd->nmcd.hdc,
|
|
||||||
rc.left - 18, rc.top + (rc.bottom - rc.top - 16) / 2,
|
|
||||||
ILD_TRANSPARENT);
|
|
||||||
} else if (chnl && chnl->type == GUILD_ANNOUNCEMENT) {
|
|
||||||
RECT rc;
|
|
||||||
TreeView_GetItemRect(hChTree, (HTREEITEM)pcd->nmcd.dwItemSpec, &rc, TRUE);
|
|
||||||
// draw icon to the left of the label rect
|
|
||||||
ImageList_Draw(hChannelImgList, 1, pcd->nmcd.hdc,
|
|
||||||
rc.left - 18, rc.top + (rc.bottom - rc.top - 16) / 2,
|
|
||||||
ILD_TRANSPARENT);
|
|
||||||
}
|
|
||||||
return CDRF_DODEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pNMHDR.code == TVN_SELCHANGED &&
|
if (pNMHDR.code == TVN_SELCHANGED &&
|
||||||
pnmv->itemNew.state & TVIS_SELECTED) {
|
pnmv->itemNew.state & TVIS_SELECTED) {
|
||||||
DiscordChannel *chnl = ((DiscordChannel *)pnmv->itemNew.lParam);
|
DiscordChannel *chnl = ((DiscordChannel *)pnmv->itemNew.lParam);
|
||||||
if (chnl->type != GUILD_CATEGORY) {
|
if (chnl->type != GUILD_CATEGORY) {
|
||||||
char *title = malloc(14 + strlen(pnmv->itemNew.pszText));
|
char *title = NULL;
|
||||||
wsprintf(title, "Backcord - %s", pnmv->itemNew.pszText);
|
title = malloc(13 + strlen(chnl->name));
|
||||||
|
wsprintf(title, "Backcord - #%s", chnl->name);
|
||||||
SetWindowTextA(hwnd, title);
|
SetWindowTextA(hwnd, title);
|
||||||
DiscordMessage *msgs;
|
DiscordMessage *msgs;
|
||||||
int msgcnt = DiscordGetChannelHistory(chnl->id, 50, &msgs);
|
int msgcnt = DiscordGetChannelHistory(chnl->id, 50, &msgs);
|
||||||
ClearChatControl(hMsgList);
|
ClearChatControl(hMsgList);
|
||||||
ListView_DeleteAllItems(hMsgList);
|
|
||||||
if (curChannel)
|
if (curChannel)
|
||||||
free(curChannel);
|
free(curChannel);
|
||||||
|
|
||||||
@@ -564,12 +609,53 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
InsertChatMessage((msgs[i]), hMsgList);
|
InsertChatMessage((msgs[i]), hMsgList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ListView_EnsureVisible(hMsgList, msgcnt - 1, FALSE);
|
|
||||||
free(title);
|
free(title);
|
||||||
free(msgs);
|
free(msgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
} else if (pNMHDR.hwndFrom == hDMsList) {
|
||||||
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
||||||
|
if (pNMHDR.code == LVN_ITEMCHANGED) {
|
||||||
|
|
||||||
|
LVITEM lvi = {};
|
||||||
|
lvi.mask = LVIF_PARAM;
|
||||||
|
lvi.iItem = pnmv->iItem;
|
||||||
|
lvi.iSubItem = 0;
|
||||||
|
|
||||||
|
ListView_GetItem(hDMsList, &lvi);
|
||||||
|
LPARAM itemData = lvi.lParam;
|
||||||
|
|
||||||
|
DiscordChannel *chnl = ((DiscordChannel *)itemData);
|
||||||
|
ClearChatControl(hMsgList);
|
||||||
|
|
||||||
|
DiscordMessage *msgs;
|
||||||
|
int msgcnt = DiscordGetChannelHistory(chnl->id, 50, &msgs);
|
||||||
|
ClearChatControl(hMsgList);
|
||||||
|
if (curChannel)
|
||||||
|
free(curChannel);
|
||||||
|
curChannel = strdup(chnl->id);
|
||||||
|
if (msgcnt > 0) {
|
||||||
|
for (int i = msgcnt - 1; i >= 0; i--) {
|
||||||
|
if (msgs[i].author.avatar) {
|
||||||
|
char tempPath[MAX_PATH];
|
||||||
|
DWORD len = GetTempPathA(MAX_PATH, tempPath);
|
||||||
|
char *path = malloc(
|
||||||
|
MAX_PATH + strlen(msgs[i].author.avatar) + 1);
|
||||||
|
wsprintfA(path, "%s%s.png", tempPath,
|
||||||
|
msgs[i].author.avatar);
|
||||||
|
if (GetFileAttributesA(path) ==
|
||||||
|
INVALID_FILE_ATTRIBUTES) {
|
||||||
|
char *path = DiscordFetchTmpPfp(
|
||||||
|
msgs[i].author.id,
|
||||||
|
msgs[i].author.avatar); // testing
|
||||||
|
}
|
||||||
|
ChatView_SetUserPfp(path, msgs[i].author.id);
|
||||||
|
}
|
||||||
|
InsertChatMessage((msgs[i]), hMsgList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
@@ -589,6 +675,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
CleanupHTTP();
|
CleanupHTTP();
|
||||||
|
DiscordHTTPClose();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 822 B |
Binary file not shown.
|
After Width: | Height: | Size: 822 B |
@@ -1,4 +1,7 @@
|
|||||||
#define IDI_BACKCORDIC 101
|
#define IDI_BACKCORDIC 101
|
||||||
#define IDI_BACKCORDBANNERIC 102
|
#define IDI_BACKCORDBANNERIC 102
|
||||||
|
#define IDI_CHANNEL_TC 110
|
||||||
#define IDI_CHANNEL_VC 111
|
#define IDI_CHANNEL_VC 111
|
||||||
#define IDI_CHANNEL_ANC 112
|
#define IDI_CHANNEL_ANC 112
|
||||||
|
#define IDI_CHANNEL_FORUM 113
|
||||||
|
#define IDI_CHANNEL_CATEGORY 114
|
||||||
@@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
IDI_BACKCORDIC RCDATA "backcord_icon.png"
|
IDI_BACKCORDIC RCDATA "backcord_icon.png"
|
||||||
IDI_BACKCORDBANNERIC BITMAP "backcordbanner.bmp"
|
IDI_BACKCORDBANNERIC BITMAP "backcordbanner.bmp"
|
||||||
|
IDI_CHANNEL_CATEGORY BITMAP "category.bmp"
|
||||||
|
IDI_CHANNEL_TC BITMAP "tc.bmp"
|
||||||
IDI_CHANNEL_VC BITMAP "vc.bmp"
|
IDI_CHANNEL_VC BITMAP "vc.bmp"
|
||||||
IDI_CHANNEL_ANC BITMAP "anc.bmp"
|
IDI_CHANNEL_ANC BITMAP "anc.bmp"
|
||||||
|
IDI_CHANNEL_FORUM BITMAP "forum.bmp"
|
||||||
@@ -22,7 +22,7 @@ int OpenWebSocket(const char *hostname, const char *path, SSL **out_ssl) {
|
|||||||
server.sin_addr = **(struct in_addr **)gethostbyname(hostname)->h_addr_list;
|
server.sin_addr = **(struct in_addr **)gethostbyname(hostname)->h_addr_list;
|
||||||
|
|
||||||
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) ==
|
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) ==
|
||||||
SOCKET_ERROR) {
|
SOCKET_ERROR) {
|
||||||
MessageBoxA(NULL, "connect failed", "WebSocket Error", 0);
|
MessageBoxA(NULL, "connect failed", "WebSocket Error", 0);
|
||||||
closesocket(sock);
|
closesocket(sock);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -64,14 +64,14 @@ int OpenWebSocket(const char *hostname, const char *path, SSL **out_ssl) {
|
|||||||
// send WebSocket upgrade request
|
// send WebSocket upgrade request
|
||||||
char request[2048];
|
char request[2048];
|
||||||
wsprintfA(request,
|
wsprintfA(request,
|
||||||
"GET %s HTTP/1.1\r\n"
|
"GET %s HTTP/1.1\r\n"
|
||||||
"Host: %s\r\n"
|
"Host: %s\r\n"
|
||||||
"Upgrade: websocket\r\n"
|
"Upgrade: websocket\r\n"
|
||||||
"Connection: Upgrade\r\n"
|
"Connection: Upgrade\r\n"
|
||||||
"Sec-WebSocket-Key: %s\r\n"
|
"Sec-WebSocket-Key: %s\r\n"
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
path, hostname, ws_key);
|
path, hostname, ws_key);
|
||||||
|
|
||||||
SSL_write(ssl, request, (int)strlen(request));
|
SSL_write(ssl, request, (int)strlen(request));
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ DWORD WINAPI WSThreadProc(LPVOID ssl) {
|
|||||||
|
|
||||||
if (length != 0 && result != 0) {
|
if (length != 0 && result != 0) {
|
||||||
WebSocketOnDataArrival(ssl, buffer, length);
|
WebSocketOnDataArrival(ssl, buffer, length);
|
||||||
// printf("%s\n",buffer);
|
printf("%s\n", buffer);
|
||||||
// LE IMPORTANT: free the buffer after processing... memleak goez
|
// LE IMPORTANT: free the buffer after processing... memleak goez
|
||||||
// brr otherewise
|
// brr otherewise
|
||||||
free(buffer);
|
free(buffer);
|
||||||
@@ -117,7 +117,8 @@ DWORD WINAPI WSThreadProc(LPVOID ssl) {
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
int SendWebSocket(SSL *ssl, const char *data, size_t length,
|
int SendWebSocket(SSL *ssl, const char *data, size_t length,
|
||||||
unsigned char flags) {
|
unsigned char flags) {
|
||||||
|
printf("%s\n", data);
|
||||||
unsigned char frame[14];
|
unsigned char frame[14];
|
||||||
size_t frame_size = 0;
|
size_t frame_size = 0;
|
||||||
|
|
||||||
@@ -153,7 +154,8 @@ int SendWebSocket(SSL *ssl, const char *data, size_t length,
|
|||||||
mask[i] = (unsigned char)(i & 0xFF);
|
mask[i] = (unsigned char)(i & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlCopyMemory(&frame[frame_size], mask, 4); // me when i rtlcopymemory to look cool
|
RtlCopyMemory(&frame[frame_size], mask,
|
||||||
|
4); // me when i rtlcopymemory to look cool
|
||||||
frame_size += 4;
|
frame_size += 4;
|
||||||
|
|
||||||
// Send frame header
|
// Send frame header
|
||||||
@@ -200,8 +202,15 @@ int ReadWebSocket(SSL *ssl, char **out_buffer, size_t *out_length) {
|
|||||||
SSL_read(ssl, &plHeaders, 1);
|
SSL_read(ssl, &plHeaders, 1);
|
||||||
unsigned char tlen = (plHeaders << 1) >> 1;
|
unsigned char tlen = (plHeaders << 1) >> 1;
|
||||||
if (tlen == 127) {
|
if (tlen == 127) {
|
||||||
SSL_read(ssl, &curPayloadLen, 8);
|
unsigned char lenbytes[8];
|
||||||
curPayloadLen = ntohl(curPayloadLen);
|
SSL_read(ssl, lenbytes,8);
|
||||||
|
curPayloadLen = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
unsigned char temp = lenbytes[i];
|
||||||
|
lenbytes[i]=lenbytes[7-i];
|
||||||
|
lenbytes[7-i]=temp;
|
||||||
|
}
|
||||||
|
curPayloadLen = *(unsigned long long*)lenbytes;
|
||||||
payloadLen += curPayloadLen;
|
payloadLen += curPayloadLen;
|
||||||
} else if (tlen == 126) {
|
} else if (tlen == 126) {
|
||||||
unsigned short templen;
|
unsigned short templen;
|
||||||
@@ -222,8 +231,8 @@ int ReadWebSocket(SSL *ssl, char **out_buffer, size_t *out_length) {
|
|||||||
unsigned long long totalRead = 0;
|
unsigned long long totalRead = 0;
|
||||||
while (totalRead < curPayloadLen) {
|
while (totalRead < curPayloadLen) {
|
||||||
int bytesRead = SSL_read(
|
int bytesRead = SSL_read(
|
||||||
ssl, *out_buffer + (payloadLen - curPayloadLen) + totalRead,
|
ssl, *out_buffer + (payloadLen - curPayloadLen) + totalRead,
|
||||||
curPayloadLen - totalRead);
|
curPayloadLen - totalRead);
|
||||||
if (bytesRead <= 0) {
|
if (bytesRead <= 0) {
|
||||||
free(*out_buffer);
|
free(*out_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user