/*****************************************************************************/ /* cgi.c Due to the many ephemeral elements (logical names, system data, time) used in many documents CGIplus doesn't do that much. Basically only short-circuts the image activation. VERSION HISTORY --------------- 21-FEB-2019 MGD initial */ /*****************************************************************************/ #include "wasdoc.h" #include int cgiPlusCount; extern int dbug, isCgi, isCgiPlus; /*****************************************************************************/ /* CGI/CGIplus usage. */ void CgiDoc () { if (isCgiPlus) { for (;;) { /* block waiting for the next request */ CgiLibVar (""); cgiPlusCount++; CgiRequest (); CgiLibCgiPlusEOF (); } } else CgiRequest (); } /*****************************************************************************/ /* Process a CGI/CGIplus request. With CGI/CGIplus the path can have a trailing "fragment" that is used to inform the browser any actual #fragment may be in a different part of the document. This is used when the "piecemeal" option is enabled. */ void CgiRequest () { static char obvious [] = "~~~~~~~~~~~~~~~~~~~~~~~~~"; int error = 0, idx, insight = 0; char ch; char *aptr, *cptr, *sptr, *zptr; char pinfo [256] = "", pchunk [32] = "", ptrans [256] = "", stats [128], uri [256] = ""; time_t utime; struct wasdoc_st *docptr, *tocptr; /* WASD stream mode will stop each fflush() carriage control added */ CgiLibEnvironmentBinaryOut (); if (cptr = getenv ("WASDOC$DBUG")) if (!(dbug = atoi(cptr))) dbug = 1; if (dbug) CgiLibResponseHeader (200, "text/plain", "Script-Control: X-stream-mode\n"); CgiLibEnvironmentSetDebug (dbug); if (!(cptr = CgiLibVar ("PATH_INFO"))) exit (SS$_BUGCHECK); zptr = (sptr = pinfo) + sizeof(pinfo)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!(cptr = CgiLibVar ("PATH_TRANSLATED"))) exit (SS$_BUGCHECK); zptr = (sptr = ptrans) + sizeof(ptrans)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (!(cptr = CgiLibVar ("REQUEST_URI"))) exit (SS$_BUGCHECK); zptr = (sptr = uri) + sizeof(uri)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; /* does the URI have a trailing numeric directory element */ for (cptr = sptr; cptr > uri && *cptr != '/'; cptr--); for (sptr = cptr; sptr > uri && isdigit(*(sptr-1)); sptr--); pchunk[0] = '\0'; if (sptr < cptr && isdigit(*sptr) && *(sptr-1) == '/') { /* looks like the uri has a trailing chunk number */ cptr = aptr = sptr; zptr = (sptr = pchunk) + sizeof(pchunk)-1; while (*cptr && isdigit(*cptr) && sptr < zptr) *sptr++ = *cptr++; *sptr = *aptr = '\0'; /* path info then also needs adjustment */ for (cptr = pinfo; *cptr; cptr++); while (cptr > pinfo && *cptr != '/') cptr--; for (sptr = cptr; sptr > pinfo && isdigit(*(sptr-1)); sptr--); *sptr = '\0'; /* translated path then also needs adjustment */ for (cptr = ptrans; *cptr; cptr++); while (cptr > ptrans && *cptr != ']') cptr--; for (sptr = cptr; sptr > ptrans && isdigit(*(sptr-1)); sptr--); if (*(sptr-1) == '.') *(sptr-1) = ']'; else if (*(sptr-1) == '[') for (cptr = "[000000]"; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; } else { /* doesn't look like it */ for (cptr = ptrans; *cptr; cptr++); while (cptr > ptrans && *cptr != ']') cptr--; if (*cptr == ']') *(cptr+1) = '\0'; } if (dbug>0) dbugThis (FI_LI, "|%s|%s|%s|", pinfo, ptrans, pchunk); docptr = InitDoc (uri, pchunk, pinfo, ptrans); docptr->isDynamic = 1; wasDocStatistics (docptr, 1); /********/ /* read */ /********/ if (!docptr->dname[0]) { zptr = (sptr = docptr->dname) + sizeof(docptr->dname)-1; for (cptr = ptrans; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; } docptr->styled = 0; error = ProcessDirectory (docptr); if (error) { CgiLibResponseHeader (404, "text/html"); fprintf (stdout, "\nwasDOC: %s\n", strerror(error)); return; } if (!docptr->tlength) { CgiLibResponseHeader (404, "text/html"); fprintf (stdout, "\nwasDOC: no document found\n"); return; } /**********/ /* render */ /**********/ if (!docptr->hlength) error = renderParse (docptr); wasDocStatistics (docptr, 0); if (cgiPlusCount) sprintf (stats, "\n", cgiPlusCount, docptr->statistics); else sprintf (stats, "\n", docptr->statistics); if (!docptr->hlength) { CgiLibResponseHeader (404, "text/html"); if (error) fprintf (stdout, "\nwasDOC: %s\n", strerror(error)); else fprintf (stdout, "\nwasDOC: empty document\n"); return; } /**********/ /* output */ /**********/ if (dbug) dbugThis (FI_LI, "%s%s%s%s", obvious, obvious, obvious, obvious); if (docptr->insight && CgiLibVarNull ("FORM_HTML")) { CgiLibResponseHeader (200, "text/plain", "Script-Control: X-stream-mode\n"); if (docptr->html) error = wasDocWrite (docptr, docptr->html, docptr->hlength); if (!error) error = wasDocWrite (docptr, stats, -1); if (!error) wasDocInsightAt (docptr); } else if (docptr->insight && CgiLibVarNull ("FORM_TEXT")) { CgiLibResponseHeader (200, "text/plain", "Script-Control: X-stream-mode\n"); if (docptr->text) error = wasDocWrite (docptr, docptr->text, docptr->tlength); } else { CgiLibResponseHeader (200, "text/html", "Script-Control: X-stream-mode\n"); if (docptr->chunked > 0) error = navig8ChunkOut (docptr); else error = wasDocWrite (docptr, docptr->html, docptr->hlength); if (!error) error = wasDocWrite (docptr, stats, -1); if (!error) wasDocInsightAt (docptr); } if (error) fprintf (stdout, "\nwasDOC: %s\n", strerror(error)); FreeDoc (docptr); } /*****************************************************************************/ /* Reinitialise the rendered HTML. */ void CgiInitHTML (struct wasdoc_st *docptr) { int idx; struct wasdoc_st *tocptr; if (!docptr) return; memset (docptr->section, 0, sizeof(docptr->section)); for (idx = 0; idx < docptr->flagCount; idx++) free (docptr->flags[idx]); docptr->flagCount = 0; free (docptr->html); docptr->html = NULL; docptr->hlength = docptr->hsize = 0; } /*****************************************************************************/