File: secure_insert.pike

package info (click to toggle)
libroxen-secureinsert 000409-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 32 kB
  • sloc: makefile: 36
file content (240 lines) | stat: -rw-r--r-- 5,529 bytes parent folder | download | duplicates (3)
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 &lt;sinsert&gt;.  "
	  "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\">&lt;sinsert&gt;</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	     
  });
}