diff --git a/cgi/feuille.cgi b/cgi/feuille.cgi new file mode 100755 index 0000000..ca71de4 Binary files /dev/null and b/cgi/feuille.cgi differ diff --git a/cgi/feuille.cgi.c b/cgi/feuille.cgi.c new file mode 100644 index 0000000..8f7596c --- /dev/null +++ b/cgi/feuille.cgi.c @@ -0,0 +1,168 @@ +/* + * misc/web/feuille.cgi.c + * Auxiliary CGI script that converts an HTTP request to a raw TCP + * one. + * + * Copyright (c) 2022 + * Tom MTT. + * + * This file is licensed under the 3-Clause BSD License. + * You should have received a copy of the 3-Clause BSD License + * along with this program. If not, see + * . + */ + +#include /* for inet_pton */ +#include /* for ERANGE, errno */ +#include /* for htons, sockaddr_in, sockaddr_in6 */ +#include /* for printf, NULL, BUFSIZ */ +#include /* for calloc, free, getenv, exit, strtoll */ +#include /* for strcmp */ +#include /* for bzero */ +#include /* for connect, socket, AF_INET, AF_INET6, recv, send */ +#include /* for close, read, STDIN_FILENO */ + +/* Initialize client socket and connect to feuille */ +int initialize_socket(char *address, unsigned short port) +{ + int server; + + /* initialize socket IPv4 and IPv6 addresses */ + struct sockaddr_in server_address_v4; + bzero(&server_address_v4, sizeof(server_address_v4)); + + struct sockaddr_in6 server_address_v6; + bzero(&server_address_v6, sizeof(server_address_v6)); + + /* dirty hack to detect and convert IPv4 / IPv6 addresses */ + if (inet_pton(AF_INET, address, &server_address_v4.sin_addr) == 1) { + /* set socket family and port */ + server_address_v4.sin_family = AF_INET; + server_address_v4.sin_port = htons(port); + + /* create socket */ + if ((server = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + /* connect to server */ + if (connect(server, (struct sockaddr *)&server_address_v4, sizeof(server_address_v4)) < 0) + return -1; + + } else if (inet_pton(AF_INET6, address, &server_address_v6.sin6_addr) == 1) { + /* set socket family and port */ + server_address_v6.sin6_family = AF_INET6; + server_address_v6.sin6_port = htons(port); + + /* create socket */ + if ((server = socket(AF_INET6, SOCK_STREAM, 0)) < 0) + return -1; + + /* connect to server */ + if (connect(server, (struct sockaddr *)&server_address_v6, sizeof(server_address_v6)) < 0) + return -1; + + } else + return -1; + + return server; +} + +/* CGI helper functions */ +void cgi_init() +{ + printf("Content-Type: text/plain\r\n"); +} + +void cgi_error(char *status) +{ + printf("Status: %s\r\n", status); + printf("\r\n"); + printf("%s\n", status); +} + +void cgi_die(char *status) +{ + cgi_error(status); + exit(1); +} + +void cgi_ok(char *response) +{ + printf("Status: 200 OK\r\n"); + printf("\r\n"); + printf("%s", response); +} + +void cgi_redirect(char *url) +{ + printf("Status: 301 Moved Permanently\r\n"); + printf("Location: %s\r\n", url); + printf("\r\n"); +} + +/* main function */ +int main(void) +{ + cgi_init(); + + /* get method */ + char *method; + if ((method = getenv("REQUEST_METHOD")) == NULL || strcmp(method, "POST") != 0) + cgi_die("405 Method Not Allowed"); + + /* get content length */ + char *content_length; + if ((content_length = getenv("CONTENT_LENGTH")) == NULL) + cgi_die("400 Bad Request"); + + /* convert content length to a long long int */ + long long length = strtoll(content_length, NULL, 10); + if (length <= 0 || errno == ERANGE) + cgi_die("400 Bad Request"); + + /* initialize socket */ + int socket; + if ((socket = initialize_socket(ADDR, PORT)) == -1) + cgi_die("500 Internal Server Error"); + + /* read paste from stdin */ + char *request; + if ((request = calloc(length + 1, sizeof(char))) == NULL) + cgi_die("500 Internal Server Error"); + + read(STDIN_FILENO, request, length); + request[length] = 0; + + /* remove `paste=' from request */ + char *paste = request; + + char *offset; + if ((offset = strstr(request, "=")) != NULL) { + paste = offset + 1; + length -= offset + 1 - request; + } + + /* send paste to feuille */ + send(socket, paste, length + 1, 0); + shutdown(socket, SHUT_WR); + + /* receive response from feuille */ + char *response; + if ((response = calloc(BUFSIZ + 1, sizeof(char))) == NULL) + cgi_die("500 Internal Server Error"); + + if (recv(socket, response, BUFSIZ, 0) > 0) { + if (strstr(response, "http") != NULL) + cgi_redirect(response); + else + cgi_ok(response); + } else + cgi_error("500 Internal Server Error"); + + /* close socket, free variables and exit */ + close(socket); + free(response); + free(request); + + return 0; +} diff --git a/cgi/form.html b/cgi/form.html new file mode 100644 index 0000000..b0a5a5b --- /dev/null +++ b/cgi/form.html @@ -0,0 +1,12 @@ + + + + + + +
+ + +
+ +