lib/htmshell.c

Go to the documentation of this file.
00001 /* htmshell - a shell to wrap around programs that generate
00002  * html files.  Write the html initial stuff (<head>, <body>, etc.)
00003  * and the final stuff too.  Also catch errors here so that
00004  * the html final stuff is written even if the program has
00005  * to abort. 
00006  *
00007  * This also includes a few routines to write commonly used
00008  * html constructs such as images, horizontal lines. etc. 
00009  *
00010  * This file is copyright 2002 Jim Kent, but license is hereby
00011  * granted for all use - public, private or commercial. */
00012 
00013 #include "common.h"
00014 #include "obscure.h"
00015 #include "cheapcgi.h"
00016 #include "htmshell.h"
00017 #include "errabort.h"
00018 #include "dnautil.h"
00019 
00020 static char const rcsid[] = "$Id: htmshell.c,v 1.32 2006/12/13 18:17:55 angie Exp $";
00021 
00022 jmp_buf htmlRecover;
00023 
00024 static bool NoEscape = FALSE;
00025 
00026 void htmlNoEscape()
00027 {
00028 NoEscape = TRUE;
00029 }
00030 
00031 void htmlDoEscape()
00032 {
00033 NoEscape = FALSE;
00034 }
00035 
00036 void htmlVaParagraph(char *line, va_list args)
00037 /* Print a line in it's own paragraph. */
00038 {
00039 fputs("<P>", stdout);
00040 vfprintf(stdout, line, args);
00041 fputs("</P>\n", stdout);
00042 }
00043 
00044 void htmlParagraph(char *line, ...)
00045 {
00046 va_list args;
00047 va_start(args, line);
00048 htmlVaParagraph(line, args);
00049 va_end(args);
00050 }
00051 
00052 void htmlVaCenterParagraph(char *line, va_list args)
00053 /* Center a line in it's own paragraph. */
00054 {
00055 fputs("<P ALIGN=\"CENTER\">", stdout);
00056 vfprintf(stdout, line, args);
00057 fputs("</P>\n", stdout);
00058 }
00059 
00060 void htmlCenterParagraph(char *line, ...)
00061 {
00062 va_list args;
00063 va_start(args, line);
00064 htmlVaCenterParagraph(line, args);
00065 va_end(args);
00066 }
00067 
00068 void htmlHorizontalLine()
00069 /* Print a horizontal line. */
00070 {
00071 htmlParagraph("<HR ALIGN=\"CENTER\">");
00072 }
00073 
00074 void htmHorizontalLine(FILE *f)
00075 /* Print a horizontal line. */
00076 {
00077 fprintf(f, "<P><HR ALIGN=\"CENTER\"></P>");
00078 }
00079 
00080 void htmlNbSpaces(int count)
00081 /* Print a number of non-breaking spaces. */
00082 {
00083 int i;
00084 for (i=0; i<count; ++i)
00085     printf("&nbsp;");
00086 }
00087 
00088 void htmTextOut(FILE *f, char *s)
00089 /* Print out string to file, if necessary replacing > with &gt; and the like */
00090 {
00091 char c;
00092 if (NoEscape)
00093     {
00094     fputs(s, f);
00095     return;
00096     }
00097 
00098 while ((c = *s++) != 0)
00099     {
00100     switch (c)
00101         {
00102         case '>':
00103             fputs("&gt;", f);
00104             break;
00105         case '<':
00106             fputs("&lt;", f);
00107             break;
00108         case '&':
00109             fputs("&amp;", f);
00110             break;
00111         case '"':
00112             fputs("&quot;", f);
00113             break;
00114         default:
00115             fputc(c, f);
00116             break;
00117         }
00118     }
00119 }
00120 
00121 void htmlTextOut(char *s)
00122 /* Print out string, if necessary replacing > with &gt; and the like */
00123 {
00124 htmTextOut(stdout, s);
00125 }
00126 
00127 char *htmlEncode(char *s)
00128 /* Return a clone of s but if necessary replacing > with &gt; and the like */
00129 {
00130 size_t len = 0;
00131 char c;
00132 char *encStr;
00133 char *p = s;
00134 /* First pass through s to determine encoded length to allocate: */
00135 /* [as a shortcut, we could simply allocate 6*length of s] */
00136 while ((c = *p++) != 0)
00137     {
00138     switch (c)
00139         {
00140         case '>':
00141         case '<':
00142             len += 4;
00143             break;
00144         case '&':
00145             len += 5;
00146             break;
00147         case '"':
00148             len += 6;
00149             break;
00150         default:
00151             len++;
00152             break;
00153         }
00154     }
00155 encStr = needMem(len+1);
00156 /* Second pass through s to encode: */
00157 len = 0;
00158 p = s;
00159 while ((c = *p++) != 0)
00160     {
00161     switch (c)
00162         {
00163         case '>':
00164             strcat(encStr+len, "&gt;");
00165             len += 4;
00166             break;
00167         case '<':
00168             strcat(encStr+len, "&lt;");
00169             len += 4;
00170             break;
00171         case '&':
00172             strcat(encStr+len, "&amp;");
00173             len += 5;
00174             break;
00175         case '"':
00176             strcat(encStr+len, "&quot;");
00177             len += 6;
00178             break;
00179         default:
00180             encStr[len++] = c;
00181             break;
00182         }
00183     }
00184 return encStr;
00185 }
00186 
00187 
00188 char *htmlWarnStartPattern()
00189 /* Return starting pattern for warning message. */
00190 {
00191 return "<!-- HGERROR-START -->\n";
00192 }
00193 
00194 char *htmlWarnEndPattern()
00195 /* Return ending pattern for warning message. */
00196 {
00197 return "<!-- HGERROR-END -->\n";
00198 }
00199 
00200 void htmlVaWarn(char *format, va_list args)
00201 /* Write an error message. */
00202 {
00203 va_list argscp;
00204 va_copy(argscp, args);
00205 
00206 htmlHorizontalLine();
00207 printf("%s", htmlWarnStartPattern());
00208 htmlVaParagraph(format,args);
00209 printf("%s", htmlWarnEndPattern());
00210 htmlHorizontalLine();
00211 
00212 /* write warning/error message to stderr so they get logged. */
00213 vfprintf(stderr, format, argscp);
00214 va_end(argscp);
00215 fputc('\n', stderr);
00216 }
00217 
00218 void htmlAbort()
00219 /* Terminate HTML file. */
00220 {
00221 longjmp(htmlRecover, -1);
00222 }
00223 
00224 void htmlMemDeath()
00225 {
00226 errAbort("Out of memory.");
00227 }
00228 
00229 static void earlyWarningHandler(char *format, va_list args)
00230 /* Write an error message so user can see it before page is really started. */
00231 {
00232 static boolean initted = FALSE;
00233 if (!initted)
00234     {
00235     htmlStart("Very Early Error");
00236     initted = TRUE;
00237     }
00238 printf("%s", htmlWarnStartPattern());
00239 htmlVaParagraph(format,args);
00240 printf("%s", htmlWarnEndPattern());
00241 }
00242 
00243 static void earlyAbortHandler()
00244 /* Exit close web page during early abort. */
00245 {
00246 printf("</BODY></HTML>");
00247 exit(0);
00248 }
00249 
00250 void htmlPushEarlyHandlers()
00251 /* Push stuff to close out web page to make sensible error
00252  * message during initialization. */
00253 {
00254 pushWarnHandler(earlyWarningHandler);
00255 pushAbortHandler(earlyAbortHandler);
00256 }
00257 
00258 
00259 static char *htmlStyle = 
00260     "<STYLE TYPE=\"text/css\">"
00261     ".hiddenText {background-color: silver}"
00262     ".normalText {background-color: white}"
00263     "</STYLE>\n";
00264 
00265 char *htmlStyleUndecoratedLink =
00266 /* Style that gets rid of underline of links. */
00267    "<STYLE TYPE=\"text/css\"> "
00268    "<!-- "
00269    "A {text-decoration: none} "
00270    "-->"
00271    "</STYLE>\n";
00272 
00273 void htmlSetStyle(char *style)
00274 /* Set document wide style. A favorite style to
00275  * use for many purposes is htmlStyleUndecoratedLink
00276  * which will remove underlines from links. 
00277  * Needs to be called before htmlStart or htmShell. */
00278 {
00279 htmlStyle = style;
00280 }
00281 
00282 static char *htmlBackground = NULL;
00283 
00284 void htmlSetBackground(char *imageFile)
00285 /* Set background - needs to be called before htmlStart
00286  * or htmShell. */
00287 {
00288 htmlBackground = imageFile;
00289 }
00290 
00291 static int htmlBgColor = 0xFFFFFF;
00292 boolean gotBgColor = FALSE;
00293 
00294 void htmlSetBgColor(int color)
00295 /* Set background color - needs to be called before htmlStart
00296  * or htmShell. */
00297 {
00298 htmlBgColor = color;
00299 gotBgColor = TRUE;
00300 }
00301 
00302 void htmlSetCookie(char* name, char* value, char* expires, char* path, char* domain, boolean isSecure)
00303 /* create a cookie with the given stats */
00304 {
00305 char* encoded_name;
00306 char* encoded_value;
00307 char* encoded_path = NULL;
00308 
00309 encoded_name = cgiEncode(name);
00310 encoded_value = cgiEncode(value);
00311 if(path != NULL)
00312         encoded_path = cgiEncode(path);
00313 
00314 printf("Set-Cookie: %s=%s; ", encoded_name, encoded_value);
00315 
00316 if(expires != NULL)
00317     printf("expires=%s; ", expires);
00318 
00319 if(path != NULL)
00320     printf("path=%s; ", encoded_path);
00321 
00322 if(domain != NULL)
00323     printf("domain=%s; ", domain);
00324 
00325 if(isSecure == TRUE)
00326     printf("secure");
00327 
00328 printf("\n");
00329 }
00330 
00331 void _htmStart(FILE *f, char *title)
00332 /* Write out bits of header that both stand-alone .htmls
00333  * and CGI returned .htmls need. */
00334 {
00335 fputs("<HTML>", f);
00336 fprintf(f,"<HEAD>\n<TITLE>%s</TITLE>\n", title);
00337 fprintf(f, "\t<META http-equiv=\"Content-Script-Type\" content=\"text/javascript\">\n");
00338 if (htmlStyle != NULL)
00339     fputs(htmlStyle, f);
00340 fputs("</HEAD>\n\n",f);
00341 fputs("<BODY",f);
00342 if (htmlBackground != NULL )
00343     fprintf(f, " BACKGROUND=\"%s\"", htmlBackground);
00344 if (gotBgColor)
00345     fprintf(f, " BGCOLOR=\"%X\"", htmlBgColor);
00346 fputs(">\n",f);
00347 }
00348 
00349 void htmlStart(char *title)
00350 /* Write the start of an html from CGI */
00351 {
00352 puts("Content-Type:text/html");
00353 puts("\n");
00354 
00355 puts("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">");
00356 _htmStart(stdout, title);
00357 }
00358 
00359 void htmStart(FILE *f, char *title)
00360 /* Write the start of a stand alone .html file. */
00361 {
00362 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n", f);
00363 _htmStart(f, title);
00364 }
00365 
00366 /* Write the end of an html file */
00367 void htmEnd(FILE *f)
00368 {
00369 fputs("\n</BODY>\n</HTML>\n", f);
00370 }
00371 
00372 /* Write the end of a stand-alone html file */
00373 void htmlEnd()
00374 {
00375 htmEnd(stdout);
00376 }
00377 
00378 void htmlEchoInput()
00379 {
00380 }
00381 
00382 void htmlBadVar(char *varName)
00383 {
00384 cgiBadVar(varName);
00385 }
00386 
00387 /* Display centered image file. */
00388 void htmlImage(char *fileName, int width, int height)
00389 {
00390 printf("<P ALIGN=\"CENTER\"><IMG SRC=\"%s\" WIDTH=\"%d\" HEIGHT=\"%d\" ALIGN=\"BOTTOM\" BORDER=\"0\"></P>", fileName, width, height);
00391 }
00392 
00393 void htmErrOnlyShell(void (*doMiddle)())
00394 /* Wrap error recovery around call to doMiddle. */
00395 {
00396 int status;
00397 
00398 /* Set up error recovery. */
00399 status = setjmp(htmlRecover);
00400 
00401 /* Do your main thing. */
00402 if (status == 0)
00403     {
00404     doMiddle();
00405     }
00406 }
00407 
00408 void htmEmptyShell(void (*doMiddle)(), char *method)
00409 /* Wrap error recovery and and input processing around call to doMiddle. */
00410 {
00411 int status;
00412 
00413 /* Set up error recovery (for out of memory and the like)
00414  * so that we finish web page regardless of problems. */
00415 pushAbortHandler(htmlAbort);
00416 pushWarnHandler(htmlVaWarn);
00417 status = setjmp(htmlRecover);
00418 
00419 /* Do your main thing. */
00420 if (status == 0)
00421     {
00422     doMiddle();
00423     }
00424 
00425 popWarnHandler();
00426 popAbortHandler();
00427 }
00428 
00429 
00430 /* Wrap an html file around the passed in function.
00431  * The passed in function is already in the body. It
00432  * should just make paragraphs and return. 
00433  */
00434 void htmShell(char *title, void (*doMiddle)(), char *method)
00435 {
00436 /* Preamble. */
00437 dnaUtilOpen();
00438 htmlStart(title);
00439 
00440 /* Call wrapper for error handling. */
00441 htmEmptyShell(doMiddle, method);
00442 
00443 /* Post-script. */
00444 htmlEnd();
00445 }
00446 
00447 /* Wrap an html file around the passed in function.
00448  * The passed in function is already in the body. It
00449  * should just make paragraphs and return. 
00450  * Method should be "query" or "get" or "post".
00451 param title - The HTML page title
00452 param head - The head text: can be a refresh directive or javascript
00453 param method - The function pointer to execute in the middle
00454 param method - The browser request method to use
00455  */
00456 void htmShellWithHead( char *title, char *head, void (*doMiddle)(), char *method)
00457 {
00458 /* Preamble. */
00459 dnaUtilOpen();
00460 
00461 puts("Content-Type:text/html");
00462 puts("\n");
00463 
00464 puts("<HTML>");
00465 printf("<HEAD>%s<TITLE>%s</TITLE>\n</HEAD>\n\n", head, title);
00466 if (htmlBackground == NULL)
00467     puts("<BODY>\n");
00468 else
00469     printf("<BODY BACKGROUND=\"%s\">\n", htmlBackground);
00470 
00471 /* Call wrapper for error handling. */
00472 htmEmptyShell(doMiddle, method);
00473 
00474 /* Post-script. */
00475 htmlEnd();
00476 }
00477 
00478 /* Include an HTML file in a CGI */
00479 void htmlIncludeFile(char *path)
00480 {
00481 char *str = NULL;
00482 size_t len = 0;
00483 
00484 if (path == NULL)
00485     errAbort("Program error: including null file");
00486 if (!fileExists(path))
00487    errAbort("Missing file %s", path); 
00488 readInGulp(path, &str, &len);
00489 
00490 if (len <= 0)
00491     errAbort("Error reading included file: %s", path);
00492 
00493 puts(str);
00494 freeMem(str);
00495 }
00496 
00497 /* Include an HTML file in a CGI.
00498  *   The file path is relative to the web server document root */
00499 void htmlIncludeWebFile(char *file)
00500 {
00501 char path[256];
00502 char *docRoot = "/usr/local/apache/htdocs";
00503 
00504 safef(path, sizeof path, "%s/%s", docRoot, file);
00505 htmlIncludeFile(path);
00506 }
00507 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2