00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <ctype.h>
00039 #include <unistd.h>
00040 #include <time.h>
00041
00042 #include "log.h"
00043 #include "hlrmisc.h"
00044 #include "format.h"
00045 #include "linestream.h"
00046
00047 #include "html.h"
00048
00049 static char *gCgiBuffer = NULL;
00050 static int gCgiBufferSize;
00051
00052
00053 static int hexdigit (register int c)
00054 {
00055
00056
00057
00058
00059 c &= 0x7f;
00060 if (c >= 'a' && c <= 'f')
00061 return (c - 'a' + 10);
00062 if (c >= 'A' && c <= 'F')
00063 return (c - 'A' + 10);
00064 return (c - '0');
00065 }
00066
00067
00068
00069 static char x2c (char *const x)
00070 {
00071
00072
00073
00074 return (hexdigit (x[0]) * 16) + hexdigit (x[1]) ;
00075 }
00076
00077
00078
00084 void cgiDecodeWord (Stringa a)
00085 {
00086 char *cp = string(a) - 1 ;
00087 char c;
00088 char *c2 = string(a);
00089
00090 while (c = *++cp) {
00091 switch (c) {
00092
00093 case '%':
00094 *c2++ = x2c(++cp);
00095 ++cp;
00096 if (!*cp)
00097 die ("cgiDecodeWord: % in post not followed by two characters.");
00098 break;
00099
00100 case '+':
00101 *c2++ = ' ';
00102 break;
00103
00104 default:
00105 *c2++ = c;
00106 }
00107 }
00108
00109 *c2 = '\0';
00110 stringAdjust(a) ;
00111 }
00112
00113
00114
00115 static char *g_domain = NULL ;
00116
00117
00123 void cgiDomainSet(char *domain)
00124 {
00125 strReplace(&g_domain, domain) ;
00126 }
00127
00128
00129
00140 char *cgiConstructCookie(char *name, char *value, int lifelength)
00141 {
00142
00143
00144
00145 static Stringa s = NULL ;
00146 static Stringa e = NULL ;
00147 stringCreateOnce(s, 40) ;
00148 stringCreateOnce(e, 40) ;
00149
00150 cgiEncodeWord (value,e) ;
00151
00152 stringCpy(s, name) ;
00153 stringCat(s, "=") ;
00154 stringCat(s, string(e)) ;
00155 if (lifelength != 0) {
00156
00157 char niceDate[40] ;
00158 time_t t;
00159 struct tm *tmp ;
00160 t = time(NULL) + lifelength ;
00161 tmp = localtime(&t) ;
00162 strftime(niceDate, sizeof(niceDate), "%a, %d-%b-%y 00:00:00 GMT", tmp) ;
00163 stringCat(s, "; expires=") ;
00164 stringCat(s, niceDate) ;
00165 }
00166 stringCat(s, "; path=/;") ;
00167 if (g_domain && *g_domain) {
00168 stringCat(s, " domain=") ;
00169 stringCat(s, g_domain) ;
00170 stringCat(s, ";") ;
00171 }
00172 return string(s) ;
00173 }
00174
00175
00176
00185 char *cgiReadCookie(char *name) {
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 char *cp ;
00228 char *cp1 ;
00229 static Array cookie = 0 ;
00230 static Array value = 0 ;
00231
00232 if (! getenv("HTTP_COOKIE"))
00233 return 0 ;
00234
00235 if (!cookie)
00236 cookie = stringCreate(100) ;
00237
00238 stringCpy(cookie, getenv("HTTP_COOKIE")) ;
00239
00240 if (!value)
00241 value = stringCreate(40) ;
00242
00243 stringCpy(value, name) ;
00244 stringCat(value, "=") ;
00245
00246 cp = NULL;
00247 cp1 = string(cookie) ;
00248
00249 while (cp1 = strstr(cp1, string(value))) {
00250 cp1 = cp1+strlen(name)+1 ;
00251 cp = cp1 ;
00252 }
00253
00254 if (!cp)
00255 return 0 ;
00256
00257 if (*cp == '"') {
00258 stringCpy(value, cp+1) ;
00259
00260 if ((cp = strchr(string(value), '"')))
00261 *cp = '\0' ;
00262 else
00263 die("Cannot parse cookie ]]%s[[. Trailing \" missing.", string(cookie)) ;
00264 }
00265 else {
00266 stringCpy(value, cp) ;
00267
00268 if ((cp = strchr(string(value), ';')))
00269 *cp = '\0' ;
00270 }
00271
00272 stringAdjust(value) ;
00273 cgiDecodeWord(value) ;
00274 return string(value) ;
00275 }
00276
00277
00278
00279 static FILE *gHeaderDestination = NULL ;
00280
00281
00282
00283 static void cgiLogImpl(char *format, va_list args) {
00284
00285
00286
00287
00288
00289 gHeaderDestination = stderr ;
00290 cgiHeader(NULL) ;
00291 }
00292
00293
00294
00302 void cgiInit(void)
00303 {
00304
00305
00306
00307
00308
00309
00310
00311
00312 char *server = getenv("SERVER_SOFTWARE");
00313
00314 if (server && strNCaseEqual(server, "apache", 6)) {
00315 int fd;
00316
00317 if (fflush(stderr))
00318 perror("PROBLEM: cgiInit: fflush") ;
00319 if (PLABLA_CLOSE(2) == -1)
00320 perror("PROBLEM: cgiInit: close(2)") ;
00321 fd = dup(1);
00322 if (fd == -1) {
00323 printf("PROBLEM: could not duplicate stdout\n") ;
00324 perror("PROBLEM: cgiInit: dup") ;
00325 }
00326 if (fd != 2)
00327 printf("PROBLEM: cgiInit(): could not redirect stderr (fd %d) - possibly cgiInit() several calls to cgiInit().\n", fd) ;
00328 setbuf(stderr, NULL) ;
00329 }
00330 gHeaderDestination = stdout;
00331 log_registerDie(&cgiLogImpl) ;
00332 log_registerWarn(&cgiLogImpl) ;
00333 log_registerUsage(&cgiLogImpl) ;
00334 log_registerRomsg(&cgiLogImpl) ;
00335 }
00336
00337
00338
00347 char *cgiGet2Post(void)
00348 {
00349
00350
00351
00352
00353 char *val = getenv("QUERY_STRING");
00354 if (val&&strlen(val)) {
00355 gCgiBufferSize=strlen(val);
00356 hlr_free(gCgiBuffer);
00357 gCgiBuffer = hlr_strdup(val);
00358 }
00359 return val;
00360 }
00361
00362
00363
00368 void cgiGet2PostReset(void)
00369 {
00370 hlr_free(gCgiBuffer);
00371 }
00372
00373
00374
00387 int cgiGetNextPair (int *first,Array item,Array value)
00388 {
00389
00390
00391
00392
00393 static char *bufferPtr;
00394 int mode;
00395 int c;
00396
00397 if (gCgiBuffer == NULL) {
00398 char *contentLength = getenv ("CONTENT_LENGTH");
00399 gCgiBufferSize = contentLength ? atoi (contentLength) : 0;
00400 gCgiBuffer = hlr_malloc (gCgiBufferSize);
00401 fread (gCgiBuffer,gCgiBufferSize,1,stdin);
00402 bufferPtr = gCgiBuffer;
00403 }
00404
00405 if (*first) {
00406 *first = 0;
00407 bufferPtr = gCgiBuffer;
00408 }
00409
00410 if (item == 0 || value == 0)
00411 die ("cgiGetNextPair: Array for item or value not initialized");
00412 arrayClear (item);
00413 arrayClear (value);
00414 mode = 'i';
00415 while (bufferPtr - gCgiBuffer < gCgiBufferSize) {
00416 c = *(bufferPtr++);
00417 if (c == '+') c = ' ';
00418 if (c == '=') {
00419 array (item,arrayMax (item),char) = '\0';
00420 cgiDecodeWord (item) ;
00421 mode = 'v';
00422
00423
00424 if (bufferPtr - gCgiBuffer == gCgiBufferSize) {
00425 array (value,arrayMax (value),char) = '\0';
00426 return 1;
00427 }
00428 }
00429 else if (c == '&' || bufferPtr - gCgiBuffer == gCgiBufferSize) {
00430 if (mode == 'i') {
00431
00432 return 0;
00433 }
00434 else {
00435 if (bufferPtr - gCgiBuffer == gCgiBufferSize)
00436 array (value,arrayMax (value),char) = c;
00437 array (value,arrayMax (value),char) = '\0';
00438 cgiDecodeWord (value);
00439 return 1;
00440 }
00441 }
00442 else {
00443 if (mode == 'i')
00444 array (item,arrayMax (item),char) = c;
00445 else if (mode == 'v' && c != '\r')
00446 array (value,arrayMax (value),char) = c;
00447 }
00448 }
00449
00450 return 0;
00451 }
00452
00453 static int gFirst = -1 ;
00454 static Stringa gItem = NULL ;
00455
00456
00457
00462 void cgiGetInit(void)
00463 {
00464 gFirst = 1 ;
00465 stringCreateOnce(gItem, 20) ;
00466 }
00467
00468
00469
00481 char *cgiGetNext(Stringa value)
00482 {
00483 if (gFirst == -1)
00484 die("cgiGetNext() without cgiGetInit()") ;
00485 if (cgiGetNextPair(&gFirst, gItem, value))
00486 return string(gItem) ;
00487 gFirst = -1 ;
00488 return NULL ;
00489 }
00490
00491
00492
00500 char *cgiGetByName(char *name)
00501 {
00502 int first = 1 ;
00503 static Array item = NULL ;
00504 static Array value = NULL ;
00505
00506 if (!value) {
00507 value = arrayCreate(10, char) ;
00508 item = arrayCreate(10, char) ;
00509 }
00510
00511 while (cgiGetNextPair (&first,item,value))
00512 if (strEqual(name, string(item)))
00513 return string(value) ;
00514 return NULL ;
00515 }
00516
00517
00518
00522 char *cgiGetByNameM(char *name)
00523 {
00524 char *cp = cgiGetByName(name) ;
00525 if (!cp)
00526 die("cgiGetByNameM: name %s not found", name) ;
00527 return cp ;
00528 }
00529
00530
00531
00541 int cgiGetFo(char *fieldName, Stringa value)
00542 {
00543 static int first = 1 ;
00544 static Array item = NULL ;
00545 stringCreateOnce(item, 10) ;
00546 if (cgiGetNextPair(&first, item, value)) {
00547 if (strDiffer(string(item), fieldName))
00548 die("cgiGetFo: expected to read field %s from form, but found %s.",
00549 fieldName, string(item)) ;
00550 return 1 ;
00551 }
00552 stringClear(value) ;
00553 return 0 ;
00554 }
00555
00556
00557
00561 void cgiGetF(char *fieldName, Stringa value)
00562 {
00563 if (! cgiGetFo(fieldName, value))
00564 die("cgiGetF: expected field %s not found", fieldName) ;
00565 }
00566
00567
00568
00575 void cgiEncodeWord (char *s, Stringa a)
00576 {
00577 char *cp = s - 1 ;
00578 unsigned char c ;
00579 char hex[3] ;
00580
00581 if (!a)
00582 die ("cgiEncode") ;
00583 arrayClear(a) ;
00584 while (c = *++cp) {
00585 if ( !isalnum(c) && c != '_' && c != '-' && c != '.' && c != ':') {
00586 sprintf(hex, "%02X", c) ;
00587 array(a, arrayMax(a), char) = '%' ;
00588 array(a, arrayMax(a), char) = hex[0] ;
00589 array(a, arrayMax(a), char) = hex[1] ;
00590 }
00591 else
00592 array(a, arrayMax(a), char) = c ;
00593 }
00594 array(a, arrayMax(a), char) = '\0' ;
00595 }
00596
00597
00598
00599
00600
00601
00602 static Stringa cgiurl = NULL ;
00603 static int cgiHasParams ;
00604 static Stringa cgiword = NULL ;
00605
00606
00607
00616 void cgiURLCreate (char *host,int port,char *program)
00617 {
00618 char portStr[20];
00619 stringCreateOnce(cgiurl, 50) ;
00620 stringCreateOnce(cgiword, 50) ;
00621 if (!host)
00622 die("cgiURLCreate: NULL host") ;
00623 stringCpy (cgiurl,"http://");
00624 stringCat (cgiurl,host);
00625 if (port) {
00626 stringCat (cgiurl,":");
00627 sprintf (portStr,"%d", port);
00628 stringCat (cgiurl,portStr);
00629 }
00630 if (program[0] != '/')
00631 stringCat (cgiurl,"/");
00632 stringCat (cgiurl, program);
00633 cgiHasParams = 0 ;
00634 }
00635
00636
00637
00646 void cgiURLCreate2(char *cgiServerUrl, char *program)
00647 {
00648
00649 stringCreateOnce(cgiurl, 50) ;
00650 stringCreateOnce(cgiword, 50) ;
00651 stringCpy(cgiurl, cgiServerUrl) ;
00652 if (program) {
00653 stringCat(cgiurl, "/") ;
00654 stringCat(cgiurl, program) ;
00655 }
00656 cgiHasParams = 0 ;
00657 }
00658
00659
00660
00667 void cgiURLAdd(char *param)
00668 {
00669 if (!cgiurl)
00670 die ("cgiURLAdd without cgiURLCreate") ;
00671 stringCat (cgiurl,cgiHasParams ? "+" : "?") ;
00672 cgiHasParams = 1 ;
00673 cgiEncodeWord (param, cgiword) ;
00674 stringCat (cgiurl,string (cgiword)) ;
00675 }
00676
00677
00678
00686 void cgiURLAddNV(char *name,char *value) {
00687
00688 if (!cgiurl)
00689 die ("cgiURLAddNV without cgiURLCreate") ;
00690 stringCat (cgiurl,cgiHasParams ? "&" : "?") ;
00691 cgiHasParams = 1 ;
00692 cgiEncodeWord (name, cgiword) ;
00693 stringCat (cgiurl,string (cgiword)) ;
00694 if (value){
00695 stringCat (cgiurl,"=");
00696 cgiEncodeWord (value, cgiword) ;
00697 stringCat (cgiurl,string (cgiword)) ;
00698 }
00699 }
00700
00701
00702
00709 void cgiURLAddInt(int param)
00710 {
00711 char s[21] ;
00712 hlr_itoa(s, param) ;
00713 cgiURLAdd(s) ;
00714 }
00715
00716
00717
00726 char *cgiURLGet(void)
00727 {
00728 return string(cgiurl);
00729 }
00730
00731
00732
00733
00734
00735
00736
00740 int cgiIsCGI(void)
00741 {
00742 return ((getenv("HTTP_HOST") != NULL) || (getenv("HTTP_USER_AGENT") != NULL)) ;
00743 }
00744
00745
00746 static int gHeaderPrinted = 0 ;
00747 static int gHeaderExpires = -1 ;
00748 static Stringa gHeaderRedirUrl = NULL ;
00749 static Stringa gHeaderCharSet = NULL ;
00750
00751
00752
00753
00764 void cgiExpiresSet(int seconds_valid)
00765 {
00766 if (seconds_valid < -1)
00767 die("cgiExpiresSet: %d", seconds_valid) ;
00768 if (gHeaderPrinted)
00769 die("cgiExpiresSet: called after cgiHeader()") ;
00770 gHeaderExpires = seconds_valid ;
00771 }
00772
00773
00774
00779 void cgiRedirSet(char *url)
00780 {
00781 stringCreateOnce(gHeaderRedirUrl, 50) ;
00782 stringCpy(gHeaderRedirUrl, url) ;
00783 }
00784
00785
00786
00794 void cgiEncodingSet(char *charset)
00795 {
00796 stringCreateOnce(gHeaderCharSet, 15) ;
00797 if (charset && *charset)
00798 stringCpy(gHeaderCharSet,charset) ;
00799 else
00800 stringDestroy(gHeaderCharSet) ;
00801 }
00802
00803
00804
00812 void cgiHeader(char *mimeType) {
00813 char exp[70] ;
00814 static Stringa charset = NULL;
00815 stringCreateOnce(charset,25);
00816
00817 if (!cgiIsCGI())
00818 return ;
00819 if (mimeType && mimeType[0] == '\0')
00820 gHeaderPrinted = 1 ;
00821 if (gHeaderPrinted)
00822 return ;
00823 gHeaderPrinted = 1 ;
00824 if (gHeaderExpires > -1) {
00825 char date[40] ;
00826 time_t t = time(0) + ((gHeaderExpires == 0) ? -36000 : gHeaderExpires) ;
00827
00828
00829
00830
00831 struct tm *gmt = gmtime(&t);
00832 strftime(date, 39, "%a, %d %b %Y %T GMT", gmt) ;
00833 sprintf(exp, "\r\nExpires: %.40s", date) ;
00834 }
00835 else
00836 exp[0] = '\0' ;
00837
00838 if (gHeaderCharSet)
00839 stringPrintf(charset,"; charset=%s",string(gHeaderCharSet));
00840 else
00841 stringClear(charset);
00842
00843 if (!gHeaderDestination)
00844 gHeaderDestination = stderr;
00845 fprintf(gHeaderDestination, "Content-Type: %s%s%s\r\n",
00846 mimeType ? mimeType : "text/html", string(charset), exp) ;
00847 if (gHeaderRedirUrl)
00848 fprintf(gHeaderDestination, "Location: %s\r\n", string(gHeaderRedirUrl)) ;
00849 fputs("\r\n", gHeaderDestination) ;
00850
00851 fflush(gHeaderDestination) ;
00852 }
00853
00854
00855
00860 void cgiHeaderCookie(char *mimeType, char *cookieSpec)
00861 {
00862 Array s = stringCreate(40) ;
00863 stringCpy(s, mimeType ? mimeType : "text/html") ;
00864 stringCat(s, "\r\nSet-Cookie: ") ;
00865 stringCat(s, cookieSpec) ;
00866 cgiHeader(string(s)) ;
00867 arrayDestroy(s) ;
00868 }
00869
00870
00871
00875 int cgiHeaderIsPrinted(void)
00876 {
00877 return gHeaderPrinted ;
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 static char *html_host = NULL ;
00893 static char *html_program = NULL ;
00894 static char *html_option = NULL ;
00895 static int html_port = 0 ;
00896
00897
00898
00899
00900
00911 void html_URLSet(char *host, int port, char *program)
00912 {
00913 if (port < 0)
00914 die("html_URLSet") ;
00915 strReplace(&html_host, host) ;
00916 html_port = port ;
00917 strReplace(&html_program, program) ;
00918 hlr_free(html_option) ;
00919 }
00920
00921
00922
00927 void html_URLSet2(char *cgiServerUrl, char *program)
00928 {
00929 html_port = -1 ;
00930 strReplace(&html_host, cgiServerUrl) ;
00931 strReplace(&html_program, program) ;
00932 hlr_free(html_option) ;
00933 }
00934
00935
00936
00943 void html_URLOptSet(char *option)
00944 {
00945 if (!html_host)
00946 die("html_URLOptSet: call html_URLSet() first") ;
00947 strReplace(&html_option, option) ;
00948 }
00949
00950
00951
00956 char *html_clink3(char *class, char *method, char *p1, char *p2, char *p3)
00957 {
00958 if (html_port == -1)
00959 cgiURLCreate2(html_host, html_program) ;
00960 else
00961 cgiURLCreate(html_host, html_port, html_program) ;
00962 if (html_option)
00963 cgiURLAdd(html_option) ;
00964 cgiURLAdd(class) ;
00965 cgiURLAdd(method) ;
00966 if (p1)
00967 cgiURLAdd(p1) ;
00968 if (p2)
00969 cgiURLAdd(p2) ;
00970 if (p3)
00971 cgiURLAdd(p3) ;
00972 return cgiURLGet() ;
00973 }
00974
00975
00976
00981 void html_hlink3(char *class, char *method, char *label, char *p1, char *p2, char *p3)
00982 {
00983 printf("<a href=\"%s\">%s</a>", html_clink3(class, method, p1, p2, p3), label) ;
00984 }
00985
00986
00987
01010 void html_encode(char *inText, Array outText, int withExceptions)
01011 {
01012 char *cp = inText ;
01013 int i = 0;
01014 int j = 0;
01015 int inAnchorExcep = 0;
01016 int doReplace = 0;
01017 int step = 1;
01018
01019 static struct {
01020 char orgChar;
01021 char *encoded;
01022 } et[] = {
01023 { '<', "<"},
01024 { '>', ">"},
01025 { '&', "&"},
01026 { '"', """},
01027 { '\0', NULL }
01028 } ;
01029
01030 static struct {
01031 char *text ;
01032 int len ;
01033 } exceptions[] = {
01034 { "<A HREF", 7 },
01035 { "</A>", 4 },
01036 { "<EM>", 4 },
01037 { "</EM>", 5 },
01038 { "<B>", 3 },
01039 { "</B>", 4 },
01040 { NULL, 0 }
01041 } ;
01042
01043 if (!inText || !outText)
01044 die("html_encode: null input") ;
01045
01046 if (withExceptions && strNCaseEqual(inText, "<html>", 6)) {
01047 stringCpy(outText, inText) ;
01048 return ;
01049 }
01050
01051 stringClear(outText);
01052
01053 while (*cp) {
01054 doReplace = 0;
01055 step = 1;
01056
01057 for (i = 0; et[i].orgChar; i ++ ) {
01058
01059 if (*cp == et[i].orgChar) {
01060
01061 if (withExceptions) {
01062 for( j = 0; exceptions[j].text; j ++ ) {
01063 if (strNCaseEqual (cp, exceptions[j].text, exceptions[j].len)) {
01064 if (j == 0)
01065 inAnchorExcep = 1;
01066 step = exceptions[j].len ;
01067 break;
01068 }
01069 }
01070
01071 if (!exceptions[j].text)
01072 if (!inAnchorExcep)
01073 doReplace = 1 ;
01074
01075 if (inAnchorExcep && *cp == '>')
01076 inAnchorExcep = 0 ;
01077 }
01078 else
01079 doReplace = 1 ;
01080
01081 break;
01082 }
01083 }
01084
01085 if (doReplace)
01086 stringCat(outText, et[i].encoded) ;
01087 else
01088 stringNCat(outText, cp, step) ;
01089
01090 cp += step ;
01091 }
01092 }
01093
01094
01095
01100 char *html_encodeS(char *s)
01101 {
01102 static Stringa b = NULL ;
01103 stringCreateOnce(b, 100) ;
01104 html_encode(s, b, 0) ;
01105 return string(b) ;
01106 }
01107
01108
01109
01110 static int gUniqueInt = 0 ;
01111
01112
01113
01123 int html_uniqueIntGet(void)
01124 {
01125 if (!gUniqueInt)
01126 gUniqueInt = time(NULL) ;
01127 return gUniqueInt ;
01128 }
01129
01130
01131
01158 char *html_tab2table(char *tab, int firstLineIsHeader, int borderWidth, int withMarkup)
01159 {
01160 static Stringa html = NULL;
01161 LineStream ls;
01162 char *line;
01163 char hd = firstLineIsHeader ? 'H' : 'D' ;
01164 WordIter wi;
01165 char *word;
01166 char *endOfMarkup;
01167 char *value ;
01168
01169 stringCreateClear (html,1000);
01170 ls = ls_createFromBuffer (tab);
01171 stringAppendf (html,"<TABLE BORDER=%d>\n",borderWidth);
01172 while (line = ls_nextLine (ls)) {
01173 if (line[0] == '\0')
01174 continue;
01175 stringCat(html,"<TR>");
01176
01177 wi = wordFldIterCreate (line,"\t");
01178 while (word = wordNext (wi))
01179 if (withMarkup && *word=='\\' && (endOfMarkup=strchr(word+1,'\\')) ) {
01180 *endOfMarkup='\0';
01181 value = endOfMarkup[1] ? endOfMarkup+1 : " " ;
01182 stringAppendf (html,"<T%c %s>%s</T%c>",
01183 hd,word+1,value,hd);
01184 }
01185 else {
01186 value = word[0] ? word : " " ;
01187 stringAppendf (html,"<T%c>%s</T%c>",
01188 hd,value,hd);
01189 }
01190
01191 wordIterDestroy (wi);
01192 stringCat(html,"</TR>\n");
01193 hd = 'D' ;
01194 }
01195 ls_destroy (ls);
01196 stringCat (html,"</TABLE>\n");
01197 return string (html);
01198 }
01199
01200
01201
01231 char *html_text2tables (char *tab,int firstLineIsHeader,int borderWidth, int withMarkup)
01232 {
01233 static Stringa html = NULL;
01234 static Stringa tabbuf = NULL;
01235 LineStream ls;
01236 char *line;
01237
01238 stringCreateClear (html,1000);
01239 stringCreateClear (tabbuf, 1000);
01240 ls = ls_createFromBuffer (tab);
01241 while (line = ls_nextLine (ls)) {
01242 if (line[0] == '\0')
01243 continue;
01244 if (!strchr(line,'\t')) {
01245 if (stringLen(tabbuf)) {
01246 stringCat(html, html_tab2table(string(tabbuf), firstLineIsHeader, borderWidth, withMarkup)) ;
01247 stringClear(tabbuf) ;
01248 }
01249 stringCat(html, line) ;
01250 stringCat(html, "<br>\n") ;
01251 continue;
01252 }
01253
01254 stringCat(tabbuf, line) ;
01255 stringCat(tabbuf, "\n") ;
01256 }
01257 ls_destroy (ls);
01258 if (stringLen(tabbuf))
01259 stringCat(html, html_tab2table(string(tabbuf), firstLineIsHeader, borderWidth, withMarkup)) ;
01260 return string (html);
01261 }
01262
01263 static FILE *gAppletTagOutFileP = NULL ;
01264 static Texta gParamNames = NULL;
01265 static Texta gParamValues = NULL;
01266 static Stringa gEmbedTag = NULL;
01267
01268
01269
01282 void html_appletTagOpen(FILE *fp, char *jarFileUrls, char *appletClass, int width, int height)
01283 {
01284 gAppletTagOutFileP = fp ;
01285 fprintf(fp, "<OBJECT classid=\"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93\"\n"
01286 "WIDTH=%d HEIGHT=%d\n"
01287 "CODEBASE=\"http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0\">\n"
01288 "<PARAM NAME=\"type\" VALUE=\"application/x-java-applet;version=1.3\">\n"
01289 "<PARAM NAME=\"code\" VALUE=\"%s\">\n"
01290 "<PARAM NAME=\"archive\" VALUE=\"%s\">\n",
01291 width, height, appletClass, jarFileUrls) ;
01292 if (!gParamNames)
01293 gParamNames = textCreate (10);
01294 else
01295 textClear (gParamNames);
01296 if (!gParamValues)
01297 gParamValues = textCreate (10);
01298 else
01299 textClear (gParamValues);
01300 stringCreateClear (gEmbedTag,100);
01301 stringCat (gEmbedTag,"<COMMENT>\n");
01302 stringAppendf (gEmbedTag,"<EMBED type=\"application/x-java-applet;version=1.3\" width=%d height=%d\n",
01303 width,height);
01304 stringCat (gEmbedTag,"pluginspage=\"http://java.sun.com/products/plugin/1.3/plugin-install.html\"\n");
01305 stringCat (gEmbedTag,"code=\"");
01306 stringCat (gEmbedTag,appletClass);
01307 stringCat (gEmbedTag,"\"\narchive=\"");
01308 stringCat (gEmbedTag,jarFileUrls);
01309 stringCat (gEmbedTag,"\"\n");
01310 }
01311
01312
01313
01321 void html_appletParam(char *name, char *value)
01322 {
01323 if (strchr(name, '"') || (value && strchr(value, '"')))
01324 die("html_appletParam: \" found.") ;
01325 textAdd (gParamNames,name);
01326 if (value)
01327 textAdd (gParamValues,value);
01328 else
01329 textAdd (gParamValues,"");
01330 }
01331
01332
01333
01338 void html_appletTagClose(void)
01339 {
01340 int i;
01341
01342 for (i=0;i<arrayMax (gParamNames);i++)
01343 fprintf(gAppletTagOutFileP,"<PARAM NAME=\"%s\" VALUE=\"%s\">\n",
01344 arru (gParamNames,i,char *),arru (gParamValues,i,char *));
01345 fprintf (gAppletTagOutFileP,"%s",string (gEmbedTag));
01346 for (i=0;i<arrayMax (gParamNames);i++)
01347 fprintf(gAppletTagOutFileP,"%s=\"%s\"\n",
01348 arru (gParamNames,i,char *),arru (gParamValues,i,char *));
01349 fprintf (gAppletTagOutFileP,"<NOEMBED>\n</COMMENT>\n");
01350 fprintf(gAppletTagOutFileP, "<B><FONT COLOR=red>Sorry, cannot start Java applet. Possible reasons: "
01351 "You are neither using MS-InternetExplorer nor Netscape (Mozilla) or your browser does not support "
01352 "Java or Java has been disabled (check your browser settings)</FONT></B>\n");
01353 fprintf (gAppletTagOutFileP,"</NOEMBED></EMBED></OBJECT>\n");
01354 }
01355
01356
01357
01358
01359
01360
01361
01362 static FILE *gFp;
01363 static Texta gJars = NULL;
01364 static Texta gArgs = NULL;
01365 static char *gMainClass = NULL;
01366
01367
01368
01380 void html_webstartOpen (FILE *fp,char *codebase,char *title,char *homepage,
01381 char *description,char *icon,int allPermissions,
01382 char *heap,char *mainClass)
01383 {
01384 gFp = fp;
01385 fprintf (fp,"<jnlp spec='1.0+' codebase='%s'>\n",codebase);
01386 fprintf (fp," <information>\n");
01387 if (!title)
01388 die ("html_webstartOpen: a title is required");
01389 fprintf (fp," <title>%s</title>\n",title);
01390 fprintf (fp," <vendor>Bioinformatics Basel</vendor>\n");
01391 if (homepage)
01392 fprintf (fp," <homepage href='%s'/>\n",homepage);
01393 if (icon)
01394 fprintf (fp," <icon href='%s'/>\n",icon);
01395 if (description)
01396 fprintf (fp," <description>%s</description>\n",description);
01397 fprintf (fp," </information>\n");
01398 if (allPermissions) {
01399 fprintf (fp," <security>\n");
01400 fprintf (fp," <all-permissions/>\n");
01401 fprintf (fp," </security>\n");
01402 }
01403 fprintf (fp," <resources>\n");
01404 if (heap)
01405 fprintf (fp," <j2se version='1.4.+' max-heap-size='%s'/>\n",
01406 heap);
01407 else
01408 fprintf (fp," <j2se version='1.4.+'/>\n");
01409 gMainClass = hlr_strdup (mainClass);
01410 if (!gJars)
01411 gJars = textCreate (5);
01412 else
01413 textClear (gJars);
01414 if (!gArgs)
01415 gArgs = textCreate (5);
01416 else
01417 textClear (gArgs);
01418 }
01419
01420
01421
01427 void html_webstartAddJar (char *jar)
01428 {
01429 textAdd (gJars,jar);
01430 }
01431
01432
01433
01439 void html_webstartAddArg (char *arg)
01440 {
01441 static Stringa enc = NULL;
01442
01443 stringCreateOnce (enc,20);
01444 html_encode (arg,enc,0);
01445 textAdd (gArgs,string (enc));
01446 }
01447
01448
01449
01453 void html_webstartClose (void)
01454 {
01455 int i;
01456
01457 for (i=0;i<arrayMax (gJars);i++)
01458 fprintf (gFp," <jar href='%s'/>\n",arru (gJars,i,char *));
01459 fprintf (gFp," </resources>\n");
01460 fprintf (gFp," <application-desc main-class='%s'>\n",gMainClass);
01461 hlr_free (gMainClass);
01462 for (i=0;i<arrayMax (gArgs);i++)
01463 fprintf (gFp," <argument>%s</argument>\n",arru (gArgs,i,char *));
01464 fprintf (gFp," </application-desc>\n");
01465 fprintf (gFp,"</jnlp>\n");
01466 if (gFp != stdout)
01467 fclose (gFp);
01468 }
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485 static int gMpUsed = 0;
01486 static int gMpBufferSize = 0;
01487 static char *gMpBuffer = NULL;
01488 static char gMpDelimiter[] = { 0x0d, 0x0a };
01489 static int gMpBoundarySize = 0;
01490 static char *gMpBoundary = NULL;
01491 static char *gMpReadPos = NULL;
01492
01493
01494 static int cgiIsMpInitialized(void) {
01495
01496
01497
01498
01499 return gMpBufferSize && gMpBuffer && gMpBoundarySize && gMpBoundary;
01500 }
01501
01502
01503 static char *memmem(char *s1, int sz1, char *s2, int sz2)
01504 {
01505
01506
01507
01508
01509 char *result = NULL;
01510 char *cp = s1;
01511 int sz = sz1 - sz2;
01512
01513 while (cp - s1 <= sz) {
01514 if (!memcmp(cp, s2, sz2)) {
01515 result = cp;
01516 break;
01517 }
01518
01519 cp ++;
01520 }
01521
01522 return result;
01523 }
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01559 void cgiMpInit(void)
01560 {
01561 char *contentType = getenv("CONTENT_TYPE");
01562 char *delimiterPos = ILLADR;
01563
01564 if (cgiIsMpInitialized())
01565 die("cgiMpInit(): illegal use - already initialized");
01566
01567 if (gMpUsed)
01568 die("cgiMpInit(): illegal use - has been used before");
01569
01570 if (!contentType || strNDiffer(contentType, "multipart/form-data", 19))
01571 die("cgiMpInit(): invalid content-type: %s", s0(contentType));
01572
01573 gMpBufferSize = atoi(getenv("CONTENT_LENGTH"));
01574 gMpBuffer = hlr_malloc(gMpBufferSize);
01575
01576 if (fread(gMpBuffer, gMpBufferSize, 1, stdin) != 1)
01577 die("cgiMpInit(): input length does not match content length %d", gMpBufferSize);
01578
01579 delimiterPos = memmem(gMpBuffer, gMpBufferSize, gMpDelimiter, sizeof(gMpDelimiter));
01580
01581 if (!delimiterPos || delimiterPos == gMpBuffer)
01582 die("cgiMpInit(): invalid content format: %s", gMpBuffer);
01583
01584 gMpBoundarySize = delimiterPos - gMpBuffer;
01585 gMpBoundary = hlr_malloc(gMpBoundarySize);
01586 memcpy(gMpBoundary, gMpBuffer, gMpBoundarySize);
01587
01588 gMpUsed = 1;
01589
01590 cgiMpReset();
01591 }
01592
01593
01594
01609 int cgiMpNext(Stringa item, Array value, Stringa filename,
01610 Stringa contentType)
01611 {
01612 int result = 0;
01613 char *readPos = ILLADR;
01614 char *boundaryPos = ILLADR;
01615 char *delimiterPos = ILLADR;
01616 char *namePos = ILLADR;
01617 char *filenamePos = ILLADR;
01618 Stringa myContentType = stringCreate(32);
01619
01620 if (!cgiIsMpInitialized())
01621 die("cgiMpNext(): illegal use - not initialized");
01622
01623 stringClear(item);
01624 stringClear(value);
01625
01626 if (filename)
01627 stringClear(filename);
01628
01629 if (contentType)
01630 stringClear(contentType);
01631
01632 boundaryPos = memmem(gMpReadPos, gMpBufferSize - (gMpReadPos - gMpBuffer),
01633 gMpBoundary, gMpBoundarySize);
01634
01635 if (boundaryPos) {
01636 result = 1;
01637 readPos = gMpReadPos;
01638 gMpReadPos = boundaryPos + gMpBoundarySize + sizeof(gMpDelimiter);
01639
01640
01641 delimiterPos = memmem(readPos, boundaryPos - readPos,
01642 gMpDelimiter, sizeof(gMpDelimiter));
01643
01644 if (delimiterPos == NULL)
01645 die("cgiMpNext(): no line delimiter found until next boundary: %s", readPos);
01646
01647 if (strNDiffer(readPos, "Content-Disposition: form-data", 30))
01648 die("cgiMpNext(): invalid part format", readPos);
01649
01650 if (namePos = memmem(readPos, delimiterPos - readPos, "name=", 5))
01651 strCopySubstr(namePos, '"', '"', item);
01652 else
01653 die("cgiMpNext(): invalid part format: %s", readPos);
01654
01655 if (filename)
01656 if (filenamePos = memmem(namePos, delimiterPos - readPos, "filename=", 9))
01657 strCopySubstr(filenamePos, '"', '"', filename);
01658
01659
01660 readPos = delimiterPos + sizeof(gMpDelimiter);
01661 delimiterPos = memmem(readPos, boundaryPos - readPos,
01662 gMpDelimiter, sizeof(gMpDelimiter));
01663
01664 if (delimiterPos == NULL)
01665 die("cgiMpNext(): no line delimiter found until next boundary: %s", readPos);
01666
01667 if (strNEqual(readPos, "Content-Type: ", 14)) {
01668 strCopySubstr(readPos + 13, ' ', 0x0d, myContentType);
01669 if(strEqual(string(myContentType), "text/plain"))
01670 stringClear(myContentType);
01671 readPos = delimiterPos + sizeof(gMpDelimiter);
01672 delimiterPos = memmem(readPos, boundaryPos - readPos,
01673 gMpDelimiter, sizeof(gMpDelimiter));
01674 }
01675
01676
01677 if (delimiterPos != readPos)
01678 die("cgiMpNext(): invalid part format: %s", readPos);
01679
01680 readPos += sizeof(gMpDelimiter);
01681
01682
01683 if (isEmptyString(myContentType)) {
01684 stringNCpy(value, readPos, boundaryPos - readPos - sizeof(gMpDelimiter));
01685 stringTranslate(value, "\r", "");
01686 }
01687 else {
01688 arraySetMax(value, 0);
01689
01690 while (readPos < boundaryPos - sizeof(gMpDelimiter)) {
01691 array(value, arrayMax(value), char) = *readPos;
01692 readPos ++;
01693 }
01694 }
01695 }
01696
01697 if (contentType)
01698 stringCpy(contentType, string(myContentType));
01699
01700 stringDestroy(myContentType);
01701
01702 return result;
01703 }
01704
01705
01706
01712 void cgiMpReset(void)
01713 {
01714 if (!cgiIsMpInitialized())
01715 die("cgiMpReset(): illegal use - not initialized");
01716
01717 gMpReadPos = gMpBuffer + gMpBoundarySize + sizeof(gMpDelimiter);
01718 }
01719
01720
01721
01728 void cgiMpDeinit(void)
01729 {
01730 if (!cgiIsMpInitialized())
01731 die("cgiMpDeinit(): illegal use - not initialized");
01732
01733 gMpReadPos = NULL;
01734 gMpBoundarySize = 0;
01735 hlr_free(gMpBoundary);
01736 gMpBufferSize = 0;
01737 hlr_free(gMpBuffer);
01738 }
01739
01740
01741
01742
01743
01744
01748 void html_printGenericStyleSheet (int bodyFontSize)
01749 {
01750 puts ("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">");
01751 puts ("<style type=\"text/css\" media=\"screen\">");
01752 printf ("body {font:%dpx Verdana,Arial,Helvetica, sans-serif; color:#2F4F4F; margin:50px 50px 50px 50px;}\n",bodyFontSize);
01753 puts ("h1 {font-size:20px; font-weight:1200; color:#0E4C92;}");
01754 puts ("h2 {font-size:14px; font-weight:1000; color:#0E4C92;}");
01755 puts (".note {font-style:italic}");
01756 puts ("a {color:#0000CD; text-decoration:none;}");
01757 puts ("a:hover {color:#4B0082; text-decoration:none;}");
01758 printf ("table {border-collapse:collapse; font-size:%dpx;}\n",bodyFontSize);
01759 puts ("</style>");
01760 }