/* * This program is a CGI script for converting it's argument, a DEC CONDIST * CDMENU data file to HTML format. The argument is the portion of the * path string following the script name in the URL (i.e. PATH_INFO). * * Author: David Jones * Date: 15-SEP-1994 * Revised: 28-OCT-1994 * Revised: 21-JUN-1995 Remove '\r' from format lines as * cgi_printf already converts the '\n'. */ #include #include #include #include #include #include "cgilib.h" static FILE *cdmf; int cdm_init(), cdm_product_scan(); char *net_unescape_string ( char *string, int *length ); static void upcase_string ( char *dst, char *src, int maxlen ) { int i; for ( i = 0; (i < maxlen) && src[i]; i++ ) { dst[i] = _toupper(src[i]); } dst[i] = '\0'; } int main ( int argc, char **argv ) { int status, count, i, ver, upi, state, kit, disc, matches; char *prod_status, *method; char *query_string, *menu_file, *rel_date, *headers[5], line[2048]; char test_line[2048], test_kit[128], test_ver[128], match_word[20][128]; /* * Set up CGI environment. */ status = cgi_init ( argc, argv ); if ( (status&1) == 0 ) exit ( status ); /* * Get requested method and make sure we can handle it. */ method = cgi_info ( "REQUEST_METHOD" ); if ( !method ) method = ""; if ( strcmp(method, "GET") && strcmp(method,"HEAD") ) { cgi_printf("status: 400 Bad request\n" ); cgi_printf("content-type: text/plain\n\n" ); cgi_printf("Method is not supported (%s).\n", method ); exit(1); } /* * Get filename. */ menu_file = cgi_info ( "PATH_TRANSLATED" ); printf("menu_file: '%s'\n", menu_file ? menu_file : "" ); if ( !menu_file ) menu_file = ""; if ( !(*menu_file) ) { cgi_printf("status: 403 forbidden\n" ); cgi_printf("content-type: text/plain\n\n" ); cgi_printf("Access to menu file disallowed by rule file\n"); exit(1); } /* * Open input file and read headers. */ status = cdm_init ( menu_file, headers, &rel_date ); if ( 0 == (1&status) ) { printf("error in cdm_init: %d\n", status ); cgi_printf("status: 404 file not found\n" ); cgi_printf("content-type: text/plain\n\n" ); cgi_printf("Error opening menu file (%d)\n", status); exit ( 1 ); } else if ( !headers[0] ) { cgi_printf("status: 500 invalid file format.\n" ); cgi_printf("content-type: text/plain\n\n" ); cgi_printf("File is not in valid CD_CONTENTS format.\n"); cgi_printf("(No product_name headers)"); exit ( 1 ); } if ( 0 == strcmp ( method, "HEAD" ) ) exit ( 1 ); /* * Print html header, using header info from cd_contents file. */ cgi_printf("content-type: text/html\n\n"); cgi_printf("\n\n%s CD contents\n", rel_date ); cgi_printf("\n\n

Condist CD contents

\n"); for ( i = 0; headers[i]; i++ ) cgi_printf("%s ", headers[i] ); cgi_printf("
Release date: %s

\n", rel_date ); /* * See if a search requested. */ query_string = cgi_info("QUERY_STRING"); if ( !query_string ) query_string = ""; else if ( *query_string ) { /* * Parse query string into separate match words, upcased. */ char *cp, *wrd; int last, j, word_length; for ( j = 0, wrd = cp = query_string; (j<19); cp++ ) { /* * Break into separate words delimited by '+' */ if ( !*cp || (*cp == '+') ) { last = *cp ? 0 : 1; *cp = '\0'; word_length = strlen ( wrd ); net_unescape_string ( wrd, &word_length ); wrd[word_length] = '\0'; upcase_string ( match_word[j++], wrd, 127 ); /* printf("match_word[%d] = '%s'\n", j-1, match_word[j-1] ); */ if ( last ) break; wrd = cp+1; } } match_word[j][0] = '\0'; /* * Report parse results. */ cgi_printf("

Search Criteria

\nThe products listed"); cgi_printf(" in the products section contain the following strings"); cgi_printf(" in their description field:
    "); for ( j = 0; match_word[j][0]; j++ ) { cgi_printf("
  • %s
  • ", match_word[j] ); } cgi_printf("
"); } /* * Make list of entries. */ count = matches = 0; cgi_printf("

Products

\n
\n"); while ( cdm_product_scan ( line, sizeof(line), &ver, &upi, &state, &kit, &disc ) ) { count++; /* * Screen products is this is a search. */ if ( *query_string ) { /* * Only accept product for listing if its description * contains every match word. */ int j; upcase_string ( test_line, line, sizeof(test_line)-1 ); upcase_string ( test_kit, &line[kit], sizeof(test_kit)-1 ); upcase_string ( test_ver, &line[ver], sizeof(test_ver)-1 ); for ( j = 0; match_word[j][0]; j++ ) { if ( strstr ( test_line, match_word[j] ) ) continue; if ( strstr ( test_kit, match_word[j] ) ) continue; if ( !strstr ( test_ver, match_word[j] ) ) break; } if ( match_word[j][0] ) continue; /* test failed */ } /* * Translate product status code. */ prod_status = &line[state]; if ( *prod_status == 'A' ) prod_status = "unchanged"; else if ( *prod_status == 'N' ) { prod_status = (line[state+1] == 'C') ? "unchanged" : "New"; } else if ( *prod_status == 'U' ) prod_status = "Updated"; cgi_printf("
%s
\n
Version: %s, Disc: %d, Kit: %s, Status: %s
\n", line, &line[ver], disc, &line[kit], prod_status ); matches++; } cgi_printf("

\n"); /* end list */ /* * Print summary of contents. */ if ( matches < count ) cgi_printf ( "Number of matches: %d, \n", matches ); cgi_printf("Number of products: %d\n\n", count ); return 1; } /* * This module defines routines to read the CDMENU contents files. * * int cdm_init ( char *fname, char **headers, char **release_date ); * int cdm_product_scan ( * char *buf, int buflen, * Product name. * int *ver, * version * int *upi, * part number * int *state, * A-already N-new U-update * int *kit, * VMSINSTAL kit name. * int *disc ) * Disc number (decoded). */ /**************************************************************************/ /* Open file and position. */ int cdm_init ( char *fname, char **headers, char **release_date ) { int j, i; char line[2048]; /* * Open file. */ cdmf = fopen ( fname, "r" ); if ( !cdmf ) { return vaxc$errno; } *release_date = ""; /* * Read lines until "%end-of-data" seen. */ i = 0; while ( fgets ( line, sizeof(line), cdmf ) ) { if ( strncmp ( line, "%END_OF_DATA", 12 ) == 0 ) break; if ( (i < 4) && (strncmp ( line, "%DISC_PRODUCT_NAME", 18) == 0) ) { /* * Copy first 4 product name lines to header. */ headers[i] = malloc ( strlen(line)+1 ); for ( j = 18; line[j] && !isspace(line[j]); j++ ); while ( isspace(line[j]) ) j++; strcpy ( headers[i], &line[j] ); for ( j = 0; headers[i][j]; j++ ) if (headers[i][j] == '\n') { headers[i][j] = '\0'; break; } i++; } else if ( 0 == strncmp(line,"%RELEASE_DATE",13 ) ) { release_date[0] = malloc ( strlen(line)+1 ); for ( j = 13; line[j] && !isspace(line[j]); j++ ); while ( isspace(line[j]) ) j++; strcpy ( release_date[0], &line[j] ); for ( j = 0; release_date[0][j]; j++ ) if (release_date[0][j] == '\n') { release_date[0][j] = '\0'; break; } } } headers[i] = NULL; return 1; } /**************************************************************************/ /* * Read next line and parse into components. Name is first component, * other components are given by offset. Comment lines are skipped. */ int cdm_product_scan ( char *buf, int buflen, /* Product name. */ int *ver, /* version */ int *upi, /* part number */ int *state, /* A-already N-new U-update */ int *kit, /* VMSINSTAL kit name. */ int *disc ) /* Disc number (decoded). */ { int status, length, i, j, in_tok, token[10]; char *tmp; /* * First read line and parse out first element. */ if ( !cdmf ) return 0; for ( length = 0; length == 0; ) { tmp = fgets ( buf, buflen, cdmf ); if ( !tmp ) return 0; /* * Find start of first element. */ for ( i = 0; buf[i] && isspace(buf[i]); i++ ); if ( (buf[i] == '\0') || (buf[i] == '!') ) continue; /* * Collapse leading space and opening quote. */ j = 0; if ( buf[i] == '"' ) { for ( i++; buf[i] && (buf[i] != '"'); ) buf[j++] = buf[i++]; buf[j] = '\0'; } else { while ( buf[i] && !isspace(buf[i]) ) buf[j++] = buf[i++]; } buf[j] = '\0'; if ( buf[i] ) i++; /* * Parse out rest of line. */ for ( j=0, in_tok = 0; (j < 9) && buf[i]; i++ ) { if ( in_tok ) { if ( isspace ( buf[i] ) ) { in_tok = 0; buf[i] = '\0'; /* terminate current */ } } else { if ( !isspace (buf[i]) ) { in_tok = 1; token[j++] = i; } } } token[j] = i; /* * Return select tokens. */ *ver = j > 1 ? token[1] : i; *upi = j > 0 ? token[0] : i; *state = j > 3 ? token[3] : i; *kit = j > 7 ? token[7] : i; *disc = j > 8 ? atoi(&buf[token[8]]) : -1; length = j; } return 1; }