URI: 
       tAdd URL shortening capabilities - bitreich-short - Fork of bitreich-httpd to shorten URLs
  HTML git clone git://git.z3bra.org/bitreich-short.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 8b89e4cff4d264ea216968e16180dbb31195f679
   DIR parent cc63ab3d1f6bbed6ea4bae99d2327a961b8807e1
  HTML Author: Willy Goiffon <dev@z3bra.org>
       Date:   Thu, 15 Oct 2020 15:50:07 +0200
       
       Add URL shortening capabilities
       
       Diffstat:
         M bitreich-httpd.c                    |     148 ++++++++++++++++++++++++-------
       
       1 file changed, 116 insertions(+), 32 deletions(-)
       ---
   DIR diff --git a/bitreich-httpd.c b/bitreich-httpd.c
       t@@ -3,6 +3,7 @@
         * by 20h
         */
        
       +#include <errno.h>
        #include <unistd.h>
        #include <stdio.h>
        #include <stdlib.h>
       t@@ -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)
        {
       t@@ -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)
        {
       t@@ -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;
       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");
       t@@ -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,
       t@@ -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;
        }
       -