root/cgi-src/redirect.c
/*DEFINITIONS
This source file includes following definitions.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 }
/*