1430c0 | 2000-03-16 | Martin Nilsson | |
|
ea72a6 | 1999-11-27 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | constant cvs_version = "$Id: piketag.pike,v 2.11 2000/08/09 07:25:05 per Exp $";
|
ea72a6 | 1999-11-27 | Per Hedbor | | constant thread_safe=1;
inherit "module";
|
e123c7 | 2000-07-17 | Johan Sundström | | #include <module.h>
|
ea72a6 | 1999-11-27 | Per Hedbor | |
constant module_type = MODULE_PARSER;
constant module_name = "Pike tag";
constant module_doc =
#"This module adds a new tag, <pike></pike>. It makes it
|
197355 | 2000-02-10 | Martin Nilsson | | possible to insert some pike code directly in the document. <br>
<img src=\"internal-roxen-err_2\" align=\"left\" alt=\"Warning\"> <br>NOTE: Enabling this
|
ea72a6 | 1999-11-27 | Per Hedbor | | module is the same thing as letting your users run programs with the
same right as the server! Example:<p><pre> <pike> return
\"Hello world!\\n\"; </pike>\n</pre> <p>Arguments: Any, all
arguments are passed to the script in the mapping args. There are also
a few helper functions available, output(string fmt, mixed ... args)
is a fast way to add new data to a dynamic buffer, flush() returns the
contents of the buffer as a string. A flush() is done automatically
if the script does not return any data, thus, another way to write the
hello world script is <tt><pike>output(\"Hello %s\n\",
\"World\");</pike></tt><p> The request id is available as id.";
|
654037 | 2000-08-09 | Per Hedbor | |
|
ea72a6 | 1999-11-27 | Per Hedbor | | void create()
{
defvar (
"debugmode", "Log", "Error messages", TYPE_STRING_LIST | VAR_MORE,
"How to report errors (e.g. backtraces generated by the Pike code):\n"
"\n"
"<p><ul>\n"
|
4f641b | 2000-07-03 | Martin Nilsson | | "<li><i>Off</i> - Silent.</li>\n"
"<li><i>Log</i> - System debug log.</li>\n"
"<li><i>HTML comment</i> - Include in the generated page as an HTML comment.</li>\n"
"<li><i>HTML text</i> - Include in the generated page as normal text.</li>\n"
|
ea72a6 | 1999-11-27 | Per Hedbor | | "</ul>\n",
({"Off", "Log", "HTML comment", "HTML text"}));
defvar("program_cache_limit", 256, "Program cache limit", TYPE_INT|VAR_MORE,
"Maximum size of the cache for compiled programs.");
}
string reporterr (string header, string dump)
{
|
4f641b | 2000-07-03 | Martin Nilsson | | if (query("debugmode") == "Off") return "";
|
ea72a6 | 1999-11-27 | Per Hedbor | |
report_error( header + dump + "\n" );
|
4f641b | 2000-07-03 | Martin Nilsson | | switch (query("debugmode"))
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
case "HTML comment":
|
4f641b | 2000-07-03 | Martin Nilsson | | return "\n<!-- " + Roxen.html_encode_string(header + dump) + "\n-->\n";
|
ea72a6 | 1999-11-27 | Per Hedbor | | case "HTML text":
|
4f641b | 2000-07-03 | Martin Nilsson | | return "\n<br><font color=\"red\"><b><pre>" + Roxen.html_encode_string (header) +
"</b></pre></font><pre>\n"+Roxen.html_encode_string (dump) + "</pre><br />\n";
|
ea72a6 | 1999-11-27 | Per Hedbor | | default:
return "";
}
}
class Helpers
{
string data = "";
void output(mixed ... args)
{
|
654037 | 2000-08-09 | Per Hedbor | | write( @args );
|
ea72a6 | 1999-11-27 | Per Hedbor | | }
|
325751 | 2000-08-09 | Per Hedbor | | void write(mixed ... args)
{
if(!sizeof(args))
return;
if(sizeof(args) > 1)
data += sprintf(@args);
else
data += args[0];
}
|
ea72a6 | 1999-11-27 | Per Hedbor | | string flush()
{
string r = data;
data ="";
return r;
}
|
654037 | 2000-08-09 | Per Hedbor | | string rxml( string what )
|
3aca38 | 2000-08-09 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | | return Roxen.parse_rxml( what, RXML.get_context()->id );
|
3aca38 | 2000-08-09 | Per Hedbor | | }
|
ea72a6 | 1999-11-27 | Per Hedbor | | constant seteuid=0;
constant setegid=0;
constant setuid=0;
constant setgid=0;
constant call_out=0;
constant all_constants=0;
constant Privs=0;
}
|
654037 | 2000-08-09 | Per Hedbor | | class HProtos
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | | void output(mixed ... args);
void write(mixed ... args);
string flush();
string rxml( string what, object id );
constant seteuid=0;
constant setegid=0;
constant setuid=0;
constant setgid=0;
constant call_out=0;
constant all_constants=0;
constant Privs=0;
|
ea72a6 | 1999-11-27 | Per Hedbor | | }
|
654037 | 2000-08-09 | Per Hedbor | | string helpers()
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | | add_constant( "__ps_magic_helpers", Helpers );
add_constant( "__ps_magic_protos", HProtos );
return "inherit __ps_magic_helpers;\nimport Roxen;\n";
|
ea72a6 | 1999-11-27 | Per Hedbor | | }
|
654037 | 2000-08-09 | Per Hedbor | | string helper_prototypes( )
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | | return "inherit __ps_magic_protos;\nimport Roxen;\n";
|
ea72a6 | 1999-11-27 | Per Hedbor | | }
private static mapping(string:program) program_cache = ([]);
|
325751 | 2000-08-09 | Per Hedbor | | string simple_pi_tag_pike( string tag, mapping m, string s,RequestID id )
{
return simpletag_pike( tag, ([]), s, id );
}
|
654037 | 2000-08-09 | Per Hedbor | | string read_roxen_file( string what, object id )
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | |
return id->conf->open_file(Roxen.fix_relative(what,id),"rR",id,1)
->read()[0];
}
|
9266a3 | 2000-08-09 | Per Hedbor | |
|
3aca38 | 2000-08-09 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | #define PS(X) (compile_string( "mixed foo(){ return "+(X)+";}")()->foo())
#define SPLIT(X) Parser.C.hide_whitespaces(Parser.C.tokenize(Parser.C.split(X)))
|
3aca38 | 2000-08-09 | Per Hedbor | | #define OCIP( ) \
if( cip ) \
{ \
|
654037 | 2000-08-09 | Per Hedbor | | cip->text=sprintf("write(rxml(%O));",cip->text); \
|
3aca38 | 2000-08-09 | Per Hedbor | | cip = 0; \
}
#define OCIPUP( ) \
if( cipup ) \
{ \
cipup->text=sprintf("write(%O);",cipup->text); \
cipup = 0; \
}
#define CIP(X) if( X ) \
{ \
flat[i]->text=flat[i]->trailing_whitespaces=""; \
X->text += flat[i]->text[3..]+"\n"; \
} \
else \
{ \
X = flat[i]; \
flat[i]->text = flat[i]->text[3..]+"\n"; \
}
|
654037 | 2000-08-09 | Per Hedbor | | #define R(X) Parser.C.simple_reconstitute(X)
|
9266a3 | 2000-08-09 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | program my_compile_string(string s, object id, int dom, string fn)
{
if( program_cache[ s ] )
return program_cache[ s ];
object key = Roxen.add_scope_constants();
[array ip, array data] = parse_magic(s,id,dom);
if( !fn )fn = "pike-tag("+id->not_query+")";
int cnt;
string pre;
if( !id->misc->__added_helpers_in_tree && !sizeof(ip))
{
id->misc->__added_helpers_in_tree=1;
pre = helpers();
}
else
pre = helper_prototypes();
foreach( ip, program ipc )
{
add_constant( "____ih_"+cnt, ipc );
pre += "inherit ____ih_"+cnt++ + ";\n";
}
program p = compile_string(pre+R(data), fn);
program_cache[ s ] = p;
|
3aca38 | 2000-08-09 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | cnt=0;
foreach( ip, program ipc ) add_constant( "____ih_"+cnt++, 0 );
destruct( key );
return p;
}
|
ea72a6 | 1999-11-27 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | program handle_inherit( string what, RequestID id )
{
array err;
return my_compile_string( read_roxen_file( what, id ),id,0,0);
}
array parse_magic( string data, RequestID id, int add_md )
{
array flat=SPLIT(data);
object cip, cipup;
array inherits = ({});
for( int i = 0; i<sizeof( flat ); i++ )
{
switch( strlen(flat[i]->text) && flat[i]->text[0] )
|
ea72a6 | 1999-11-27 | Per Hedbor | | {
|
654037 | 2000-08-09 | Per Hedbor | | case 'i':
OCIP(); OCIPUP();
if( flat[i] == "inherit" )
{
flat[i]->text="";
int start = ++i;
while( flat[++i] != ";" ) ;
inherits += ({ handle_inherit( PS(R(flat[start..i])), id ) });
flat = flat[..start-1] + flat[i+1..];
i = start;
}
break;
case 'p':
OCIP(); OCIPUP();
if( flat[i] == "parse" && flat[i+1] == "(")
add_md = 0;
break;
case '.':
OCIP(); OCIPUP();
if( flat[i] == "." && flat[++i] != "." )
flat[i-1]->text = "->";
break;
case '/':
if( flat[i]->text[..2] == "//#" )
{
OCIPUP();
CIP( cip );
}
else if( flat[i]->text[..2] == "//@" )
{
OCIP();
CIP( cipup );
}
else
{
OCIPUP();
OCIP();
}
break;
case '#':
OCIP(); OCIPUP();
if( sscanf( flat[i]->text, "#include%s", string fn) )
{
sscanf( fn, "%*s<%s>", fn );
sscanf( fn, "%*s\"%s\"", fn );
[array ih,flat[i]] = parse_magic(read_roxen_file(fn,id), id, 0);
inherits += ih;
}
break;
default:
OCIP();
OCIPUP();
}
}
OCIP();
OCIPUP();
if( add_md )
{
flat =SPLIT( "string|int parse(RequestID id)\n{\n" )
+ flat
+ SPLIT( "}\n" );
}
return ({ inherits, flat });
}
|
9266a3 | 2000-08-09 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | |
string simpletag_pike(string tag, mapping m, string s,RequestID request_id )
{
program p;
object o;
string res;
mixed err;
|
325751 | 2000-08-09 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | request_id->misc->__added_helpers_in_tree=0;
request_id->misc->cacheable=0;
|
ea72a6 | 1999-11-27 | Per Hedbor | |
|
654037 | 2000-08-09 | Per Hedbor | | object e = ErrorContainer();
master()->set_inhibit_compile_errors(e);
if(err=catch
{
p = my_compile_string( s,request_id,1,0 );
if (sizeof(program_cache) > query("program_cache_limit"))
{
array a = indices(program_cache);
int i;
for(i = query("program_cache_limit")/2; i > 0; i--)
m_delete(program_cache, a[random(sizeof(a))]);
|
ea72a6 | 1999-11-27 | Per Hedbor | | }
})
{
master()->set_inhibit_compile_errors(0);
|
654037 | 2000-08-09 | Per Hedbor | | return reporterr(sprintf("Error handling <pike> tag in %s:\n%s\n"
"%s\n\n",
request_id->not_query,
s, describe_backtrace(err[..1])),
|
ea72a6 | 1999-11-27 | Per Hedbor | | e->get());
}
master()->set_inhibit_compile_errors(0);
if(err = catch{
|
325751 | 2000-08-09 | Per Hedbor | | res = (o=p())->parse(request_id);
|
ea72a6 | 1999-11-27 | Per Hedbor | | })
{
return (res || "") + (o && o->flush() || "") +
reporterr ("Error in <pike> tag in " + request_id->not_query + ":\n",
(describe_backtrace (err) / "\n")[0..1] * "\n");
}
res = (res || "") + (o && o->flush() || "");
if(o)
destruct(o);
return res;
}
|