This is HTFile.c in view mode; [Download] [Up]
/* File Access HTFile.c
** ===========
**
** This is unix-specific code in general, with some VMS bits.
** These are routines for file access used by WWW browsers.
**
** History:
** Feb 91 Written Tim Berners-Lee CERN/CN
** Apr 91 vms-vms access included using DECnet syntax
**
** Bugs:
** Cannot access VMS files from a unix machine. How can we know that the
** target machine runs VMS?
*/
#ifdef EXPLICIT_INCLUDES
#ifdef vms
include <unixio.h>
#else
#include <sys/param.h>
#include <sys/stat.h>
#endif
#endif
#include "HTUtils.h"
#include "WWW.h"
#include "HTParse.h"
#include "tcp.h"
#include "HTTCP.h"
#include "HTFTP.h"
PRIVATE char *HTMountRoot = "/Net/"; /* Where to find mounts */
/* PRIVATE char *HTCacheRoot = "/tmp/Cache/";*/ /* Where to cache things */
/* PRIVATE char *HTSaveRoot = "$(HOME)/WWW/";*/ /* Where to save things */
/* Convert filenames between local and WWW formats
** -----------------------------------------------
** Make up a suitable name for saving the node in
**
** E.g. $(HOME)/WWW/news/1234@cernvax.cern.ch
** $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
**
** On exit,
** returns a malloc'ed string which must be freed by the caller.
*/
#ifdef __STDC__
PUBLIC char * HTLocalName(const char * name)
#else
PUBLIC char * HTLocalName(name)
char * name;
#endif
{
char * access = HTParse(name, "", PARSE_ACCESS);
char * host = HTParse(name, "", PARSE_HOST);
char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
if (0==strcmp(access, "file")) {
free(access);
if ((0==strcmp(host, HTHostName())) || !*host) {
free(host);
if (TRACE) printf("Node `%s' means path `%s'\n", name, path);
return(path);
} else {
char * result = (char *)malloc(
strlen("/Net/")+strlen(host)+strlen(path)+1);
sprintf(result, "%s%s%s", "/Net/", host, path);
free(host);
free(path);
if (TRACE) printf("Node `%s' means file `%s'\n", name, result);
return result;
}
} else { /* other access */
char * result;
CONST char * home = (CONST char*)getenv("HOME");
if (!home) home = "/tmp";
result = (char *)malloc(
strlen(home)+strlen(access)+strlen(host)+strlen(path)+6+1);
sprintf(result, "%s/WWW/%s/%s%s", home, access, host, path);
free(path);
free(access);
free(host);
return result;
}
}
/* Make a WWW name from a full local path name
**
** Bugs:
** At present, only the names of two network root nodes are hand-coded
** in and valid for the NeXT only. This should be configurable in
** the general case.
*/
#ifdef __STDC__
PUBLIC char * WWW_nameOfFile(const char * name)
#else
PUBLIC char * WWW_nameOfFile(name)
char * name;
#endif
{
char * result;
if (0==strncmp("/private/Net/", name, 13)) {
result = (char *)malloc(7+strlen(name+13)+1);
sprintf(result, "file://%s", name+13);
} else if (0==strncmp(HTMountRoot, name, 5)) {
result = (char *)malloc(7+strlen(name+5)+1);
sprintf(result, "file://%s", name+5);
} else {
result = (char *)malloc(7+strlen(HTHostName())+strlen(name)+1);
sprintf(result, "file://%s%s", HTHostName(), name);
}
if (TRACE) printf("File `%s'\n\tmeans node `%s'\n", name, result);
return result;
}
/* Determine file format from file name
** ------------------------------------
**
**
*/
#ifdef __STDC__
PUBLIC WWW_Format HTFileFormat(const char * filename)
#else
PUBLIC WWW_Format HTFileFormat(filename)
char * filename;
#endif
{
CONST char * extension;
for (extension=filename+strlen(filename);
(extension>filename) &&
(*extension != '.') &&
(*extension!='/');
extension--) /* search */ ;
if (*extension == '.') {
return 0==strcmp(".html", extension) ? WWW_HTML
: 0==strcmp(".rtf", extension) ? WWW_RICHTEXT
: 0==strcmp(".txt", extension) ? WWW_PLAINTEXT
: WWW_INVALID; /* Unrecognised */
} else {
return WWW_PLAINTEXT;
}
}
/* Determine write access to a file
// --------------------------------
//
// On exit,
// return value YES if file can be accessed and can be written to.
//
// Isn't there a quicker way?
*/
#ifdef __STDC__
PUBLIC BOOL HTEditable(const char * filename)
#else
PUBLIC BOOL HTEditable(filename)
char * filename;
#endif
{
#ifndef vms
#ifndef NO_UNIX_IO
int groups[NGROUPS];
uid_t myUid;
int ngroups; /* The number of groups */
struct stat fileStatus;
int i;
if (stat(filename, &fileStatus)) /* Get details of filename */
return NO; /* Can't even access file! */
ngroups = getgroups(NGROUPS, groups); /* Groups to which I belong */
myUid = geteuid(); /* Get my user identifier */
if (TRACE) {
int i;
printf("File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (",
fileStatus.st_mode, fileStatus.st_uid, fileStatus.st_gid,
myUid, ngroups);
for (i=0; i<ngroups; i++) printf(" %d", groups[i]);
printf(")\n");
}
if (fileStatus.st_mode & 0002) /* I can write anyway? */
return YES;
if ((fileStatus.st_mode & 0200) /* I can write my own file? */
&& (fileStatus.st_uid == myUid))
return YES;
if (fileStatus.st_mode & 0020) /* Group I am in can write? */
{
for (i=0; i<ngroups; i++) {
if (groups[i] == fileStatus.st_gid)
return YES;
}
}
if (TRACE) printf("\tFile is not editable.\n");
return NO; /* If no excuse, can't do */
#else /* NO_UNIX_IO */
return NO; /* Safe answer if no files exist anyway */
#endif
#else /* vms */
return NO; /* Safe answer till we find the correct algorithm */
#endif
}
/* Open a file descriptor for a document
** -------------------------------------
**
** On entry,
** addr must point to the fully qualified hypertext reference.
**
** On exit,
** returns <0 Error has occured.
** >=0 Value of file descriptor or socket to be used
** to read data.
** *pFormat Set to the format of the file, if known.
** (See WWW.h)
**
*/
#ifdef __STDC__
int HTOpenFile(const char * addr, WWW_Format * pFormat)
#else
int HTOpenFile(addr, pFormat)
char * addr;
WWW_Format * pFormat;
#endif
{
char * filename;
int fd = -1; /* Unix file descriptor number = INVALID */
char * nodename = 0;
char * newname=0; /* Simplified name of file */
/* Reduce the filename to a basic form (hopefully unique!)
*/
StrAllocCopy(newname, addr);
HTSimplify(newname);
filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);
nodename=HTParse(newname, "", PARSE_HOST);
free(newname);
*pFormat = HTFileFormat(filename);
#ifdef vms
/* Assume that the file is remote ultrix! @@ */
{
/* We try converting the filename into Files-11 syntax. That is, we assume
** first that the file is, like us, on a VMS node. We try remote
** (or local) DECnet access. Files-11, VMS, VAX and DECnet
** are trademarks of Digital Equipment Corporation.
*/
char wholename[255]; /* VMS Fudge */
char vmsname[255];
char *second = strchr(filename+1, '/'); /* 2nd slash */
char *last = strrchr(filename, '/'); /* last slash */
if (!second) { /* Only one slash */
sprintf(vmsname, "%s::%s", nodename, filename);
} else if(second==last) { /* Exactly two slashes */
*second = 0; /* Split filename from disk */
sprintf(vmsname, "%s::%s:%s", nodename, filename+1, second+1);
*second = '/'; /* restore */
} else { /* More than two slashes */
char * p;
*second = 0; /* Split disk from directories */
*last = 0; /* Split dir from filename */
sprintf(vmsname, "%s::%s:[%s]%s",
nodename, filename+1, second+1, last+1);
*second = *last = '/'; /* restore filename */
for (p=strchr(vmsname, '['); *p!=']'; p++)
if (*p=='/') *p='.'; /* Convert dir sep. to dots */
}
fd = open(vmsname, O_RDONLY, 0);
/* If the file wasn't VMS syntax, then perhaps it is ultrix
*/
if (fd<0) {
if (TRACE) printf("HTAccess: Can't open as %s\n", vmsname);
sprintf(vmsname, "%s::\"%s\"", nodename, filename);
fd = open(vmsname, O_RDONLY, 0);
if (fd<0) {
if (TRACE) printf("HTAccess: Can't open as %s\n", vmsname);
}
}
}
#else
/* For unix, we try to translate the name into the name of a transparently
** mounted file.
*/
#ifndef NO_UNIX_IO
{
char * localname = HTLocalName(addr);
fd = open(localname, O_RDONLY, 0);
if(TRACE) printf ("HTAccess: Opening `%s' gives %d\n",
localname, fd);
free(localname);
}
#endif
#endif
/* Now, as transparently mounted access has failed, we try FTP.
*/
if (fd<0)
if (strcmp(nodename, HTHostName())!=0) {
free(filename);
return HTFTP_open_file_read(addr);
}
/* All attempts have failed if fd<0.
*/
if (fd<0) printf("Can't open `%s', errno=%d\n", filename, errno);
free(filename);
return fd;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.