d1de94 | 2000-08-19 | Martin Nilsson | | #include <module.h>
#include <roxen.h>
static inherit "html";
static inline string getloclang() {
return roxenp()->locale->get();
}
#if constant(Locale.DeferredLocale)
#define LOCALE(X,Y) \
([string](mixed)Locale.DeferredLocale("roxen_config",getloclang,X,Y))
#else /* !Locale.DeferredLocale */
#define LOCALE(X,Y) \
([string](mixed)RoxenLocale.DeferredLocale("roxen_config",getloclang,X,Y))
#endif /* Locale.DeferredLocale */
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 );
class Variable
{
constant is_variable = 1;
constant type = "Basic";
static int _id = unique_vid++;
static mixed _initial;
static string _path;
static string|object __name, __doc;
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 flags = get_flags();
function cb;
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( (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 );
}
function(RequestID,Variable:int) get_invisibility_check_callback()
{
return invisibility_callbacks[_id];
}
string doc( )
{
return __doc || "";
}
string name( )
{
return __name || "unnamed "+_id;
}
string 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 );
}
int set( mixed to )
{
string err, e2;
if( e2 = catch( [err,to] = verify_set( to )) )
{
if( stringp( e2 ) )
{
set_warning( e2 );
return ([])[0];
}
throw( e2 );
}
set_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( 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 )
{
return what;
}
void set_from_form( RequestID id )
{
mapping val;
if( sizeof( val = get_form_vars(id)) && val[""] &&
transform_from_form( val[""] ) != query() )
set( transform_from_form( val[""] ));
}
string path()
{
return _path;
}
void set_path( string to )
{
_path = to;
}
string render_form( RequestID id );
string render_view( RequestID id )
{
return Roxen.html_encode_string( (string)query() );
}
static string _sprintf( int i )
{
if( i == 'O' )
return sprintf( "Variables.%s(%s) [%O]", type,
(string)name(),
query() );
}
static void create(mixed default_value,int flags,
string|object std_name,string|object std_doc)
{
set_flags( flags );
_initial = default_value;
__name = std_name;
__doc = std_doc;
}
}
class Float
{
inherit Variable;
constant type = "Float";
static float _max, _min;
static int _prec = 2, mm_set;
static string _format( float m )
{
if( !_prec )
return sprintf( "%d", (int)m );
return sprintf( "%1."+_prec+"f", m );
}
void set_range(float minimum, float maximum )
{
if( minimum == maximum )
mm_set = 0;
else
mm_set = 1;
_max = maximum;
_min = minimum;
}
void set_precision( int prec )
{
_prec = prec;
}
array(string|float) verify_set( float new_value )
{
string warn;
if( mm_set )
{
if( new_value > _max )
{
warn = sprintf("Value is bigger than %s, adjusted", _format(_max) );
new_value = _max;
}
else if( new_value < _min )
{
warn = sprintf("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 )
{
int size = 15;
if( mm_set )
size = max( strlen(_format(_max)), strlen(_format(_min)) )+2;
return input(path(), _format(query()), size);
}
}
class Int
{
inherit Variable;
constant type = "Int";
static int _max, _min, mm_set;
void set_range(int minimum, int maximum )
{
if( minimum == maximum )
mm_set = 0;
else
mm_set = 1;
_max = maximum;
_min = minimum;
}
array(string|int) verify_set( int new_value )
{
string warn;
if( mm_set )
{
if( new_value > _max )
{
warn = sprintf("Value is bigger than %d, adjusted", _max );
new_value = _max;
}
else if( new_value < _min )
{
warn = sprintf("Value is less than %d, adjusted", _min );
new_value = _min;
}
}
return ({ warn, new_value });
}
int transform_from_form( string what )
{
return (int)what;
}
string render_form( RequestID id )
{
int size = 10;
if( mm_set )
size = max( strlen((string)_max), strlen((string)_min) )+2;
return input(path(), (string)query(), size);
}
}
class String
{
inherit Variable;
constant type = "String";
constant width = 40;
string render_form( RequestID id )
{
return input(path(), (string)query(), width);
}
}
class Text
{
inherit String;
constant type = "Text";
constant cols = 60;
constant rows = 10;
string render_form( RequestID id )
{
return "<textarea cols='"+cols+"' rows='"+rows+"' name='"+path()+"'>"
+ Roxen.html_encode_string( query() || "" ) +
"</textarea>";
}
}
class Password
{
inherit String;
constant width = 20;
constant type = "Password";
void set_from_form( RequestID id )
{
mapping val;
if( sizeof( val = get_form_vars(id)) &&
val[""] && strlen(val[""]) )
set( crypt( val[""] ) );
}
string render_view( RequestID id )
{
return "******";
}
string render_form( RequestID id )
{
return "<input name=\""+path()+"\" type=\"password\" size=\"30\">";
}
}
class File
{
inherit String;
constant type = "File";
constant width = 50;
string read( )
{
return Stdio.read_bytes( query() );
}
array stat()
{
return file_stat( query() );
}
}
class Location
{
inherit String;
constant type = "Location";
constant width = 50;
}
class URL
{
inherit String;
constant type = "URL";
constant width = 50;
array verify_set( string new_value )
{
return verify_port( new_value, 1 );
}
}
class Directory
{
inherit String;
constant type = "Directory";
constant width = 50;
array verify_set( string value )
{
if( !(r_file_stat( value ) && (r_file_stat( value )[ ST_SIZE ] == -2 )))
return ({value+" is not a directory", value });
return ::verify_set( value );
}
array stat()
{
return file_stat( query() );
}
array get( )
{
return get_dir( query() );
}
}
class MultipleChoice
{
inherit Variable;
static array _list = ({});
static mapping _table = ([]);
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 )
{
string res = "<select name='"+path()+"'>\n";
foreach( get_choice_list(), mixed elem )
{
mapping m = ([]);
m->value = _name( elem );
if( m->value == query() )
m->selected="selected";
res += " "+Roxen.make_container( "option", m, _title( elem ) )+"\n";
}
return res + "</select>";
}
static void create( mixed default_value, array|mapping choices,
int _flags, string std_name, string 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,int flags,
string std_name,string std_doc)
{
::create( default_value, 0, flags,std_name, std_doc );
}
}
class List
{
inherit String;
constant type="List";
constant width = 40;
string transform_to_form( mixed what )
{
return (string)what;
}
mixed transform_from_form( string what )
{
return what;
}
static int _current_count = time()*100+(gethrtime()/10000);
void set_from_form(RequestID id)
{
int rn;
array l = query();
mapping vl = get_form_vars(id);
if( (int)vl[".count"] != _current_count )
return;
_current_count++;
foreach( indices( vl ), string vv )
if( sscanf( vv, ".set.%d", rn ) )
{
m_delete( id->variables, path()+vv );
l[rn] = transform_from_form( vl[vv] );
m_delete( vl, vv );
}
foreach( indices(vl), string vv )
if( sscanf( vv, ".up.%d.x%*s", rn ) == 2 )
{
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 )
{
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"] )
{
m_delete( id->variables, path()+".new.x" );
l += ({ transform_from_form( "" ) });
}
foreach( indices(vl), string vv )
if( sscanf( vv, ".delete.%d.x%*s", rn )==2 )
{
m_delete( id->variables, path()+vv );
l = l[..rn-1] + l[rn+1..];
}
set( l );
}
string render_form( RequestID id )
{
string prefix = path()+".";
int i;
_current_count++;
string res = "<table>\n"
"<input type='hidden' name='"+prefix+"count' value='"+_current_count+"' />";
foreach( map(query(), transform_to_form), string val )
{
res += "<tr><td><font size='-1'>"+ input( prefix+"set."+i, val, width) + "</font></td>";
#define BUTTON(X,Y) ("<submit-gbutton2 name='"+X+"'>"+Y+"</submit-gbutton2>")
if( i )
res += "\n<td>"+
BUTTON(prefix+"up."+i, "^")+
"</td>";
else
res += "<td></td>";
if( i != sizeof( query())- 1 )
res += "\n<td>"+
BUTTON(prefix+"down."+i, "v")
+"</td>";
else
res += "<td></td>";
res += "\n<td>"+
BUTTON(prefix+"delete."+i, LOCALE("", "Delete") )
+"</td>";
"</tr>";
i++;
}
res +=
"<tr><td colspan='2'>"+
BUTTON(prefix+"new", LOCALE("", "New row") )+
"</td></tr></table>\n";
return res;
}
}
class DirectoryList
{
inherit List;
constant type="DirectoryList";
array verify_set( array(string) value )
{
string warn = "";
foreach( value, string value )
if( !(r_file_stat( value ) && (r_file_stat( value )[ ST_SIZE ] == -2 )))
warn += value+" is not a directory\n";
if( strlen( warn ) )
return ({ warn, value });
return ::verify_set( value );
}
}
class StringList
{
inherit List;
constant type="StringList";
}
class IntList
{
inherit List;
constant type="IntList";
constant width=20;
string transform_to_form(int what) { return (string)what; }
int transform_from_form(string what) { return (int)what; }
}
class FloatList
{
inherit List;
constant type="DirectorYList";
constant 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) { return (float)what; }
}
class URLList
{
inherit List;
constant type="UrlList";
array verify_set( array(string) new_value )
{
string warn = "";
array res = ({});
foreach( new_value, string vv )
{
string tmp1, tmp2;
[tmp1,tmp2] = verify_port( vv, 1 );
if( tmp1 )
warn += tmp1;
res += ({ tmp2 });
}
if( !strlen( warn ) )
warn = 0;
return ({ warn, res });
}
}
class PortList
{
inherit List;
constant type="PortList";
array verify_set( array(string) new_value )
{
string warn = "";
array res = ({});
foreach( new_value, string vv )
{
string tmp1, tmp2;
[tmp1,tmp2] = verify_port( vv, 0 );
if( tmp1 )
warn += tmp1;
res += ({ tmp2 });
}
if( !strlen( warn ) )
warn = "";
return ({ warn, res });
}
}
class FileList
{
inherit List;
constant type="FileList";
}
class Flag
{
inherit Variable;
constant type = "Flag";
int transform_from_form( string what )
{
return (int)what;
}
string render_form( RequestID id )
{
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>";
}
}
array(string) verify_port( string port, int nofhttp )
{
if(!strlen(port))
return ({ 0, port });
string warning="";
if( (int)port )
{
warning += "Assuming http://*:"+port+"/ for "+port+"\n";
port = "http://*:"+port+"/";
}
string protocol, host, path;
if(!strlen( port ) )
return ({ "Empty URL field", port });
if(sscanf( port, "%[^:]://%[^/]%s", protocol, host, path ) != 3)
return ({""+port+" does not conform to URL syntax\n", port });
if( path == "" )
{
warning += "Added / to the end of "+port+"\n";
host += "/";
}
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 += "Removed the "
"default port number ("+pno+") from "+port+"\n";
else
host = host+":"+pno;
}
if( nofhttp && protocol == "fhttp" )
{
warning += "Changed " + protocol + " to http\n";
protocol = "http";
}
if( protocol != lower_case( protocol ) )
{
warning += "Changed "+protocol+" to "+ lower_case( protocol )+"\n";
}
port = lower_case( protocol )+"://"+host+path;
if( !roxenp()->protocols[ lower_case( protocol ) ] )
warning += "Warning: The protocol "+lower_case(protocol)+" is unknown\n";
return ({ (strlen(warning)?warning:0), port });
}
|