chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / storage / overdata.c
diff --git a/storage/overdata.c b/storage/overdata.c
deleted file mode 100644 (file)
index b2de7c8..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-/*  $Id: overdata.c 7477 2005-12-24 21:34:38Z eagle $
-**
-**  Overview data processing.
-**
-**  Here be routines for creating and checking the overview data, the
-**  tab-separated list of overview fields.
-*/
-
-#include "config.h"
-#include "clibrary.h"
-#include <ctype.h>
-
-#include "inn/buffer.h"
-#include "inn/innconf.h"
-#include "inn/messages.h"
-#include "inn/qio.h"
-#include "inn/wire.h"
-#include "inn/vector.h"
-#include "libinn.h"
-#include "ovinterface.h"
-#include "paths.h"
-
-
-/* The standard overview fields. */
-static const char * const fields[] = {
-    "Subject", "From", "Date", "Message-ID", "References", "Bytes", "Lines"
-};
-
-
-/*
-**  Return a vector of the standard overview fields. Note there is no
-**  way to free up the resulting data structure.
-*/
-const struct cvector *
-overview_fields(void)
-{
-    static struct cvector *list = NULL;
-
-    if (list == NULL) {
-       unsigned int field;
-
-       list = cvector_new();
-       cvector_resize(list, ARRAY_SIZE(fields));
-
-       for (field = 0; field < ARRAY_SIZE(fields); ++field) {
-           cvector_add(list, fields[field]);
-       }
-    }
-    return list;
-}
-
-/*
-**  Parse the overview schema and return a vector of the additional fields
-**  over the standard ones.  Caller is responsible for freeing the vector.
-*/
-struct vector *
-overview_extra_fields(void)
-{
-    struct vector *list = NULL;
-    struct vector *result = NULL;
-    char *schema = NULL;
-    char *line, *p;
-    QIOSTATE *qp = NULL;
-    unsigned int field;
-    bool full = false;
-
-    schema = concatpath(innconf->pathetc, _PATH_SCHEMA);
-    qp = QIOopen(schema);
-    if (qp == NULL) {
-        syswarn("cannot open %s", schema);
-        goto done;
-    }
-    list = vector_new();
-    for (field = 0, line = QIOread(qp); line != NULL; line = QIOread(qp)) {
-        while (ISWHITE(*line))
-            line++;
-        p = strchr(line, '#');
-        if (p != NULL)
-            *p = '\0';
-        p = strchr(line, '\n');
-        if (p != NULL)
-            *p = '\0';
-        if (*line == '\0')
-            continue;
-        p = strchr(line, ':');
-        if (p != NULL) {
-            *p++ = '\0';
-            full = (strcmp(p, "full") == 0);
-        }
-        if (field >= ARRAY_SIZE(fields)) {
-            if (!full)
-                warn("additional field %s not marked with :full", line);
-            vector_add(list, line);
-        } else {
-            if (strcasecmp(line, fields[field]) != 0)
-                warn("field %d is %s, should be %s", field, line,
-                     fields[field]);
-        }
-        field++;
-    }
-    if (QIOerror(qp)) {
-        if (QIOtoolong(qp)) {
-            warn("line too long in %s", schema);
-        } else {
-            syswarn("error while reading %s", schema);
-        }
-    }
-    result = list;
-
-done:
-    if (schema != NULL)
-        free(schema);
-    if (qp != NULL)
-        QIOclose(qp);
-    if (result == NULL && list != NULL)
-        vector_free(list);
-    return result;
-}
-
-
-/*
-**  Given an article, its length, the name of a header, and a buffer to append
-**  the data to, append header data for that header to the overview data
-**  that's being constructed.  Doesn't append any data if the header isn't
-**  found.
-*/
-static void
-build_header(const char *article, size_t length, const char *header,
-             struct buffer *overview)
-{
-    ptrdiff_t size;
-    size_t offset;
-    const char *data, *end, *p;
-
-    data = wire_findheader(article, length, header);
-    if (data == NULL)
-        return;
-    end = wire_endheader(data, article + length - 1);
-    if (end == NULL)
-        return;
-
-    /* Someone managed to break their server so that they were appending
-       multiple Xref headers, and INN had a bug where it wouldn't notice this
-       and reject the article.  Just in case, see if there are multiple Xref
-       headers and use the last one. */
-    if (strcasecmp(header, "xref") == 0) {
-        const char *next = end + 1;
-
-        while (next != NULL) {
-            next = wire_findheader(next, length - (next - article), header);
-            if (next != NULL) {
-                data = next;
-                end = wire_endheader(data, article + length - 1);
-                if (end == NULL)
-                    return;
-            }
-        }
-    }
-
-    size = end - data + 1;
-    offset = overview->used + overview->left;
-    buffer_resize(overview, offset + size);
-
-    for (p = data; p <= end; p++) {
-        if (*p == '\r' && p[1] == '\n') {
-            p++;
-            continue;
-        }
-        if (*p == '\0' || *p == '\t' || *p == '\n' || *p == '\r')
-            overview->data[offset++] = ' ';
-        else
-            overview->data[offset++] = *p;
-        overview->left++;
-    }
-}
-
-
-/*
-**  Given an article number, an article, and a vector of additional headers,
-**  generate overview data into the provided buffer.  If the buffer parameter
-**  is NULL, a new buffer is allocated.  The article should be in wire format.
-**  Returns the buffer containing the overview data.
-*/
-struct buffer *
-overview_build(ARTNUM number, const char *article, size_t length,
-               const struct vector *extra, struct buffer *overview)
-{
-    unsigned int field;
-    char buffer[32];
-
-    snprintf(buffer, sizeof(buffer), "%lu", number);
-    if (overview == NULL)
-        overview = buffer_new();
-    buffer_set(overview, buffer, strlen(buffer));
-    for (field = 0; field < ARRAY_SIZE(fields); field++) {
-        buffer_append(overview, "\t", 1);
-        if (field == 5) {
-            snprintf(buffer, sizeof(buffer), "%lu", (unsigned long) length);
-            buffer_append(overview, buffer, strlen(buffer));
-        } else
-            build_header(article, length, fields[field], overview);
-    }
-    for (field = 0; field < extra->count; field++) {
-        buffer_append(overview, "\t", 1);
-        buffer_append(overview, extra->strings[field],
-                      strlen(extra->strings[field]));
-        buffer_append(overview, ": ", 2);
-        build_header(article, length, extra->strings[field], overview);
-    }
-    buffer_append(overview, "\r\n", 2);
-    return overview;
-}
-
-
-/*
-**  Check whether a given string is a valid number.
-*/
-static bool
-valid_number(const char *string)
-{
-    const char *p;
-
-    for (p = string; *p != '\0'; p++)
-        if (!CTYPE(isdigit, *p))
-            return false;
-    return true;
-}
-
-
-/*
-**  Check whether a given string is a valid overview string (doesn't contain
-**  CR or LF, and if the second argument is true must be preceeded by a header
-**  name, colon, and space).  Allow CRLF at the end of the data, but don't
-**  require it.
-*/
-static bool
-valid_overview_string(const char *string, bool full)
-{
-    const unsigned char *p;
-
-    /* RFC 2822 says that header fields must consist of printable ASCII
-       characters (characters between 33 and 126, inclusive) excluding colon.
-       We also allow high-bit characters, just in case, but not DEL. */
-    p = (const unsigned char *) string;
-    if (full) {
-        for (; *p != '\0' && *p != ':'; p++)
-            if (*p < 33 || *p == 127)
-                return false;
-        if (*p != ':')
-            return false;
-        p++;
-        if (*p != ' ')
-            return false;
-    }
-    for (p++; *p != '\0'; p++) {
-        if (*p == '\015' && p[1] == '\012' && p[2] == '\0')
-            break;
-        if (*p == '\015' || *p == '\012')
-            return false;
-    }
-    return true;
-}
-
-
-/*
-**  Check the given overview data and make sure it's well-formed.  Extension
-**  headers are not checked against overview.fmt (having a different set of
-**  extension headers doesn't make the data invalid), but the presence of the
-**  standard fields is checked.  Also checked is whether the article number in
-**  the data matches the passed article number.  Returns true if the data is
-**  okay, false otherwise.
-*/
-bool
-overview_check(const char *data, size_t length, ARTNUM article)
-{
-    char *copy;
-    struct cvector *overview;
-    ARTNUM overnum;
-    size_t i;
-
-    copy = xstrndup(data, length);
-    overview = cvector_split(copy, '\t', NULL);
-
-    /* The actual checks.  We don't verify all of the data, since that data
-       may be malformed in the article, but we do check to be sure that the
-       fields that should be numbers are numbers.  That should catch most
-       positional errors.  We can't check Lines yet since right now INN is
-       still accepting the value from the post verbatim. */
-    if (overview->count < 8)
-        goto fail;
-    if (!valid_number(overview->strings[0]))
-        goto fail;
-    overnum = strtoul(overview->strings[0], NULL, 10);
-    if (overnum != article)
-        goto fail;
-    if (!valid_number(overview->strings[6]))
-        goto fail;
-    for (i = 1; i < 6; i++)
-        if (!valid_overview_string(overview->strings[i], false))
-            goto fail;
-    for (i = 8; i < overview->count; i++)
-        if (!valid_overview_string(overview->strings[i], true))
-            goto fail;
-    cvector_free(overview);
-    free(copy);
-    return true;
-
- fail:
-    cvector_free(overview);
-    free(copy);
-    return false;
-}
-
-
-/*
-**  Given an overview header, return the offset of the field within
-**  the overview data, or -1 if the field is not present in the
-**  overview schema for this installation.
-*/
-int
-overview_index(const char *field, const struct vector *extra)
-{
-    int i;
-
-    for (i = 0; i < (sizeof fields / sizeof fields[0]); ++i) {
-       if (strcasecmp(field, fields[i]) == 0)
-           return i;
-    }
-    for (i = 0; i < extra->count; i++) {
-       if (strcasecmp(field, extra->strings[i]) == 0)
-           return i + (sizeof fields / sizeof fields[0]);
-    }
-    return -1;
-}
-
-
-/*
-**  Given an overview header line, split out a vector pointing at each
-**  of the components (within line), returning a pointer to the
-**  vector. If the vector initially passed in is NULL a new vector is
-**  created, else the existing one is filled in.
-**
-**  A member `n' of the vector is of length (vector->strings[n+1] -
-**  vector->strings[n] - 1). Note that the last member of the vector
-**  will always point beyond (line + length).
-*/
-struct cvector *
-overview_split(const char *line, size_t length, ARTNUM *number,
-              struct cvector *vector)
-{
-    const char *p = NULL;
-
-    if (vector == NULL) {
-       vector = cvector_new();
-    } else {
-       cvector_clear(vector);
-    }
-    while (line != NULL) {
-       /* the first field is the article number */
-       if (p == NULL) {
-           if (number != NULL) {
-               *number = atoi(line);
-           }
-       } else {
-           cvector_add(vector, line);
-       }
-       p = memchr(line, '\t', length);
-       if (p != NULL) {
-           /* skip over the tab */
-           ++p;
-           /* and calculate the remaining length */
-           length -= (p - line);
-       } else {
-           /* add in a pointer to beyond the end of the final
-            * component, so you can always calculate the length.
-            * overview lines are always terminated with \r\n, so the
-            * -1 ends up chopping those off */
-           cvector_add(vector, line + length - 1);
-       }
-       line = p;
-    }
-    return vector;
-}
-
-/*
-**  Given an overview vector (from overview_split), return a copy of
-**  the member which the caller is interested in (and must free).
-*/
-char *
-overview_getheader(const struct cvector *vector, int element,
-                  const struct vector *extra)
-{
-    char *field = NULL;
-    size_t len;
-    const char *p;
-
-    if ((element + 1) >= vector->count ||
-       (element >= ARRAY_SIZE(fields) &&
-        (element - ARRAY_SIZE(fields)) >= extra->count)) {
-       warn("request for invalid overview field %d", element);
-       return NULL;
-    }
-    /* Note... this routine does not synthesise Newsgroups: on behalf
-     * of the caller... */
-    if (element >= ARRAY_SIZE(fields)) {
-       /* +2 for `: ' */
-       p = vector->strings[element] +
-           strlen(extra->strings[element - ARRAY_SIZE(fields)]) + 2;
-       len = vector->strings[element + 1] - p - 1;
-    } else {
-       p = vector->strings[element];
-       len = vector->strings[element + 1] - vector->strings[element] - 1;
-    }
-    field = xstrndup(p, len);
-    return field;
-}