/* New object ** ---------- */ PUBLIC HTStream* HTMosaicHTMLPresent ARGS5( HTPresentation *, pres, HTParentAnchor *, anchor, HTStream *, sink, HTFormat, format_in, int, compressed) { HTStream* me = (HTStream*)malloc(sizeof(*me)); #ifndef DISABLE_TRACE if (www2Trace) fprintf (stderr, "[HTMosaicHTMLPresent] Hi there! Compressed is %d\n", compressed); #endif me->isa = &HTMosaicHTML; me->text = HText_new(); me->interrupted = 0; me->compressed = compressed; HText_beginAppend(me->text); return (HTStream*) me; }
/* 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 */
/* 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; }