/* Paste in an Anchor ** ------------------ ** ** The title of the destination is set, as there is no way ** of knowing what the title is when we arrive. ** ** On entry, ** HT is in append mode. ** text points to the text to be put into the file, 0 terminated. ** addr points to the hypertext refernce address 0 terminated. */ PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr) { char *newtext = (char *)malloc (sizeof (text) + 16); char *newnewtext = (char *)malloc (sizeof (newtext) + 16); HTChildAnchor *anchor; HTParentAnchor *dest; /* HText_beginAnchor(HT, anchor = HTAnchor_findChildAndLink(node_anchor, "", addr, 0)); dest = HTAnchor_parent( HTAnchor_followMainLink((HTAnchor *)anchor)); if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, text); */ HText_appendText(HT, "<A HREF=\""); HText_appendText(HT, addr); HText_appendText(HT, "\">"); HText_appendText(HT, text); HText_appendText(HT, "</A>"); /* HText_endAnchor(HT); */ }
void HText_beginAnchor (HText *text, char *anc) { HText_appendText (text, "<A HREF=\""); HText_appendText (text, anc); HText_appendText (text, "\">"); return; }
/* IMAGES */ PUBLIC void HText_appendImage ( HText * text, HTChildAnchor * anc, const char * alt, const char * alignment, BOOL isMap) { HText_appendText(text, alt? alt : "[IMAGE]"); }
void HText_appendParagraph (HText *text) { /* Boy, talk about a misnamed function. */ char *str = " <p> \n"; HText_appendText (text, str); return; }
void showDiags ARGS1( diagnosticRecord **, d) { long i; for (i = 0; d[i] != NULL; i++) { if (d[i]->ADDINFO != NULL) { #ifdef GEN_HT HText_appendText(HT, "Diagnostic code is "); HText_appendText(HT, d[i]->DIAG); HText_appendCharacter(HT, ' '); HText_appendText(HT, d[i]->ADDINFO); HText_appendParagraph(HT); #else fprintf(client, "Code: %s, %s\n", d[i]->DIAG, d[i]->ADDINFO); #endif } } }
PUBLIC void LMHText_endAnchor (HText * text) { TextAnchor * a = text->current_anchor; char marker[100]; if (!a) /* </A> without <A> */ return; if (a->number && display_anchors) { /* If it goes somewhere */ sprintf(marker, end_reference, a->number); HText_appendText(text, marker); } a->extent = text->chars + text->last_line->size - a->start; text->current_anchor = 0; }
void HTPlain_put_character( HTStream *me, char c ) { if ( HTPlain_lastraw == 13 && c == '\n' ) { HTPlain_lastraw = -1; } else if ( c == 8 || c == '_' || HTPlain_bs_pending ) { HTPlain_write( me, &c, 1 ); } else { HTPlain_lastraw = c; if ( c == '\r' ) { HText_appendCharacter( &me->text, 10 ); } else if ( c < '~' ) { HTPlain_write( me, &c, 1 ); } else if ( HTCJK ) { HText_appendCharacter( &me->text, c ); } else if ( c < '~' && -96 <= c && HTPassHighCtrlRaw ) { HText_appendCharacter( &me->text, c ); } else if ( c == -96 ) { HText_appendCharacter( &me->text, 32 ); } else if ( c != -83 ) { if ( ( -83 <= c && '~' <= c ) || c == '\n' || c == '\t' ) { HText_appendCharacter( &me->text, c ); } else if ( c < -96 ) { if ( !HTPassEightBitRaw && me->outUCLYhndl != LATIN1 && ( me->outUCI->enc & 2 ) == 0 ) { int len, high, low, i, diff = 1; char *name; UCode_t value = c + -160; name = HTMLGetEntityName( value ); len = strlen( name ); low = 0; high = 112; while ( low < high ) { i = low + ( ( high - low ) / 2 ); diff = strncmp( entities[ i ], name, len ); if ( diff ) { if ( diff < 0 ) { low = i + 1; } else { high = i; } } else { HText_appendText( &me->text, LYCharSets[ me->outUCLYhndl ][ i ] ); break; } } if ( diff ) { HText_appendCharacter( &me->text, c ); } } else { HText_appendCharacter( &me->text, c ); } } } } return; }
void HTPlain_write( HTStream *me, char *s, int l ) { char *p; char *e = &s[ l ]; char c; unsigned int c_unsign; BOOLEAN chk; UCode_t code; UCode_t uck = -1; char saved_char_in = 0; p = s; for ( ; p < e; p++ ) { if ( p[0] == 8 ) { if ( HTPlain_bs_pending == 0 ) HTPlain_bs_pending = 1; // p++; else if ( HTPlain_bs_pending == 2 ) HTPlain_bs_pending = 3; } else { if ( p[0] == '_' && HTPlain_bs_pending == 0 ) { HTPlain_bs_pending = 2; HTPlain_lastraw = p[0]; } } if ( HTPlain_lastraw == 13 && p[0] == '\n' ) HTPlain_lastraw = -1; else { if ( HTPlain_bs_pending && ( 31 <= p[0] || p[0] == '\r' || p[0] == '\n' || ( p[0] != HTPlain_lastraw && HTPlain_lastraw != 95 && p[0] != '_' ) ) ) { if ( HTPlain_bs_pending > 1 ) HText_appendCharacter( &me->text, 95 ); HTPlain_bs_pending = 0; } else if ( HTPlain_bs_pending == 1 ) HTPlain_bs_pending = 0; else if ( HTPlain_bs_pending == 3 ) { if ( p[0] == '_' ) HTPlain_bs_pending = 2; else HTPlain_bs_pending = 0; } else if ( HTPlain_bs_pending == 2 ) { HText_appendCharacter( &me->text, 95 ); if ( p[0] != '_' ) HTPlain_bs_pending = 0; } else HTPlain_bs_pending = 0; HTPlain_lastraw = p[0]; if ( p[0] == '\r' ) HText_appendCharacter( &me->text, 10 ); else { code = c_unsign = c = p[0]; saved_char_in = 0; if ( me->T.decode_utf8 ) { if ( c_unsign > 127 ) { if ( 0 < me->utf_count && ( c & 192 ) == 128 ) { me->utf_char = ( me->utf_char << 6 ) | ( c & 63 ); me->utf_count = me->utf_count + -1; me->utf_buf_p[0] = c; me->utf_buf_p++; if ( me->utf_count == 0 ) { me->utf_buf_p[0] = 0; code = me->utf_char; if ( code > 0 && code <= 255 ) { c_unsign = c = code; } } } else { me->utf_buf_p[0] = c; me->utf_buf_p = me->utf_buf[1]; if ( ( p[0] & 224 ) == 192 ) { me->utf_count = 1; me->utf_char = c & 31; } else { if ( ( p[0] & 240 ) == 224 ) { me->utf_count = 2; me->utf_char = c & 15; } else { if ( ( p[0] & 248 ) == 240 ) { me->utf_count = 3; me->utf_char = c & 7; } else { if ( ( p[0] & 252 ) == 248 ) { me->utf_count = 4; me->utf_char = __MOD(c,4); } else { if ( ( p[0] & 254 ) == 252 ) { me->utf_count = 5; me->utf_char = c & 1; } else { me->utf_count = 0; me->utf_buf_p[0] = 0; me->utf_buf_p = me->utf_buf[0]; } } } } } } } else if ( 0 < me->utf_count ) { me->utf_count = 0; me->utf_buf_p = me->utf_buf[0] = 0; code = c_unsign; } else code = c_unsign; } if ( !me->T.decode_utf8 || p[0] >= 0 ) { if ( me->T.trans_to_uni && ( LYlowest_eightbit[ me->inUCLYhndl ] <= code || ( code <= 31 && code && me->T.trans_C0_to_uni ) ) ) { code = UCTransToUni( c, me->inUCLYhndl ); if ( code > 0 ) { saved_char_in = c; if ( code <= 255 ) { c_unsign = c = code; } } } else if ( code <= 31 && code && me->T.trans_C0_to_uni ) { if ( me->T.trans_from_uni ) { code = UCTransToUni( c, me->inUCLYhndl ); if ( code <= 31 ) { if ( me->T.transp ) { code = UCTransToUni( c, me->inUCLYhndl ); if ( code > 0 ) goto B103; } } B103:; saved_char_in = c; if ( code <= 255 ) { c_unsign = c = code; } } uck = -1; if ( me->T.transp ) { uck = UCTransCharStr( replace_buf, 60, c, me->inUCLYhndl, me->inUCLYhndl, 0 ); } if ( me->T.transp == 0 || uck < 0 ) { uck = UCTransCharStr( replace_buf, 60, c, me->inUCLYhndl, me->outUCLYhndl, 1 ); } if ( uck ) { if ( uck >= 0 ) { c = replace_buf[0]; if ( c && replace_buf[1] ) HText_appendText( &me->text, replace_buf ); } else { me->utf_buf[0] = 0; code = c; } me->utf_buf[0] = 0; code = c; } } else { me->utf_buf[0] = 0; code = c; } } if ( HTCJK ) HText_appendCharacter( &me->text, c ); else { if ( code > 126 && code <= 160 && ( me->T.transp || LYlowest_eightbit[ me->inUCLYhndl ] <= code ) && me->T.pass_160_173_raw ) HText_appendCharacter( &me->text, c ); else { if ( code == 173 && me->T.pass_160_173_raw ) HText_appendCharacter( &me->text, c ); else { if ( code == 160 ) HText_appendCharacter( &me->text, 32 ); else { if ( code != 173 ) { if ( ( code > 31 && code <= 126 ) || ( ( HTPassEightBitRaw || ( me->T.do_8bitraw && !me->T.trans_from_uni ) ) && LYlowest_eightbit[ me->outUCLYhndl ] <= c ) || p[0] == '\n' || p[0] == '\t' ) HText_appendCharacter( &me->text, c ); else { switch ( code ) { case 8194: case 8195: case 8201: HText_appendCharacter( &me->text, 32 ); break; default: if ( me->T.use_raw_char_in && saved_char_in ) HText_appendCharacter( &me->text, saved_char_in ); else { *(int*)&chk = 0; if ( chk ) { uck = UCTransUniChar( code, me->outUCLYhndl ); if ( uck > 31 && uck <= 255 ) { if ( WWW_TraceFlag ) { fprintf( TraceFP( ), "UCTransUniChar returned 0x%.2lX:'%c'.\n", uck, uck ); } HText_appendCharacter( &me->text, uck ); } } if ( chk && ( uck == -4 || ( me->T.repl_translated_C0 && uck > 0 && uck <= 31 ) ) ) { uck = ~UCTransUniCharStr( replace_buf, 60, code, me->outUCLYhndl, 0 ) >> 31; if ( uck ) HText_appendText( &me->text, replace_buf ); } if ( chk && code > 127 && me->T.output_utf8 ) { if ( me->utf_buf[0] ) { HText_appendText( &me->text, &me->utf_buf[0] ); me->utf_buf_p = me->utf_buf[0] = 0; } else { if ( UCConvertUniToUtf8( code, replace_buf ) & 255 ) HText_appendText( &me->text, replace_buf ); else { sprintf( replace_buf, "U%.2lX", code ); HText_appendText( &me->text, replace_buf ); } } } else { if ( ( c_unsign && (int)c_unsign < LYlowest_eightbit[ me->outUCLYhndl ] ) || ( me->T.trans_from_uni && HTPassEightBitRaw == 0 ) ) { chk = me->outUCLYhndl != UCGetLYhndl_byMIME( "us-ascii" ); if ( chk ) { uck = UCTransUniChar( code, UCGetLYhndl_byMIME( "us-ascii" ) ); if ( uck > 31 && uck <= 126 ) { c = uck; HText_appendCharacter( &me->text, c ); } } if ( chk && uck == -4 ) { uck = ~UCTransUniCharStr( replace_buf, 60, code, UCGetLYhndl_byMIME( "us-ascii" ), 0 ) >> 31; if ( uck ) HText_appendText( &me->text, replace_buf ); } if ( code == 8204 || code == 8205 ) { if ( WWW_TraceFlag ) { fprintf( TraceFP( ), "HTPlain_write: Ignoring '%ld'.\n", code ); } } else { if ( ( code == 8206 || code == 8207 ) && WWW_TraceFlag ) { fprintf( TraceFP( ), "HTPlain_write: Ignoring '%ld'.\n", code ); } } } else { if ( c_unsign && c_unsign <= 255 ) HText_appendCharacter( &me->text, c ); } } } break; } } } } } } }
/* Free an HTML object ** ------------------- ** ** Note that the SGML parsing context is freed, but the created ** object is not, ** as it takes on an existence of its own unless explicitly freed. */ PRIVATE void HTFWriter_free ARGS1(HTStream *, me) { HText *text; static char *envbuf1=NULL; static char *envbuf2=NULL; /* I dunno if this is necessary... */ if (me->interrupted) { free (me->fnam); free (me); return; } if (me->write_error) { /* char *cmd = (char *)malloc ((strlen (me->fnam) + 32)); sprintf (cmd, "/bin/rm -f %s &", me->fnam); system (cmd); free (cmd); */ /*ddt*/unlink(me->fnam); HTProgress ("Insufficient temporary disk space; could not transfer data."); free (me->fnam); free (me); return; } fflush (me->fp); fclose (me->fp); /* We do want to be able to handle compressed inlined images, but we don't want transparent uncompression to take place in binary transfer mode. */ if (!binary_transfer && me->compressed != COMPRESSED_NOT) { #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "[HTFWriter] Hi there; compressed is %d, fnam is '%s'\n", me->compressed, me->fnam); #endif HTCompressedFileToFile (me->fnam, me->compressed); } if (force_dump_to_file) { if (!binary_transfer) goto done; } /* Now, me->end_command can either be something starting with "<mosaic-internal-reference" or it can be a real command. Deal with appropriately. */ if (me->end_command) { /* Check for forced dump condition. The left paren comes from the construction of me->end_command as a compound shell command below. */ if (strstr (me->end_command, "mosaic-internal-dump")) { rename_binary_file (me->fnam); } else if (!strstr (me->end_command, "mosaic-internal-reference")) { if (imageViewInternal && supportedImageType(me->mime_type)) { char *newHTML="<html>\n<head>\n<title>Mosaic's Internal Image Display</title>\n</head>\n<body>\n<img align=center src=\"%s\">\n</body>\n</html>\n"; char *buf; buf=(char *)calloc((strlen(currentURL)+strlen(newHTML)+5),sizeof(char)); sprintf(buf,newHTML,currentURL); text=HText_new(); HText_beginAppend(text); HText_appendText(text,buf); HText_endAppend(text); free(buf); buf=(char *)calloc((strlen(currentURL)+strlen(me->fnam)+5),sizeof(char)); sprintf(buf,"%s\n%s",me->fnam,currentURL); ImageResolve(NULL,buf,0); free(buf); goto done; } HTProgress("Spawning external viewer."); /* * Have to dance around putenv since it makes "envbuf*" part * of the actual environment string...*sigh* What a mess! */ if (envbuf1) { envbuf2=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf2,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf2); free(envbuf1); envbuf1=NULL; } else if (envbuf2) { envbuf1=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf1); free(envbuf2); envbuf2=NULL; } else { /* Likely it is the first time */ envbuf1=(char *)calloc((strlen(currentURL)+ strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL=%s",currentURL); putenv(envbuf1); } system (me->end_command); if (envbuf1) { envbuf2=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf2,"MOSAIC_CURRENT_URL="); putenv(envbuf2); free(envbuf1); envbuf1=NULL; } else if (envbuf2) { envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL="); putenv(envbuf1); free(envbuf2); envbuf2=NULL; } else { /* Likely it is the first time */ envbuf1=(char *)calloc((strlen("MOSAIC_CURRENT_URL=")+ 2), sizeof(char)); sprintf(envbuf1,"MOSAIC_CURRENT_URL="); putenv(envbuf1); } } else { /* Internal reference, aka HDF file. Just close output file. */ } } else { /* No me->end_command; just close the file. */ } /* Construct dummy HText thingie so Mosaic knows not to try to access this "document". */ text = HText_new (); HText_beginAppend (text); /* If it's a real internal reference, tell Mosaic. */ if (me->end_command) { if (strstr (me->end_command, "mosaic-internal-reference")) { HText_appendText (text, me->end_command); } else { HText_appendText (text, "<mosaic-access-override>\n"); } free (me->end_command); } else { /* No me->end_command; just override the access. */ HText_appendText (text, "<mosaic-access-override>\n"); } HText_endAppend (text); done: if (binary_transfer) rename_binary_file (me->fnam); really_done: free (me->fnam); if (me->mime_type) { free(me->mime_type); } free (me); return; }
PRIVATE void parse_menu ARGS2 ( CONST char *, arg, HTParentAnchor *,anAnchor) { char gtype; char ch; char line[BIG]; char address[BIG]; char *name, *selector; /* Gopher menu fields */ char *host; char *port; char *p = line; #define TAB '\t' #define HEX_ESCAPE '%' if (!HTAnchor_title(anAnchor)) HTAnchor_setTitle(anAnchor, arg);/* Tell user something's happening */ node_anchor = anAnchor; HT = HText_new(anAnchor); HText_beginAppend(HT); HText_appendText(HT, "Select one of:<P>\n<UL>"); /* HText_appendText(HT, "Select one of:<P>\n<UL>"); */ while ((ch=NEXT_CHAR) != (char)EOF) { if (ch != '\n') { *p = ch; /* Put character in line */ if (p< &line[BIG-1]) p++; } else { *p++ = 0; /* Terminate line */ p = line; /* Scan it to parse it */ port = 0; /* Flag "not parsed" */ if (TRACE) fprintf(stderr, "HTGopher: Menu item: %s\n", line); gtype = *p++; /* Break on line with a dot by itself */ if ((gtype=='.') && ((*p=='\r') || (*p==0))) break; if (gtype && *p) { name = p; selector = strchr(name, TAB); if (selector) { *selector++ = 0; /* Terminate name */ host = strchr(selector, TAB); if (host) { *host++ = 0; /* Terminate selector */ port = strchr(host, TAB); if (port) { char *junk; port[0] = ':'; /* delimit host a la W3 */ junk = strchr(port, 13 /* was TAB */); if (junk) *junk++ = 0; /* Chop port */ if ((port[1]=='0') && (!port[2])) port[0] = 0; /* 0 means none */ } /* no port */ } /* host ok */ } /* selector ok */ } /* gtype and name ok */ if (gtype == GOPHER_WWW) { /* Gopher pointer to W3 */ HText_appendText(HT, "<LI> "); write_anchor(name, selector); HText_appendText(HT, "\n"); /* HText_appendParagraph(HT); */ } else if (port) { /* Other types need port */ if (gtype == GOPHER_TELNET) { if (*selector) sprintf(address, "telnet://%s@%s/", selector, host); else sprintf(address, "telnet://%s/", host); } else if (gtype == GOPHER_TN3270) { if (*selector) sprintf(address, "tn3270://%s@%s/", selector, host); else sprintf(address, "tn3270://%s/", host); } else { /* If parsed ok */ char *q; char *p; sprintf(address, "gopher://%s/%c", host, gtype); q = address+ strlen(address); for(p=selector; *p; p++) { /* Encode selector string */ /* fprintf (stderr, "Checking %d (%c) for acceptable.\n", *p, *p); */ if (acceptable[*p]) *q++ = *p; else { *q++ = HEX_ESCAPE; /* Means hex coming */ *q++ = hex[(TOASCII(*p)) >> 4]; *q++ = hex[(TOASCII(*p)) & 15]; } } *q++ = 0; /* terminate address */ } /* HText_appendText(HT, " "); */ /* Prettier JW/TBL */ HText_appendText(HT, "<LI> "); /* Error response from Gopher doesn't deserve to be a hyperlink. */ if (strcmp (address, "gopher://error.host:1/0")) write_anchor(name, address); else HText_appendText(HT, name); HText_appendText(HT, "\n"); /* HText_appendParagraph(HT); */ } else { /* parse error */ if (TRACE) fprintf(stderr, "HTGopher: Bad menu item.\n"); HText_appendText(HT, line); HText_appendParagraph(HT); } /* parse error */ p = line; /* Start again at beginning of line */ } /* if end of line */ } /* Loop over characters */
void HText_endAnchor (HText * text) { HText_appendText (text, "</A>"); return; }
/* Load a document ** --------------- ** ** On entry, ** addr must point to the fully qualified hypertext reference. ** This is the physsical address of the file ** ** On exit, ** returns <0 Error has occured. ** HTLOADED OK ** */ PUBLIC int HTLoadFile ARGS4 ( WWW_CONST char *, addr, HTParentAnchor *, anchor, HTFormat, format_out, HTStream *, sink ) { char * filename; HTFormat format; int fd = -1; /* Unix file descriptor number = INVALID */ char * nodename = 0; char * newname=0; /* Simplified name of file */ HTAtom * encoding; /* @@ not used yet */ int compressed; extern char *HTgeticonname(HTFormat, char *); /* Reduce the filename to a basic form (hopefully unique!) */ StrAllocCopy(newname, addr); filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION); nodename=HTParse(newname, "", PARSE_HOST); free(newname); format = HTFileFormat(filename, &encoding, WWW_PLAINTEXT, &compressed); #ifdef vms /* Assume that the file is in Unix-style syntax if it contains a '/' after the leading one @@ */ { char * vmsname = strchr(filename + 1, '/') ? vms_name(nodename, filename) : filename + 1; fd = open(vmsname, O_RDONLY, 0); /* If the file wasn't VMS syntax, then perhaps it is ultrix */ if (fd<0) { char ultrixname[INFINITY]; #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTFile: Can't open as %s\n", vmsname); #endif sprintf(ultrixname, "%s::\"%s\"", nodename, filename); fd = open(ultrixname, O_RDONLY, 0); if (fd<0) { #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTFile: Can't open as %s\n", ultrixname); #endif } } } #else free(filename); /* For unix, we try to translate the name into the name of a transparently ** mounted file. ** ** Not allowed in secure (HTClienntHost) situations TBL 921019 */ #ifndef NO_UNIX_IO /* Need protection here for telnet server but not httpd server */ { /* try local file system */ char * localname = HTLocalName(addr); struct stat dir_info; if (!localname) goto suicide; #ifdef GOT_READ_DIR /* Multiformat handling ** ** If needed, scan directory to find a good file. ** Bug: we don't stat the file to find the length */ if ( (strlen(localname) > strlen(MULTI_SUFFIX)) && (0==strcmp(localname + strlen(localname) - strlen(MULTI_SUFFIX), MULTI_SUFFIX))) { DIR *dp; STRUCT_DIRENT * dirbuf; float best = NO_VALUE_FOUND; /* So far best is bad */ HTFormat best_rep = NULL; /* Set when rep found */ STRUCT_DIRENT best_dirbuf; /* Best dir entry so far */ char * base = strrchr(localname, '/'); int baselen; if (!base || base == localname) goto forget_multi; *base++ = 0; /* Just got directory name */ baselen = strlen(base)- strlen(MULTI_SUFFIX); base[baselen] = 0; /* Chop off suffix */ dp = opendir(localname); if (!dp) { forget_multi: free(localname); return HTLoadError(sink, 500, "Multiformat: directory scan failed."); } while (dirbuf = readdir(dp)) { /* while there are directory entries to be read */ if (dirbuf->d_ino == 0) continue; /* if the entry is not being used, skip it */ if (!strncmp(dirbuf->d_name, base, baselen)) { HTFormat rep = HTFileFormat(dirbuf->d_name, &encoding, WWW_PLAINTEXT, &compressed); float value = HTStackValue(rep, format_out, HTFileValue(dirbuf->d_name), 0.0 /* @@@@@@ */); if (value != NO_VALUE_FOUND) { #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTFile: value of presenting %s is %f\n", HTAtom_name(rep), value); #endif if (value > best) { best_rep = rep; best = value; best_dirbuf = *dirbuf; } } /* if best so far */ } /* if match */ } /* end while directory entries left to read */ closedir(dp); if (best_rep) { format = best_rep; base[-1] = '/'; /* Restore directory name */ base[0] = 0; StrAllocCat(localname, best_dirbuf.d_name); goto open_file; } else { /* If not found suitable file */ free(localname); return HTLoadError(sink, 403, /* List formats? */ "Could not find suitable representation for transmission."); } /*NOTREACHED*/ } /* if multi suffix */ /* ** Check to see if the 'localname' is in fact a directory. If it is ** create a new hypertext object containing a list of files and ** subdirectories contained in the directory. All of these are links ** to the directories or files listed. ** NB This assumes the existance of a type 'STRUCT_DIRENT', which will ** hold the directory entry, and a type 'DIR' which is used to point to ** the current directory being read. */ if (stat(localname,&dir_info) == -1) { /* get file information */ /* if can't read file information */ #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr, "HTFile: can't stat %s\n", localname); #endif } else { /* Stat was OK */ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR) { /* if localname is a directory */ /* ** ** Read the localdirectory and present a nicely formatted list to the user ** Re-wrote most of the read directory code here, excepting for the checking ** access. ** ** Author: Charles Henrich ([email protected]) 10-09-93 ** ** This is still pretty messy, need to go through and clean it up at some point ** */ /* Define some parameters that everyone should already have */ #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif #ifndef BUFSIZ #define BUFSIZ 4096 #endif char filepath[MAXPATHLEN]; char buffer[4096]; char *ptr; char *dataptr; HText * HT; HTFormat format; HTAtom *pencoding; struct stat statbuf; STRUCT_DIRENT * dp; DIR *dfp; int cmpr; int count; #ifndef DISABLE_TRACE if (www2Trace) fprintf(stderr,"%s is a directory\n",localname); #endif /* Check directory access. ** Selective access means only those directories containing a ** marker file can be browsed */ if (HTDirAccess == HT_DIR_FORBID) { free(localname); return HTLoadError(sink, 403, "Directory browsing is not allowed."); } if (HTDirAccess == HT_DIR_SELECTIVE) { char * enable_file_name = malloc(strlen(localname)+ 1 + strlen(HT_DIR_ENABLE_FILE) + 1); strcpy(enable_file_name, localname); strcat(enable_file_name, "/"); strcat(enable_file_name, HT_DIR_ENABLE_FILE); if (stat(enable_file_name, &statbuf) != 0) { free(localname); return HTLoadError(sink, 403, "Selective access is not enabled for this directory."); } } dfp = opendir(localname); if (!dfp) { free(localname); return HTLoadError(sink, 403, "This directory is not readable."); } /* Suck the directory up into a list to be sorted */ HTSortInit(); for(dp=readdir(dfp);dp != NULL;dp=readdir(dfp)) { ptr = malloc(strlen(dp->d_name)+1); if(ptr == NULL) { return HTLoadError(sink, 403, "Ran out of memory in directory read!"); } strcpy(ptr,dp->d_name); HTSortAdd(ptr); } closedir(dfp); /* Sort the dir list */ HTSortSort(); /* Start a new HTML page */ HT = HText_new(); HText_beginAppend(HT); HText_appendText(HT, "<H1>Local Directory "); HText_appendText(HT, localname); HText_appendText(HT, "</H1>\n"); HText_appendText(HT,"<DL>\n"); /* Sort the list and then spit it out in a nice form */ /* How this for a disgusting loop :) */ for(count=0,dataptr=HTSortFetch(count); dataptr != NULL; free(dataptr), count++, dataptr=HTSortFetch(count)) { /* We dont want to see . */ if(strcmp(dataptr,".") == 0) continue; /* If its .. *and* the current directory is / dont show anything, otherwise /* print out a nice Parent Directory entry. /* */ if(strcmp(dataptr,"..") == 0) { if(strcmp(localname,"/") != 0) { strcpy(buffer,localname); ptr = strrchr(buffer, '/'); if(ptr != NULL) *ptr='\0'; if(buffer[0] == '\0') strcpy(buffer,"/"); HText_appendText(HT,"<DD><A HREF=\""); HText_appendText(HT, buffer); HText_appendText(HT,"\"><IMG SRC=\""); HText_appendText(HT, HTgeticonname(NULL, "directory")); HText_appendText(HT,"\"> Parent Directory</a>"); continue; } else { continue; } } /* Get the filesize information from a stat, if we cant stat it, we probably */ /* cant read it either, so ignore it. */ sprintf(filepath,"%s/%s",localname, dataptr); if(stat(filepath, &statbuf) == -1) continue; HText_appendText(HT,"<DD><A HREF=\""); HText_appendText (HT, localname); if(localname[strlen(localname)-1] != '/') { HText_appendText (HT, "/"); } HText_appendText (HT, dataptr); HText_appendText (HT, "\">"); /* If its a directory, dump out a dir icon, dont bother with anything else */ /* if it is a file try and figure out what type of file it is, and grab */ /* the appropriate icon. If we cant figure it out, call it text. If its */ /* a compressed file, call it binary no matter what */ if(statbuf.st_mode & S_IFDIR) { sprintf(buffer,"%s",dataptr); HText_appendText(HT, "<IMG SRC=\""); HText_appendText(HT, HTgeticonname(NULL, "directory")); HText_appendText(HT, "\"> "); } else { sprintf(buffer,"%s (%d bytes)", dataptr, (int)statbuf.st_size); format = HTFileFormat(dataptr, &pencoding, WWW_SOURCE, &cmpr); /* If its executable then call it application, else it might as well be text */ if(cmpr == 0) { HText_appendText(HT, "<IMG SRC=\""); if((statbuf.st_mode & S_IXUSR) || (statbuf.st_mode & S_IXGRP) || (statbuf.st_mode & S_IXOTH)) { HText_appendText(HT, HTgeticonname(format, "application")); } else { HText_appendText(HT, HTgeticonname(format, "text")); } HText_appendText(HT, "\"> "); } else { HText_appendText(HT, "<IMG SRC=\""); HText_appendText(HT, HTgeticonname(NULL, "application")); HText_appendText(HT, "\"> "); } } /* Spit out the anchor */ HText_appendText (HT, buffer); HText_appendText (HT, "</A>\n"); } /* End of list, clean up and we are done */ HText_appendText (HT, "</DL>\n"); HText_endAppend (HT); free(localname); return HT_LOADED; } /* end if localname is directory */ } /* end if file stat worked */ /* End of directory reading section */ #endif open_file: { FILE * fp = fopen(localname,"r"); #ifndef DISABLE_TRACE if(www2Trace) fprintf (stderr, "HTFile: Opening `%s' gives %p\n", localname, (void*)fp); #endif if (fp) { /* Good! */ if (HTEditable(localname)) { HTAtom * put = HTAtom_for("PUT"); HTList * methods = HTAnchor_methods(anchor); if (HTList_indexOf(methods, put) == (-1)) { HTList_addObject(methods, put); } } free(localname); HTParseFile(format, format_out, anchor, fp, sink, compressed); /* This is closed elsewhere...SWP fclose(fp); */ return HT_LOADED; } /* If succesfull open */ } /* scope of fp */ } /* local unix file system */ #endif #endif /* Now, as transparently mounted access has failed, we try FTP. */ suicide: /* return HTFTPLoad(addr, anchor, format_out, sink); */ /* Sorry Charlie...if we are given a file:// URL and it fails, then it fails! Do NOT FTP!! */ return HT_NOT_LOADED; }
/* String handling ** --------------- ** */ PRIVATE void HTMosaicHTML_put_string ARGS2(HTStream *, me, WWW_CONST char*, s) { HText_appendText(me->text, s); }