]>
git.gir.st - ttxd.git/blob - src/thttpd-2.27/cgi-src/redirect.c
1 /* redirect - simple redirection CGI program
3 ** Copyright © 1995 by Jef Poskanzer <jef@mail.acme.com>.
4 ** All rights reserved.
6 ** Redistribution and use in source and binary forms, with or without
7 ** modification, are permitted provided that the following conditions
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.
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
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
38 /test/oldfile.html http://www.acme.com/test/newfile.html
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.
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.
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.
60 #include <sys/types.h>
73 internal_error( char* reason
)
75 char* title
= "500 Internal Error";
79 Content-type: text/html\n\
81 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
83 Something unusual went wrong during a redirection request:\n\
87 </BODY></HTML>\n", title
, title
, title
, reason
);
92 not_found( char* script_name
)
94 char* title
= "404 Not Found";
98 Content-type: text/html\n\
100 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\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
);
109 moved( char* script_name
, char* url
)
111 char* title
= "Moved";
115 Content-type: text/html\n\
117 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\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
);
126 main( int argc
, char** argv
)
133 char buf
[5000], file
[5000], url
[5000];
137 /* Get the name that we were run as, which is the filename being
140 script_name
= getenv( "SCRIPT_NAME" );
141 if ( script_name
== (char*) 0 )
143 internal_error( "Couldn't get SCRIPT_NAME environment variable." );
147 /* Append the PATH_INFO, if any. This allows redirection of whole
150 path_info
= getenv( "PATH_INFO" );
151 if ( path_info
!= (char*) 0 )
153 cp
= (char*) malloc( strlen( script_name
) + strlen( path_info
) + 1 );
154 if ( cp
== (char*) 0 )
156 internal_error( "Out of memory." );
159 (void) sprintf( cp
, "%s%s", script_name
, path_info
);
163 /* Open the redirects file. */
164 fp
= fopen( ".redirects", "r" );
165 if ( fp
== (FILE*) 0 )
167 internal_error( "Couldn't open .redirects file." );
171 /* Search the file for a matching entry. */
172 while ( fgets( buf
, sizeof(buf
), fp
) != (char*) 0 )
174 /* Remove comments. */
175 cp
= strchr( buf
, '#' );
176 if ( cp
!= (char*) 0 )
178 /* Skip leading whitespace. */
180 cp
+= strspn( cp
, " \t" );
181 /* Check for blank line. */
185 if ( sscanf( cp
, "%[^ \t\n] %[^ \t\n]", file
, url
) == 2 )
187 /* Check for wildcard match. */
188 star
= strchr( file
, '*' );
189 if ( star
!= (char*) 0 )
191 /* Check for leading match. */
192 if ( strncmp( file
, script_name
, star
- file
) == 0 )
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
);
201 /* Check for exact match. */
202 if ( strcmp( file
, script_name
) == 0 )
205 moved( script_name
, url
);
212 /* No match found. */
213 not_found( script_name
);