📄 ssi.c
字号:
/* ssi - server-side-includes CGI program**** Copyright (C) 1995 by Jef Poskanzer <jef@acme.com>. All rights reserved.**** Redistribution and use in source and binary forms, with or without** modification, are permitted provided that the following conditions** are met:** 1. Redistributions of source code must retain the above copyright** notice, this list of conditions and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright** notice, this list of conditions and the following disclaimer in the** documentation and/or other materials provided with the distribution.**** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF** SUCH DAMAGE.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <sys/types.h>#include <sys/stat.h>#include "config.h"#define ST_GROUND 0#define ST_LESSTHAN 1#define ST_BANG 2#define ST_MINUS1 3#define ST_MINUS2 4static void read_file( char* vfilename, char* filename, FILE* fp );static char* argv0;static char* url;static char timefmt[100];static int sizefmt;#define SF_BYTES 0#define SF_ABBREV 1static struct stat sb;static voidinternal_error( char* reason ) { char* title = "500 Internal Error"; (void) printf( "\Content-type: text/html\n\\n\<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\<BODY><H2>%s</H2>\n\Something unusual went wrong during a server-side-includes request:\n\<BLOCKQUOTE>\n\%s\n\</BLOCKQUOTE>\n\</BODY></HTML>\n", title, title, reason ); }static voidnot_found( char* filename ) { char* title = "404 Not Found"; (void) printf( "\Content-type: text/html\n\\n\<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\<BODY><H2>%s</H2>\n\The requested server-side-includes filename, %s,\n\does not seem to exist.\n\</BODY></HTML>\n", title, title, filename ); }static voidnot_found2( char* directive, char* tag, char* filename2 ) { char* title = "Not Found"; (void) printf( "\<HR><H2>%s</H2>\n\The filename requested in a %s %s directive, %s,\n\does not seem to exist.\n\<HR>\n", title, directive, tag, filename2 ); }static voidnot_permitted( char* directive, char* tag, char* val ) { char* title = "Not Permitted"; (void) printf( "\<HR><H2>%s</H2>\n\The filename requested in the %s %s=%s directive\n\contains .. or is an absolute pathname.\n\<HR>\n", title, directive, tag, val ); }static voidunknown_directive( char* filename, char* directive ) { char* title = "Unknown Directive"; (void) printf( "\<HR><H2>%s</H2>\n\The requested server-side-includes filename, %s,\n\tried to use an unknown directive, %s.\n\<HR>\n", title, filename, directive ); }static voidunknown_tag( char* filename, char* directive, char* tag ) { char* title = "Unknown Tag"; (void) printf( "\<HR><H2>%s</H2>\n\The requested server-side-includes filename, %s,\n\tried to use the directive %s with an unknown tag, %s.\n\<HR>\n", title, filename, directive, tag ); }static voidunknown_value( char* filename, char* directive, char* tag, char* val ) { char* title = "Unknown Value"; (void) printf( "\<HR><H2>%s</H2>\n\The requested server-side-includes filename, %s,\n\tried to use the directive %s %s with an unknown value, %s.\n\<HR>\n", title, filename, directive, tag, val ); }static intget_filename( char* vfilename, char* filename, char* directive, char* tag, char* val, char* fn, int fnsize ) { int vl, fl; char* cp; /* Used for the various commands that accept a file name. ** These commands accept two tags: ** virtual ** Gives a virtual path to a document on the server. ** file ** Gives a pathname relative to the current directory. ../ cannot ** be used in this pathname, nor can absolute paths be used. */ vl = strlen( vfilename ); fl = strlen( filename ); if ( strcmp( tag, "virtual" ) == 0 ) { if ( strstr( val, "../" ) != (char*) 0 ) { not_permitted( directive, tag, val ); return -1; } /* Figure out root using difference between vfilename and filename. */ if ( vl > fl || strcmp( vfilename, &filename[fl - vl] ) != 0 ) return -1; if ( fl - vl + strlen( val ) >= fnsize ) return -1; (void) strncpy( fn, filename, fl - vl ); (void) strcpy( &fn[fl - vl], val ); } else if ( strcmp( tag, "file" ) == 0 ) { if ( val[0] == '/' || strstr( val, "../" ) != (char*) 0 ) { not_permitted( directive, tag, val ); return -1; } if ( fl + 1 + strlen( val ) >= fnsize ) return -1; (void) strcpy( fn, filename ); cp = strrchr( fn, '/' ); if ( cp == (char*) 0 ) { cp = &fn[strlen( fn )]; *cp = '/'; } (void) strcpy( ++cp, val ); } else { unknown_tag( filename, directive, tag ); return -1; } return 0; }static voidshow_time( time_t t, int gmt ) { struct tm* tmP; char tbuf[500]; if ( gmt ) tmP = gmtime( &t ); else tmP = localtime( &t ); if ( strftime( tbuf, sizeof(tbuf), timefmt, tmP ) > 0 ) (void) fputs( tbuf, stdout ); }static voidshow_size( off_t size ) { switch ( sizefmt ) { case SF_BYTES: (void) printf( "%ld", (long) size ); /* spec says should have commas */ break; case SF_ABBREV: if ( size < 1024 ) (void) printf( "%ld", (long) size ); else if ( size < 1024 ) (void) printf( "%ldK", (long) size / 1024L ); else if ( size < 1024*1024 ) (void) printf( "%ldM", (long) size / (1024L*1024L) ); else (void) printf( "%ldG", (long) size / (1024L*1024L*1024L) ); break; } }static voiddo_config( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val ) { /* The config directive controls various aspects of the file parsing. ** There are two valid tags: ** timefmt ** Gives the server a new format to use when providing dates. This ** is a string compatible with the strftime library call. ** sizefmt ** Determines the formatting to be used when displaying the size of ** a file. Valid choices are bytes, for a formatted byte count ** (formatted as 1,234,567), or abbrev for an abbreviated version ** displaying the number of kilobytes or megabytes the file occupies. */ if ( strcmp( tag, "timefmt" ) == 0 ) { (void) strncpy( timefmt, val, sizeof(timefmt) - 1 ); timefmt[sizeof(timefmt) - 1] = '\0'; } else if ( strcmp( tag, "sizefmt" ) == 0 ) { if ( strcmp( val, "bytes" ) == 0 ) sizefmt = SF_BYTES; else if ( strcmp( val, "abbrev" ) == 0 ) sizefmt = SF_ABBREV; else unknown_value( filename, directive, tag, val ); } else unknown_tag( filename, directive, tag ); }static voiddo_include( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val ) { char vfilename2[1000]; char filename2[1000]; FILE* fp2; /* Inserts the text of another document into the parsed document. */ if ( get_filename( vfilename, filename, directive, tag, val, filename2, sizeof(filename2) ) < 0 ) return; fp2 = fopen( filename2, "r" ); if ( fp2 == (FILE*) 0 ) { not_found2( directive, tag, filename2 ); return; } if ( strcmp( tag, "virtual" ) == 0 ) { if ( strlen( val ) < sizeof( vfilename2 ) ) (void) strcpy( vfilename2, val ); else (void) strcpy( vfilename2, filename2 ); /* same size, has to fit */ } else { if ( strlen( vfilename ) + 1 + strlen( val ) < sizeof(vfilename2) ) { char* cp; (void) strcpy( vfilename2, vfilename ); cp = strrchr( vfilename2, '/' ); if ( cp == (char*) 0 ) { cp = &vfilename2[strlen( vfilename2 )]; *cp = '/'; } (void) strcpy( ++cp, val ); } else (void) strcpy( vfilename2, filename2 ); /* same size, has to fit */ } read_file( vfilename2, filename2, fp2 ); (void) fclose( fp2 ); }static voiddo_echo( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val ) { char* cp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -