[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456]
/* * This module is called by the webbook main routine sees a path_info * string ending in slash, implying that the the atarget is a shelf. * The main routine deletes the trailing slash and passes the path as an * argument to webbook_shelf(). This string is assumed to be the name of * the bookshelf file to read (default decw$book:library.decw$bookshelf). * Succeeding elements are used to hold the history of which shelves were * travered to get to the current shelf. * * Conditional compilation symbols: * NOCGILIB * * Revised: 29-JUN-1996 Incorporate bug fixes supplied by Jose Baars, * baarsj@abnamro.nl. * Revsied: 12-JUL-1999 Update for ODL/BKB. * */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include "cgilib.h" #define SHELF_ICON "<IMG SRC=\"%s/shelf.xbm\">" #define BOOK_ICON "<IMG SRC=\"%s/book.xbm\">" #define HTML_ICON "<IMG SRC=\"%s/text.gif\">" #define DEFAULT_ICON_DIR "/demo" static char *icon_dir; struct shelf_rec { struct shelf_rec *next; char *type; /* first element. */ char *fname; char *desc; int is_odl; /* true if newer ODL format */ }; typedef struct shelf_rec *shelf_recp; static shelf_recp get_shelf_rec ( FILE *sf, shelf_recp prev ); static char *escape_string ( char * ); static char *entify_string ( char * ); static char *apply_default ( char *fname, char *defname, char *out ); static int send_http_header ( char *stsline, char *content ); int webbook_shelf ( char *path, char *software_version ) { char *title, *script_name, *elem[20]; int status, i, j, lvl; FILE *sf; struct shelf_rec *rec, first_rec; char *default_library; char title_spec[256]; char shelf_spec[256]; char dna_spec[260]; char shelf_history[2048]; char icon_image[300]; /* * Parse the path elements. */ strncpy ( shelf_history, path, sizeof(shelf_history)-1 ); path = shelf_history; path[sizeof(shelf_history)-1] = '\0'; if ( *path == '/' ) path++; elem[0] = path; for ( j = i = 0; path[i]; i++ ) if ( path[i] == '/' ) { path[i] = '\0'; j++; elem[j] = &path[i+1]; if ( j >= 19 ) break; } /* * Determine approiate default name for open based upon existence * of odlibrary logical. */ default_library = getenv("odlibrary"); if (!default_library) default_library = "decw$book:library.decw$bookshelf"; else if (strlen(default_library) > sizeof(dna_spec)-5 ) default_library = "library.odl"; sprintf ( dna_spec, "dna=%s", default_library ); /* * Attempt to open the shelf file and parse. */ first_rec.next = (shelf_recp) 0; first_rec.type = ""; rec = &first_rec; title = path; #ifdef VERBOSE printf("<!-- path: '%s', shelf file (elem[%d]): '%s'-->\n", path, j, elem[j] ); #endif sf = fopen ( elem[j], "r", dna_spec, "mbc=64" ); if ( sf ) { while ( rec = get_shelf_rec ( sf, rec ) ) { if ( 0 == strcmp ( rec->type, "TITLE" ) ) { title = rec->desc; if ( rec->is_odl ) { if ( (strlen(rec->fname)+strlen(rec->desc)+2) < 256) { sprintf(title_spec, "%s %s", rec->fname, rec->desc ); title = title_spec; } } } } fgetname(sf, shelf_spec, 1); /* full file name of bookshelf */ fclose ( sf ); } /* * Generate HTML header. */ send_http_header ( "200 Sending generated HTML", "Text/html" ); cgi_printf("<HTML>\n<HEAD><TITLE>%s</TITLE>\n", entify_string(title) ); cgi_printf("<!-- Software: %s -->\n</HEAD>", software_version ); cgi_printf("<BODY>\n<H2>%s</H2><P>\n", path); script_name = cgi_info ( "SCRIPT_NAME" ); /* * Generate history path. */ lvl = 2; for ( i = 1; i < j; i++ ) { lvl++; if ( lvl > 6 ) lvl = 6; cgi_printf ( "<H%d>%s</H%d>\n", lvl, entify_string(elem[i]), lvl ); } cgi_printf("<BR><HR>\n"); /* * determine icon directory from environment variable. */ icon_dir = getenv ( "WEBBOOK_ICON_PATH" ); if ( !icon_dir ) icon_dir = DEFAULT_ICON_DIR; else if ( (strlen(icon_dir)+50) > sizeof(icon_image) ) icon_dir = DEFAULT_ICON_DIR; /* * Generate directory with links to each. */ if ( ! first_rec.next ) { cgi_printf ( "Error opening bookshelf file %s\n", path); } for ( rec = first_rec.next; rec; rec = rec->next ) { char *escaped_target, *escaped_desc, *entified; char target[256]; if ( *rec->type == '#' ) continue; /* comment */ apply_default ( rec->fname, shelf_spec, target ); entified = entify_string(rec->desc); escaped_target = escape_string(target); if ( 0 == strcmp ( rec->type, "SHELF" ) ) { escaped_desc = escape_string(rec->desc); sprintf ( icon_image, SHELF_ICON, icon_dir ); cgi_printf("%s <A HREF=\"../%s/%s/\">%s</A><BR>\n", icon_image, escaped_desc, escaped_target, entified ); if ( escaped_desc != rec->desc ) free ( escaped_desc ); } else if ( 0 == strcmp ( rec->type, "BOOK" ) ) { sprintf ( icon_image, BOOK_ICON, icon_dir ); cgi_printf("%s <A HREF=\"%s/%s\">%s</A><BR>\n", icon_image, script_name, escaped_target, entified ); } else if ( 0 == strcmp ( rec->type, "TITLE" ) ) { } else { /* * convert the target back to unix format, and make direct * HREF to it. */ int state, k; for ( state = k = 0; target[k]; k++ ) switch ( state ) { case 0: if ( target[k] == ':' ) { state = 1; target[k] = '/'; } else if ( target[k] == '[' || target[k] == '<' ) { state = 4; target[k] = '/'; } break; case 1: if ( target[k] == '[' ) { state = 2; } if ( target[k] == '<' ) { state = 2; } break; case 2: if ( target[k] == '.' ) target[k] = '/'; if ( target[k] == ']' || target[k] == '>' ) { target[k] = '/'; state = 3; } target[k-1] = target[k]; break; case 3: target[k-1] = target[k]; break; case 4: if ( target[k] == '.' || target[k] == ']' || target[k] == '>' ) target[k] = '/'; break; } if ( state == 2 || state == 3 ) target[k-1] = '\0'; /* printf("rewritten target: '%s'\n", target ); */ /* * Insert proper icon for filetype. */ if ( 0 == strcmp ( rec->type, "HTML" ) ) { sprintf ( icon_image, HTML_ICON, icon_dir ); } else if ( strlen(rec->type) < (sizeof(icon_image)-3) ) { sprintf ( icon_image, "[%s]", rec->type ); } else { strcpy ( icon_image, "???" ); } cgi_printf("%s <A HREF=\"/%s\">%s</A><BR>\n", icon_image, target, entified ); } /* * Only free string if malloc'ed */ if ( escaped_target != target ) free ( escaped_target ); if ( entified != rec->desc ) free ( entified ); } cgi_printf ( "</BODY></HTML>\n" ); return 1; } /****************************************************************************/ /* Convert strings containing punctuation characters into escaped strings. */ static char *escape_string ( char *source ) { int i, j, punct_count; char *dest; dest = source; punct_count = 0; for ( i = 0; source[i]; i++ ) if ( ispunct ( source[i] ) ) { if ( (source[i] != '.') && (source[i] != '$') )punct_count++; } else if ( isspace ( source[i] ) ) punct_count++; if ( punct_count > 0 ) { dest = malloc ( i + punct_count*3 + 1 ); if ( !dest ) return source; for ( i = j = 0; source[i]; i++ ) { if ( isspace(source[i]) || (ispunct ( source[i] ) && (source[i] != '.') && (source[i] != '$')) ) { sprintf ( &dest[j], "%%%02x", source[i] ); if ( dest[j+1] == ' ' ) dest[j+1] = '0'; j += 3; } else dest[j++] = source[i]; } dest[j] = '\0'; } return dest; } /****************************************************************************/ /* Convert strings containing punctuation characters into escaped strings. */ static char *entify_string ( char *source ) { int i, j,brack_count; char *dest; dest = source; brack_count = 0; for ( i = 0; source[i]; i++ ) { if ( (source[i] == '<') || (source[i] == '>') || (source[i] == '&') ) brack_count++; } if ( brack_count > 0 ) { dest = malloc ( i + brack_count*4 + 1 ); if ( !dest ) return source; for ( i = j = 0; source[i]; i++ ) { if ( source[i] == '<' ) { dest[j++] = '&'; dest[j++] = 'l'; dest[j++] = 't'; dest[j++] = ';'; } else if ( source[i] == '>' ) { dest[j++] = '&'; dest[j++] = 'g'; dest[j++] = 't'; dest[j++] = ';'; } else if ( source[i] == '&' ) { dest[j++] = '&'; dest[j++] = 'a'; dest[j++] = 'm'; dest[j++] = 'p'; dest[j++] = ';'; } else dest[j++] = source[i]; } dest[j] = '\0'; } return dest; } /****************************************************************************/ /* Read next record from bookshelf file and copy to structure. */ static shelf_recp get_shelf_rec ( FILE *sf, shelf_recp previous ) { int i,j, backslash_count; shelf_recp cur; char *line, tline[4096]; /* * Be optimistic and allocate new structure. */ cur = malloc ( sizeof(struct shelf_rec) ); if ( !cur ) return cur; cur->next = (shelf_recp) 0; cur->type = cur->fname = cur->desc = ""; cur->is_odl = 0; backslash_count = 0; if ( fgets ( tline, sizeof(tline)-1, sf ) ) { /* * Copy and Parse the record on backslashes or tabs. It will * also parse on the first space. */ for ( i = 0; i < sizeof(tline) && tline[i] && tline[i] != '\n'; i++ ); line = malloc ( i + 1 ); if ( !line ) return (shelf_recp) 0; strncpy ( line, tline, i ); line[i] = '\0'; cur->type = line; for ( j = i = 0; line[i]; i++ ) if ( (line[i]=='\\') || ((backslash_count==0) && (line[i] == ' ')) || (line[i] == '\t') ) { if ( line[i] == '\\' ) backslash_count++; line[i] = '\0'; if ( backslash_count == 0 ) { /* * compress whitespace. */ while ( line[i+1] && isspace(line[i+1]) ) i++; } if ( j == 0 ) { cur->fname = &line[i+1]; j++; } else { cur->desc = &line[i+1]; /* rest of line */ break; } } if ( backslash_count == 0 ) cur->is_odl = 1; /* * Unescape characters and upcase type. */ for ( i = 0; line[i]; i++ ) if ( islower(line[i]) ) line[i] = _toupper(line[i]); } else { /* * Read error, return null. */ free ( cur ); cur = (shelf_recp) 0; } #ifdef DEBUG if ( cur ) printf("shelf rec parse: '%s' '%s' '%s'\n", cur->type, cur->fname, cur->desc ); #endif /* * append new record to list. */ previous->next = cur; return cur; } /**************************************************************************/ /* Prepare to send back response. Build standard response header. */ static int send_http_header ( char *stsline, char *content ) { int status; /* */ cgi_printf ( "content-type: %s\n", content ); if ( strncmp(stsline,"200",3) != 0 ) cgi_printf ( "status: %s\n\n", stsline ); else cgi_printf("\n"); return 1; } /**************************************************************************/ /* Take default directory from defname and apply to fname. If fname * begins with a percent sign, convert ODL shelf syntax to VMS filespec. */ static char *apply_default ( char *fname, char *defname, char *out ) { int i, j, d_limit, slash_fixup; if ( *fname == '%' ) { /* * Change "%devname/dir/file" --> "devname:[dir]file" */ j = 0; /* output position */ d_limit = -1; /* position of last slash */ for ( i = 1; fname[i]; i++ ) { if ( fname[i] == '/' ) { if ( d_limit < 0 ) { /* first slash */ out[j++] = ':'; out[j++] = '['; } else { out[j++] = '.'; } d_limit = j-1; } else { out[j++] = fname[i]; } } out[j] = '\0'; if ( d_limit >= 0 ) { if ( out[d_limit] == '.' ) out[d_limit] = ']'; else for ( i = d_limit; out[i]; i++ ) out[i] = out[i+1]; } return out; } /* * Find end of directory string, default to "decw$book:". */ for ( d_limit = i = 0; defname[i]; i++ ) { if ( defname[i] == ':' || defname[i] == ']' || defname[i] == '>' ) d_limit = i+1; /* end of defname directory */ } if ( d_limit == 0 ) { defname = "decw$book:"; d_limit = 10; } /* * If fname looks like it supplies it's own directory, make defname NULL. */ for ( slash_fixup = i = 0; fname[i]; i++ ) { if ( fname[i] == ':' || fname[i] == ']' || fname[i] == '>' ) { d_limit = 0; } else if ( fname[i] == '/' ) { slash_fixup = 1; } } /* * concatenate defname//fname. */ if ( d_limit ) { strncpy ( out, defname, d_limit ); if ( slash_fixup ) { if ( defname[d_limit-1] == ':' ) { strcpy ( &out[d_limit], "[000000." ); d_limit += 8; } else { out[d_limit-1] = '.'; } } } if ( i+d_limit > 255 ) i = 255-d_limit; strncpy ( &out[d_limit], fname, i ); out[i+d_limit] = '\0'; if ( slash_fixup ) { for ( i = d_limit+i-1; i > d_limit; --i ) if ( out[i] == '/' ) { out[i] = (slash_fixup) ? ']' : '.'; slash_fixup = '\0'; } } return out; }