//
// Készítette: Toldi Balázs Ádám
// Dátum: 2019. 10. 14..
//
#include "webio.h"
int webio_create(Config config, struct Node_data myData, WebIO *webIo) {
char *port = map_getValue(config, "interface-port");
if (port == NULL)
port = DEFAULT_INTERFACE_PORT;
char *folder = map_getValue(config, "interface-folder");
if (folder == NULL)
folder = DEFAULT_WWW_FOLDER;
char *local_mode_str = map_getValue(config, "interface-local");
bool local_mode = false;
if (local_mode_str != NULL && strcmp(local_mode_str, "true") == 0)
local_mode = true;
struct addrinfo *result = NULL;
SOCKET listening;
result = tcp_createIPv4Socket(&listening, atoi(port), !local_mode);
if (result == NULL) {
return 1;
}
int res = tcp_bindnlisten(listening, result, SOMAXCONN);
if (res != 0) {
return 2;
}
WebIO wio;
wio.sockaddr = tcp_getAddr_in(listening);
wio.socket = listening;
wio.nodeData = myData;
strcpy(wio.folder, folder);
*webIo = wio;
return 0;
}
int webio_handleRequest(WebIO wio, const PeerList *list) {
SOCKET client = accept(wio.socket, NULL, NULL);
char buf[8192];
memset(buf, 0, 8192);
int res = recv(client, buf, 8192, 0);
if (res <= 0) {
logger_log("Error with web interface!");
closesocket(client);
return -1;
}
if (strncmp(buf, "GET", 3) == 0) {
char file[50];
sscanf(buf, "%*s %s", file);
res = webio_handleGETrequest(client, wio, file, list);
} else if (strncmp(buf, "POST", 4) == 0) {
int i = (int) strlen(buf) - 1;
while (buf[i] != '\n') {
i--;
}
i++;
char tmp[8196];
strcpy(tmp, buf + i);
Map post = getPacketData(tmp);
res = webio_handlePOSTrequest(client, wio, list, post);
free(post.pairs);
} else
res = -1;
return res;
}
char *webio_getMIMEtype(char *filename) {
char type[10];
char *ext = webio_getFiletype(filename);
strcpy(type, ext);
free(ext);
if (strcmp(type, "html") == 0)
return "text/html";
else if (strcmp(type, "json") == 0)
return "application/json";
else if (strcmp(type, "svg") == 0)
return "image/svg+xml";
else if (strcmp(type, "js") == 0)
return "application/javascript";
else if (strcmp(type, "css") == 0)
return "text/css";
else if (strcmp(type, "jpg") == 0)
return "image/jpeg";
else if (strcmp(type, "png") == 0)
return "image/png";
else if (strcmp(type, "bmp") == 0)
return "image/bmp";
else if (strcmp(type, "ico") == 0)
return "image/x-icon";
else if (strcmp(type, "xml") == 0)
return "text/xml";
else if (strcmp(type, "zip") == 0)
return "application/zip";
else return "text/plain";
}
char *webio_getFiletype(char *filename) {
char *ext = (char *) malloc(sizeof(char) * 10);
char *tmp = strtok(filename, ".");
while (tmp != NULL) {
strncpy(ext, tmp, 10);
tmp = strtok(NULL, ".");
}
return ext;
}
static int webio_handleGETrequest(SOCKET client, WebIO wio, char *file, const PeerList *list) {
char path[129];
memset(path, 0, sizeof(path));
strcat(path, wio.folder);
int len = 0;
if (file[0] == '/')
memmove(file, file + 1, strlen(file));
if (strcmp(file, "") == 0) {
char index[8192] = "";
webio_getIndex(wio.folder, list, index);
webio_sendPage(client, index);
} else if (peer_ID_isFound(*list, file) || webio_isPeerFound(wio.folder, file)) {
char cnt[8192] = "";
webio_getPeerPage(wio.folder, file, (peer_ID_getPeer(*list, file) != -1), cnt);
webio_sendPage(client, cnt);
} else if (strcmp(file, "kill") == 0) {
webio_sendPage(client, "
Server Killed!
");
logger_log("Exit sign received.Exiting...");
return -2;
} else {
strcat(path, file);
//File küldés windows-on
#ifdef _WIN32
HANDLE file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
DWORD size = GetFileSize(file, NULL);
if (file == INVALID_HANDLE_VALUE || size < 0)
webio_send404Page(client);
else {
webio_sendOKHeader_wSize(client, path, size);
TransmitFile(client, file, 0, 0, NULL, NULL, 0);
CloseHandle(file);
}
#else
int fd = open(path, O_RDONLY);
if (fd == -1)
webio_send404Page(client);
else {
struct stat stat_struct;
fstat(fd, &stat_struct);
int length = stat_struct.st_size;
webio_sendOKHeader(client, path);
size_t total_bytes_sent = 0;
ssize_t bytes_sent;
char puf[len];
while (total_bytes_sent < length) {
bytes_sent = sendfile(client,fd,0,length);
if(bytes_sent == -1) logger_log("Error: %s",strerror(errno));
total_bytes_sent += bytes_sent;
}
}
#endif
shutdown(client, SD_BOTH);
}
closesocket(client);
return 0;
}
static int webio_handlePOSTrequest(SOCKET client, WebIO wio, const PeerList *list, Map post) {
shutdown(client, SD_RECEIVE);
char *response = "HTTP/1.1 304 Not Modified ";
int res = send(client, response, (int) strlen(response), 0);
if (res == SOCKET_ERROR) {
logger_log("Error with io");
return -1;
}
shutdown(client, SD_BOTH);
if (map_isFound(post, "id") && map_isFound(post, "message") &&
strcmp(map_getValue(post, "message"), "%0D%0A") != 0) {
char file[64];
char folder[72];
sprintf(folder, "%s/peers/", wio.folder);
#if defined(_WIN32)
mkdir(folder);
#else
mkdir(folder, 0777); // notice that 777 is different than 0777
#endif
sprintf(file, "%s%s.txt", folder, map_getValue(post, "id"));
FILE *f;
f = fopen(file, "a");
fprintf(f, "Me: %s\n", map_getValue(post, "message"));
fclose(f);
char buf[DEFAULT_BUFLEN];
int i = peer_ID_getPeer(*list, map_getValue(post, "id"));
if (i < 0) {
logger_log("Error sending message! Error: Peer offline!");
return 1;
}
sprintf(buf, "@message=%s", map_getValue(post, "message"));
res = send(list->array[i].socket, buf, DEFAULT_BUFLEN, 0);
if (res == SOCKET_ERROR) {
logger_log("Error sending message.Error: %d", errno);
return 2;
}
logger_log("Message sent to %s", map_getValue(post, "id"));
} else map_dump(post);
return 0;
}
static void webio_getHeader(char *folder, char result[]) {
char path[65];
strcpy(path, folder);
strcat(path, "/header.html");
FILE *fp;
fp = fopen(path, "r");
if (fp != NULL) {
char buf[1024];
while (fgets(buf, 1024, fp) != NULL) {
strcat(result, buf);
}
fclose(fp);
} else
result = "";
}
static void webio_getIndex(char *folder, const PeerList *list, char *outputBuffer) {
char content[8192] = "";
char header[4096] = "";
webio_getHeader(folder, header);
strcpy(content, header);
strcat(content, "Peers:
\n");
if (list->length > 0) {
strcat(content, "\n");
for (int i = 0; i < list->length; ++i) {
sprintf(content, "%s- "
"",
content, list->array[i].peerData.id);
if (strcmp(list->array[i].peerData.nick, "") != 0) {
sprintf(content, "%s%s - ", content, list->array[i].peerData.nick);
}
sprintf(content, "%s%s
\n", content, list->array[i].peerData.id);
}
strcat(content, "
\n");
} else
sprintf(content, "%s\n"
" No peers connected!\n"
"
\n", content);
strcat(content, "Offline messages:
\n");
char path[65];
sprintf(path, "%s/peers/", folder);
#ifdef _DIRENT_H_
DIR *d;
d = opendir(path);
if (d != NULL){
strcat(content, "\n");
struct dirent *de;
while ((de = readdir(d)) != NULL) {
if(strcmp(de->d_name,".") == 0 || strcmp(de->d_name,"..") == 0) continue;
char peer[33];
sscanf(de->d_name,"%[^.]",peer);
sprintf(content,"%s- %s
",content, peer, peer);
}
closedir(d);
strcat(content, "
\n");
}else{
sprintf(content, "%s\n"
" No offline messages!\n"
"
\n", content);
}
#else
HANDLE dir;
WIN32_FIND_DATA file_data;
strcat(path,"/*");
if ((dir = FindFirstFile(path, &file_data)) == INVALID_HANDLE_VALUE)
sprintf(content, "%s\n"
" No offline messages!\n"
"
\n", content);
else{
strcat(content, "\n");
do{
if(strcmp(file_data.cFileName,".") == 0 || strcmp(file_data.cFileName,"..") == 0) continue;
char peer[33];
sscanf(file_data.cFileName,"%[^.]",peer);
sprintf(content,"%s- %s
",content, peer, peer);
}while(FindNextFile(dir,&file_data));
FindClose(dir);
}
#endif
sprintf(content, "%s\n"
"\n"
"\n"
"