itInitial commit - phroxy - Gopher to HTTP proxy Err z3bra.org 70 hgit clone git://git.z3bra.org/phroxy.git URL:git://git.z3bra.org/phroxy.git z3bra.org 70 1Log /scm/phroxy/log.gph z3bra.org 70 1Files /scm/phroxy/files.gph z3bra.org 70 1Refs /scm/phroxy/refs.gph z3bra.org 70 1LICENSE /scm/phroxy/file/LICENSE.gph z3bra.org 70 i--- Err z3bra.org 70 1commit c3904deacd7faa41c91e97ae247e0791c945138f /scm/phroxy/commit/c3904deacd7faa41c91e97ae247e0791c945138f.gph z3bra.org 70 hAuthor: Willy Goiffon URL:mailto:dev@z3bra.org z3bra.org 70 iDate: Fri, 11 Sep 2020 21:56:03 +0200 Err z3bra.org 70 i Err z3bra.org 70 iInitial commit Err z3bra.org 70 i Err z3bra.org 70 iBased off sacc and bitreich-httpd from bitreich.org. Thank you :) Err z3bra.org 70 i Err z3bra.org 70 iDiffstat: Err z3bra.org 70 i A LICENSE | 13 +++++++++++++ Err z3bra.org 70 i A config.mk | 9 +++++++++ Err z3bra.org 70 i A makefile | 19 +++++++++++++++++++ Err z3bra.org 70 i A mkfile | 22 ++++++++++++++++++++++ Err z3bra.org 70 i A phroxy.c | 309 +++++++++++++++++++++++++++++++ Err z3bra.org 70 i Err z3bra.org 70 i5 files changed, 372 insertions(+), 0 deletions(-) Err z3bra.org 70 i--- Err z3bra.org 70 1diff --git a/LICENSE b/LICENSE /scm/phroxy/file/LICENSE.gph z3bra.org 70 it@@ -0,0 +1,13 @@ Err z3bra.org 70 i+Copyright (c) 2020 Willy Goiffon Err z3bra.org 70 i+ Err z3bra.org 70 i+Permission to use, copy, modify, and/or distribute this software for any Err z3bra.org 70 i+purpose with or without fee is hereby granted, provided that the above Err z3bra.org 70 i+copyright notice and this permission notice appear in all copies. Err z3bra.org 70 i+ Err z3bra.org 70 i+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH Err z3bra.org 70 i+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND Err z3bra.org 70 i+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, Err z3bra.org 70 i+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM Err z3bra.org 70 i+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR Err z3bra.org 70 i+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR Err z3bra.org 70 i+PERFORMANCE OF THIS SOFTWARE. Err z3bra.org 70 1diff --git a/config.mk b/config.mk /scm/phroxy/file/config.mk.gph z3bra.org 70 it@@ -0,0 +1,9 @@ Err z3bra.org 70 i+CC = cc Err z3bra.org 70 i+LD = ${CC} Err z3bra.org 70 i+ Err z3bra.org 70 i+PREFIX = /usr/local Err z3bra.org 70 i+MANDIR = ${PREFIX}/man Err z3bra.org 70 i+ Err z3bra.org 70 i+CPPFLAGS = Err z3bra.org 70 i+CFLAGS = -Wall -Wextra Err z3bra.org 70 i+LDFLAGS = Err z3bra.org 70 1diff --git a/makefile b/makefile /scm/phroxy/file/makefile.gph z3bra.org 70 it@@ -0,0 +1,19 @@ Err z3bra.org 70 i+include config.mk Err z3bra.org 70 i+ Err z3bra.org 70 i+all: phroxy Err z3bra.org 70 i+ Err z3bra.org 70 i+phroxy: phroxy.o Err z3bra.org 70 i+ ${LD} ${LDFLAGS} -o $@ phroxy.o Err z3bra.org 70 i+ Err z3bra.org 70 i+install: phroxy phroxy.8 Err z3bra.org 70 i+ mkdir -p ${DESTDIR}${PREFIX}/bin Err z3bra.org 70 i+ mkdir -p ${DESTDIR}${MANDIR}/man1 Err z3bra.org 70 i+ cp phroxy ${DESTDIR}${PREFIX}/bin/phroxy Err z3bra.org 70 i+ cp phroxy.8 ${DESTDIR}${MANDIR}/man8/phroxy.8 Err z3bra.org 70 i+ Err z3bra.org 70 i+uninstall: Err z3bra.org 70 i+ rm ${DESTDIR}${PREFIX}/bin/phroxy Err z3bra.org 70 i+ rm ${DESTDIR}${MANDIR}/man1/phroxy.8 Err z3bra.org 70 i+ Err z3bra.org 70 i+clean: Err z3bra.org 70 i+ rm -f phroxy *.o Err z3bra.org 70 1diff --git a/mkfile b/mkfile /scm/phroxy/file/mkfile.gph z3bra.org 70 it@@ -0,0 +1,22 @@ Err z3bra.org 70 i+ Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+ Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+#include Err z3bra.org 70 i+ Err z3bra.org 70 i+const char *host = "z3bra.org"; Err z3bra.org 70 i+ Err z3bra.org 70 i+void * Err z3bra.org 70 i+xreallocarray(void *m, const size_t n, const size_t s) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ void *nm; Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (n == 0 || s == 0) { Err z3bra.org 70 i+ free(m); Err z3bra.org 70 i+ return NULL; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ if (s && n > (size_t)-1/s) Err z3bra.org 70 i+ errx(1, "realloc: overflow"); Err z3bra.org 70 i+ if (!(nm = realloc(m, n * s))) Err z3bra.org 70 i+ errx(1, "realloc: %s", strerror(errno)); Err z3bra.org 70 i+ Err z3bra.org 70 i+ return nm; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+ Err z3bra.org 70 i+static int Err z3bra.org 70 i+connectto(const char *host, const char *port) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ sigset_t set, oset; Err z3bra.org 70 i+ static const struct addrinfo hints = { Err z3bra.org 70 i+ .ai_family = AF_UNSPEC, Err z3bra.org 70 i+ .ai_socktype = SOCK_STREAM, Err z3bra.org 70 i+ .ai_protocol = IPPROTO_TCP, Err z3bra.org 70 i+ }; Err z3bra.org 70 i+ struct addrinfo *addrs, *addr; Err z3bra.org 70 i+ int r, sock = -1; Err z3bra.org 70 i+ Err z3bra.org 70 i+ sigemptyset(&set); Err z3bra.org 70 i+ sigaddset(&set, SIGWINCH); Err z3bra.org 70 i+ sigprocmask(SIG_BLOCK, &set, &oset); Err z3bra.org 70 i+ Err z3bra.org 70 i+ if ((r = getaddrinfo(host, port, &hints, &addrs))) { Err z3bra.org 70 i+ fprintf(stderr, "Can't resolve hostname \"%s\": %s", host, gai_strerror(r)); Err z3bra.org 70 i+ goto err; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ for (addr = addrs; addr; addr = addr->ai_next) { Err z3bra.org 70 i+ if ((sock = socket(addr->ai_family, addr->ai_socktype, Err z3bra.org 70 i+ addr->ai_protocol)) < 0) Err z3bra.org 70 i+ continue; Err z3bra.org 70 i+ if ((r = connect(sock, addr->ai_addr, addr->ai_addrlen)) < 0) { Err z3bra.org 70 i+ close(sock); Err z3bra.org 70 i+ continue; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ break; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ freeaddrinfo(addrs); Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (sock < 0) { Err z3bra.org 70 i+ fprintf(stderr, "Can't open socket: %s", strerror(errno)); Err z3bra.org 70 i+ goto err; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ if (r < 0) { Err z3bra.org 70 i+ fprintf(stderr, "Can't connect to: %s:%s: %s", host, port, strerror(errno)); Err z3bra.org 70 i+ goto err; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ sigprocmask(SIG_SETMASK, &oset, NULL); Err z3bra.org 70 i+ return sock; Err z3bra.org 70 i+ Err z3bra.org 70 i+err: Err z3bra.org 70 i+ sigprocmask(SIG_SETMASK, &oset, NULL); Err z3bra.org 70 i+ return -1; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+int Err z3bra.org 70 i+sendselector(int sock, const char *selector) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ char *msg, *p; Err z3bra.org 70 i+ size_t ln; Err z3bra.org 70 i+ ssize_t n; Err z3bra.org 70 i+ Err z3bra.org 70 i+ ln = strlen(selector) + 3; Err z3bra.org 70 i+ msg = p = malloc(ln); Err z3bra.org 70 i+ snprintf(msg, ln--, "%s\r\n", selector); Err z3bra.org 70 i+ Err z3bra.org 70 i+ while ((n = write(sock, p, ln)) > 0) { Err z3bra.org 70 i+ ln -= n; Err z3bra.org 70 i+ p += n; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ free(msg); Err z3bra.org 70 i+ if (n == -1) Err z3bra.org 70 i+ fprintf(stderr, "Can't send message: %s", strerror(errno)); Err z3bra.org 70 i+ Err z3bra.org 70 i+ return n; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+char * Err z3bra.org 70 i+getrawitem(int sock, size_t *sz) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ char *raw, *buf; Err z3bra.org 70 i+ size_t bn, bs; Err z3bra.org 70 i+ ssize_t n; Err z3bra.org 70 i+ Err z3bra.org 70 i+ raw = buf = NULL; Err z3bra.org 70 i+ bn = bs = n = 0; Err z3bra.org 70 i+ Err z3bra.org 70 i+ do { Err z3bra.org 70 i+ bs -= n; Err z3bra.org 70 i+ buf += n; Err z3bra.org 70 i+ if (bs < 1) { Err z3bra.org 70 i+ raw = xreallocarray(raw, ++bn, BUFSIZ); Err z3bra.org 70 i+ buf = raw + (bn-1) * BUFSIZ; Err z3bra.org 70 i+ bs = BUFSIZ; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ } while ((n = read(sock, buf, bs)) > 0); Err z3bra.org 70 i+ Err z3bra.org 70 i+ *buf = '\0'; Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (sz) Err z3bra.org 70 i+ *sz = buf - raw; Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (n < 0) { Err z3bra.org 70 i+ fprintf(stderr, "Can't read socket: %s", strerror(errno)); Err z3bra.org 70 i+ free(raw); Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ return raw; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+print400(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ printf("HTTP/1.1 400 That's Illegal\r\n"); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+print404(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ printf("HTTP/1.1 404 Google Broke The Web\r\n"); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+print405(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ printf("HTTP/1.1 405 Don't Do That\r\n"); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+print415(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ printf("HTTP/1.1 415 Gopher Type Not Handled\r\n"); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+print500(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ printf("HTTP/1.1 500 You Broke The Web\r\n"); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+char * Err z3bra.org 70 i+contenttype(char i) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ switch(i) { Err z3bra.org 70 i+ case '0': Err z3bra.org 70 i+ case '1': Err z3bra.org 70 i+ return "text/plain; charset=utf-8"; Err z3bra.org 70 i+ break; /* NOTREACHED */ Err z3bra.org 70 i+ case '9': Err z3bra.org 70 i+ return "application/octet-stream"; Err z3bra.org 70 i+ break; /* NOTREACHED */ Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ return NULL; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+void Err z3bra.org 70 i+printheaders(char *ctype) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ time_t t; Err z3bra.org 70 i+ Err z3bra.org 70 i+ t = time(NULL); Err z3bra.org 70 i+ if (t > 0) Err z3bra.org 70 i+ printf("Date: %s", asctime(gmtime(&t))); Err z3bra.org 70 i+ if (ctype) Err z3bra.org 70 i+ printf("Content-Type: %s\r\n", ctype); Err z3bra.org 70 i+ printf("Server: phroxy\r\n"); Err z3bra.org 70 i+ printf("Host: %s\r\n", host); Err z3bra.org 70 i+ printf("Connection: close\r\n"); Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+ Err z3bra.org 70 i+int Err z3bra.org 70 i+serveitem(char item, char *data, size_t len) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ char *sendi; Err z3bra.org 70 i+ int sent; Err z3bra.org 70 i+ Err z3bra.org 70 i+ switch(item) { Err z3bra.org 70 i+ case '0': Err z3bra.org 70 i+ case '1': Err z3bra.org 70 i+ case '6': Err z3bra.org 70 i+ case '9': Err z3bra.org 70 i+ case 'g': Err z3bra.org 70 i+ case 'I': Err z3bra.org 70 i+ break; Err z3bra.org 70 i+ Err z3bra.org 70 i+ case '2': // Item is a CSO phone-book server Err z3bra.org 70 i+ case '3': // Error Err z3bra.org 70 i+ case '4': // Item is a BinHexed Macintosh file. Err z3bra.org 70 i+ case '5': // Item is DOS binary archive of some sort. Err z3bra.org 70 i+ case '7': // Item is an Index-Search server. Err z3bra.org 70 i+ case '8': // Item points to a text-based telnet session. Err z3bra.org 70 i+ case 'T': // Item points to a text-based tn3270 session. Err z3bra.org 70 i+ case '+': Err z3bra.org 70 i+ default: Err z3bra.org 70 i+ /* IGNORE */ Err z3bra.org 70 i+ print415(); Err z3bra.org 70 i+ break; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ printf("HTTP/1.1 200 OK\r\n"); Err z3bra.org 70 i+ printheaders(contenttype(item)); Err z3bra.org 70 i+ Err z3bra.org 70 i+ Err z3bra.org 70 i+ printf("Content-Length: %ld\r\n", len); Err z3bra.org 70 i+ printf("\r\n"); Err z3bra.org 70 i+ fflush(stdout); Err z3bra.org 70 i+ Err z3bra.org 70 i+ sendi = data; Err z3bra.org 70 i+ while (len > 0) { Err z3bra.org 70 i+ if ((sent = write(1, sendi, len)) < 0) Err z3bra.org 70 i+ return 1; Err z3bra.org 70 i+ len -= sent; Err z3bra.org 70 i+ sendi += sent; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ return 0; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+int Err z3bra.org 70 i+phroxy(char *url) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ int sock; Err z3bra.org 70 i+ size_t len; Err z3bra.org 70 i+ char item, *hole, *path, *host, *port; Err z3bra.org 70 i+ char *data; Err z3bra.org 70 i+ Err z3bra.org 70 i+ hole = url + 1; Err z3bra.org 70 i+ hole = strsep(&hole, "/"); Err z3bra.org 70 i+ item = hole[strlen(hole) + 1]; Err z3bra.org 70 i+ path = hole + strlen(hole) + 2; Err z3bra.org 70 i+ Err z3bra.org 70 i+ host = strtok(hole, ":"); Err z3bra.org 70 i+ port = strtok(NULL, "\0"); Err z3bra.org 70 i+ if (!port) Err z3bra.org 70 i+ port = "70"; Err z3bra.org 70 i+ Err z3bra.org 70 i+ sock = connectto(host, port); Err z3bra.org 70 i+ if (!sendselector(sock, path)) Err z3bra.org 70 i+ data = getrawitem(sock, &len); Err z3bra.org 70 i+ Err z3bra.org 70 i+ close(sock); Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (!data) Err z3bra.org 70 i+ return 1; Err z3bra.org 70 i+ Err z3bra.org 70 i+ serveitem(item, data, len); Err z3bra.org 70 i+ Err z3bra.org 70 i+ return 0; Err z3bra.org 70 i+} Err z3bra.org 70 i+ Err z3bra.org 70 i+int Err z3bra.org 70 i+main(void) Err z3bra.org 70 i+{ Err z3bra.org 70 i+ ssize_t rlen; Err z3bra.org 70 i+ char request[512], *url; Err z3bra.org 70 i+ Err z3bra.org 70 i+ rlen = read(0, request, sizeof(request) - 1); Err z3bra.org 70 i+ if (rlen < 0) Err z3bra.org 70 i+ return 1; Err z3bra.org 70 i+ Err z3bra.org 70 i+ request[rlen] = '\0'; Err z3bra.org 70 i+ Err z3bra.org 70 i+ if (strncmp(request, "GET ", 4)) { Err z3bra.org 70 i+ print405(); Err z3bra.org 70 i+ return 1; Err z3bra.org 70 i+ } Err z3bra.org 70 i+ Err z3bra.org 70 i+ url = strtok(request + 4, " "); Err z3bra.org 70 i+ Err z3bra.org 70 i+ return phroxy(url); Err z3bra.org 70 i+} Err z3bra.org 70 .