root/cgi-src/redirect.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. internal_error
  2. not_found
  3. moved
  4. main

   1 /* redirect - simple redirection CGI program
   2 **
   3 ** Copyright (c) 1995 by Jef Poskanzer <jef@mail.acme.com>.
   4 ** Copyright (c) 2023 by Amelia Zabardast Ziabari <ame@psianesia.org>.
   5 ** All rights reserved.
   6 **
   7 ** Redistribution and use in source and binary forms, with or without
   8 ** modification, are permitted provided that the following conditions
   9 ** are met:
  10 ** 1. Redistributions of source code must retain the above copyright
  11 **    notice, this list of conditions and the following disclaimer.
  12 ** 2. Redistributions in binary form must reproduce the above copyright
  13 **    notice, this list of conditions and the following disclaimer in the
  14 **    documentation and/or other materials provided with the distribution.
  15 **
  16 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26 ** SUCH DAMAGE.
  27 */
  28 
  29 /* Three steps to set up a redirection:
  30 **  1. Make sure your web server is set up to allow CGI programs.
  31 **  2. Make a symbolic link from the file you want to redirect,
  32 **     pointing at this program in the CGI bin directory.
  33 **  3. Add an entry to the file ".redirects" in the directory where your
  34 **     http server runs CGI programs.  For most servers, this is the
  35 **     directory where the given CGI program lives.  The format of the
  36 **     file is a bunch of lines with a filename, whitespace, and the new
  37 **     URL.  For example:
  38 
  39 /test/oldfile.html    http://www.acme.com/test/newfile.html
  40 
  41 **     The easiest way to figure out precisely what filename to put into
  42 **     .redirects is to set up the symlink and then click on it.  You'll get
  43 **     back a "404 Not Found" page which includes the filename as received by
  44 **     the redirect program, and that's what you want to use.
  45 **
  46 ** Note: this is designed for xthttpd and using it with other web servers
  47 ** may require some hacking.  A possible gotcha is with the symbolic link
  48 ** from the old file pointing at this script - servers other than xthttpd may
  49 ** not allow that link to be run as a CGI program, because they don't check
  50 ** the link to see that it points into the allowed CGI directory.
  51 **
  52 ** Note two: It would be really cool to have this program look for
  53 ** the .redirects file in the same directory as the file being redirected,
  54 ** instead of in the binaries directory.  Unfortunately, this appears
  55 ** to be impossible with the information CGI gives, plus the non-standardized
  56 ** but widespread practice of running CGI programs in the directory where
  57 ** the binary lives.  Perhaps CGI 1.2 will address this.
  58 */
  59 
  60 #include <sys/types.h>
  61 
  62 #include <stdio.h>
  63 #include <stdlib.h>
  64 #include <string.h>
  65 
  66 #include "config.h"
  67 
  68 
  69 static char* argv0;
  70 
  71 
  72 static void
  73 internal_error( char* reason )
  74     {
  75     char* title = "500 Internal Error";
  76 
  77     (void) printf( "\
  78 Status: %s\n\
  79 Content-type: text/html\n\
  80 \n\
  81 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
  82 <BODY><H2>%s</H2>\n\
  83 Something unusual went wrong during a redirection request:\n\
  84 <BLOCKQUOTE>\n\
  85 %s\n\
  86 </BLOCKQUOTE>\n\
  87 </BODY></HTML>\n", title, title, title, reason );
  88     }
  89 
  90 
  91 static void
  92 not_found( char* script_name )
  93     {
  94     char* title = "404 Not Found";
  95 
  96     (void) printf( "\
  97 Status: %s\n\
  98 Content-type: text/html\n\
  99 \n\
 100 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
 101 <BODY><H2>%s</H2>\n\
 102 The requested filename, %s, is set up to be redirected to another URL;\n\
 103 however, the new URL has not yet been specified.\n\
 104 </BODY></HTML>\n", title, title, title, script_name );
 105     }
 106 
 107 
 108 static void
 109 moved( char* script_name, char* url )
 110     {
 111     char* title = "Moved";
 112 
 113     (void) printf( "\
 114 Location: %s\n\
 115 Content-type: text/html\n\
 116 \n\
 117 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
 118 <BODY><H2>%s</H2>\n\
 119 The requested filename, %s, has moved to a new URL:\n\
 120 <A HREF=\"%s\">%s</A>.\n\
 121 </BODY></HTML>\n", url, title, title, script_name, url, url );
 122     }
 123 
 124 
 125 int
 126 main( int argc, char** argv )
 127     {
 128     char* script_name;
 129     char* path_info;
 130     char* cp;
 131     FILE* fp;
 132     char *star;
 133     char buf[5000], file[5000], url[5000];
 134 
 135     (void) argc; /* XXX: gcc */
 136 
 137     argv0 = argv[0];
 138 
 139     /* Get the name that we were run as, which is the filename being
 140     ** redirected.
 141     */
 142     script_name = getenv( "SCRIPT_NAME" );
 143     if ( script_name == (char*) 0 )
 144         {
 145         internal_error( "Couldn't get SCRIPT_NAME environment variable." );
 146         exit( 1 );
 147         }
 148 
 149     /* Append the PATH_INFO, if any.  This allows redirection of whole
 150     ** directories.
 151     */
 152     path_info = getenv( "PATH_INFO" );
 153     if ( path_info != (char*) 0 )
 154         {
 155         cp = (char*) malloc( strlen( script_name ) + strlen( path_info ) + 1 );
 156         if ( cp == (char*) 0 )
 157             {
 158             internal_error( "Out of memory." );
 159             exit( 1 );
 160             }
 161         (void) sprintf( cp, "%s%s", script_name, path_info );
 162         script_name = cp;
 163         }
 164 
 165     /* Open the redirects file. */
 166     fp = fopen( ".redirects", "r" );
 167     if ( fp == (FILE*) 0 )
 168         {
 169         internal_error( "Couldn't open .redirects file." );
 170         exit( 1 );
 171         }
 172 
 173     /* Search the file for a matching entry. */
 174     while ( fgets( buf, sizeof(buf), fp ) != (char*) 0 )
 175         {
 176         /* Remove comments. */
 177         cp = strchr( buf, '#' );
 178         if ( cp != (char*) 0 )
 179             *cp = '\0';
 180         /* Skip leading whitespace. */
 181         cp = buf;
 182         cp += strspn( cp, " \t" );
 183         /* Check for blank line. */
 184         if ( *cp != '\0' )
 185             {
 186             /* Parse line. */
 187             if ( sscanf( cp, "%4999[^ \t\n] %4999[^ \t\n]", file, url ) == 2 )
 188                 {
 189                 /* Check for wildcard match. */
 190                 star = strchr( file, '*' );
 191                 if ( star != (char*) 0 )
 192                     {
 193                     /* Check for leading match. */
 194                     if ( strncmp( file, script_name, star - file ) == 0 )
 195                         {
 196                         /* Got it; put together the full name. */
 197                         strcat( url, script_name + ( star - file ) );
 198                         /* XXX Whack the script_name, too? */
 199                         moved( script_name, url );
 200                         exit( 0 );
 201                         }
 202                     }
 203                 /* Check for exact match. */
 204                 if ( strcmp( file, script_name ) == 0 )
 205                     {
 206                     /* Got it. */
 207                     moved( script_name, url );
 208                     exit( 0 );
 209                     }
 210                 }
 211             }
 212         }
 213 
 214     /* No match found. */
 215     not_found( script_name );
 216     exit( 1 );
 217     }

/* [previous][next][first][last][top][bottom][index][help] */