]> git.gir.st - ttxd.git/blob - src/thttpd-2.27/cgi-src/redirect.c
initial code import
[ttxd.git] / src / thttpd-2.27 / cgi-src / redirect.c
1 /* redirect - simple redirection CGI program
2 **
3 ** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
4 ** All rights reserved.
5 **
6 ** Redistribution and use in source and binary forms, with or without
7 ** modification, are permitted provided that the following conditions
8 ** are met:
9 ** 1. Redistributions of source code must retain the above copyright
10 ** notice, this list of conditions and the following disclaimer.
11 ** 2. Redistributions in binary form must reproduce the above copyright
12 ** notice, this list of conditions and the following disclaimer in the
13 ** documentation and/or other materials provided with the distribution.
14 **
15 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 ** SUCH DAMAGE.
26 */
27
28 /* Three steps to set up a redirection:
29 ** 1. Make sure your web server is set up to allow CGI programs.
30 ** 2. Make a symbolic link from the file you want to redirect,
31 ** pointing at this program in the CGI bin directory.
32 ** 3. Add an entry to the file ".redirects" in the directory where your
33 ** http server runs CGI programs. For most servers, this is the
34 ** directory where the given CGI program lives. The format of the
35 ** file is a bunch of lines with a filename, whitespace, and the new
36 ** URL. For example:
37
38 /test/oldfile.html http://www.acme.com/test/newfile.html
39
40 ** The easiest way to figure out precisely what filename to put into
41 ** .redirects is to set up the symlink and then click on it. You'll get
42 ** back a "404 Not Found" page which includes the filename as received by
43 ** the redirect program, and that's what you want to use.
44 **
45 ** Note: this is designed for thttpd (http://www.acme.com/software/thttpd/)
46 ** and using it with other web servers may require some hacking. A possible
47 ** gotcha is with the symbolic link from the old file pointing at this
48 ** script - servers other than thttpd may not allow that link to be run
49 ** as a CGI program, because they don't check the link to see that it
50 ** 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 argv0 = argv[0];
136
137 /* Get the name that we were run as, which is the filename being
138 ** redirected.
139 */
140 script_name = getenv( "SCRIPT_NAME" );
141 if ( script_name == (char*) 0 )
142 {
143 internal_error( "Couldn't get SCRIPT_NAME environment variable." );
144 exit( 1 );
145 }
146
147 /* Append the PATH_INFO, if any. This allows redirection of whole
148 ** directories.
149 */
150 path_info = getenv( "PATH_INFO" );
151 if ( path_info != (char*) 0 )
152 {
153 cp = (char*) malloc( strlen( script_name ) + strlen( path_info ) + 1 );
154 if ( cp == (char*) 0 )
155 {
156 internal_error( "Out of memory." );
157 exit( 1 );
158 }
159 (void) sprintf( cp, "%s%s", script_name, path_info );
160 script_name = cp;
161 }
162
163 /* Open the redirects file. */
164 fp = fopen( ".redirects", "r" );
165 if ( fp == (FILE*) 0 )
166 {
167 internal_error( "Couldn't open .redirects file." );
168 exit( 1 );
169 }
170
171 /* Search the file for a matching entry. */
172 while ( fgets( buf, sizeof(buf), fp ) != (char*) 0 )
173 {
174 /* Remove comments. */
175 cp = strchr( buf, '#' );
176 if ( cp != (char*) 0 )
177 *cp = '\0';
178 /* Skip leading whitespace. */
179 cp = buf;
180 cp += strspn( cp, " \t" );
181 /* Check for blank line. */
182 if ( *cp != '\0' )
183 {
184 /* Parse line. */
185 if ( sscanf( cp, "%[^ \t\n] %[^ \t\n]", file, url ) == 2 )
186 {
187 /* Check for wildcard match. */
188 star = strchr( file, '*' );
189 if ( star != (char*) 0 )
190 {
191 /* Check for leading match. */
192 if ( strncmp( file, script_name, star - file ) == 0 )
193 {
194 /* Got it; put together the full name. */
195 strcat( url, script_name + ( star - file ) );
196 /* XXX Whack the script_name, too? */
197 moved( script_name, url );
198 exit( 0 );
199 }
200 }
201 /* Check for exact match. */
202 if ( strcmp( file, script_name ) == 0 )
203 {
204 /* Got it. */
205 moved( script_name, url );
206 exit( 0 );
207 }
208 }
209 }
210 }
211
212 /* No match found. */
213 not_found( script_name );
214 exit( 1 );
215 }
Imprint / Impressum