gophra

gopher client for plan9
git clone git://nsmpr.xyz/gophra.git
Log | Files | Refs

commit 023ea793d7f8276c8d80841f0362c34a6573225b
parent 8e1a3abd20fe784d91368edc1f53cd8dde8a75f2
Author: glenda <glenda@9front.local>
Date:   Sun, 24 May 2020 17:04:59 +0000

uri parsing done, more or less

Diffstat:
Mgophra.c | 70+++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mmkfile | 6++++--
Auri.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Auri.h | 14++++++++++++++
4 files changed, 144 insertions(+), 19 deletions(-)

diff --git a/gophra.c b/gophra.c @@ -7,6 +7,8 @@ #include <keyboard.h> #include <frame.h> +#include "uri.h" + enum { DBorder = DBlue, DWBG = DBlack, @@ -19,7 +21,7 @@ typedef struct Text Text; struct Text { char *data; long size; -} text; +}; typedef struct History History; struct History { @@ -28,6 +30,8 @@ struct History { History *prev; }; +Text text; + History hzero, *hp; Image *Iborder, *Iwbg, *Iwfg, *Iwfgl, *Istatus; @@ -50,11 +54,12 @@ void drawtext(void); void drawmenu(void); int extracturl(char*); char* getline(long); -void handlelink(void); +void handlelink(char*, char, char*); int loadtext(char*, char*); void runhold(void*); void runpage(void*); -int save(void); +int save(char*, char*); +int runuri(char*); void threadmain(int argc, char **argv) @@ -95,17 +100,19 @@ threadmain(int argc, char **argv) snprint(status, 255, "gophra!"); - if (argv[0] != 0) { - strncpy(hzero.addr, argv[0], 256); - loadtext(argv[0], ""); - } - calcrects(); drawborder(); drawstatus(); drawmenu(); flushimage(display, 1); + if (argc == 1) { + strncpy(hzero.addr, argv[0], 256); + runuri(argv[0]); + } else if (argc > 0) { + usage(); + } + if((mc = initmouse(0, screen)) == nil) sysfatal("initmouse failed: %r"); if((kc = initkeyboard(0)) == nil) @@ -126,7 +133,7 @@ threadmain(int argc, char **argv) char buf[256]; buf[0] = 0; if (enter("goto:", buf, 255, mc, kc, 0) >=0) - if (loadtext(buf, "") == 0){ + if (runuri(buf) == 0){ drawmenu(); flushimage(display, 1); } @@ -166,7 +173,7 @@ threadmain(int argc, char **argv) scroll; s = getline(sline); extracturl(s); - handlelink(); + handlelink(addr, type, path); if (s != 0) free(s); } if (mv.buttons == 4) { @@ -190,7 +197,7 @@ threadmain(int argc, char **argv) void usage(void) { - fprint(2, "usage: %s", argv0); + fprint(2, "usage: %s [gopher_uri]\n", argv0); exits("usage"); } @@ -356,13 +363,12 @@ extracturl(char *s) } void -handlelink(void) +handlelink(char *addr, char type, char *path) { History *hnew; switch (type) { case '0': - save(); - proccreate(runhold, 0, 1024 * 8); + if (save(addr, path) == 0) proccreate(runhold, 0, 1024 * 8); break; case '1': hnew = malloc(sizeof(History)); @@ -376,8 +382,7 @@ handlelink(void) flushimage(display, 1); break; case 'I': - save(); - proccreate(runpage, 0, 1024 * 8); + if (save(addr, path) == 0) proccreate(runpage, 0, 1024 * 8); break; default: snprint(status, 255, "unknown type - %c", type); @@ -433,8 +438,9 @@ runpage(void*) procexecl(nil, "/bin/window", "window", "-m", "page", tmpfile, nil); } + int -save(void) +save(char *addr, char *path) { int dcfd, wfd; long n; @@ -467,4 +473,34 @@ save(void) drawstatus(); flushimage(display, 1); return 0; +} + + +int +runuri(char *s) +{ + URI *uri; + char *addr, *port, type, *path; + uri = chewuri(s); + if (uri == nil) { + snprint(status, 255, "invalid URI: %s", s); + return -1; + } + if (strcmp("gopher", uri->scheme) == 0){ + port = (uri->port == nil) ? "gopher" : uri->port; + addr = netmkaddr(uri->host, "tcp", port); + type = '1'; + path = "/"; + if (strlen(uri->path) >=2) type = uri->path[1]; + if (strlen(uri->path) > 2) path = uri->path + 2; + handlelink(addr, type, path); + } else { + snprint(status, 255, "Unknown scheme: %s", uri->scheme); + freeuri(uri); + free(uri); + return -1; + } + freeuri(uri); + free(uri); + return 0; } \ No newline at end of file diff --git a/mkfile b/mkfile @@ -1,8 +1,10 @@ </$objtype/mkfile -BIN=/$objtype/bin +# BIN=/$objtype/bin + +BIN=$home/bin/$objtype TARG=gophra -OFILES=gophra.$O +OFILES=gophra.$O uri.$O </sys/src/cmd/mkone \ No newline at end of file diff --git a/uri.c b/uri.c @@ -0,0 +1,73 @@ +#include <u.h> +#include <libc.h> +#include <regexp.h> + +#include "uri.h" + +char* +match2str(Resub *m) +{ + long n; + char *r; + if (m->sp == 0) return 0; + n = m->ep - m->sp + 1; + r = mallocz(n, 1); + strncpy(r, m->sp, n - 1); + return r; +} + +URI* +chewuri(char *s) +{ + URI *r; + Reprog *uriprog, *authprog; + Resub *m, *n; + char *auth; + auth = 0; + r = mallocz(sizeof(URI), 1); + m = mallocz(sizeof(Resub) * 16, 1); + n = mallocz(sizeof(Resub) * 8, 1); + /* scheme://user@host:port/path?query#fragment */ + + uriprog = regcomp( + "(([^:]+):)" + "(//([^/?#]+))?" + "(/?[^?#]*)?" + "(\\?([^#]+))?" + "(#(.*))?" + ); + authprog = regcomp( + "(([^@]+)@)?" + "([^:]+)" + "(:([0-9]+))?" + ); + if (regexec(uriprog, s, m, 16) == 1){ + r->scheme = match2str(&m[2]); + auth = match2str(&m[4]); + r->path = match2str(&m[5]); + r->query = match2str(&m[7]); + r->fragment = match2str(&m[9]); + } + if ((auth != nil) && (regexec(authprog, auth, n, 8) == 1)) { + r->user = match2str(&n[2]); + r->host = match2str(&n[3]); + r->port = match2str(&n[5]); + } + free(uriprog); + free(authprog); + free(m); + free(n); + return r; +} + +void +freeuri(URI *uri) +{ + realloc(uri->scheme, 0); + realloc(uri->user, 0); + realloc(uri->host, 0); + realloc(uri->port, 0); + realloc(uri->path, 0); + realloc(uri->query, 0); + realloc(uri->fragment, 0); +} diff --git a/uri.h b/uri.h @@ -0,0 +1,13 @@ +typedef struct URI URI; +struct URI{ + char *scheme; + char *user; + char *host; + char *port; + char *path; + char *query; + char *fragment; +}; + +URI* chewuri(char*); +void freeuri(URI*); +\ No newline at end of file