|
|
#include <module.h> |
#include <roxen.h> |
|
|
|
|
#define LOCALE(X,Y) \ |
([string](mixed)Locale.translate("roxen_config",roxenp()->locale->get(),X,Y)) |
|
|
static int unique_vid; |
|
|
|
|
|
static mapping(int:mixed) changed_values = ([]); |
static mapping(int:function(object:void)) changed_callbacks = ([]); |
static mapping(int:int) all_flags = ([]); |
static mapping(int:string) all_warnings = ([]); |
static mapping(int:function(RequestID,object:int)) |
invisibility_callbacks = set_weak_flag( ([]), 1 ); |
|
mapping(string:Variable) all_variables = set_weak_flag( ([]), 1 ); |
|
mapping get_all_variables() |
{ |
return all_variables; |
} |
|
Variable get_variables( string v ) |
{ |
return all_variables[v]; |
} |
|
class Diff |
{ |
static private array(string) diff; |
|
static private |
array(string) print_row(array(string) diff_old, array(string) diff_new, |
int line, int|void start, int|void end) |
{ |
if(!sizeof(diff_old) && sizeof(diff_new)) |
|
return Array.map(diff_new, lambda(string s) {return "+ " + s;} ); |
|
if(sizeof(diff_old) && !sizeof(diff_new)) |
|
return Array.map(diff_old, lambda(string s) {return "- " + s;} ); |
|
if(diff_old != diff_new) |
|
return Array.map(diff_old, lambda(string s) {return "- " + s;} ) |
+ Array.map(diff_new, lambda(string s) {return "+ " + s;} ); |
|
if(start + end < sizeof(diff_old) && (start || end)) |
{ |
if(start && !end) |
diff_old = diff_old[.. start - 1]; |
else |
{ |
diff_old = diff_old[.. start - 1] + |
({ line + sizeof(diff_old) - end }) + |
diff_old[sizeof(diff_old) - end ..]; |
} |
} |
|
return Array.map(diff_old, lambda(string|int s) |
{ if(intp(s)) return "Line "+s+":"; |
return " " + s; } ); |
} |
|
string html(void|int hide_header) |
{ |
string r = ""; |
int added, deleted; |
if(sizeof(diff) && diff[-1] == " ") |
diff = diff[..sizeof(diff)-2]; |
foreach(diff, string row) |
{ |
row = Roxen.html_encode_string(row); |
row = replace(row, "\t", " "); |
row = replace(row, " ", " "); |
switch(row[0]) |
{ |
case '&': r += "<tt>"+row+"</tt><br>\n"; |
break; |
case '+': r += "<tt><font color='darkgreen'>"+row+"</font></tt><br>\n"; |
added++; |
break; |
case '-': r += "<tt><font color='darkred'>"+row+"</font></tt><br>\n"; |
deleted++; |
break; |
case 'L': r += "<i>"+row+"</i><br>\n"; |
break; |
} |
} |
if (!hide_header) |
r = |
"<b>" + LOCALE(201, "Change in content") + "</b><br />\n"+ |
"<i>"+(added==1? LOCALE(452, "1 line added."): |
sprintf(LOCALE(453, "%d lines added."), added)) + " " + |
(deleted==1? LOCALE(454, "1 line deleted."): |
sprintf(LOCALE(455, "%d lines deleted."), deleted)) + |
"</i><p>\n"+ |
r; |
return r; |
} |
|
array get() |
{ |
return diff; |
} |
|
void create(array(string) new, array(string) old, int context) |
{ |
array(array(string)) diff_old, diff_new; |
|
[diff_old, diff_new] = Array.diff(old, new); |
int line = 1; |
int diffp = 0; |
diff = ({ }); |
for(int i = 0; i < sizeof(diff_old); i++) |
{ |
if(diff_old[i] != diff_new[i]) |
{ |
diff += print_row(diff_old[i], diff_new[i], line); |
|
diffp = 1; |
} |
else if(sizeof(diff_old) > 1) |
{ |
diff += print_row(diff_old[i], diff_new[i], line, |
diffp?context:0, |
sizeof(diff_old) - 1 > i?context:0 ); |
diffp = 0; |
} |
line += sizeof(diff_old[i] - ({ })); |
} |
} |
} |
|
|
|
class Variable |
|
|
{ |
constant is_variable = 1; |
|
constant type = "Basic"; |
|
|
int _id = unique_vid++; |
|
|
static mixed _initial; |
static string _path = sprintf("v%x",_id); |
static LocaleString __name, __doc; |
|
string diff( int render ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
return 0; |
} |
|
void destroy() |
{ |
|
m_delete( all_flags, _id ); |
m_delete( all_warnings, _id ); |
m_delete( invisibility_callbacks, _id ); |
m_delete( changed_values, _id ); |
} |
|
string get_warnings() |
|
{ |
return all_warnings[ _id ]; |
} |
|
int get_flags() |
|
|
|
|
|
|
|
{ |
return all_flags[_id]; |
} |
|
void set_flags( int flags ) |
|
|
|
|
|
|
|
{ |
if(!flags ) |
m_delete( all_flags, _id ); |
else |
all_flags[_id] = flags; |
} |
|
int check_visibility( RequestID id, |
int more_mode, |
int expert_mode, |
int devel_mode, |
int initial, |
int|void variable_in_cfif ) |
|
|
|
|
|
|
|
{ |
int flags = get_flags(); |
function cb; |
if( flags & VAR_INVISIBLE ) return 0; |
if( initial && !(flags & VAR_INITIAL) ) return 0; |
if( (flags & VAR_EXPERT) && !expert_mode ) return 0; |
if( (flags & VAR_MORE) && !more_mode ) return 0; |
if( (flags & VAR_DEVELOPER) && !devel_mode ) return 0; |
if( (flags & VAR_NOT_CFIF) && variable_in_cfif ) return 0; |
if( (cb = get_invisibility_check_callback() ) && |
cb( id, this_object() ) ) |
return 0; |
return 1; |
} |
|
void set_invisibility_check_callback( function(RequestID,Variable:int) cb ) |
|
|
|
|
{ |
if( functionp( cb ) ) |
invisibility_callbacks[ _id ] = cb; |
else |
m_delete( invisibility_callbacks, _id ); |
} |
|
function(Variable:void) get_changed_callback( ) |
|
{ |
return changed_callbacks[ _id ]; |
} |
|
void set_changed_callback( function(Variable:void) cb ) |
|
|
|
|
{ |
if( functionp( cb ) ) |
changed_callbacks[ _id ] = cb; |
else |
m_delete( changed_callbacks, _id ); |
} |
|
void add_changed_callback( function(Variable:void) cb ) |
|
|
|
{ |
mixed oc = get_changed_callback( ); |
if( arrayp( oc ) ) |
oc += ({ cb }); |
else |
oc = ({ oc, cb }) - ({ 0 }); |
changed_callbacks[ _id ] = oc; |
} |
|
function(RequestID,Variable:int) get_invisibility_check_callback() |
|
{ |
return invisibility_callbacks[_id]; |
} |
|
LocaleString doc( ) |
|
|
|
|
{ |
return __doc || ""; |
} |
|
LocaleString name( ) |
|
|
|
|
{ |
return __name || LOCALE(326,"unnamed")+" "+_id; |
} |
|
LocaleString type_hint( ) |
|
|
|
{ |
} |
|
mixed default_value() |
|
{ |
return _initial; |
} |
|
void set_warning( string to ) |
|
{ |
if( to && strlen(to) ) |
all_warnings[ _id ] = to; |
else |
m_delete( all_warnings, _id ); |
} |
|
void add_warning( string to ) |
|
{ |
if(to) set_warning( (get_warnings()||"") + to ); |
} |
|
int set( mixed to ) |
|
|
|
|
|
|
|
|
|
|
|
{ |
string err, e2; |
if( e2 = catch( [err,to] = verify_set( to )) ) |
{ |
if( stringp( e2 ) ) |
{ |
add_warning( e2 ); |
return ([])[0]; |
} |
throw( e2 ); |
} |
add_warning( err ); |
return low_set( to ); |
} |
|
int low_set( mixed to ) |
|
|
|
|
{ |
if( equal( to, query() ) ) |
return 0; |
|
if( !equal(to, default_value() ) ) |
{ |
changed_values[ _id ] = to; |
if( get_changed_callback() ) |
catch( get_changed_callback()( this_object() ) ); |
return 1; |
} |
else |
{ |
m_delete( changed_values, _id ); |
if( get_changed_callback() ) |
catch( get_changed_callback()( this_object() ) ); |
return -1; |
} |
} |
|
mixed query() |
|
{ |
mixed v; |
if( !zero_type( v = changed_values[ _id ] ) ) |
return v; |
return default_value(); |
} |
|
int is_defaulted() |
|
{ |
return zero_type( changed_values[ _id ] ) || |
equal(changed_values[ _id ], default_value()); |
} |
|
array(string|mixed) verify_set_from_form( mixed new_value ) |
|
|
{ |
return ({ 0, new_value }); |
} |
|
array(string|mixed) verify_set( mixed new_value ) |
|
|
|
|
|
|
|
|
{ |
return ({ 0, new_value }); |
} |
|
mapping(string:string) get_form_vars( RequestID id ) |
|
{ |
string p = path(); |
array names = glob( p+"*", indices(id->variables) ); |
mapping res = ([ ]); |
foreach( sort(names), string n ) |
res[ n[strlen(p).. ] ] = id->variables[ n ]; |
return res; |
} |
|
mixed transform_from_form( string what, mapping|void v ) |
|
|
{ |
return what; |
} |
|
int(0..1) set_from_form( RequestID id, void|int(0..1) force ) |
|
|
|
|
|
|
|
|
|
|
|
{ |
mixed val; |
if( sizeof( val = get_form_vars(id)) && val[""]) |
{ |
val = transform_from_form( val[""], val ); |
if( !force && val == query() ) |
return 0; |
array b; |
mixed q = catch( b = verify_set_from_form( val ) ); |
if( q || sizeof( b ) != 2 ) |
{ |
if( q ) |
add_warning( q ); |
else |
add_warning( "Internal error: Illegal sized array " |
"from verify_set_from_form\n" ); |
return 0; |
} |
if( b ) |
{ |
set_warning( b[0] ); |
set( b[1] ); |
return 1; |
} |
} |
} |
|
string path() |
|
|
|
|
|
|
|
|
{ |
return _path; |
} |
|
void set_path( string to ) |
|
|
|
|
|
|
{ |
m_delete( all_variables, _path ); |
_path = to; |
all_variables[ to ] = this_object(); |
} |
|
string render_form( RequestID id, void|mapping additional_args ); |
|
|
|
|
string render_view( RequestID id ) |
|
{ |
mixed v = query(); |
if( arrayp(v) ) v = map(v,lambda(mixed v){return(string)v;})*", " ; |
return Roxen.html_encode_string( (string)v ); |
} |
|
static string _sprintf( int i ) |
{ |
if( i == 'O' ) |
return sprintf( "Variable.%s(%s)",type,(string)name()); |
} |
|
static void create(mixed default_value, void|int flags, |
void|LocaleString std_name, void|LocaleString std_doc) |
|
|
|
|
|
|
|
|
|
|
{ |
set_flags( flags ); |
_initial = default_value; |
__name = std_name; |
__doc = std_doc; |
all_variables[ path() ] = this_object(); |
} |
} |
|
|
|
|
|
|
|
|
class Float |
|
{ |
inherit Variable; |
constant type = "Float"; |
static float _max, _min; |
static int _prec = 2; |
|
static string _format( float m ) |
{ |
if( !_prec ) |
return sprintf( "%d", (int)m ); |
return sprintf( "%1."+_prec+"f", m ); |
} |
|
string diff( int render ) |
{ |
if(!render) |
return "("+_format(default_value())+")"; |
} |
|
void set_range(float minimum, float maximum ) |
|
|
{ |
_max = maximum; |
_min = minimum; |
} |
|
void set_precision( int prec ) |
|
|
|
{ |
_prec = prec; |
} |
|
array(string|float) verify_set( float new_value ) |
{ |
string warn; |
if( new_value > _max && _max > _min) |
{ |
warn = sprintf(LOCALE(328,"Value is bigger than %s, adjusted"), |
_format(_max) ); |
new_value = _max; |
} |
else if( new_value < _min && _min < _max) |
{ |
warn = sprintf(LOCALE(329,"Value is less than %s, adjusted"), |
_format(_min) ); |
new_value = _min; |
} |
return ({ warn, new_value }); |
} |
|
float transform_from_form( string what ) |
{ |
return (float)what; |
} |
|
string render_view( RequestID id ) |
{ |
return Roxen.html_encode_string( _format(query()) ); |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
int size = 15; |
if( _max != _min ) |
size = max( strlen(_format(_max)), strlen(_format(_min)) )+2; |
return input(path(), (query()==""?"":_format(query())), size, additional_args); |
} |
} |
|
|
|
|
|
|
|
|
class Int |
|
{ |
inherit Variable; |
constant type = "Int"; |
static int _max, _min; |
|
void set_range(int minimum, int maximum ) |
|
|
{ |
_max = maximum; |
_min = minimum; |
} |
|
string diff( int render ) |
{ |
if(!render) |
return "("+default_value()+")"; |
} |
|
array(string|int) verify_set( mixed new_value ) |
{ |
string warn; |
if(!intp( new_value ) ) |
return ({ sprintf(LOCALE(152,"%O is not an integer"),new_value), |
query() }); |
if( new_value > _max && _max > _min ) |
{ |
warn = sprintf(LOCALE(328,"Value is bigger than %s, adjusted"), |
(string)_max ); |
new_value = _max; |
} |
else if( new_value < _min && _min < _max) |
{ |
warn = sprintf(LOCALE(329,"Value is less than %s, adjusted"), |
(string)_min ); |
new_value = _min; |
} |
return ({ warn, new_value }); |
} |
|
int transform_from_form( mixed what ) |
{ |
sscanf( what, "%d", what ); |
return what; |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
int size = 10; |
if( _min != _max ) |
size = max( strlen((string)_max), strlen((string)_min) )+2; |
return input(path(), (string)query(), size, additional_args); |
} |
} |
|
|
|
|
|
class String |
|
{ |
inherit Variable; |
constant type = "String"; |
int width = 40; |
|
|
string diff( int render ) |
{ |
if(!render) |
return "("+Roxen.html_encode_string( default_value() )+")"; |
} |
|
array(string) verify_set_from_form( mixed new ) |
{ |
return ({ 0, [string]new-"\r" }); |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
return input(path(), (string)query(), width, additional_args); |
} |
} |
|
|
|
|
class Text |
|
{ |
inherit String; |
constant type = "Text"; |
|
int cols = 60; |
|
|
int rows = 10; |
|
|
string diff( int render ) |
{ |
switch( render ) |
{ |
case 0: return 0; |
case 1: return ""; |
case 2: |
array lines_orig = default_value()/"\n"; |
array lines_new = query()/"\n"; |
|
Diff diff = Diff( lines_new, lines_orig, 2 ); |
|
if( sizeof(diff->get()) ) |
return diff->html(); |
else |
return "<i>"+LOCALE(0,"No difference\n" )+"</i>"; |
} |
} |
|
array(string) verify_set_from_form( mixed new ) |
{ |
return ({ 0, [string]new-"\r" }); |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
return "<textarea cols='"+cols+"' rows='"+rows+"' name='"+path()+"'>" |
+ Roxen.html_encode_string( query() || "" ) + |
"</textarea>"; |
} |
|
static void create(mixed default_value, void|int flags, |
void|LocaleString std_name, void|LocaleString std_doc) |
|
|
|
|
|
|
|
|
|
|
{ |
if( strlen( default_value ) && default_value[0] == '\n' ) |
|
default_value = default_value[1..]; |
::create( default_value, flags, std_name, std_doc ); |
} |
|
} |
|
|
|
|
|
|
class Password |
|
{ |
inherit String; |
int width = 20; |
constant type = "Password"; |
|
int(0..1) set_from_form( RequestID id ) |
{ |
mapping val; |
if( sizeof( val = get_form_vars(id)) && |
val[""] && strlen(val[""]) ) { |
set( crypt( val[""] ) ); |
return 1; |
} |
return 0; |
} |
|
string render_view( RequestID id ) |
{ |
return "******"; |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
additional_args = additional_args || ([]); |
additional_args->type="password"; |
return input(path(), "", 30, additional_args); |
} |
} |
|
class File |
|
{ |
inherit String; |
constant type = "File"; |
int width = 50; |
|
string read( ) |
|
{ |
return Stdio.read_bytes( query() ); |
} |
|
Stat stat() |
|
{ |
return file_stat( query() ); |
} |
|
#ifdef __NT__ |
array verify_set( string value ) |
{ |
return ::verify_set( replace( value, "\\", "/" ) ); |
} |
#endif |
|
} |
|
class Location |
|
{ |
inherit String; |
constant type = "Location"; |
int width = 50; |
|
array verify_set( string value ) |
{ |
if( !strlen( value ) || !((<'~','/'>)[value[-1]]) ) |
return ({ |
LOCALE(330,"You most likely want an ending '/' on this variable"), |
value |
}); |
return ::verify_set( value ); |
} |
} |
|
class URL |
|
{ |
inherit String; |
constant type = "URL"; |
int width = 50; |
|
array verify_set_from_form( string new_value ) |
{ |
return verify_port( new_value ); |
} |
} |
|
class Directory |
|
{ |
inherit String; |
constant type = "Directory"; |
int width = 50; |
|
array verify_set( string value ) |
{ |
#ifdef __NT__ |
value = replace( value, "\\", "/" ); |
#endif |
if( strlen(value) && value[-1] != '/' ) |
value += "/"; |
if( !strlen( value ) ) |
return ::verify_set( value ); |
if( !(r_file_stat( value ) && (r_file_stat( value )[ ST_SIZE ] == -2 ))) |
return ({sprintf(LOCALE(331,"%s is not a directory"),value)+"\n",value}); |
return ::verify_set( value ); |
} |
|
Stat stat() |
|
{ |
return file_stat( query() ); |
} |
|
array get( ) |
|
{ |
return get_dir( query() ); |
} |
} |
|
|
|
|
|
|
|
class MultipleChoice |
|
{ |
inherit Variable; |
static array _list = ({}); |
static mapping _table = ([]); |
|
string diff( int render ) |
{ |
if(!render) |
return "("+_title( default_value() )+")"; |
} |
|
void set_choice_list( array to ) |
|
{ |
_list = to; |
} |
|
array get_choice_list( ) |
|
|
{ |
return _list; |
} |
|
void set_translation_table( mapping to ) |
|
{ |
_table = to; |
} |
|
mapping get_translation_table( ) |
|
|
{ |
return _table; |
} |
|
static string _name( mixed what ) |
|
|
{ |
return (string)what; |
} |
|
static string _title( mixed what ) |
|
|
{ |
if( mapping tt = get_translation_table() ) |
return tt[ what ] || (string)what; |
return (string)what; |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
string res = "<select name='"+path()+"'>\n"; |
string current = _name (query()); |
int selected = 0; |
foreach( get_choice_list(), mixed elem ) |
{ |
mapping m = ([]); |
m->value = _name( elem ); |
if( equal( m->value, current ) ) { |
m->selected="selected"; |
selected = 1; |
} |
res += " "+Roxen.make_container( "option", m, _title( elem ) )+"\n"; |
} |
if (!selected) |
|
|
|
res += " " + Roxen.make_container ( |
"option", (["value":_name(current), "selected": "selected"]), |
sprintf(LOCALE(332,"(keep stale value %s)"),_name(current))); |
return res + "</select>"; |
} |
|
static void create( mixed default_value, array|mapping choices, |
void|int _flags, void|LocaleString std_name, |
void|LocaleString std_doc ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
::create( default_value, _flags, std_name, std_doc ); |
if( mappingp( choices ) ) { |
set_translation_table( choices ); |
set_choice_list( indices(choices) ); |
} else |
set_choice_list( choices ); |
} |
} |
|
|
|
|
|
|
class StringChoice |
|
{ |
inherit MultipleChoice; |
constant type = "StringChoice"; |
} |
|
|
class IntChoice |
|
{ |
inherit MultipleChoice; |
constant type = "IntChoice"; |
int transform_from_form( string what ) |
{ |
return (int)what; |
} |
} |
|
class FloatChoice |
|
{ |
inherit MultipleChoice; |
constant type = "FloatChoice"; |
static int _prec = 3; |
|
void set_precision( int prec ) |
|
|
|
{ |
_prec = prec; |
} |
|
static string _title( mixed what ) |
{ |
if( !_prec ) |
return sprintf( "%d", (int)what ); |
return sprintf( "%1."+_prec+"f", what ); |
} |
|
int transform_from_form( string what ) |
{ |
array q = get_choice_list(); |
mapping a = mkmapping( map( q, _name ), q ); |
return a[what] || (float)what; |
} |
} |
|
class FontChoice |
|
{ |
inherit StringChoice; |
constant type = "FontChoice"; |
void set_choice_list() |
{ |
} |
array get_choice_list() |
{ |
return roxenp()->fonts->available_fonts(); |
} |
|
static void create(mixed default_value, void|int flags, |
void|LocaleString std_name, void|LocaleString std_doc) |
|
|
|
|
|
|
|
|
|
|
{ |
::create( default_value, 0, flags,std_name, std_doc ); |
} |
} |
|
class DatabaseChoice |
|
{ |
inherit StringChoice; |
constant type = "DatabaseChoice"; |
|
function(void:void|object) config = lambda() { return 0; }; |
|
DatabaseChoice set_configuration_pointer( function(void:object) configuration ) |
|
|
|
|
{ |
config = configuration; |
return this_object(); |
} |
|
array get_choice_list( ) |
{ |
return ({ " none" }) + sort(DBManager.list( config() )); |
} |
|
static void create(string default_value, void|int flags, |
void|LocaleString std_name, void|LocaleString std_doc) |
{ |
::create( default_value, ({}), flags, std_name, std_doc ); |
} |
} |
|
|
|
|
|
class List |
|
{ |
inherit Variable; |
constant type="List"; |
int width = 40; |
|
string transform_to_form( mixed what ) |
|
|
{ |
return (string)what; |
} |
|
mixed transform_from_form( string what,mapping v ) |
{ |
return what; |
} |
|
static int _current_count = time()*100+(gethrtime()/10000); |
int(0..1) set_from_form(RequestID id) |
{ |
int rn, do_goto; |
array l = query(); |
mapping vl = get_form_vars(id); |
|
if( (int)vl[".count"] != _current_count ) |
return 0; |
_current_count++; |
|
foreach( indices( vl ), string vv ) |
if( sscanf( vv, ".set.%d", rn ) && (vv == ".set."+rn) ) |
{ |
m_delete( id->variables, path()+vv ); |
l[rn] = transform_from_form( vl[vv], vl ); |
m_delete( vl, vv ); |
} |
|
foreach( indices(vl), string vv ) |
if( sscanf( vv, ".up.%d.x%*s", rn ) == 2 ) |
{ |
do_goto = 1; |
m_delete( id->variables, path()+vv ); |
m_delete( vl, vv ); |
l = l[..rn-2] + l[rn..rn] + l[rn-1..rn-1] + l[rn+1..]; |
} |
else if( sscanf( vv, ".down.%d.x%*s", rn )==2 ) |
{ |
do_goto = 1; |
m_delete( id->variables, path()+vv ); |
l = l[..rn-1] + l[rn+1..rn+1] + l[rn..rn] + l[rn+2..]; |
} |
|
if( vl[".new.x"] ) |
{ |
do_goto = 1; |
m_delete( id->variables, path()+".new.x" ); |
l += ({ transform_from_form( "",vl ) }); |
} |
|
|
foreach( indices(vl), string vv ) |
if( sscanf( vv, ".delete.%d.x%*s", rn )==2 ) |
{ |
do_goto = 1; |
m_delete( id->variables, path()+vv ); |
l = l[..rn-1] + l[rn+1..]; |
} |
|
array b; |
mixed q = catch( b = verify_set_from_form( l ) ); |
if( q || sizeof( b ) != 2 ) |
{ |
if( q ) |
set_warning( q ); |
else |
set_warning( "Internal error: Illegal sized array " |
"from verify_set_from_form\n" ); |
return 0; |
} |
|
int ret; |
if( b ) |
{ |
set_warning( b[0] ); |
set( b[1] ); |
ret = 1; |
} |
|
if( do_goto && !id->misc->do_not_goto ) |
{ |
RequestID nid = id; |
while( nid->misc->orig ) |
nid = id->misc->orig; |
|
string section = RXML.get_var("section", "var"); |
string query = nid->query; |
if( !query ) |
query = ""; |
else |
query += "&"; |
query += "random="+random(4949494)+(section?"§ion="+section:""); |
|
nid->misc->moreheads = |
([ |
"Location":nid->not_query+(nid->misc->path_info||"")+ |
"?"+query+"#"+path(), |
]); |
if( nid->misc->defines ) |
nid->misc->defines[ " _error" ] = 302; |
else if( id->misc->defines ) |
id->misc->defines[ " _error" ] = 302; |
} |
|
return ret; |
} |
|
|
string render_row(string prefix, mixed val, int width) |
{ |
return input( prefix, val, width ); |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
string prefix = path()+"."; |
int i; |
|
string res = "<a name='"+path()+"'>\n</a><table>\n" |
"<input type='hidden' name='"+prefix+"count' value='"+_current_count+"' />\n"; |
|
foreach( map(query(), transform_to_form), mixed val ) |
{ |
res += "<tr>\n<td><font size='-1'>"+ render_row(prefix+"set."+i, val, width) |
+ "</font></td>\n"; |
#define BUTTON(X,Y) ("<submit-gbutton2 name='"+X+"'>"+Y+"</submit-gbutton2>") |
#define REORDER(X,Y) ("<submit-gbutton2 name='"+X+"' icon-src='"+Y+"'></submit-gbutton2>") |
if( i ) |
res += "\n<td>"+ |
REORDER(prefix+"up."+i, "/internal-roxen-up")+ |
"</td>"; |
else |
res += "\n<td></td>"; |
if( i != sizeof( query())- 1 ) |
res += "\n<td>"+ |
REORDER(prefix+"down."+i, "/internal-roxen-down") |
+"</td>"; |
else |
res += "\n<td></td>"; |
res += "\n<td>"+ |
BUTTON(prefix+"delete."+i, LOCALE(227, "Delete") ) |
+"</td>"; |
"</tr>"; |
i++; |
} |
res += |
"\n<tr><td colspan='2'>"+ |
BUTTON(prefix+"new", LOCALE(297, "New row") )+ |
"</td></tr></table>\n\n"; |
|
return res; |
} |
} |
|
|
|
|
|
class DirectoryList |
|
{ |
inherit List; |
constant type="DirectoryList"; |
|
array verify_set( array(string) value ) |
{ |
string warn = ""; |
foreach( value, string vi ) |
{ |
if(!strlen(vi)) |
continue; |
if( !(r_file_stat( vi ) && (r_file_stat( vi )[ ST_SIZE ] == -2 ))) |
warn += sprintf(LOCALE(331,"%s is not a directory"),vi)+"\n"; |
if( strlen(vi) && vi[-1] != '/' ) |
value = replace( value, vi, vi+"/" ); |
} |
#ifdef __NT__ |
value = map( value, replace, "\\", "/" ); |
#endif |
if( strlen( warn ) ) |
return ({ warn, value }); |
|
return ::verify_set( value ); |
} |
} |
|
class StringList |
|
{ |
inherit List; |
constant type="StringList"; |
} |
|
class IntList |
|
{ |
inherit List; |
constant type="IntList"; |
int width=20; |
|
string transform_to_form(int what) { return (string)what; } |
int transform_from_form(string what,mapping v) { return (int)what; } |
} |
|
class FloatList |
|
{ |
inherit List; |
constant type="DirectoryList"; |
int width=20; |
|
static int _prec = 3; |
|
void set_precision( int prec ) |
|
|
|
{ |
_prec = prec; |
} |
|
string transform_to_form(int what) |
{ |
return sprintf("%1."+_prec+"f", what); |
} |
float transform_from_form(string what,mapping v) { return (float)what; } |
} |
|
class URLList |
|
{ |
inherit List; |
constant type="URLList"; |
|
array verify_set_from_form( array(string) new_value ) |
{ |
string warn = ""; |
array res = ({}); |
foreach( new_value, string vv ) |
{ |
string tmp1, tmp2; |
[tmp1,tmp2] = verify_port( vv ); |
if( tmp1 ) |
warn += tmp1; |
res += ({ tmp2 }); |
} |
if( !strlen( warn ) ) |
warn = 0; |
return ({ warn, res }); |
} |
} |
|
class PortList |
|
{ |
inherit List; |
constant type="PortList"; |
|
string render_row( string prefix, mixed val, int width ) |
{ |
string res = "<input type=hidden name='"+prefix+"' value='"+prefix+"' />"; |
|
Standards.URI split = Standards.URI( val ); |
|
res += "<select name='"+prefix+"prot'>"; |
foreach( sort(indices( roxenp()->protocols )), string p ) |
{ |
if( p == split->scheme ) |
res += "<option selected='t'>"+p+"</option>"; |
else |
res += "<option>"+p+"</option>"; |
} |
res += "</select>"; |
|
res += "://<input type=string name='"+prefix+"host' value='"+ |
Roxen.html_encode_string(split->host)+"' />"; |
res += ":<input type=string size=5 name='"+prefix+"port' value='"+ |
split->port+"' />"; |
|
res += "/<input type=string name='"+prefix+"path' value='"+ |
Roxen.html_encode_string(split->path[1..])+"' />"; |
|
return res; |
} |
|
string transform_from_form( string v, mapping va ) |
{ |
if( v == "" ) return "http://*/"; |
v = v[strlen(path())..]; |
return (string)Standards.URI(va[v+"prot"]+"://"+va[v+"host"]+":"+va[v+"port"]+"/"+va[v+"path"]); |
} |
|
array verify_set_from_form( array(string) new_value ) |
{ |
string warn = ""; |
array res = ({}); |
foreach( new_value, string vv ) |
{ |
string tmp1, tmp2; |
[tmp1,tmp2] = verify_port( vv ); |
if( tmp1 ) |
warn += tmp1; |
res += ({ tmp2 }); |
} |
if( !strlen( warn ) ) |
warn = ""; |
return ({ warn, res }); |
} |
} |
|
|
class FileList |
|
{ |
inherit List; |
constant type="FileList"; |
|
#ifdef __NT__ |
array verify_set( array(string) value ) |
{ |
return ::verify_set( map( value, replace, "\\", "/" ) ); |
} |
#endif |
} |
|
|
|
|
|
|
class Flag |
|
{ |
inherit Variable; |
constant type = "Flag"; |
|
int transform_from_form( string what ) |
{ |
return (int)what; |
} |
|
string render_form( RequestID id, void|mapping additional_args ) |
{ |
string res = "<select name=\""+path()+"\"> "; |
if(query()) |
res += "<option value=\"1\" selected=\"selected\">" + |
LOCALE("yes", "Yes")+ "</option>\n" |
"<option value=\"0\">" +LOCALE("no", "No")+ "</option>\n"; |
else |
res += "<option value=\"1\">" +LOCALE("yes", "Yes")+ "</option>\n" |
"<option value=\"0\" selected>" +LOCALE("no", "No")+ "</option>\n"; |
return res+"</select>"; |
} |
} |
|
|
|
|
|
|
|
static array(string) verify_port( string port ) |
{ |
if(!strlen(port)) |
return ({ 0, port }); |
|
string warning=""; |
if( (int)port ) |
{ |
warning += sprintf(LOCALE(333,"Assuming http://*:%[0]d/ for %[0]d")+"\n", |
(int)port); |
port = "http://*:"+port+"/"; |
} |
string protocol, host, path; |
|
if(!strlen( port ) ) |
return ({ LOCALE(334,"Empty URL field")+"\n", port }); |
|
if(sscanf( port, "%[^:]://%[^/]%s", protocol, host, path ) != 3) |
return ({ sprintf(LOCALE(335,"%s does not conform to URL syntax")+"\n",port), |
port }); |
|
if( path == "" || path[-1] != '/' ) |
{ |
warning += sprintf(LOCALE(336,"Added / to the end of %s")+"\n",port); |
path += "/"; |
} |
if( protocol != lower_case( protocol ) ) |
{ |
warning += sprintf(LOCALE(338,"Changed %s to %s"), |
protocol, lower_case( protocol ))+"\n"; |
protocol = lower_case( protocol ); |
} |
#if constant(SSL.sslfile) |
|
#else |
if( (protocol == "https" || protocol == "ftps") ) |
warning += |
LOCALE(339,"SSL support not available in this Pike version.")+"\n"+ |
sprintf(LOCALE(340,"Please use %s instead."), |
protocol[..strlen(protocol)-2])+"\n"; |
#endif |
int pno; |
if( sscanf( host, "%s:%d", host, pno ) == 2) |
if( roxenp()->protocols[ lower_case( protocol ) ] |
&& (pno == roxenp()->protocols[ lower_case( protocol ) ]->default_port )) |
warning += sprintf(LOCALE(341,"Removed the default port number " |
"(%d) from %s"),pno,port)+"\n"; |
else |
host = host+":"+pno; |
|
|
port = protocol+"://"+host+path; |
|
if( !roxenp()->protocols[ protocol ] ) |
warning += sprintf(LOCALE(342,"Warning: The protocol %s is not known " |
"by roxen"),protocol)+"\n"; |
return ({ (strlen(warning)?warning:0), port }); |
} |
|
string input(string name, string value, int size, |
void|mapping(string:string) args, void|int noxml) |
{ |
if(!args) |
args=([]); |
else |
args+=([]); |
|
args->name=name; |
if(value) |
args->value=value; |
if(!args->size && size) |
args->size=(string)size; |
|
string render="<input"; |
|
foreach(indices(args), string attr) { |
render+=" "+attr+"="; |
if(!has_value(args[attr], "\"")) render+="\""+args[attr]+"\""; |
else if(!has_value(args[attr], "'")) render+="'"+args[attr]+"'"; |
else render+="\""+replace(args[attr], "'", "'")+"\""; |
} |
|
if(noxml) return render+">"; |
return render+" />"; |
} |
|
|