From e7803f7520bd591c37557ffd853dd40541854357 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 9 Aug 2006 13:01:38 +0000 Subject: Maple Worksheet repository CGI frontend --- math/Makefile | 13 ++ math/Makefile.inc | 12 ++ math/crc.c | 103 ++++++++++ math/crc.h | 26 +++ math/math.c | 497 +++++++++++++++++++++++++++++++++++++++++++++ math/math.css | 161 +++++++++++++++ math/math/Makefile | 7 + math/metadb.c | 581 +++++++++++++++++++++++++++++++++++++++++++++++++++++ math/metadb.h | 68 +++++++ math/mkdb.c | 130 ++++++++++++ math/mkdb/Makefile | 7 + math/query.c | 81 ++++++++ math/query.h | 27 +++ math/readmeta.c | 158 +++++++++++++++ 14 files changed, 1871 insertions(+) create mode 100644 math/Makefile create mode 100644 math/Makefile.inc create mode 100644 math/crc.c create mode 100644 math/crc.h create mode 100644 math/math.c create mode 100644 math/math.css create mode 100644 math/math/Makefile create mode 100644 math/metadb.c create mode 100644 math/metadb.h create mode 100644 math/mkdb.c create mode 100644 math/mkdb/Makefile create mode 100644 math/query.c create mode 100644 math/query.h create mode 100644 math/readmeta.c diff --git a/math/Makefile b/math/Makefile new file mode 100644 index 0000000..9278b34 --- /dev/null +++ b/math/Makefile @@ -0,0 +1,13 @@ +# $Id$ + +.include "Makefile.inc" + +.include + +SUBDIR= mkdb math + +beforeinstall: + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m 444 \ + math.css ${BINDIR}/.. + +.include diff --git a/math/Makefile.inc b/math/Makefile.inc new file mode 100644 index 0000000..a4d6c59 --- /dev/null +++ b/math/Makefile.inc @@ -0,0 +1,12 @@ +# $Id$ + +.PATH: ${.CURDIR}/.. +CFLAGS+= -I${.CURDIR}/.. + +WARNINGS= yes + +CDIAGFLAGS+= -Wall -Wpointer-arith \ + -Wstrict-prototypes -Wmissing-prototypes \ + -ggdb + +BINDIR= /var/www/htdocs/cgi-bin diff --git a/math/crc.c b/math/crc.c new file mode 100644 index 0000000..9af785b --- /dev/null +++ b/math/crc.c @@ -0,0 +1,103 @@ +/* $Id$ */ +/* $OpenBSD: crc.c,v 1.2 2004/05/10 19:48:07 deraadt Exp $ */ + +/* + * Copyright (c) 2004 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "crc.h" + +/* + * Table-driven version of the following polynomial from POSIX 1003.2: + * G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + + * x^7 + x^5 + x^4 + x^2 + x + 1 + */ +static const u_int32_t crc32tab[] = { + 0x00000000U, + 0x04c11db7U, 0x09823b6eU, 0x0d4326d9U, 0x130476dcU, 0x17c56b6bU, + 0x1a864db2U, 0x1e475005U, 0x2608edb8U, 0x22c9f00fU, 0x2f8ad6d6U, + 0x2b4bcb61U, 0x350c9b64U, 0x31cd86d3U, 0x3c8ea00aU, 0x384fbdbdU, + 0x4c11db70U, 0x48d0c6c7U, 0x4593e01eU, 0x4152fda9U, 0x5f15adacU, + 0x5bd4b01bU, 0x569796c2U, 0x52568b75U, 0x6a1936c8U, 0x6ed82b7fU, + 0x639b0da6U, 0x675a1011U, 0x791d4014U, 0x7ddc5da3U, 0x709f7b7aU, + 0x745e66cdU, 0x9823b6e0U, 0x9ce2ab57U, 0x91a18d8eU, 0x95609039U, + 0x8b27c03cU, 0x8fe6dd8bU, 0x82a5fb52U, 0x8664e6e5U, 0xbe2b5b58U, + 0xbaea46efU, 0xb7a96036U, 0xb3687d81U, 0xad2f2d84U, 0xa9ee3033U, + 0xa4ad16eaU, 0xa06c0b5dU, 0xd4326d90U, 0xd0f37027U, 0xddb056feU, + 0xd9714b49U, 0xc7361b4cU, 0xc3f706fbU, 0xceb42022U, 0xca753d95U, + 0xf23a8028U, 0xf6fb9d9fU, 0xfbb8bb46U, 0xff79a6f1U, 0xe13ef6f4U, + 0xe5ffeb43U, 0xe8bccd9aU, 0xec7dd02dU, 0x34867077U, 0x30476dc0U, + 0x3d044b19U, 0x39c556aeU, 0x278206abU, 0x23431b1cU, 0x2e003dc5U, + 0x2ac12072U, 0x128e9dcfU, 0x164f8078U, 0x1b0ca6a1U, 0x1fcdbb16U, + 0x018aeb13U, 0x054bf6a4U, 0x0808d07dU, 0x0cc9cdcaU, 0x7897ab07U, + 0x7c56b6b0U, 0x71159069U, 0x75d48ddeU, 0x6b93dddbU, 0x6f52c06cU, + 0x6211e6b5U, 0x66d0fb02U, 0x5e9f46bfU, 0x5a5e5b08U, 0x571d7dd1U, + 0x53dc6066U, 0x4d9b3063U, 0x495a2dd4U, 0x44190b0dU, 0x40d816baU, + 0xaca5c697U, 0xa864db20U, 0xa527fdf9U, 0xa1e6e04eU, 0xbfa1b04bU, + 0xbb60adfcU, 0xb6238b25U, 0xb2e29692U, 0x8aad2b2fU, 0x8e6c3698U, + 0x832f1041U, 0x87ee0df6U, 0x99a95df3U, 0x9d684044U, 0x902b669dU, + 0x94ea7b2aU, 0xe0b41de7U, 0xe4750050U, 0xe9362689U, 0xedf73b3eU, + 0xf3b06b3bU, 0xf771768cU, 0xfa325055U, 0xfef34de2U, 0xc6bcf05fU, + 0xc27dede8U, 0xcf3ecb31U, 0xcbffd686U, 0xd5b88683U, 0xd1799b34U, + 0xdc3abdedU, 0xd8fba05aU, 0x690ce0eeU, 0x6dcdfd59U, 0x608edb80U, + 0x644fc637U, 0x7a089632U, 0x7ec98b85U, 0x738aad5cU, 0x774bb0ebU, + 0x4f040d56U, 0x4bc510e1U, 0x46863638U, 0x42472b8fU, 0x5c007b8aU, + 0x58c1663dU, 0x558240e4U, 0x51435d53U, 0x251d3b9eU, 0x21dc2629U, + 0x2c9f00f0U, 0x285e1d47U, 0x36194d42U, 0x32d850f5U, 0x3f9b762cU, + 0x3b5a6b9bU, 0x0315d626U, 0x07d4cb91U, 0x0a97ed48U, 0x0e56f0ffU, + 0x1011a0faU, 0x14d0bd4dU, 0x19939b94U, 0x1d528623U, 0xf12f560eU, + 0xf5ee4bb9U, 0xf8ad6d60U, 0xfc6c70d7U, 0xe22b20d2U, 0xe6ea3d65U, + 0xeba91bbcU, 0xef68060bU, 0xd727bbb6U, 0xd3e6a601U, 0xdea580d8U, + 0xda649d6fU, 0xc423cd6aU, 0xc0e2d0ddU, 0xcda1f604U, 0xc960ebb3U, + 0xbd3e8d7eU, 0xb9ff90c9U, 0xb4bcb610U, 0xb07daba7U, 0xae3afba2U, + 0xaafbe615U, 0xa7b8c0ccU, 0xa379dd7bU, 0x9b3660c6U, 0x9ff77d71U, + 0x92b45ba8U, 0x9675461fU, 0x8832161aU, 0x8cf30badU, 0x81b02d74U, + 0x857130c3U, 0x5d8a9099U, 0x594b8d2eU, 0x5408abf7U, 0x50c9b640U, + 0x4e8ee645U, 0x4a4ffbf2U, 0x470cdd2bU, 0x43cdc09cU, 0x7b827d21U, + 0x7f436096U, 0x7200464fU, 0x76c15bf8U, 0x68860bfdU, 0x6c47164aU, + 0x61043093U, 0x65c52d24U, 0x119b4be9U, 0x155a565eU, 0x18197087U, + 0x1cd86d30U, 0x029f3d35U, 0x065e2082U, 0x0b1d065bU, 0x0fdc1becU, + 0x3793a651U, 0x3352bbe6U, 0x3e119d3fU, 0x3ad08088U, 0x2497d08dU, + 0x2056cd3aU, 0x2d15ebe3U, 0x29d4f654U, 0xc5a92679U, 0xc1683bceU, + 0xcc2b1d17U, 0xc8ea00a0U, 0xd6ad50a5U, 0xd26c4d12U, 0xdf2f6bcbU, + 0xdbee767cU, 0xe3a1cbc1U, 0xe760d676U, 0xea23f0afU, 0xeee2ed18U, + 0xf0a5bd1dU, 0xf464a0aaU, 0xf9278673U, 0xfde69bc4U, 0x89b8fd09U, + 0x8d79e0beU, 0x803ac667U, 0x84fbdbd0U, 0x9abc8bd5U, 0x9e7d9662U, + 0x933eb0bbU, 0x97ffad0cU, 0xafb010b1U, 0xab710d06U, 0xa6322bdfU, + 0xa2f33668U, 0xbcb4666dU, 0xb8757bdaU, 0xb5365d03U, 0xb1f740b4U +}; + +#define UPDATE(crc, byte) do \ + (crc) = ((crc) << 8) ^ crc32tab[((crc) >> 24) ^ (byte)]; \ +while(0) + +u_int32_t +crc32(unsigned char *buf, size_t len) +{ + u_int32_t crc = 0; + size_t i; + + for (i = 0; i < len; i++) + UPDATE(crc, buf[i]); + + while (len != 0) { + UPDATE(crc, len & 0xff); + len >>= 8; + } + + return ~crc; +} diff --git a/math/crc.h b/math/crc.h new file mode 100644 index 0000000..9738c47 --- /dev/null +++ b/math/crc.h @@ -0,0 +1,26 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _CRC_H_ +#define _CRC_H_ + +__BEGIN_DECLS +u_int32_t crc32(unsigned char *, size_t); +__END_DECLS + +#endif /* not _CRC_H_ */ diff --git a/math/math.c b/math/math.c new file mode 100644 index 0000000..0f00140 --- /dev/null +++ b/math/math.c @@ -0,0 +1,497 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if 0 +#include /* gettimeofday() */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "metadb.h" +#include "query.h" + +#define SHOWNEW 5 +enum jflag { J_HTML, J_PDF, J_MWS, J_MW, J_CODE, J_EMAIL, J_IMG, J_NONE }; +char *sname; +char *datadir = "data"; + +void pr_head(struct meta *); +void pr_foot(void); +void pr_path(struct meta *, size_t); +void pr_set(struct meta *, size_t); +void pr_opts(struct meta *); +char *pr_lang(char *); +void pr_record(struct meta *, size_t, enum sorder); +void pr_new(size_t); +int have(struct meta *, size_t, enum mtype); +__dead void jmp(struct meta *, size_t, enum jflag); +__dead void mailto(unsigned int); + +void +pr_head(struct meta *mp) +{ + puts(""); + puts(""); + printf("%s\n", mp->title); + puts(""); + puts(""); + puts(""); + + puts("
"); +#if 0 + printf("

%s

\n", sname, mp->id, mp->title); +#else + printf("

%s

\n", mp->title); +#endif + + printf("
\n", sname); + puts("Search: "); + puts(""); + puts("
"); + puts("
"); +} + +void +pr_foot(void) +{ + puts("
"); + puts("

Copyright © 2006 Dimitri A. Sokolyuk"); + puts("Worksheets are copyright their respective authors,"); + puts("submission implies license to publish on this web site."); + puts("This size runs as CGI on OpenBSD,"); + puts("the source code"); + puts("is MIT licensed.

"); + +#if 0 + puts("

"); +#if 0 + puts(""); + puts("\"hacker"); + + puts(""); + puts("\"Powered"); + + puts(""); + puts("\"vi"); +#endif + puts(""); + puts(""); + + puts(""); + puts(""); + + puts("

"); +#endif + + puts("
"); + puts(""); + puts(""); +} + +void +pr_path(struct meta *mp, size_t n) +{ + puts("
"); + for (; n--; ++mp) { + if (mp->id != 0) + puts(" ·"); + printf("%s", sname, mp->id, mp->title); + } + puts("
"); +} + +void +pr_set(struct meta *mp, size_t n) +{ + for (; n--; ++mp) { + if (mp->type == M_SET) { + printf("

%s\n", sname, mp->id, mp->title); + printf("(%zu)

\n", db_nelem(mp->id)); + if (*mp->abstract != '\0') + printf("
%s
\n", mp->abstract); + } + } +} + +void +pr_opts(struct meta *mp) +{ + struct { + char *str; + char *alt; + char *img; + char trg; + char *dsc; + } *op, o[] = { + { mp->html, "HTML", "htmlicon.gif", 'h', "View HTML version" }, + { mp->pdf, "PDF", "pdficon.gif", 'p', "View as PDF" }, + { mp->mws, "MWS", "mwicon.gif", 's', "Download Maple classic worksheet" }, + { mp->mw, "MW", "mwicon.gif", 'm', "Download Maple worksheet" }, + { mp->code, "CODE", "codeicon.gif", 'c', "Download Maple code" }, + { mp->email, "EMAIL", "emailicon.gif", 'e', "E-mail to a colleague" }, + { NULL, NULL, NULL, 0, NULL } + }; + + puts("

"); + for (op = o; op->str != NULL; ++op) { + if (*op->str != '\0') { + printf("", sname, mp->id, op->trg); + printf("\"%s\" ", op->alt, "images", op->img); + printf("%s
\n", op->dsc); + } + } + puts("

"); +} + +char * +pr_lang(char *lang) +{ + char l[3]; + + struct { + char *lang; + char *img; + char *name; + } *lp, language[] = { + { "en", "uk_small.png", "English" }, + { "de", "germany_small.png", "Deutsch" }, + { "fr", "france_small.png", "Francaise" }, + { "ru", "ussr_small.png", "Russian" }, + { NULL, NULL, NULL } + + }; + + l[0] = tolower(lang[0]); + l[1] = tolower(lang[1]); + l[2] = '\0'; + + for (lp = language; lp->lang != NULL; ++lp) { + if (strncmp(lang, lp->lang, 2) == 0) + break; + } + + if (lp->lang == NULL) + lp = language; + + printf("\"%s\"\n", lp->name, lp->img); + + return lp->name; +} + +void +pr_record(struct meta *mp, size_t n, enum sorder curso) +{ + int i = 0; + char *uri, *p; + + uri = getenv("REQUEST_URI"); + + /* HACK: strip all args exept the first */ + if ((p = strchr(uri, '&')) != NULL) + *p = '\0'; + + puts(""); + puts(""); + printf("\n", uri, curso == TITLEI ? 'd' : 'a'); + puts(""); + puts(""); + printf("\n", uri, curso == DATEI ? 'd' : 'a'); + printf("\n", uri, curso == AUTHORI ? 'd' : 'a'); + puts(""); + + for (; n--; ++mp) { + if (mp->type == M_RECORD) { + printf(""); + printf("\n", ctime(&mp->date)); + printf("\n", mp->author); + } + } + + puts("
TitleLanguageOptionsDate PubllishedAuthor
", (i++ & 1) == 0 ? "odd" : "even"); + printf("

%s

\n", sname, mp->id, mp->title); + if (*mp->abstract != '\0') + printf("
%s
\n", mp->abstract); + puts("
"); + pr_lang(mp->language); + puts(""); + pr_opts(mp); + puts("%s%s
"); +} + +#if 0 +void +pr_image(struct meta *mp, size_t n) +{ + puts("
"); + printf("dir); + printf("%s\" />", mp->img); + puts("
"); +} +#endif + +void +pr_new(size_t max) +{ + struct meta *mp; + size_t n; + + mp = db_find("", &n); + if (mp == NULL) + return; + + db_sort(mp, n, DATED); + + for (; n-- && max; ++mp) { + if (mp->type == M_RECORD) { + puts("

"); + printf("%s
\n", sname, mp->id, mp->title); + puts(ctime(&mp->date)); + puts("

"); + --max; + } + } +} + +int +have(struct meta *mp, size_t n, enum mtype t) +{ + while (n--) + if ((mp++)->type == t) + return 1; + return 0; +} + +__dead void +jmp(struct meta *mp, size_t n, enum jflag jf) +{ + char *p[16]; + + printf("Location: http://%s/%s/", getenv("SERVER_NAME"), datadir); + while (--n) + printf("%s/", (++mp)->dir); + + p[0] = mp->html; + p[1] = mp->pdf; + p[2] = mp->mws; + p[3] = mp->mw; + p[4] = mp->code; + p[5] = mp->email; + p[6] = mp->img; + + printf("%s\n\n", p[jf]); + + exit(0); +} + +__dead void +mailto(unsigned int id) +{ + struct meta m; + + if (db_get(&m, id) != NULL) + printf("Location: mailto:%s\n\n", m.email); + + exit(0); +} + + +int +main(int argc, char **argv) +{ + struct meta *curr, *chld, *path, *found; + size_t nchld, npath, nfound; + unsigned int id; + enum jflag jf; + enum sorder so; + char *q, *srchq, *lang; + + sname = getenv("SCRIPT_NAME"); + + id = 0; + if ((q = getquery("id")) != NULL) { + id = atoll(q); + free(q); + } + + jf = J_NONE; + if ((q = getquery("jump")) != NULL) { + switch (*q) { + case 'h': jf = J_HTML; break; + case 'p': jf = J_PDF; break; + case 's': jf = J_MWS; break; + case 'm': jf = J_MW; break; + case 'c': jf = J_CODE; break; + case 'e': jf = J_EMAIL; break; + case 'i': jf = J_IMG; break; + } + free(q); + } + + so = TITLEI; + if ((q = getquery("a")) != NULL) { + switch (*q) { + case 'a': so = AUTHORI; break; + case 'd': so = DATEI; break; + case 't': so = TITLEI; break; + } + free(q); + } else if ((q = getquery("d")) != NULL) { + switch (*q) { + case 'a': so = AUTHORD; break; + case 't': so = TITLED; break; + case 'd': so = DATED; break; + } + free(q); + } + + if (db_open(O_RDONLY) != 0) + exit(0); + + found = NULL; + srchq = NULL; + if ((q = getquery("search")) != NULL) { + srchq = decode(q); + found = db_find(srchq, &nfound); + free(q); + } + + curr = db_get(NULL, id); + chld = db_children(id, &nchld); + path = db_path(id, &npath); + + if (jf != J_NONE && path != NULL) + jmp(path, npath, jf); + /* NOTREACHED */ + + puts("Content-type: text/html; charset=iso-8859-1;\n"); + + puts(""); + puts(""); + + if (curr == NULL) { + + puts(""); +#if 0 + printf("

%s has just experienced an error

", getenv("SERVER_NAME")); + puts("

Our technical team has been notified of the issue."); + puts("Please refresh the page or use the back button to return to the site.

"); +#else + puts("

oops

"); + printf("id %u doesn't exist, try another number ;-)", id); +#endif + puts(""); + exit(0); + } + + pr_head(curr); + + if (id != 0 && path != NULL) + pr_path(path, npath); + + puts("
"); + + if (srchq != NULL) { + if (found != NULL) { + puts("

Search results for:"); + printf("%s

\n", sname, srchq, srchq); + db_sort(found, nfound, so); + if (have(found, nfound, M_SET)) { + puts("

Sections

"); + pr_set(found, nfound); + } + if (have(found, nfound, M_RECORD)) { + puts("

Content

"); + pr_record(found, nfound, so); + } + free(q); + } else { + puts("

Nothing found for:"); + printf("%s

\n", sname, srchq, srchq); + } + } else { + if (id == 0) { + puts("
"); + puts("

Recent

"); + pr_new(SHOWNEW); + puts("
"); + } + + if (chld != NULL) { + if (*curr->abstract != '\0') + printf("

%s

\n", curr->abstract); + db_sort(chld, nchld, so); + if (have(chld, nchld, M_SET)) { + printf("

%sections

", (id == 0) ? "S" : "Subs"); + pr_set(chld, nchld); + } + if (have(chld, nchld, M_RECORD)) { + puts("

Content

"); + pr_record(chld, nchld, so); + } + } else if (curr->type == M_RECORD) { + if (*curr->img != '\0') { + puts("
"); + printf("\"illustration\"", sname, curr->id); + puts("
"); + } + + puts("
"); + puts("

Options

"); + pr_opts(curr); + puts("
"); + + if (*curr->abstract != '\0') + printf("

%s

\n", curr->abstract); + + puts("

"); + printf("Author: %s
\n", curr->author); + printf("Date: %s
\n", ctime(&curr->date)); + printf("Language: "); + lang = pr_lang(curr->language); + printf("%s\n", lang); + puts("

"); + } else if (curr->type == M_SET) { + if (*curr->abstract != '\0') + printf("

%s

\n", curr->abstract); + } else { + puts("oops"); + } + + } + + puts("
"); + + pr_foot(); + + db_close(); + + return 0; +} diff --git a/math/math.css b/math/math.css new file mode 100644 index 0000000..ad6a82c --- /dev/null +++ b/math/math.css @@ -0,0 +1,161 @@ +/* $Id$ */ + +body { + padding: 0px; + margin: 0px; + color: #000000; + background: #ffffff; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 90%; +} + +.foot { + font-size: x-small; + text-align: center; + padding: 5px 20px; + clear: both; +} + +.right { + float: right; + border: 2px solid #cccccc; + padding: 0px 10px 10px 10px; + margin-left: 20px; + margin-bottom: 20px; + font-size: smaller; +} + +.image { + float: left; + margin-right: 20px; + margin-bottom: 20px; + font-size: smaller; +} + +.image img { + max-width: 200px; +} + +input { + border: 1px solid #000000; +} + + +.head { + position: relative; + background: #777777; + color: #ffffff; + border-bottom: 2px solid #cccccc; + margin: 0px; + padding: 5px 30px; +} + +.head form { + position: absolute; + margin: 20px; + padding: 0px; + right: 0px; + top: 0px; +} + +/* +.head a { + color: #ffffff; +} +*/ + + + +.path { + position: relative; + background: #eaeaea; + color: #000000; + border-bottom: 1px solid #000000; + margin: 0px; + padding: 5px 20px 5px 30px; +} + +.path a { + color: #777777; +} + + + + +/* contents */ + +.content { + margin: 0px; + margin-top: 30px; + padding: 0px 20px 50px 30px; +} + +.content h2 { + margin-top: 50px; +} + +.content h3 { + margin-top: 30px; +} + + +a { + color: #777777; +} + +a:link, a:visited, a:active { + text-decoration: none; +} + +a:hover { + text-decoration: underline; + color: #000000; +/* color: #ffa500; */ +} + +th a { + color: #ffffff; +} + +a img { + border: 0px; +} + +table { +/* + width: 100%; +*/ + border-collapse: collapse; +} + +th { + background: #777777; + color: #eaeaea; + border-bottom: 2px solid #cccccc; + padding: 5px 10px; + text-align: left; +} + +td { + vertical-align: top; + padding: 5px 10px; + border-bottom: 1px solid #cccccc; +} + +.options { + font-size: smaller; + text-align: left; + margin: 0px; +} + +tr.odd td { + background: #eaeaea; +} + +tr.even td { + background: #ffffff; +} + +p { + text-align: justify; +} diff --git a/math/math/Makefile b/math/math/Makefile new file mode 100644 index 0000000..d2a56fc --- /dev/null +++ b/math/math/Makefile @@ -0,0 +1,7 @@ +# $Id$ + +PROG= index.cgi +SRCS= math.c metadb.c query.c +NOMAN= + +.include diff --git a/math/metadb.c b/math/metadb.c new file mode 100644 index 0000000..7e50959 --- /dev/null +++ b/math/metadb.c @@ -0,0 +1,581 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "metadb.h" + +/* O_RDONLY */ +#define DB_FLAGS O_CREAT|O_RDWR +#define DB_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH + +#define P(f1,f2) printf( #f1 " = '%s'\t" #f2 " = '%s'\n", (f1), (f2)) + +DB *idx, *meta, *srch; + +struct meta *decode_meta(struct meta *, char *); +int cmptitle_i(const void *, const void *); +int cmptitle_d(const void *, const void *); +int cmpdate_i(const void *, const void *); +int cmpdate_d(const void *, const void *); +int cmpauthor_i(const void *, const void *); +int cmpauthor_d(const void *, const void *); + +int +db_open(int flags) +{ + idx = dbopen(INDEXDB, flags, DB_MODE, DB_HASH, NULL); + meta = dbopen(METADB, flags, DB_MODE, DB_HASH, NULL); + srch = dbopen(SEARCHDB, flags, DB_MODE, DB_HASH, NULL); + if (idx == NULL || meta == NULL || srch == NULL) { + db_close(); + return -1; + } + return 0; +} + +void +db_close(void) +{ + if (idx != NULL) + (idx->close)(idx); + if (meta != NULL) + (meta->close)(meta); + if (srch != NULL) + (srch->close)(srch); +} + +static int +chkid(unsigned int *p, size_t n, unsigned int id) +{ + while (n--) + if (*p++ == id) + return 1; + return 0; +} + +static int +addindex(int parent, int id) +{ + DBT k, d; + int ret, *buf; + size_t siz = 0; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + /* add new record, payload is parents id */ + k.data = &id; + k.size = sizeof(int); + d.data = &parent; + d.size = sizeof(int); + + ret = (idx->put)(idx, &k, &d, 0); + + /* go further and update parent only if id isn't root */ + if (id == 0 || ret == -1) + return ret; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + k.data = &parent; + k.size = sizeof(int); + + /* try to get perent */ + if ((ret = (idx->get)(idx, &k, &d, 0)) != 0) + return ret; + + siz = d.size + sizeof(int); + buf = malloc(siz); + assert(buf); + memset(buf, 0, siz); + + memcpy(buf, (int *)d.data, sizeof(int)); + memcpy(buf + 1, &id, sizeof(int)); + memcpy(buf + 2, (int *)d.data + 1, d.size - sizeof(int)); + + d.data = buf; + d.size = siz; + + ret = (idx->put)(idx, &k, &d, 0); + free(buf); + + return ret; +} + +#define EMPTY(s) ((s) == NULL ? "" : (s)) + +#define LENGTH(s) (strlen(EMPTY(s)) + 1) + +#define PUTSTR(d, s, b, l) do { \ + (l) = LENGTH(s); \ + memcpy((d) + (b), EMPTY(s), (l)); \ + (b) += (l); \ +} while (0) + +static char * +encode_meta(struct meta *mp, size_t *siz) +{ + char *buf; + size_t len, blen; + + *siz = sizeof(mp->type); + *siz += sizeof(mp->date); + *siz += sizeof(mp->id); + + *siz += LENGTH(mp->dir); + *siz += LENGTH(mp->title); + *siz += LENGTH(mp->abstract); + *siz += LENGTH(mp->author); + *siz += LENGTH(mp->email); + *siz += LENGTH(mp->html); + *siz += LENGTH(mp->mws); + *siz += LENGTH(mp->mw); + *siz += LENGTH(mp->pdf); + *siz += LENGTH(mp->code); + *siz += LENGTH(mp->img); + *siz += LENGTH(mp->language); + *siz += LENGTH(mp->tokens); + + buf = malloc(*siz); + assert(buf); + memset(buf, 0, *siz); + + len = sizeof(mp->type); + memcpy(buf, &mp->type, len); + blen = len; + + len = sizeof(mp->date); + memcpy(buf + blen, &mp->date, len); + blen += len; + + len = sizeof(mp->id); + memcpy(buf + blen, &mp->id, len); + blen += len; + + PUTSTR(buf, mp->dir, blen, len); + PUTSTR(buf, mp->title, blen, len); + PUTSTR(buf, mp->abstract, blen, len); + PUTSTR(buf, mp->author, blen, len); + PUTSTR(buf, mp->email, blen, len); + PUTSTR(buf, mp->html, blen, len); + PUTSTR(buf, mp->mws, blen, len); + PUTSTR(buf, mp->mw, blen, len); + PUTSTR(buf, mp->pdf, blen, len); + PUTSTR(buf, mp->code, blen, len); + PUTSTR(buf, mp->img, blen, len); + PUTSTR(buf, mp->language, blen, len); + PUTSTR(buf, mp->tokens, blen, len); + + return buf; +} + +#define GETSTR(d, s, l) do { \ + (d) = strdup((s) + (l)); \ + (l) += strlen(d) + 1; \ +} while (0) + +struct meta * +decode_meta(struct meta *mp, char *buf) +{ + size_t blen; + + mp->type = *(unsigned int *)buf; + blen = sizeof(mp->type); + mp->date = *(time_t *)(buf + blen); + blen += sizeof(mp->date); + mp->id = *(unsigned int *)(buf + blen); + blen += sizeof(mp->id); + GETSTR(mp->dir, buf, blen); + GETSTR(mp->title, buf, blen); + GETSTR(mp->abstract, buf, blen); + GETSTR(mp->author, buf, blen); + GETSTR(mp->email, buf, blen); + GETSTR(mp->html, buf, blen); + GETSTR(mp->mws, buf, blen); + GETSTR(mp->mw, buf, blen); + GETSTR(mp->pdf, buf, blen); + GETSTR(mp->code, buf, blen); + GETSTR(mp->img, buf, blen); + GETSTR(mp->language, buf, blen); + GETSTR(mp->tokens, buf, blen); + + return mp; +} + +static int +addmeta(struct meta *mp, int id) +{ + DBT k, d; + char *buf; + size_t siz; + int ret; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + mp->id = id; + buf = encode_meta(mp, &siz); + + k.data = &id; + k.size = sizeof(int); + d.data = buf; + d.size = siz; + + ret = (meta->put)(meta, &k, &d, 0); + free(buf); + + return ret; +} + +static int +addsearch(char *s, int id) +{ + DBT k, d; + int ret, *buf; + size_t siz = 0; + char *t, *p; + char sep[] = " \t\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + while ((t = strsep(&s, sep)) != NULL) { + for (p = t; *p != '\0'; p++) + *p = tolower(*p); + + k.data = t; + k.size = strlen(t) + 1; + + switch (ret = (srch->get)(srch, &k, &d, 0)) { + case -1: /* error */ + return -1; + case 0: /* found */ + siz = d.size + sizeof(int); + if (chkid(d.data, d.size / sizeof(int), id) == 1) + return 1; + break; + case 1: /* not found */ + siz = sizeof(int); + break; + } + + buf = malloc(siz); + assert(buf); + memset(buf, 0, siz); + + memcpy(buf, &id, sizeof(int)); + if (ret == 0) + memcpy(buf + 1, (int *)d.data, d.size); + + d.data = buf; + d.size = siz; + + if ((srch->put)(srch, &k, &d, 0) == -1) + return -1; + + free(buf); + } + + return 0; +} + +int +db_add(struct meta *mp, int parent, int id) +{ + addindex(parent, id); + addmeta(mp, id); + + addsearch(mp->title, id); + addsearch(mp->abstract, id); + addsearch(mp->author, id); + addsearch(mp->tokens, id); + + /* XXX */ + addsearch("", id); + + return 0; +} + +struct meta * +db_find(char *key, size_t *n) +{ + DBT k, d; + struct meta *mp; + char *p; + size_t i; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + for (p = key; *p != '\0'; p++) + *p = tolower(*p); + + k.data = key; + k.size = strlen(key) + 1; + + *n = 0; + if ((srch->get)(srch, &k, &d, 0) != 0) + return NULL; + + *n = d.size / sizeof(int); + + mp = calloc(*n, sizeof(struct meta)); + assert(mp); + + for (i = 0; i < *n; i++) + db_get(&mp[i], ((unsigned int *)d.data)[i]); + + return mp; +} + +struct meta * +db_get(struct meta *mp, unsigned int id) +{ + DBT k, d; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + k.data = &id; + k.size = sizeof(int); + + if ((meta->get)(meta, &k, &d, 0) == 0) { + if (mp == NULL) { + mp = malloc(sizeof(struct meta)); + assert(mp); + } + + return decode_meta(mp, d.data); + } + + return NULL; +} + +size_t +db_nelem(unsigned int id) +{ + DBT k, d; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + k.data = &id; + k.size = sizeof(int); + + if ((idx->get)(idx, &k, &d, 0) == 0) + return d.size / sizeof(int) - 1; + + return 0; +} + +struct meta * +db_children(unsigned int id, size_t *n) +{ + DBT k, d; + struct meta *mp; + size_t i; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + k.data = &id; + k.size = sizeof(int); + + *n = 0; + if ((idx->get)(idx, &k, &d, 0) != 0) + return NULL; + + if ((*n = d.size / sizeof(int) - 1) == 0) + return NULL; + + mp = calloc(*n, sizeof(struct meta)); + assert(mp); + + for (i = 0; i < *n; i++) + db_get(&mp[i], ((unsigned int *)d.data)[i + 1]); + + return mp; +} + +struct meta * +db_path(unsigned int id, size_t *n) +{ + DBT k, d; + struct meta *mp; + unsigned int path[32], *p, i; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + p = path; + *p = id; + + k.data = &id; + k.size = sizeof(int); + + while (*p != 0 && p - path < 32) { + if ((idx->get)(idx, &k, &d, 0) != 0) + return NULL; + id = *(unsigned int *)d.data; + *(++p) = id; + } + + *n = p - path + 1; + mp = calloc(*n, sizeof(struct meta)); + assert(mp); + + for (i = 0; i < *n; i++) { + db_get(&mp[i], *p--); + }; + + return mp; +} + +/* increasing sort order */ +int +cmptitle_i(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + return strcmp(m1->title, m2->title); +} + +/* decreasing sort order */ +int +cmptitle_d(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + return strcmp(m2->title, m1->title); +} + +/* increasing sort order */ +/* oldest first */ +int +cmpdate_i(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + if (m1->date > m2->date) + return 1; + else if (m1->date < m2->date) + return -1; + else + return 0; +} + +/* decreasing sort order */ +/* newest first */ +int +cmpdate_d(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + if (m1->date > m2->date) + return -1; + else if (m1->date < m2->date) + return 1; + else + return 0; +} + +/* increasing sort order */ +int +cmpauthor_i(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + return strcmp(m1->author, m2->author); +} + +/* decreasing sort order */ +int +cmpauthor_d(const void *p1, const void *p2) +{ + struct meta *m1, *m2; + + m1 = (struct meta *)p1; + m2 = (struct meta *)p2; + + return strcmp(m2->author, m1->author); +} + +int (*cmp[])(const void *, const void *) = { + cmptitle_i, cmptitle_d, + cmpdate_i, cmpdate_d, + cmpauthor_i, cmpauthor_d +}; + +void +db_sort(struct meta *mp, size_t n, enum sorder o) +{ + qsort(mp, n, sizeof(struct meta), cmp[o]); +} + +#if 0 +int +(*cmp(enum sorder o))(const void *, const void *) +{ + return fct[o]; +} +#endif + +void +db_wipe(void) +{ + DBT k, d; + + memset(&k, 0, sizeof(DBT)); + memset(&d, 0, sizeof(DBT)); + + while ((idx->seq)(idx, &k, &d, 0) != 0) + (idx->del)(idx, &k, 0); + + while ((meta->seq)(meta, &k, &d, 0) != 0) + (meta->del)(meta, &k, 0); + + while ((srch->seq)(srch, &k, &d, 0) != 0) + (srch->del)(srch, &k, 0); +} diff --git a/math/metadb.h b/math/metadb.h new file mode 100644 index 0000000..d00f34a --- /dev/null +++ b/math/metadb.h @@ -0,0 +1,68 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _METADB_H_ +#define _METADB_H_ + +#define INDEXDB "_index.db" +#define METADB "_meta.db" +#define SEARCHDB "_search.db" + +#define METADATA "meta.txt" +#define SECTION "section.txt" + +enum mtype { M_SET, M_RECORD }; +enum sorder { TITLEI, TITLED, DATEI, DATED, AUTHORI, AUTHORD }; + +struct meta { + enum mtype type; + time_t date; + unsigned int id; + char *dir; + char *title; + char *abstract; + char *author; + char *email; + char *html; + char *mws; + char *mw; + char *pdf; + char *code; + char *img; + char *language; + char *tokens; +}; + +__BEGIN_DECLS +struct meta *openmeta(char *); +void closemeta(struct meta *); + +int db_open(int); +void db_close(void); +void db_wipe(void); +int db_add(struct meta *, int, int); +size_t db_nelem(unsigned int); + +struct meta *db_get(struct meta *, unsigned int); +struct meta *db_children(unsigned int, size_t *); +struct meta *db_path(unsigned int, size_t *); +struct meta *db_find(char *, size_t *); +void db_sort(struct meta *, size_t, enum sorder); +__END_DECLS + +#endif /* not _METADB_H_ */ diff --git a/math/mkdb.c b/math/mkdb.c new file mode 100644 index 0000000..db07eff --- /dev/null +++ b/math/mkdb.c @@ -0,0 +1,130 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crc.h" +#include "metadb.h" + +void twiddle(void); +void walk(char **); + +void +twiddle(void) +{ + static int i; + + putchar("|/-\\"[i++ & 3]); + putchar('\b'); + fflush(stdout); +} + +void +walk(char **fname) +{ + FTS *fts; + FTSENT *ftp, *chld, *cp; + char *p, pathmeta[BUFSIZ], pathset[BUFSIZ]; + int parent, id; + struct meta *mp; + + fts = fts_open(fname, FTS_LOGICAL, NULL); + assert(fts); + + printf("Scanning: "); + + db_open(O_CREAT|O_RDWR); + +// db_wipe(); + + while ((ftp = fts_read(fts)) != NULL) { + twiddle(); + if (ftp->fts_info == FTS_D) { + p = ftp->fts_parent->fts_name; + if (ftp->fts_parent->fts_level <= 0) + parent = 0; + else + parent = crc32(p, strlen(p)); + + p = ftp->fts_name; + if (ftp->fts_level <= 0) + id = 0; + else + id = crc32(p, strlen(p)); + + snprintf(pathmeta, sizeof(pathmeta), "%s/%s", ftp->fts_accpath, METADATA); + snprintf(pathset, sizeof(pathset), "%s/%s", ftp->fts_accpath, SECTION); + + if ((mp = openmeta(pathmeta)) != NULL) { + mp->dir = strdup(p); + mp->date = ftp->fts_statp->st_ctimespec.tv_sec; + mp->type = M_RECORD; + + chld = fts_children(fts, 0); + for (cp = chld; cp != NULL; cp = cp->fts_link) { + if (cp->fts_info == FTS_F) { + p = cp->fts_name; + if (strstr(p, ".htm") != NULL) + mp->html = strdup(p); + else if (strstr(p, ".mws") != NULL) + mp->mws = strdup(p); + else if (strstr(p, ".mw") != NULL) + mp->mw = strdup(p); + else if (strstr(p, ".pdf") != NULL) + mp->pdf = strdup(p); + else if (strstr(p, ".zip") != NULL) + mp->code = strdup(p); + } + } + + + db_add(mp, parent, id); + closemeta(mp); + } else if ((mp = openmeta(pathset)) != NULL) { + mp->dir = strdup(p); + mp->date = ftp->fts_statp->st_ctimespec.tv_sec; + mp->type = M_SET; + db_add(mp, parent, id); + } + } + } + + db_close(); + fts_close(fts); + + printf("done\n"); +} + +int +main(int argc, char **argv) +{ + + if (argc != 2) + return -1; + + walk(&argv[1]); + + return 0; +} diff --git a/math/mkdb/Makefile b/math/mkdb/Makefile new file mode 100644 index 0000000..043647a --- /dev/null +++ b/math/mkdb/Makefile @@ -0,0 +1,7 @@ +# $Id$ + +PROG= mkdb +SRCS= crc.c metadb.c mkdb.c readmeta.c +NOMAN= + +.include diff --git a/math/query.c b/math/query.c new file mode 100644 index 0000000..c275547 --- /dev/null +++ b/math/query.c @@ -0,0 +1,81 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "query.h" + +char * +decode(const char *s) +{ + char *buf, *t; + + assert(s); + buf = malloc(sizeof(char) * strlen(s) + 1); + assert(buf); + + for (t = buf; *s != '\0'; ++t, ++s) { + if (*s == '%') { + *t = *++s; + *t -= isdigit(*s) ? '0' : ((isupper(*s) ? 'A' : 'a') - 0x0a); + *t *= 0x10; + *t += *++s; + *t -= isdigit(*s) ? '0' : ((isupper(*s) ? 'A' : 'a') - 0x0a); + } else if (*s == '+') + *t = ' '; + else + *t = *s; + } + *t = '\0'; + + return buf; +} + +char * +getquery(char *var) +{ + const char *qstr; + char *buf, *s, *p; + + assert(var); + qstr = getenv("QUERY_STRING"); + if (!qstr) + return NULL; + buf = decode(qstr); + + for (s = buf; *s != '\0'; s = p + 1) { + for (p = s; *p && *p != '&'; ++p) + ; + *p = '\0'; + if (strncmp(s, var, strlen(var)) == 0) { + s = strchr(s, '=') + 1; + if (strlen(s) == 0) + break; /* XXX */ + p = strdup(s); + free(buf); + return p; + } + } + + free(buf); + return NULL; +} diff --git a/math/query.h b/math/query.h new file mode 100644 index 0000000..f5fdc52 --- /dev/null +++ b/math/query.h @@ -0,0 +1,27 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _QUERY_H_ +#define _QUERY_H_ + +__BEGIN_DECLS +char *decode(const char *); +char *getquery(char *); +__END_DECLS + +#endif /* not _QUERY_H_ */ diff --git a/math/readmeta.c b/math/readmeta.c new file mode 100644 index 0000000..33fc5f7 --- /dev/null +++ b/math/readmeta.c @@ -0,0 +1,158 @@ +/* $Id$ */ + +/* + * Copyright (c) 2006 Dimitri A. Sokolyuk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "metadb.h" + +char *freadall(char *); + +#define STRIPWS(p) do { \ + while (*(p) != '\0' && isascii(*(p)) && isblank(*(p))) \ + ++(p); \ +} while (0) + +#define INITTAB(k, v) do { \ + (k)->key = k; ((k)++)->val = (v); \ +} while (0) + +/* TODO: rewrite it all */ + +char * +freadall(char *fname) +{ + FILE *fd; + char *buf; + size_t len; + + if ((fd = fopen(fname, "r")) == NULL) + return NULL; + + fseek(fd, 0L, SEEK_END); + len = ftell(fd); + fseek(fd, 0L, SEEK_SET); + + if ((buf = calloc(len + 1, sizeof(char))) == NULL) + return NULL; + + fread(buf, sizeof(char), len, fd); + fclose(fd); + + buf[len + 1] = '\0'; + + return buf; +} + +struct meta * +openmeta(char *fname) +{ + char *buf, *p, *key, *eol; + struct meta *mp; + struct kwords { + char *key; + char **val; + } *kwp, kw[16]; + + if ((buf = freadall(fname)) == NULL) + return NULL; + + mp = malloc(sizeof(struct meta)); + assert(mp); + memset(mp, 0, sizeof(struct meta)); + + kwp = kw; + kwp->key = "title"; (kwp++)->val = &mp->title; + kwp->key = "abstract"; (kwp++)->val = &mp->abstract; + kwp->key = "author"; (kwp++)->val = &mp->author; + kwp->key = "email"; (kwp++)->val = &mp->email; + kwp->key = "image"; (kwp++)->val = &mp->img; + kwp->key = "language"; (kwp++)->val = &mp->language; + kwp->key = "tokens"; (kwp++)->val = &mp->tokens; + kwp->key = NULL; + +#if DEBUG + printf("file: %s\n", fname); +#endif + for (p = buf; p != NULL; p = eol) { + /* join lines */ + for (eol = p; (eol = strchr(eol, '\n')) != NULL;) { + ++eol; + if (isascii(*eol) && !isblank(*eol)) { + *(eol - 1) = '\0'; + break; + } + } + + /* skip commentars and empty lines */ + if (*p == '\0' || *p == '#' || (isascii(*p) && (isspace(*p)))) + continue; + + key = p; + while (*p != '\0' && isascii(*p) && !isblank(*p) && *p != ':' && *p != '=') + ++p; + *p++ = '\0'; + + /* strip whitespace */ + while (*p != '\0' && isascii(*p) && isblank(*p)) + ++p; + +#if DEBUG + printf("key: %s\tval: %s\n", key, p); +#endif + for (kwp = kw; kwp->key != NULL; kwp++) { + if (strcmp(key, kwp->key) == 0) + *kwp->val = strdup(p); + } + } + + free(buf); + + if (mp->language == NULL) + mp->language = "en"; + + return mp; +} + +void +closemeta(struct meta *mp) +{ + if (mp->title != NULL) + free(mp->title); + if (mp->abstract != NULL) + free(mp->abstract); + if (mp->author != NULL) + free(mp->author); + if (mp->email != NULL) + free(mp->email); + if (mp->html != NULL) + free(mp->html); + if (mp->mw != NULL) + free(mp->mw); + if (mp->pdf != NULL) + free(mp->pdf); + if (mp->code != NULL) + free(mp->code); + if (mp->tokens != NULL) + free(mp->tokens); + free(mp); +} -- cgit v1.2.3