/* * htn2html.c - World-Wide Web gateway for Peter Scott's HYTELNET program. * * SYNOPSIS: * htn2html [path] * * EXPLANATION * This is a format converter to put Hytelnet files into HTML. * HTML is the markup language used by the World-Wide Web global * information initiative. * * This file may be used in a a server to make Peter Scott's data * or any other data in the same format, available to the world. * * Peter Scott's database of Internet-accessible telnet sites. * Hytelnet lists libraries, Campus-Wide Information Systems, * Freenets and more. This version was written for Unix, but * should work on any system. * * The database consists of many more-or-less plain text files, * all in a single directory. Any text in angle brackets (eg ) * is a link. Selecting it moves you to the named file. Filenames * are mapped to lower case (so refers to the file 'help'). * * The program notices telnet commands embedded in the text files, * and will generate links to the telnet sites. * * NOTES * This corresponds to HYTELNET 5.x for the IBM PC. * * * BUGS * - Ignores the page & line numbers in more complex HYPERRES * links . * - Should be able to handle more than one database. * * AUTHORS * Earl Fogel, Computing Services, University of Saskatchewan * fogel@jester.usask.ca * Tim Berners-Lee, CERN, Geneva, Switzerland. timbl@info.cern.ch * * CHANGE LOG * Dec 1992 - W3 gateway made from interactive program (TBL) * * NOTICE * Permissions to copy, use and redistribute this program are hereby * granted provided the Copyright notice and this comment remain * intact. * * (c) Copyright 1992 Earl Fogel * */ #include #include #include #include #include /* For stat() */ #include /* For stat() */ #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif /* * Things you may want to adjust */ #ifdef VMS # define STARTDIR "pub:[hytelnet]" #else # define STARTDIR "/usr/local/hytelnet" #endif #define MAXFNAME 30 /* max filename length DDD/FILENAME.EXT */ #define STARTFILE "w3start" #define ON 1 #define OFF 0 #define STREQ(a,b) (strcmp(a,b) == 0) #define STRNEQ(a,b,c) (strncmp(a,b,c) == 0) #define printable(c) (((c)>31 && (c)<=127) || (c)==9 || (c)==10) #define HLINE -60 /* horizontal line segment */ #define VLINE -77 /* vertical line segment */ #define VLINE2 -70 /* vertical line segment */ #define UL -38 /* upper left corner */ #define UR -65 /* upper right corner */ #define LL -64 /* lower left corner */ #define LR -39 /* lower right corner */ #define UL2 -42 /* upper left corner */ #define UR2 -73 /* upper right corner */ #define LL2 -45 /* lower left corner */ #define LR2 -67 /* lower right corner */ #define BULLET 4 /* list item marker */ #define BLOT1 -78 #define BLOT2 -79 #define BLOT3 -80 #define UPARROW 201 #define DNARROW 202 #define RTARROW 203 #define LTARROW 204 /* values for links.tcmd */ #define TELNET 1 #define TN3270 2 int col=0; /* column number on output */ int more = FALSE; char *interaddr(), *nextword(), *mystrncpy(); void getlinkname(); void convert(); void outch(); /* may need to comment out this line on IBM RS 6000 */ extern char *strcpy(), *strncpy(); #ifdef VMS # define strncasecmp strncmp /* vms doesn't have strncasecmp */ #endif extern int chdir(); extern int exit(); int server; /* Use telnet-style CRLF? */ int main(argc, argv) int argc; char *argv[]; { int i; char *startfile = STARTFILE; char *startdir = STARTDIR; char *cp; FILE *fp; /* * Process arguments - with none, look for the database in STARTDIR, * starting with STARTFILE. * * If a pathname is given, use it as the starting point. Split it * into directory and file components, 'cd' to the directory, and * view the file. */ server = TRUE; /* Doesn't harm much anyway */ for (i=1; i */ if (*cp == '\r') *cp-- = '\0'; /* remove trailing */ while(cp>line && *cp==' ') *cp-- = '\0';/* remove trailing space */ if (lineno == 0) { char *p; for(p=line; *p==' '; p++) /* void */ ; printf("\n%s\n\n\n
", p);
	}
	col = 0;
	for (cp=line; *cp != '\0'; cp++) {
	    if (*cp == '<') {	/* start of link? */
		for (cp2 = cp+1;
		    *cp2 != '>' && *cp2 != '<' && *cp2 != '\0' &&
		    cp2-cp+1 < MAXFNAME; cp2++)
		    ; /* NULL BODY */
		    
		if (*cp2 == '>') { /* it's a link to a file */
    		    char newfile[MAXFNAME], altfile[MAXFNAME];
		    struct stat stat_buf;
		    char lname[MAXFNAME];
		    mystrncpy(lname, cp, cp2-cp+1);
		    getlinkname(newfile, lname);
		    /*
			* Try to open the new file.
			* If the file is not found in the current directory, use
			* the first three letters of the filename as a directory name,
			* and try again.  This is for compatibility with HYPERRES,
			* not because I like it.
			*/
		    if (stat(newfile, &stat_buf) == 0) {
			printf("", newfile);
		    } else {
			strcpy(altfile, "../");
			strncat(altfile, newfile, 3); /* Try sister directory */
			strcat(altfile, "/");
			strcat(altfile, newfile);
			if (stat(altfile, &stat_buf) == 0) {
			    printf("", altfile);
			} else {			/* Try daughter directory */
			    if (stat(altfile+3, &stat_buf) == 0) {
				printf("", altfile+3);
			    } else {			/* bad file, so no link */
				printf("");
			    } /* not sitster */
			} /* not daughter */
		    } /* not here */
		    
		    while(cp<=cp2) {		/* Contents of anchor element */
		        outch(*cp++);
		    }
		    printf("");
		}

	    } else if ((*cp == 't' || *cp == 'T')	/* telnet command? */
		   && (
		    (col == 0 || isspace(*(cp-1))) &&
		      (STRNEQ(cp,"telnet ",7) ||
		       STRNEQ(cp,"Telnet ",7) ||
		       STRNEQ(cp,"TELNET ",7) ||
		       STRNEQ(cp,"tn3270 ",7) ||
		       STRNEQ(cp,"TN3270 ",7) ) ) ) {	/* yes, telnet command */

		char lname[MAXFNAME];
		char taddr[MAXFNAME];
		int tcmd;

		acp=interaddr(cp+7, taddr);
		while (acp != NULL) {
		    char * port;
		    char * next = nextword(acp);
		    mystrncpy(lname, cp, 6);
		    if (*(cp+5) == '0')
			tcmd = TN3270;
		    else
			tcmd = TELNET;

		    port = strchr(taddr, ' ');
		    if (port) {
			*port = '\0';
			printf("",
			    *(cp+5) == '0' ? "tn3270" : "telnet",
			    taddr,
			    port+1);
		    } else {
			printf("",
			    *(cp+5) == '0' ? "tn3270" : "telnet",
			    taddr);
		    }
		    
		    while(cp < next ) {	/* Contents of anchor element */
			outch(*cp++);
		    }
		    printf("");
		    
		    acp=interaddr(next, taddr);
		}		/* while */
		
	    }			/* if telnet or tn3270 */
	    
	    outch(*cp);
	}			/* next character */

	lineno++;
	outch('\n');		/* newline */
    }				/* next line */
    return;
}




/*	Display one charceter
 *
 *   Converts from IBM-PC format to SGML representation of basic ascii.
 */
 
void outch(ch)
    char ch;
{
    if (!printable(ch)) {
	if      (ch == HLINE)	putchar('-');
	else if (ch == VLINE)	putchar('|');
	else if (ch == VLINE2)	putchar('|');
	else if (ch == UL)	putchar('+');
	else if (ch == UR)	putchar('+');
	else if (ch == LL)	putchar('+');
	else if (ch == LR)	putchar('+');
	else if (ch == UL2)	putchar('+');
	else if (ch == UR2)	putchar('+');
	else if (ch == LL2)	putchar('+');
	else if (ch == LR2)	putchar('+');
	else if (ch == BULLET)	putchar('*');
	else if (ch == BLOT1)	putchar('*');
	else if (ch == BLOT2)	putchar('*');
	else if (ch == BLOT3)	putchar('*');
	else {
#ifdef DEBUG
	    /* shouldn't happen - see what we've missed */
	    if (ch != 13) {
		printw("%d", ch);
		refresh();
	    }
#endif
	    putchar(' ');
	}
    }
    else if (ch == '<') printf("<");
    else if (ch == '>') printf(">");
    else if (ch == '&') printf("&");
    else if (ch == '\t') {			/* expand tabs */
    	do { outch(' '); } while ((col % 8) != 0);
	return;
    }
    else if (ch == '\n') {
    	printf(server ? "\r\n" : "\n");   /* Telnet style for server */
	col= 0;
	return;
    }
    else putchar(ch);
    col++;
}


/*
 * Search through a string for the first valid internet address.
 * We define an internet address as a word consisting of alpha-
 * numeric characters and dots (and with at least one embedded dot).
 *
 * If the address is immediately followed by a space and a port number,
 * those are included as well.
 *
 * This is not a general purpose routine.
 *
 * Returns an pointer to the address if one is found, NULL otherwise.
 */
char *
interaddr(cp, buf)
char *cp, *buf;
{
    int isaddr, isname;
    char *cp2, *word;

    while (*cp != '\0') {

	isaddr = FALSE;
	isname = FALSE;

	while (*cp == ' ') cp++;		/* skip spaces */

	word = cp;				/* start of word? */
	while (*cp == '"' || *cp == '-' || *cp == '.' || isalnum(*cp)) {
	    if (*cp == '.' && isalnum(*(cp+1)) )
		isaddr = TRUE;
	    if (isalpha(*cp))
		isname = TRUE;
	    cp++;
	}

	if (isaddr) {			/* it's an internet address */
/*	    if ((telnet_by_name && isname) ||
		(telnet_by_number && !isname) ) 
*/
	    {
		if (*cp == ' ') {	/* check for port number */
		    for (cp2=cp+1; isdigit(*cp2); cp2++)
			; /* NULL BODY */
		    if (cp2 > cp+1)
			cp = cp2;
		}
		while (!isalnum(*cp) && *cp != '"') cp--;
		mystrncpy(buf,word,cp-word+1);
		/* printw("interaddr: %s\n", buf); refresh(); */
		return(word);
	    }
	} else {  /* if it's the word "or", try again, otherwise give up */
	    if (strncmp(word, "or", 2) != 0)
		return(NULL);
	}
    }
    return(NULL);
}

/*
 * Return pointer to the second word in a string
 */
char *
nextword(cp)
char *cp;
{
    while (*cp != ' ' && *cp != '\0') cp++;	/* skip non-spaces */
    while (*cp == ' ') cp++;			/* skip spaces */
    return(cp);
}


/*
 * my strncpy() terminates strings with a null byte.
 * Writes a null byte into the n+1 byte of dst.
 */
char *
mystrncpy(dst, src, n)
char *dst, *src;
int n;
{
    char *val;

    val = strncpy(dst, src, n);
    *(dst+n) = '\0';
    return val;
}



/*
 * extract the filename portion of a link 
 */
void getlinkname(buf, lname)
char *lname;
char *buf;
{
    char *cp;

    for (cp=lname+1;
	    *cp != '>' && *cp != '\0' && *cp != ' ';
	    cp++) {
	*buf = *cp;
	if (isupper(*buf))
	    *buf = tolower(*buf);
	buf++;
    }
    *buf = '\0';
}