bitreich-short

fork of git.z3bra.org/bitreich-short
git clone git://git.pyratebeard.net/bitreich-short.git
Log | Files | Refs | README | LICENSE

commit 8b89e4cff4d264ea216968e16180dbb31195f679
parent cc63ab3d1f6bbed6ea4bae99d2327a961b8807e1
Author: Willy Goiffon <dev@z3bra.org>
Date:   Thu, 15 Oct 2020 15:50:07 +0200

Add URL shortening capabilities

Diffstat:
Mbitreich-httpd.c | 148++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 116 insertions(+), 32 deletions(-)

diff --git a/bitreich-httpd.c b/bitreich-httpd.c @@ -3,6 +3,7 @@ * by 20h */ +#include <errno.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -14,6 +15,12 @@ #include <sys/socket.h> #include <netdb.h> +#define WWWBASE "/var/cache/shorturl" +#define CHARSET "abcdefghijklmnopqrstuvwxyz" +#define NAMELEN 3 + +char *host = "url.short"; + void * xmalloc(size_t size) { @@ -27,6 +34,20 @@ xmalloc(size_t size) return p; } +char * +randomname(int len) +{ + int i; + static char out[NAMELEN + 1]; + static char charset[] = CHARSET; + + srand((unsigned long)&i); + for (i = 0; i < len; i++) + out[i] = charset[rand() % (int)(sizeof(charset) -1)]; + + return out; +} + void print404(void) { @@ -35,6 +56,13 @@ print404(void) } void +print500(void) +{ + printf("HTTP/1.1 500 You Broke The Web\r\n"); + printf("\r\n"); +} + +void printheaders(char *ctype) { time_t t; @@ -42,11 +70,7 @@ printheaders(char *ctype) t = time(NULL); if (t > 0) printf("Date: %s", asctime(gmtime(&t))); - printf("X-Future: Gopher ftw!\r\n"); printf("Content-Type: %s\r\n", ctype); - printf("X-Irritate: Be irritated.\r\n"); - printf("X-Use-Gopher: gopher://bitreich.org\r\n"); - printf("If-By-Whiskey: Terrorist\r\n"); printf("Server: bitreich-httpd/2.0\r\n"); printf("Host: bitreich.org\r\n"); printf("Connection: close\r\n"); @@ -95,16 +119,80 @@ servefile(char *path, char *ctype, int sock) } int +redirect(char *path) +{ + struct stat st; + char *location; + size_t bufsiz = BUFSIZ; + int len, fd; + + fd = open(path, O_RDONLY); + if (fd < 0) { + print404(); + return 1; + } + + if (fstat(fd, &st) >= 0) + if ((bufsiz = st.st_blksize) < BUFSIZ) + bufsiz = BUFSIZ; + + location = xmalloc(bufsiz); + len = read(fd, location, bufsiz); + + location[len - 1] = '\0'; + + printf("HTTP/1.1 307 Moved Temporarily\r\n"); + printheaders("text/html"); + printf("Location: %s\r\n", location); + printf("\r\n"); + + free(location); + + return 0; +} + +int +saveurl(char *wwwbase, char *location) +{ + int fd; + char *path, *name, *url; + + if (!(name = randomname(NAMELEN))) + return 1; + + asprintf(&path, "%s/%s", wwwbase, name); + asprintf(&url, "http://%s/%s", host, name); + + if ((fd = open(path, O_WRONLY|O_CREAT, 0644)) < 0) + return 1; + + write(fd, location, strlen(location)); + write(fd, "\n", 1); + close(fd); + + printf("HTTP/1.1 200 OK\r\n"); + printheaders("text/plain"); + printf("Content-Length: %ld\r\n", strlen(url)); + printf("\r\n"); + fflush(stdout); + printf("%s", url); + + free(path); + free(url); + + return 0; +} + +int main(int argc, char *argv[]) { - char *wwwbase, *wwwindex, request[512], *ctype, *path, + char *wwwbase, request[512], *path, *url, clienth[NI_MAXHOST], clientp[NI_MAXSERV]; int rlen; struct sockaddr_storage clt; socklen_t cltlen = sizeof(clt); - wwwbase = "/bitreich/www"; - wwwindex = "index.html"; + wwwbase = WWWBASE; if (!getpeername(0, (struct sockaddr *)&clt, &cltlen)) { if (getnameinfo((struct sockaddr *)&clt, cltlen, clienth, @@ -124,31 +212,27 @@ main(int argc, char *argv[]) request[rlen] = '\0'; - if (strncmp(request, "GET ", 4)) - return 1; - - if (strstr(request, "s/bitreich.sh")) { - asprintf(&path, "%s/s/bitreich.sh", wwwbase); - ctype = "text/plain"; - } else if (strstr(request, "favicon.gif")) { - asprintf(&path, "%s/s/favicon.gif", wwwbase); - ctype = "image/gif"; - } else if (strstr(request, "dickbutt")) { - asprintf(&path, - "/home/annna/bin/annna-say -c \"#bitreich-tv\" \"%s:%s cake hater appeared.\"", - clienth, clientp); - system(path); - free(path); - asprintf(&path, "%s/s/dickbutt.jpg", wwwbase); - ctype = "image/jpeg"; - } else { - asprintf(&path, "%s/%s", wwwbase, wwwindex); - ctype = "text/html"; + if (!strncmp(request, "PUT ", 4)) { + url = strstr(request, "\r\n\r\n") + 4; + if (!url || !strlen(url) || saveurl(wwwbase, url)) { + perror(url); + print500(); + return 1; + } + return 0; + } else if (!strncmp(request, "GET ", 4)) { + if (!strncmp(request + 4, "/ ", 2) || strstr(request, "/../")) { + print404(); + return 1; + } else { + char *p = strstr(request + 4, " "); + *p = '\0'; + asprintf(&path, "%s%s", wwwbase, request + 4); + rlen = redirect(path); + free(path); + return rlen; + } } - rlen = servefile(path, ctype, 1); - free(path); - - return rlen; + return -1; } -