commit 8b89e4cff4d264ea216968e16180dbb31195f679
parent cc63ab3d1f6bbed6ea4bae99d2327a961b8807e1
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(-)
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;
}
-