/********************************************************************
* lindner
* 3.9
* 1994/04/22 03:35:16
* /home/arcwelder/GopherSrc/CVS/gopher+/gopherd/dedot.c,v
* Exp
*
* Paul Lindner, University of Minnesota CIS.
*
* Copyright 1991, 1992 by the Regents of the University of Minnesota
* see the file "Copyright" in the distribution for conditions of use.
*********************************************************************
* MODULE: dedot.c
* See below.
*********************************************************************
* Revision History:
* dedot.c,v
* Revision 3.9  1994/04/22  03:35:16  lindner
* Fix for spinning gopherd processes
*
* Revision 3.8  1994/04/14  15:48:52  lindner
* Fix for files with single quotes
*
* Revision 3.7  1994/03/04  23:25:14  lindner
* Fix for dedot weirdness
*
* Revision 3.6  1993/09/18  03:26:38  lindner
* Important Security fix
*
* Revision 3.5  1993/08/23  18:33:57  lindner
* Fix off by one error
*
* Revision 3.4  1993/08/06  14:28:14  lindner
* Further strip out single quotes
*
* Revision 3.3  1993/08/05  22:19:43  lindner
* Fix for single quotes
*
* Revision 3.2  1993/08/05  20:43:07  lindner
* Added fix for dedot to remove quotes for when using system or popen
*
* Revision 3.1.1.1  1993/02/11  18:02:50  lindner
* Gopher+1.2beta release
*
* Revision 1.1  1992/12/10  23:13:27  lindner
* gopher 1.1 release
*
*
*********************************************************************/


#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 [email protected]
*/

void dequote1();
void dedot1();
void dedot2();


void
dequote1(src)
 char *src;
{
    char *cp2;

    /** Strip out the quotes.. **/
    while (*src != '\0') {
         if (*src == '"' || *src == '\'') {
              for (cp2=src; *cp2 != '\0'; cp2++) {
                   *cp2 = *(cp2+1);
              }
         }
         src++;
    }
}

void
dedot1( src )
char *src;
{
    dequote1(src);
    if ( *src == '.' ) {
         if (src[1] == '\0' || src[1] == '/' ||
             ( src[1] == '.' && ( src[2] == '\0' || src[2] == '/' ) ) ) {
              dedot2( src, src );
              return;
         }
    }
    while ( *src ) {
         if ( *src++ == '/' ) {
              if ( *src == '.' ) {
                   if (src[1] == '\0' || src[1] == '/' ||
                       ( src[1] == '.' && ( src[2] == '\0' || src[2] == '/' ) ) ) {
                        dedot2( src, src );
                        return;
                   }
              }
         }
    }
    return;
}

/* copy src to dst, blindly removing (not interpreting) ./ and ../ */

void
dedot2( src, dst )
 char *src;
 char *dst;
{
    /*
     ** We either have /, a filename, ./ or ../
     */
    int i;

    while ( *src ) {
         switch ( *src ) {
         case '/':
              /* copy it, and skip any extras e.g. /a///b */
              *dst++ = *src++;
              while ( *src == '/' )
                   src++;
              break;
         case '.':
              /* don't forget about trailing . and .. */

              /* Nuke any quotes */
              for (i=1; src[i] == '"' || src[i] == '\''; i++)
                   ;

              if ( src[i] == '/'  ) {          /* ./ */
                   src += i+1;
                   break;
              }
              if ( src[i] == '\0'  ) { /* .\0 */
                   src += i;   /* only 1 so we don't fall off the end */
                   break;
              }
              if ( src[i] == '.' &&
                   (src[i+1] == '"' || src[i+1] == '\'')) { /* ..", ..' */
                   src += i+2;
                   break;
              }
              if ( src[i] == '.' && src[i+1] == '/' ) { /* ../ */
                   src += i+2;
                   break;
              }
              if ( src[i] == '.' && src[i+1] == '\0' ) {       /* .. */
                   src += i+1; /* don't fall off the end */
                   break;
              }
              /* must be a filename - fall through */
         default:
              /* must be filename - copy it over */
              while ( *src != '\0' && *src != '/')
                   /** Note quotes are taken care of by Gpopen **/
                   *dst++ = *src++;
              break;
         }
    }
    /* and terminate it */
    *dst = '\0';
}