Handle (hopefuly) all invalid format streams - sacc - sacc(omys), simple console gopher client
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/sacc/
Log
Files
Refs
Tags
LICENSE
---
commit fdae99f75651ec33854a55654887608fb4f2947c
parent 4dff6dde00bd2e8062f678d6ca2207d00119474f
Author: Quentin Rameau 
Date:   Fri,  7 Jul 2017 15:16:30 +0200

Handle (hopefuly) all invalid format streams

Diffstat:
  M sacc.c                              |     112 +++++++++++++++----------------
  M ui_ti.c                             |      37 ++++++++++++++++---------------
  M ui_txt.c                            |      23 ++++++++++-------------

3 files changed, 84 insertions(+), 88 deletions(-)
---
diff --git a/sacc.c b/sacc.c
@@ -57,6 +57,17 @@ xmalloc(const size_t n)
         return m;
 }
 
+static void *
+xcalloc(size_t n)
+{
+        char *m = xmalloc(n);
+
+        while (n)
+                m[--n] = 0;
+
+        return m;
+}
+
 static char *
 xstrdup(const char *str)
 {
@@ -147,20 +158,8 @@ pickfield(char **raw, char sep)
 {
         char *c, *f = *raw;
 
-        for (c = *raw; *c != sep; ++c) {
-                switch (*c) {
-                case '\t':
-                        if (sep == '\r')
-                                *c = '\0';
-                case '\n':
-                case '\r':
-                case '\0':
-                        return NULL;
-                default:
-                        continue;
-                }
-                break;
-        }
+        for (c = *raw; *c && *c != sep; ++c)
+                ;
 
         *c = '\0';
         *raw = c+1;
@@ -168,35 +167,47 @@ pickfield(char **raw, char sep)
         return f;
 }
 
+static char *
+invaliditem(char *raw)
+{
+        char c;
+        int tabs;
+
+        for (tabs = 0; (c = *raw) && c != '\n'; ++raw) {
+                if (c == '\t')
+                        ++tabs;
+        }
+        if (c)
+                *raw++ = '\0';
+
+        return (tabs == 3) ? NULL : raw;
+}
+
 static Item *
 molditem(char **raw)
 {
         Item *item;
-        char type, *username, *selector, *host, *port;
+        char *next;
 
         if (!*raw)
                 return NULL;
 
-        if (!(type = *raw[0]++) ||
-            !(username = pickfield(raw, '\t')) ||
-            !(selector = pickfield(raw, '\t')) ||
-            !(host = pickfield(raw, '\t')) ||
-            !(port = pickfield(raw, '\r')) ||
-            *raw[0]++ != '\n')
-                return NULL;
+        item = xcalloc(sizeof(Item));
 
-        item = xmalloc(sizeof(Item));
+        if ((next = invaliditem(*raw))) {
+                item->type = 'i';
+                item->username = *raw;
+                *raw = next;
+                return item;
+        }
 
-        item->type = type;
-        item->username = username;
-        item->selector = selector;
-        item->host = host;
-        item->port = port;
-        item->raw = NULL;
-        item->dir = NULL;
-        item->entry = NULL;
-        item->printoff = 0;
-        item->curline = 0;
+        item->type = *raw[0]++;
+        item->username = pickfield(raw, '\t');
+        item->selector = pickfield(raw, '\t');
+        item->host = pickfield(raw, '\t');
+        item->port = pickfield(raw, '\r');
+        if (!*raw[0])
+                ++*raw;
 
         return item;
 }
@@ -204,38 +215,25 @@ molditem(char **raw)
 static Dir *
 molddiritem(char *raw)
 {
-        Item *item, **items = NULL;
-        char *crlf, *p;
+        Item **items = NULL;
+        char *s, *nl, *p;
         Dir *dir;
         size_t i, nitems;
 
-        for (crlf = raw, nitems = 0; p = strstr(crlf, "\r\n"); ++nitems)
-                crlf = p+2;
-        if (nitems <= 1)
-                return NULL;
-        if (!strcmp(crlf-3, ".\r\n"))
+        for (s = nl = raw, nitems = 0; p = strchr(nl, '\n'); ++nitems) {
+                s = nl;
+                nl = p+1;
+        }
+        if (!strcmp(s, ".\r\n") || !strcmp(s, ".\n"))
                 --nitems;
-        else
-                fprintf(stderr, "Parsing error: missing .\\r\\n last line\n");
+        if (!nitems)
+                return NULL;
 
         dir = xmalloc(sizeof(Dir));
         items = xreallocarray(items, nitems, sizeof(Item*));
 
-        for (i = 0; i < nitems; ++i) {
-                if (item = molditem(&raw)) {
-                        items[i] = item;
-                } else {
-                        fprintf(stderr, "Parsing error: dir entity: %d\n", i+1);
-                        items = xreallocarray(items, i, sizeof(Item*));
-                        nitems = i;
-                        break;
-                }
-        }
-
-        if (!items) {
-                free(dir);
-                return NULL;
-        }
+        for (i = 0; i < nitems; ++i)
+                items[i] = molditem(&raw);
 
         dir->items = items;
         dir->nitems = nitems;
diff --git a/ui_ti.c b/ui_ti.c
@@ -57,7 +57,7 @@ help(void)
 static void
 displaystatus(Item *item)
 {
-        size_t nitems = item->dir->nitems;
+        size_t nitems = item->dir ? item->dir->nitems : 0;
 
         putp(tparm(save_cursor));
 
@@ -75,13 +75,18 @@ displaystatus(Item *item)
 void
 display(Item *entry)
 {
-        Item *item, **items;
+        Item **items;
         size_t i, curln, lastln, nitems, printoff;
 
         if (entry->type != '1')
                 return;
 
         putp(tparm(clear_screen));
+        displaystatus(entry);
+
+        if (!entry->dir)
+                return;
+
         putp(tparm(save_cursor));
 
         items = entry->dir->items;
@@ -91,22 +96,19 @@ display(Item *entry)
         lastln = printoff + lines-1; /* one off for status bar */
 
         for (i = printoff; i < nitems && i < lastln; ++i) {
-                if (item = items[i]) {
-                        if (i != printoff)
-                                putp(tparm(cursor_down));
-                        if (i == curln) {
-                                putp(tparm(save_cursor));
-                                putp(tparm(enter_standout_mode));
-                        }
-                        printitem(item);
-                        putp(tparm(column_address, 0));
-                        if (i == curln)
-                                putp(tparm(exit_standout_mode));
+                if (i != printoff)
+                        putp(tparm(cursor_down));
+                if (i == curln) {
+                        putp(tparm(save_cursor));
+                        putp(tparm(enter_standout_mode));
                 }
+                printitem(items[i]);
+                putp(tparm(column_address, 0));
+                if (i == curln)
+                        putp(tparm(exit_standout_mode));
         }
 
         putp(tparm(restore_cursor));
-        displaystatus(entry);
         fflush(stdout);
 }
 
@@ -166,8 +168,7 @@ movecurline(Item *item, int l)
 Item *
 selectitem(Item *entry)
 {
-        Item *hole;
-        int item, nitems;
+        Dir *dir = entry->dir;
 
         for (;;) {
                 switch (getchar()) {
@@ -199,8 +200,8 @@ selectitem(Item *entry)
                 case _key_pgnext:
                 case '\r':
                 pgnext:
-                        if (entry->dir->items[entry->curline]->type < '2')
-                                return entry->dir->items[entry->curline];
+                        if (dir)
+                                return dir->items[entry->curline];
                         continue;
                 case _key_lndown:
                 lndown:
diff --git a/ui_txt.c b/ui_txt.c
@@ -54,7 +54,7 @@ ndigits(size_t n)
 static void
 printstatus(Item *item)
 {
-        size_t nitems = item->dir->nitems;
+        size_t nitems = item->dir ? item->dir->nitems : 0;
 
         printf("%3lld%%%*c %s:%s%s (h for help): ",
                (item->printoff + lines >= nitems) ? 100 :
@@ -65,11 +65,11 @@ printstatus(Item *item)
 void
 display(Item *entry)
 {
-        Item *item, **items;
+        Item **items;
         size_t i, lines, nitems;
         int nd;
 
-        if (entry->type != '1')
+        if (entry->type != '1' || !entry->dir)
                 return;
 
         items = entry->dir->items;
@@ -78,15 +78,12 @@ display(Item *entry)
         nd = ndigits(nitems);
 
         for (i = entry->printoff; i < nitems && i < lines; ++i) {
-                if (item = items[i]) {
-                        printf("%*zu %-4s%c %s\n", nd, i+1,
-                               item->type != 'i' ?
-                               typedisplay(item->type) : "",
-                               item->type > '1' ? '|' : '+',
-                               items[i]->username);
-                } else {
-                        printf("%*zu  !! |\n", nd, i+1);
-                }
+                item = items[i];
+                printf("%*zu %-4s%c %s\n", nd, i+1,
+                       item->type != 'i' ?
+                       typedisplay(item->type) : "",
+                       item->type > '1' ? '|' : '+',
+                       item->username);
         }
 
         fflush(stdout);
@@ -113,7 +110,7 @@ selectitem(Item *entry)
 
                 if (!strcmp(buf, "n\n")) {
                         lines = termlines();
-                        if (lines < entry->dir->nitems - entry->printoff &&
+                        if (lines < nitems - entry->printoff &&
                             lines < (size_t)-1 - entry->printoff)
                                 entry->printoff += lines;
                         return entry;