1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
|
#!/usr/local/bin/pike
#include <module.h>
inherit "module";
inherit "roxenlib";
inherit Stdio;
// CRD 09/04/2000 cdawson@webiphany.com
//
// Secure insert
//
// Used to insert macro files in a secure way. Files are stored in a
// root outside of the nromal http root. Fiesl cannot be referenced
// via normal get requests. So, you can have information that will
// be inserted into your files and parsed only once, but there is no
// security risk if someone were to figure out your paths.
//
// v 0.1 09/04/2000 CRD
//
#define false 0
#define true 1
#define SCRIPT_ERROR "Error with the script"
class cached_file {
string contents;
string filename;
int timestamp;
}
int last_index = 0;
// Cache for one hour
int threshold = ( 60 * 60 );
#define FILE_CACHE_SIZE 100
array( object( cached_file ) ) cfiles = ({});
#define SECURE_DIR "secdir"
#define FILE_NOT_FOUND( x ) ( "<!-- File not found: " + x + " -->" )
void create() {
defvar( SECURE_DIR,
"NONE",
"Secured include directory",
TYPE_DIR,
"This directory is a secure place to place files which don't "
"need to be parsed (or can't) and insert them outside the "
"normal http directory tree. Usage is <sinsert>. "
"Use the cache attribute to cache files and speed up insertion." );
}
string secure_insert(string tag, mapping args, object id );
string real_get_file( string name ) {
string contents = "";
string dir = query( SECURE_DIR );
object file = Stdio.File();
if( file->open( dir + name, "r" ) ) {
contents = file->read();
}
return contents;
}
string get_contents( string name, int cache ) {
string contents = "";
int current = time();
int found = false;
int index = 0;
// Start at the last_index, instead of zero...
int better_index = 0;
if( !cfiles || sizeof( cfiles ) == 0 ) {
cfiles = ({});
for( index = 0; index < FILE_CACHE_SIZE; index++ ) {
cfiles += ({ cached_file() });
}
}
if( cache ) {
// See if we have it, and check the timeout
for( index = 0; index < sizeof( cfiles ); index++ ) {
better_index = ( index + last_index ) % FILE_CACHE_SIZE;
if( // cfiles[ better_index ] &&
cfiles[ better_index ]->filename &&
cfiles[ better_index ]->filename == name ) {
if( cfiles[ better_index ]->timestamp + threshold < current ) {
// Cached has expired, reload
contents = real_get_file( name );
if( "" != contents ) {
cfiles[ better_index ]->timestamp = current;
cfiles[ better_index ]->contents = contents;
}
else {
// Yikes, clear it here.
cfiles[ better_index ] = cached_file();
contents = FILE_NOT_FOUND( name );
}
}
else {
contents = cfiles[ better_index ]->contents;
}
// Escape the loop
index = FILE_CACHE_SIZE;
found = true;
}
}
if( !found ) {
last_index = ( last_index+1 ) % FILE_CACHE_SIZE;
// kick out the one at the last index
contents = real_get_file( name );
if( "" != contents ) {
cfiles[ last_index ]->contents = contents;
cfiles[ last_index ]->filename = name;
cfiles[ last_index ]->timestamp = current;
}
else {
contents = FILE_NOT_FOUND( name );
}
}
} // if ( cache )
else {
contents = real_get_file( name );
if( "" == contents ) {
contents = FILE_NOT_FOUND( name );
}
}
return contents;
}
string usage() {
return "<br><br><font size=\"+2\"><sinsert></font>"
"<br><br>\n<i>attributes</i>:<br>"
"<b>filename</b>: filename, added to the directory specified in "
"the module, used to resolve the file<br><b>nocache</b>: don't cache the file, "
"for more rapid access<br><b>debug</b>: print out debugging "
"information<br><br>Use no attributes for this usage message<br><br>";
}
string debug() {
string return_string = "";
int index = 0;
int better_index = 0;
int current = time();
return_string += "<br>Summary of cached files, sorted by timestamp:<br>";
if( !cfiles || sizeof( cfiles ) == 0 ) {
return_string += "No files cached<br>";
}
else
{
for( index = 0;
index < FILE_CACHE_SIZE;
index++ ) {
better_index = ( index + last_index + 1 ) % FILE_CACHE_SIZE;
if( cfiles[ better_index ] &&
cfiles[ better_index ]->filename &&
cfiles[ better_index ]->filename != "" ) {
return_string += "<i>File #" + (string)index + "</i> ";
return_string +=
"<b>filename</b>: " + cfiles[ better_index ]->filename +
" expires in " +
(string)( ( current + threshold ) -
cfiles[ better_index ]->timestamp ) +
" seconds" +
"<br>\n";
}
else {
// return_string += "</b>uncached</b>\n<br>";
}
}
}
return return_string;
}
string secure_insert(string tag, mapping args, object id ) {
string return_string = "";
// Resolve file
string filename = args->filename;
int cache = ( !args->nocache );
if( !filename || filename == "" ) {
if( args->debug ) {
return_string += debug();
}
else {
return_string += usage();
}
}
else {
return_string = get_contents( filename, cache );
}
return return_string;
}
mapping query_tag_callers() {
return ( [ "sinsert" : secure_insert ] );
}
array register_module()
{
return ({ MODULE_PARSER,
"Secure insert",
"This module is used to inesrt files securely. The files are "
"setup in a special directory outside the normal http directory." +
usage(),
0, 1
});
}
|