/* $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_VIDEO, J_VIDEO_HQ, J_VIDEO_LQ, 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 site 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->mw, "MW", "mwicon.gif", 'm', "Download Maple worksheet" }, { mp->mws, "MWS", "mwsicon.gif", 's', "Download Maple classic worksheet" }, { mp->code, "CODE", "codeicon.gif", 'c', "Download Code" }, { mp->email, "EMAIL", "emailicon.gif", 'e', "E-mail to a colleague" }, { mp->video, "VIDEO", "videoicon.gif", 'v', "View Video" }, { mp->video_hq, "VIDEO_HQ", "videohqicon.gif", 'q', "View HQ Video" }, { mp->video_lq, "VIDEO_LQ", "videolqicon.gif", 'l', "View LQ Video" }, { NULL, NULL, NULL, 0, NULL } }; puts("

"); for (op = o; op->str != NULL; ++op) { if (*op->str != '\0') { printf("\"%s\"\n", op->alt, "images", op->img); printf("%s", sname, mp->id, op->trg, op->dsc); puts("
"); } } 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; struct author a; 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", db_getauthor(&a, mp->author) ? a.name : 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[J_HTML] = mp->html; p[J_PDF] = mp->pdf; p[J_MWS] = mp->mws; p[J_MW] = mp->mw; p[J_CODE] = mp->code; p[J_EMAIL] = mp->email; p[J_IMG] = mp->img; p[J_VIDEO] = mp->video; p[J_VIDEO_HQ] = mp->video_hq; p[J_VIDEO_LQ] = mp->video_lq; 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; struct author a; 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; case 'v': jf = J_VIDEO; break; case 'q': jf = J_VIDEO_HQ; break; case 'l': jf = J_VIDEO_LQ; 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", db_getauthor(&a, curr->author) ? a.name : 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; }