2025-05-02 05:58:01 +02:00
|
|
|
#include "netlib/src/netlib.h"
|
2025-05-03 04:12:38 +02:00
|
|
|
#ifdef __linux__
|
2025-05-02 05:58:01 +02:00
|
|
|
#include <sys/sendfile.h>
|
2025-05-03 04:12:38 +02:00
|
|
|
#endif
|
2025-05-02 05:58:01 +02:00
|
|
|
#include <print>
|
|
|
|
#include <fstream>
|
2025-05-13 04:52:03 +02:00
|
|
|
#include <map>
|
2025-05-02 05:58:01 +02:00
|
|
|
|
|
|
|
int atoi_newline(const char *data)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
ret += *data - '0';
|
|
|
|
data++;
|
|
|
|
if (*data == '\n' || *data == '\0' || *data == '\r')
|
|
|
|
break;
|
|
|
|
ret *= 10;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2025-05-03 04:12:38 +02:00
|
|
|
std::string get_filename(std::string_view data)
|
|
|
|
{
|
|
|
|
int index = 1;
|
|
|
|
std::string ret;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (data[index] == '"')
|
|
|
|
break;
|
|
|
|
ret.push_back(data[index]);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2025-05-13 04:52:03 +02:00
|
|
|
static std::vector<std::string> split_until_newline(const std::string &data, const char c)
|
|
|
|
{
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
size_t index = 0;
|
|
|
|
size_t previous_start = 0;
|
|
|
|
|
|
|
|
while (data[index] != '\n' && data[index] != '\0')
|
|
|
|
{
|
|
|
|
if (data[index] == c || data[index] == '\r')
|
|
|
|
{
|
|
|
|
ret.push_back(data.substr(previous_start, index - previous_start));
|
|
|
|
previous_start = index + 1;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
ret.push_back(data.substr(previous_start, index - previous_start));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<std::string> split(const std::string &data, const std::string d)
|
|
|
|
{
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
size_t index = 0;
|
|
|
|
size_t index2 = 0;
|
|
|
|
size_t previous_start = 0;
|
|
|
|
|
|
|
|
while (index < data.size())
|
|
|
|
{
|
|
|
|
if (data[index] == d[index2])
|
|
|
|
{
|
|
|
|
index2++;
|
|
|
|
if (index2 >= d.size())
|
|
|
|
{
|
|
|
|
ret.push_back(data.substr(previous_start, (index - previous_start)));
|
|
|
|
previous_start = index + 1;
|
|
|
|
index2 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
index2 = 0;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
ret.push_back(data.substr(previous_start, index - previous_start));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void print_container(T &container)
|
|
|
|
{
|
|
|
|
for (auto x: container)
|
|
|
|
{
|
|
|
|
std::println("{}", x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void print_map(T container)
|
|
|
|
{
|
|
|
|
for (auto [key, value]: container)
|
|
|
|
{
|
|
|
|
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
|
|
|
|
value.erase(std::remove(value.begin(), value.end(), '\r'), value.end());
|
|
|
|
std::println("key {} value {}", key, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::map<std::string, std::string> parse_header(const std::string &x)
|
|
|
|
{
|
|
|
|
std::map<std::string, std::string> ret;
|
|
|
|
if (x.contains(": "))
|
|
|
|
{
|
|
|
|
std::vector<std::string> s = split(x, ": ");
|
|
|
|
ret.insert({s[0], s[1]});
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::map<std::string, std::string> parse_headers(const std::vector<std::string> &data)
|
|
|
|
{
|
|
|
|
std::map<std::string, std::string> ret;
|
|
|
|
for (auto &x: data)
|
|
|
|
{
|
|
|
|
if (x.contains(": "))
|
|
|
|
{
|
|
|
|
std::vector<std::string> s = split(x, ": ");
|
|
|
|
ret.insert({s[0], s[1]});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2025-05-14 06:00:45 +02:00
|
|
|
std::string get_filename(std::string data)
|
|
|
|
{
|
|
|
|
bool started_quote = false;
|
|
|
|
std::string ret;
|
|
|
|
for (auto x: data)
|
|
|
|
{
|
|
|
|
if (x == '"' && !started_quote)
|
|
|
|
started_quote = true;
|
|
|
|
else if (x == '"' && started_quote)
|
|
|
|
break;
|
|
|
|
else if (started_quote)
|
|
|
|
ret.push_back(x);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2025-05-02 05:58:01 +02:00
|
|
|
int main()
|
|
|
|
{
|
2025-05-09 00:46:24 +02:00
|
|
|
netlib::server_raw server(false, 0);
|
2025-05-02 05:58:01 +02:00
|
|
|
server.open_server("0.0.0.0", 8080);
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2025-05-03 12:20:20 +02:00
|
|
|
std::vector<int> readable = server.wait_readable();
|
2025-05-13 04:52:03 +02:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
2025-05-02 05:58:01 +02:00
|
|
|
for (auto user: readable)
|
|
|
|
{
|
2025-05-13 04:52:03 +02:00
|
|
|
char * data = server.get_line(user);
|
2025-05-02 05:58:01 +02:00
|
|
|
if (data)
|
|
|
|
{
|
2025-05-13 04:52:03 +02:00
|
|
|
std::string dat = std::string(data);
|
|
|
|
std::vector<std::string> head = split(dat, " ");
|
|
|
|
print_container(head);
|
|
|
|
if (head[0] == "GET")
|
2025-05-02 05:58:01 +02:00
|
|
|
{
|
2025-05-13 04:52:03 +02:00
|
|
|
if (head[1] == "/")
|
2025-05-02 05:58:01 +02:00
|
|
|
{
|
|
|
|
netlib::send_packet(std::make_tuple(std::string("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n")), user);
|
|
|
|
std::ifstream file("../test.html",std::ios::binary);
|
|
|
|
std::streampos size = file.tellg();
|
|
|
|
file.seekg(0, std::ios::end);
|
|
|
|
size = file.tellg() - size;
|
|
|
|
file.close();
|
|
|
|
int filefd = open("../test.html", O_RDONLY);
|
2025-05-03 04:12:38 +02:00
|
|
|
#ifdef __linux__
|
2025-05-02 05:58:01 +02:00
|
|
|
sendfile(user, filefd, 0, size);
|
2025-05-03 04:12:38 +02:00
|
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
|
|
sendfile(filefd, user, 0, (long long*)&size, nullptr, 0);
|
|
|
|
#endif
|
2025-05-02 05:58:01 +02:00
|
|
|
}
|
|
|
|
}
|
2025-05-13 04:52:03 +02:00
|
|
|
else if (head[0] == "POST")
|
2025-05-02 05:58:01 +02:00
|
|
|
{
|
2025-05-14 04:09:27 +02:00
|
|
|
int state = 0;
|
|
|
|
std::string boundary;
|
|
|
|
size_t file_size = 0;
|
2025-05-13 04:52:03 +02:00
|
|
|
while (true)
|
2025-05-09 00:46:24 +02:00
|
|
|
{
|
2025-05-13 04:52:03 +02:00
|
|
|
char *line = server.get_line(user);
|
|
|
|
if (line)
|
|
|
|
{
|
2025-05-14 04:09:27 +02:00
|
|
|
if (state == 0)
|
|
|
|
{
|
|
|
|
std::string line_str = std::string(line);
|
|
|
|
auto h = parse_header(line_str);
|
|
|
|
|
|
|
|
if (h.contains("Content-Type:"))
|
|
|
|
{
|
|
|
|
print_map(h);
|
|
|
|
std::vector<std::string> a = split(h["Content-Type:"], "; ");
|
|
|
|
boundary = a[1];
|
2025-05-14 06:00:45 +02:00
|
|
|
boundary = boundary.substr(strlen("boundary="), boundary.size() - strlen("boundary=") - 2);
|
2025-05-14 04:09:27 +02:00
|
|
|
std::println("{}", boundary);
|
|
|
|
}
|
2025-05-14 06:00:45 +02:00
|
|
|
else if (h.contains("Content-Length:"))
|
2025-05-14 04:09:27 +02:00
|
|
|
{
|
|
|
|
file_size = atoi(h["Content-Length:"].c_str());
|
|
|
|
}
|
2025-05-14 06:00:45 +02:00
|
|
|
else if (line_str.contains(boundary) && boundary.contains("----"))
|
2025-05-14 04:09:27 +02:00
|
|
|
{
|
|
|
|
state = 1;
|
|
|
|
std::println("Changed state");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (state == 1)
|
|
|
|
{
|
2025-05-14 06:00:45 +02:00
|
|
|
char *line = server.get_line(user);
|
|
|
|
char *line2 = server.get_line(user);
|
|
|
|
char *line3 = server.get_line(user);
|
|
|
|
if (line && line2)
|
2025-05-14 04:09:27 +02:00
|
|
|
{
|
2025-05-14 06:00:45 +02:00
|
|
|
std::string line_str = std::string(line);
|
|
|
|
auto h = parse_header(line_str);
|
|
|
|
std::vector<std::string> file_ = split(h.begin()->second, "; ");
|
|
|
|
std::string filename = get_filename(file_.back());
|
|
|
|
size_t size = file_size - line_str.size() - std::string(line2).size() - std::string(line3).size();
|
|
|
|
char *file_data = server.receive_data_ensured(user, size);
|
|
|
|
std::ofstream a(filename, std::ios::binary);
|
|
|
|
a.write(file_data, size);
|
|
|
|
print_map(h);
|
|
|
|
free(file_data);
|
|
|
|
std::println("File {} received with {}B size", filename, size);
|
2025-05-14 04:09:27 +02:00
|
|
|
}
|
2025-05-14 06:00:45 +02:00
|
|
|
free(line);
|
|
|
|
free(line2);
|
|
|
|
free(line3);
|
|
|
|
break;
|
2025-05-14 04:09:27 +02:00
|
|
|
}
|
2025-05-13 04:52:03 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
free(line);
|
2025-05-09 00:46:24 +02:00
|
|
|
}
|
2025-05-02 05:58:01 +02:00
|
|
|
}
|
2025-05-13 04:52:03 +02:00
|
|
|
server.disconnect_user(user);
|
2025-05-05 05:38:31 +02:00
|
|
|
free(data);
|
2025-05-02 05:58:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|