home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.muug.mb.ca
/
2014.06.ftp.muug.mb.ca.tar
/
ftp.muug.mb.ca
/
pub
/
src
/
gopher
/
gopher1.01
/
gopherd
/
dedot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-08
|
3KB
|
107 lines
#include <stdio.h>
/*
** These routines can be used to remove ../ and ./ entries from
** pathnames. These routines do it radically, without any attempt
** at all at interpretation. This is okay for a gopher server,
** because clients aren't supposed to ask for .. or . in a request.
**
** We want to do this so that we can avoid the chroot(), so that we
** can have symbolic links under the gopher directory to other things
** (like man pages for example) outside our structure, and still be
** safe. Unless of course someone makes a link to / or somewhere silly.
**
** dedot1 will remove dots from one string in place, dedot2 will copy
** one to the other, removing in the process - the src and dst can be
** the same. dedot1 can use this to advantage - it checks first if
** things have to be removed, and calls dedot2 if necessary. This
** is a slight advantage because in most cases we won't do anything,
** and we save the expense of copying data back and forth. This
** seems to save almost half the time (very loose testing though).
**
** John Sellens jmsellens@watdragon.waterloo.edu
*/
/* If DOSINGLE is defined, references to '.' are also removed */
#define DOSINGLE
dedot1( src )
char *src;
{
if ( *src == '.' ) {
if (
#ifdef DOSINGLE
src[1] == '\0' || src[1] == '/' ||
#endif
( src[1] == '.' && ( src[2] == '\0' || src[2] == '/' ) ) ) {
dedot2( src, src );
return;
}
}
while ( *src ) {
if ( *src++ == '/' ) {
if ( *src == '.' ) {
if (
#ifdef DOSINGLE
src[1] == '\0' || src[1] == '/' ||
#endif
( src[1] == '.' && ( src[2] == '\0' || src[2] == '/' ) ) ) {
dedot2( src, src );
return;
}
}
}
}
return;
}
/* copy src to dst, blindly removing (not interpreting) ./ and ../ */
dedot2( src, dst )
char *src;
char *dst;
{
/*
** We either have /, a filename, ./ or ../
*/
while ( *src ) {
switch ( *src ) {
case '/':
/* copy it, and skip any extras e.g. /a///b */
*dst++ = *src++;
while ( *src == '/' )
src++;
break;
case '.':
#ifdef DOSINGLE
/* don't forget about trailing . and .. */
if ( src[1] == '/' ) { /* ./ */
src += 2;
break;
}
if ( src[1] == '\0' ) { /* .\0 */
src += 1; /* only 1 so we don't fall off the end */
break;
}
#endif
if ( src[1] == '.' && src[2] == '/' ) { /* ../ */
src += 3;
break;
}
if ( src[1] == '.' && src[2] == '\0' ) { /* .. */
src += 2; /* don't fall off the end */
break;
}
/* must be a filename - fall through */
default:
/* must be filename - copy it over */
while ( *src != '\0' && *src != '/' )
*dst++ = *src++;
break;
}
}
/* and terminate it */
*dst = '\0';
}