ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/thttpd/cgi-src/redirect.c
Revision: 1.1
Committed: Mon Jun 18 21:11:58 2001 UTC (25 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: mp_j, dp_j, cp_j, HEAD
Branch point for: connpatch, dirpatch, mmapppatch
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /* redirect - simple redirection CGI program
2     **
3     ** Copyright © 1995 by Jef Poskanzer <jef@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     }