string cvs_version = "$Id: configuration.pike,v 1.180 1999/03/28 21:23:01 grubba Exp $"; |
#include <module.h> |
#include <roxen.h> |
|
|
#ifdef PROFILE |
mapping profile_map = ([]); |
#endif |
|
#define CATCH(P,X) do{mixed e;if(e=catch{X;})report_error("While "+P+"\n"+describe_backtrace(e));}while(0) |
|
|
#define LOCALE LOW_LOCALE->base_server |
|
|
|
|
#include "rxml.pike"; |
|
public string real_file(string file, object id); |
|
|
function store = roxen->store; |
function retrieve = roxen->retrieve; |
function remove = roxen->remove; |
function do_dest = roxen->do_dest; |
function create_listen_socket = roxen->create_listen_socket; |
|
|
object parse_module =this_object(); |
|
object types_module; |
object auth_module; |
object dir_module; |
|
function types_fun; |
function auth_fun; |
|
string name; |
|
|
|
|
|
mapping variables = ([]); |
|
|
|
string get_doc_for( string region, string variable ) |
{ |
object module; |
if(variable[0] == '_') |
return 0; |
if((int)reverse(region)) |
return 0; |
if(module = find_module( region )) |
{ |
if(module->variables[variable]) |
return module->variables[variable][VAR_NAME]+ |
"\n"+module->variables[ variable ][ VAR_DOC_STR ]; |
} |
if(variables[ variable ]) |
return variables[variable][VAR_NAME]+ |
"\n"+variables[ variable ][ VAR_DOC_STR ]; |
} |
|
public mixed query(string var) |
{ |
if(var && variables[var]) |
return variables[var][ VAR_VALUE ]; |
if(!var) return variables; |
error("query("+var+"): Unknown variable.\n"); |
} |
|
mixed set(string var, mixed val) |
{ |
#if DEBUG_LEVEL > 30 |
perror(sprintf("MAIN: set(\"%s\", %O)\n", var, val)); |
#endif |
if(variables[var]) |
{ |
#if DEBUG_LEVEL > 28 |
perror("MAIN: Setting global variable.\n"); |
#endif |
return variables[var][VAR_VALUE] = val; |
} |
error("set("+var+"). Unknown variable.\n"); |
} |
|
int setvars( mapping (string:mixed) vars ) |
{ |
string v; |
|
foreach( indices( vars ), v ) |
if(variables[v]) |
variables[v][ VAR_VALUE ] = vars[ v ]; |
return 1; |
} |
|
|
|
void killvar(string name) |
{ |
m_delete(variables, name); |
} |
|
static class ConfigurableWrapper |
{ |
int mode; |
function f; |
int check() |
{ |
if ((mode & VAR_EXPERT) && |
(!roxen->configuration_interface()->expert_mode)) { |
return 1; |
} |
if ((mode & VAR_MORE) && |
(!roxen->configuration_interface()->more_mode)) { |
return 1; |
} |
return(f()); |
} |
void create(int mode_, function f_) |
{ |
mode = mode_; |
f = f_; |
} |
}; |
|
int defvar(string var, mixed value, string name, int type, |
string|void doc_str, mixed|void misc, |
int|function|void not_in_config) |
{ |
variables[var] = allocate( VAR_SIZE ); |
variables[var][ VAR_VALUE ] = value; |
variables[var][ VAR_TYPE ] = type & VAR_TYPE_MASK; |
variables[var][ VAR_DOC_STR ] = doc_str; |
variables[var][ VAR_NAME ] = name; |
variables[var][ VAR_MISC ] = misc; |
|
Locale.Roxen.standard |
->register_module_doc( this_object(), var, name, doc_str ); |
|
type &= ~VAR_TYPE_MASK; |
type &= (VAR_EXPERT | VAR_MORE); |
if (functionp(not_in_config)) { |
if (type) { |
variables[var][ VAR_CONFIGURABLE ] = ConfigurableWrapper(type, not_in_config)->check; |
} else { |
variables[var][ VAR_CONFIGURABLE ] = not_in_config; |
} |
} else if (type) { |
variables[var][ VAR_CONFIGURABLE ] = type; |
} else if(intp(not_in_config)) { |
variables[var][ VAR_CONFIGURABLE ] = !not_in_config; |
} |
|
variables[var][ VAR_SHORTNAME ] = var; |
} |
|
void deflocaledoc( string locale, string variable, |
string name, string doc, mapping|void translate ) |
{ |
if( !Locale.Roxen[locale] ) |
report_debug("Invalid locale: "+locale+". Ignoring.\n"); |
else |
Locale.Roxen[locale] |
->register_module_doc( this_object(), variable, name, doc, translate ); |
} |
|
int definvisvar(string var, mixed value, int type) |
{ |
return defvar(var, value, "", type, "", 0, 1); |
} |
|
string query_internal_location(object|void mod) |
{ |
return QUERY(InternalLoc)+(mod? replace(otomod[mod]||"", "#", "!")+"/":""); |
} |
|
string query_name() |
{ |
if(strlen(QUERY(name))) return QUERY(name); |
return name; |
} |
|
string comment() |
{ |
return QUERY(comment); |
} |
|
class Priority |
{ |
array (object) url_modules = ({ }); |
array (object) logger_modules = ({ }); |
array (object) location_modules = ({ }); |
array (object) filter_modules = ({ }); |
array (object) last_modules = ({ }); |
array (object) first_modules = ({ }); |
|
mapping (string:array(object)) extension_modules = ([ ]); |
mapping (string:array(object)) file_extension_modules = ([ ]); |
mapping (object:multiset) provider_modules = ([ ]); |
|
|
void stop() |
{ |
foreach(url_modules, object m) |
CATCH("stopping url modules",m->stop && m->stop()); |
foreach(logger_modules, object m) |
CATCH("stopping logging modules",m->stop && m->stop()); |
foreach(filter_modules, object m) |
CATCH("stopping filter modules",m->stop && m->stop()); |
foreach(location_modules, object m) |
CATCH("stopping location modules",m->stop && m->stop()); |
foreach(last_modules, object m) |
CATCH("stopping last modules",m->stop && m->stop()); |
foreach(first_modules, object m) |
CATCH("stopping first modules",m->stop && m->stop()); |
foreach(indices(provider_modules), object m) |
CATCH("stopping provider modules",m->stop && m->stop()); |
} |
} |
|
|
|
|
|
|
|
|
array (object) allocate_pris() |
{ |
int a; |
array (object) tmp; |
tmp=allocate(10); |
for(a=0; a<10; a++) tmp[a]=Priority(); |
return tmp; |
} |
|
class Bignum { |
#if constant(Gmp.mpz) // Perfect. :-) |
object gmp = Gmp.mpz(); |
float mb() |
{ |
return (float)(gmp/1024)/1024.0; |
} |
|
object `+(int i) |
{ |
gmp = gmp+i; |
return this_object(); |
} |
|
object `-(int i) |
{ |
gmp = gmp-i; |
return this_object(); |
} |
#else |
int msb; |
int lsb=-0x7ffffffe; |
|
object `-(int i); |
object `+(int i) |
{ |
if(!i) return this_object(); |
if(i<0) return `-(-i); |
object res = object_program(this_object())(lsb+i,msb,2); |
if(res->lsb < lsb) res->msb++; |
return res; |
} |
|
object `-(int i) |
{ |
if(!i) return this_object(); |
if(i<0) return `+(-i); |
object res = object_program(this_object())(lsb-i,msb,2); |
if(res->lsb > lsb) res->msb--; |
return res; |
} |
|
float mb() |
{ |
return ((((float)lsb/1024.0/1024.0)+2048.0)+(msb*4096.0)); |
} |
|
void create(int|void num, int|void bnum, int|void d) |
{ |
if(!d) |
lsb = num-0x7ffffffe; |
else |
lsb = num; |
msb = bnum; |
} |
#endif |
} |
|
|
|
|
int requests; |
|
mapping(string:mixed) extra_statistics = ([]); |
mapping(string:mixed) misc = ([]); |
|
object sent=Bignum(); |
object hsent=Bignum(); |
object received=Bignum(); |
|
object this = this_object(); |
|
|
|
|
|
private object *_toparse_modules = ({}); |
|
|
|
|
|
function log_function; |
|
|
|
private mapping (string:string) log_format = ([]); |
|
|
private array (object) pri = allocate_pris(); |
|
|
|
public mapping (string:mapping(string:mixed)) modules = ([]); |
|
|
public mapping (object:string) otomod = ([]); |
|
|
|
|
|
private array (function) url_module_cache, last_module_cache; |
private array (function) logger_module_cache, first_module_cache; |
private array (function) filter_module_cache; |
private array (array (string|function)) location_module_cache; |
private mapping (string:array (function)) extension_module_cache=([]); |
private mapping (string:array (function)) file_extension_module_cache=([]); |
private mapping (string:array (object)) provider_module_cache=([]); |
|
|
|
void stop() |
{ |
CATCH("stopping type modules", |
types_module && types_module->stop && types_module->stop()); |
CATCH("stopping auth module", |
auth_module && auth_module->stop && auth_module->stop()); |
CATCH("stopping directory module", |
dir_module && dir_module->stop && dir_module->stop()); |
for(int i=0; i<10; i++) |
CATCH("stopping priority group", |
pri[i] && pri[i]->stop && pri[i]->stop()); |
} |
|
public string type_from_filename( string file, int|void to ) |
{ |
mixed tmp; |
string ext=extension(file); |
|
if(!types_fun) |
return to?({ "application/octet-stream", 0 }):"application/octet-stream"; |
|
|
|
|
if(tmp = types_fun(ext)) |
{ |
mixed tmp2,nx; |
if(tmp[0] == "strip") |
{ |
tmp2=file/"."; |
if(sizeof(tmp2) > 2) |
nx=tmp2[-2]; |
if(nx && (tmp2=types_fun(nx))) |
tmp[0] = tmp2[0]; |
else if(tmp2=types_fun("default")) |
tmp[0] = tmp2[0]; |
else |
tmp[0]="application/octet-stream"; |
} |
} else if(!(tmp = types_fun("default"))) { |
tmp = ({ "application/octet-stream", 0 }); |
} |
return to?tmp:tmp[0]; |
} |
|
|
array (object) get_providers(string provides) |
{ |
|
|
|
if(!provider_module_cache[provides]) |
{ |
int i; |
provider_module_cache[provides] = ({ }); |
for(i = 9; i >= 0; i--) |
{ |
foreach(indices(pri[i]->provider_modules), object d) |
if(pri[i]->provider_modules[ d ][ provides ]) |
provider_module_cache[provides] += ({ d }); |
} |
} |
return provider_module_cache[provides]; |
} |
|
|
object get_provider(string provides) |
{ |
array (object) prov = get_providers(provides); |
if(sizeof(prov)) |
return prov[0]; |
return 0; |
} |
|
|
array(mixed) map_providers(string provides, string fun, mixed ... args) |
{ |
array (object) prov = get_providers(provides); |
array error; |
array a=({ }); |
mixed m; |
foreach(prov, object mod) |
{ |
if(!objectp(mod)) |
continue; |
if(functionp(mod[fun])) |
error = catch(m=mod[fun](@args)); |
if(arrayp(error)) |
roxen_perror(describe_backtrace(error+({ "Error in map_providers:"}))); |
else |
a += ({ m }); |
error = 0; |
} |
return a; |
} |
|
|
|
mixed call_provider(string provides, string fun, mixed ... args) |
{ |
foreach(get_providers(provides), object mod) { |
function f; |
if(objectp(mod) && functionp(f = mod[fun])) { |
mixed error; |
if (arrayp(error = catch { |
mixed ret; |
if (ret = f(@args)) { |
return(ret); |
} |
})) { |
throw(error + ({ "Error in call_provider:"})); |
} |
} |
} |
} |
|
array (function) extension_modules(string ext, object id) |
{ |
if(!extension_module_cache[ext]) |
{ |
int i; |
extension_module_cache[ext] = ({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d = pri[i]->extension_modules[ext]) |
foreach(d, p) |
extension_module_cache[ext] += ({ p->handle_extension }); |
} |
} |
return extension_module_cache[ext]; |
} |
|
|
array (function) file_extension_modules(string ext, object id) |
{ |
if(!file_extension_module_cache[ext]) |
{ |
int i; |
file_extension_module_cache[ext] = ({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d = pri[i]->file_extension_modules[ext]) |
foreach(d, p) |
file_extension_module_cache[ext] += ({ p->handle_file_extension }); |
} |
} |
return file_extension_module_cache[ext]; |
} |
|
array (function) url_modules(object id) |
{ |
if(!url_module_cache) |
{ |
int i; |
url_module_cache=({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->url_modules) |
foreach(d, p) |
url_module_cache += ({ p->remap_url }); |
} |
} |
return url_module_cache; |
} |
|
mapping api_module_cache = ([]); |
mapping api_functions(object id) |
{ |
return copy_value(api_module_cache); |
} |
|
array (function) logger_modules(object id) |
{ |
if(!logger_module_cache) |
{ |
int i; |
logger_module_cache=({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->logger_modules) |
foreach(d, p) |
if(p->log) |
logger_module_cache += ({ p->log }); |
} |
} |
return logger_module_cache; |
} |
|
array (function) last_modules(object id) |
{ |
if(!last_module_cache) |
{ |
int i; |
last_module_cache=({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->last_modules) |
foreach(d, p) |
if(p->last_resort) |
last_module_cache += ({ p->last_resort }); |
} |
} |
return last_module_cache; |
} |
|
#ifdef __NT__ |
static mixed strip_fork_information(object id) |
{ |
array a = id->not_query/"::"; |
id->not_query = a[0]; |
id->misc->fork_information = a[1..]; |
return(0); |
} |
#endif /* __NT__ */ |
|
array (function) first_modules(object id) |
{ |
if(!first_module_cache) |
{ |
int i; |
first_module_cache=({ |
#ifdef __NT__ |
strip_fork_information, |
#endif /* __NT__ */ |
}); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->first_modules) { |
foreach(d, p) { |
if(p->first_try) { |
first_module_cache += ({ p->first_try }); |
} |
} |
} |
} |
} |
|
return first_module_cache; |
} |
|
|
array location_modules(object id) |
{ |
if(!location_module_cache) |
{ |
int i; |
array new_location_module_cache=({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->location_modules) { |
array level_find_files = ({}); |
array level_locations = ({}); |
foreach(d, p) { |
string location; |
|
if(p->find_file && (location = p->query_location())) { |
level_find_files += ({ p->find_file }); |
level_locations += ({ location }); |
} |
} |
sort(level_locations, level_find_files); |
int j; |
for (j = sizeof(level_locations); j--;) { |
|
new_location_module_cache += ({ ({ level_locations[j], |
level_find_files[j] }) }); |
} |
} |
} |
location_module_cache = new_location_module_cache; |
} |
return location_module_cache; |
} |
|
array filter_modules(object id) |
{ |
if(!filter_module_cache) |
{ |
int i; |
filter_module_cache=({ }); |
for(i=9; i>=0; i--) |
{ |
object *d, p; |
if(d=pri[i]->filter_modules) |
foreach(d, p) |
if(p->filter) |
filter_module_cache+=({ p->filter }); |
} |
} |
return filter_module_cache; |
} |
|
|
void init_log_file() |
{ |
remove_call_out(init_log_file); |
|
if(log_function) |
{ |
destruct(function_object(log_function)); |
|
} |
|
if(query("Log")) |
{ |
mapping m = localtime(time()); |
string logfile = query("LogFile"); |
m->year += 1900; |
m->mon++; |
if(m->mon < 10) m->mon = "0"+m->mon; |
if(m->mday < 10) m->mday = "0"+m->mday; |
if(m->hour < 10) m->hour = "0"+m->hour; |
logfile = replace(logfile,({"%d","%m","%y","%h" }), |
({ (string)m->mday, (string)(m->mon), |
(string)(m->year),(string)m->hour,})); |
if(strlen(logfile)) |
{ |
do { |
|
|
|
object lf=open( logfile, "wac"); |
|
|
|
|
|
if(!lf) { |
mkdirhier(logfile); |
if(!(lf=open( logfile, "wac"))) { |
report_error(LOCALE->failed_to_open_logfile(logfile)); |
log_function=0; |
break; |
} |
} |
log_function=lf->write; |
|
lf=0; |
} while(0); |
} else |
log_function=0; |
call_out(init_log_file, 60); |
} else |
log_function=0; |
} |
|
|
private inline string fix_logging(string s) |
{ |
string pre, post, c; |
sscanf(s, "%*[\t ]", s); |
s = replace(s, ({"\\t", "\\n", "\\r" }), ({"\t", "\n", "\r" })); |
|
|
|
|
while(s[0] == ' ') s = s[1..]; |
while(s[0] == '\t') s = s[1..]; |
while(sscanf(s, "%s$char(%d)%s", pre, c, post)==3) |
s=sprintf("%s%c%s", pre, c, post); |
while(sscanf(s, "%s$wchar(%d)%s", pre, c, post)==3) |
s=sprintf("%s%2c%s", pre, c, post); |
while(sscanf(s, "%s$int(%d)%s", pre, c, post)==3) |
s=sprintf("%s%4c%s", pre, c, post); |
if(!sscanf(s, "%s$^%s", pre, post)) |
s+="\n"; |
else |
s=pre+post; |
return s; |
} |
|
private void parse_log_formats() |
{ |
string b; |
array foo=query("LogFormat")/"\n"; |
foreach(foo, b) |
if(strlen(b) && b[0] != '#' && sizeof(b/":")>1) |
log_format[(b/":")[0]] = fix_logging((b/":")[1..]*":"); |
} |
|
|
|
|
private void write_to_log( string host, string rest, string oh, function fun ) |
{ |
int s; |
if(!host) host=oh; |
if(!stringp(host)) |
host = "error:no_host"; |
else |
host = (host/" ")[0]; |
if(fun) fun(replace(rest, "$host", host)); |
} |
|
|
nomask private inline string host_ip_to_int(string s) |
{ |
int a, b, c, d; |
sscanf(s, "%d.%d.%d.%d", a, b, c, d); |
return sprintf("%c%c%c%c",a, b, c, d); |
} |
|
nomask private inline string unsigned_to_bin(int a) |
{ |
return sprintf("%4c", a); |
} |
|
nomask private inline string unsigned_short_to_bin(int a) |
{ |
return sprintf("%2c", a); |
} |
|
nomask private inline string extract_user(string from) |
{ |
array tmp; |
if (!from || sizeof(tmp = from/":")<2) |
return "-"; |
|
return tmp[0]; |
} |
|
public void log(mapping file, object request_id) |
{ |
|
string a; |
string form; |
function f; |
|
foreach(logger_modules(request_id), f) |
if(f(request_id,file))return; |
|
if(!log_function || !request_id) return; |
|
|
if(QUERY(NoLog) && _match(request_id->remoteaddr, QUERY(NoLog))) |
return; |
|
if(!(form=log_format[(string)file->error])) |
form = log_format["*"]; |
|
if(!form) return; |
|
form=replace(form, |
({ |
"$ip_number", "$bin-ip_number", "$cern_date", |
"$bin-date", "$method", "$resource", "$protocol", |
"$response", "$bin-response", "$length", "$bin-length", |
"$referer", "$user_agent", "$user", "$user_id", |
"$request-time" |
}), ({ |
(string)request_id->remoteaddr, |
host_ip_to_int(request_id->remoteaddr), |
cern_http_date(time(1)), |
unsigned_to_bin(time(1)), |
(string)request_id->method, |
http_encode_string((string)request_id->not_query + |
((request_id->misc && |
request_id->misc->path_info) || "") + |
((request_id->query && |
strlen(request_id->query))? |
"?"+request_id->query:"")), |
(string)request_id->prot, |
(string)(file->error||200), |
unsigned_short_to_bin(file->error||200), |
(string)(file->len>=0?file->len:"?"), |
unsigned_to_bin(file->len), |
(string) |
(sizeof(request_id->referer||({}))?request_id->referer[0]:"-"), |
http_encode_string(sizeof(request_id->client||({}))?request_id->client*" ":"-"), |
extract_user(request_id->realauth), |
(string)request_id->cookies->RoxenUserID, |
(string)(time(1)-request_id->time) |
})); |
|
if(search(form, "host") != -1) |
roxen->ip_to_host(request_id->remoteaddr, write_to_log, form, |
request_id->remoteaddr, log_function); |
else |
log_function(form); |
|
} |
|
|
public string status() |
{ |
float tmp; |
string res=""; |
float dt = (float)(time(1) - roxen->start_time + 1); |
|
if(!sent||!received||!hsent) |
return(LOCALE->status_bignum_gone()); |
|
res = "<table>"; |
res += LOCALE->config_status(sent->mb(), (sent->mb()/dt) * 8192.0, |
hsent->mb(), requests, |
(((float)requests * 60.0)/dt), received->mb()); |
|
if (!zero_type(misc->ftp_users)) { |
res += LOCALE->ftp_status(misc->ftp_users, |
(((float)misc->ftp_users*(float)60.0)/dt), |
misc->ftp_users_now); |
} |
res += "</table><p>\n\n"; |
|
if ((roxen->configuration_interface()->more_mode) && |
(extra_statistics->ftp) && (extra_statistics->ftp->commands)) { |
|
res += LOCALE->ftp_statistics() + "<br>\n" |
"<ul><table>\n"; |
foreach(sort(indices(extra_statistics->ftp->commands)), string cmd) { |
res += LOCALE->ftp_stat_line(upper_case(cmd), |
extra_statistics->ftp->commands[cmd]); |
} |
res += "</table></ul>\n"; |
} |
|
return res; |
} |
|
public string *userinfo(string u, object|void id) |
{ |
if(auth_module) return auth_module->userinfo(u); |
else report_warning(sprintf("userinfo(): %s\n" |
"%s\n", |
LOCALE->no_auth_module(), |
describe_backtrace(backtrace()))); |
} |
|
public string *userlist(object|void id) |
{ |
if(auth_module) return auth_module->userlist(); |
else report_warning(sprintf("userlist(): %s\n" |
"%s\n", |
LOCALE->no_auth_module(), |
describe_backtrace(backtrace()))); |
} |
|
public string *user_from_uid(int u, object|void id) |
{ |
if(auth_module) |
return auth_module->user_from_uid(u); |
else report_warning(sprintf("user_from_uid(): %s\n" |
"%s\n", |
LOCALE->no_auth_module(), |
describe_backtrace(backtrace()))); |
} |
|
|
|
|
|
private mapping internal_gopher_image(string from) |
{ |
sscanf(from, "%s.gif", from); |
sscanf(from, "%s.jpg", from); |
from -= "."; |
|
|
|
return (["file":open("roxen-images/dir/"+from+".gif","r"), |
"type":"image/gif"]); |
} |
|
private static int nest = 0; |
|
#ifdef MODULE_LEVEL_SECURITY |
private mapping misc_cache=([]); |
|
int|mapping check_security(function a, object id, void|int slevel) |
{ |
array level; |
array seclevels; |
int ip_ok = 0; |
int auth_ok = 0; |
|
|
|
|
|
|
|
if(!(seclevels = misc_cache[ a ])) |
if(function_object(a)->query_seclevels) |
misc_cache[ a ] = seclevels = ({ |
function_object(a)->query_seclevels(), |
function_object(a)->query("_seclvl"), |
function_object(a)->query("_sec_group") |
}); |
else |
misc_cache[ a ] = seclevels = ({({}),0,"foo" }); |
|
if(slevel && (seclevels[1] > slevel)) |
return 1; |
|
if(!sizeof(seclevels[0])) |
return 0; |
|
mixed err; |
err = catch { |
foreach(seclevels[0], level) { |
switch(level[0]) { |
case MOD_ALLOW: |
if(level[1](id->remoteaddr)) { |
ip_ok = ~0; |
} else { |
ip_ok |= 1; |
} |
break; |
|
case MOD_DENY: |
|
|
if(level[1](id->remoteaddr)) |
return http_low_answer(403, "<h2>Access forbidden</h2>"); |
break; |
|
case MOD_USER: |
if(id->auth && id->auth[0] && level[1](id->auth[1])) { |
auth_ok = ~0; |
} else { |
auth_ok |= 1; |
} |
break; |
|
case MOD_PROXY_USER: |
if (ip_ok != 1) { |
|
if(id->misc->proxyauth && id->misc->proxyauth[0] && |
level[1](id->misc->proxyauth[1])) return 0; |
return http_proxy_auth_required(seclevels[2]); |
} else { |
|
return(1); |
} |
break; |
|
case MOD_ACCEPT: |
|
if(level[1](id->remoteaddr)) { |
|
return(0); |
} else { |
ip_ok |= 1; |
} |
break; |
|
case MOD_ACCEPT_USER: |
|
if(id->auth && id->auth[0] && level[1](id->auth[1])) { |
|
return(0); |
} else { |
if (id->auth) { |
auth_ok |= 1; |
} else { |
|
return(http_auth_failed(seclevels[2])); |
} |
} |
break; |
} |
} |
}; |
|
if (err) { |
report_error(LOCALE->module_security_error(describe_backtrace(err))); |
return(1); |
} |
|
if (ip_ok == 1) { |
|
return(1); |
} else { |
|
if (auth_ok == 1) { |
|
|
return(http_auth_failed(seclevels[2])); |
} else { |
|
return(0); |
} |
} |
} |
#endif |
|
void invalidate_cache() |
{ |
last_module_cache = 0; |
filter_module_cache = 0; |
first_module_cache = 0; |
url_module_cache = 0; |
location_module_cache = 0; |
logger_module_cache = 0; |
extension_module_cache = ([]); |
file_extension_module_cache = ([]); |
provider_module_cache = ([]); |
#ifdef MODULE_LEVEL_SECURITY |
if(misc_cache) |
misc_cache = ([ ]); |
#endif |
} |
|
|
void clear_memory_caches() |
{ |
invalidate_cache(); |
foreach(indices(otomod), object m) { |
if (m && m->clear_memory_caches) { |
mixed err = catch { |
m->clear_memory_caches(); |
}; |
if (err) { |
report_error(LOCALE-> |
clear_memory_cache_error(otomod[m], |
describe_backtrace(err))); |
} |
} |
} |
} |
|
|
string draw_saturation_bar(int hue,int brightness, int where) |
{ |
object bar=Image.image(30,256); |
|
for(int i=0;i<128;i++) |
{ |
int j = i*2; |
bar->line(0,j,29,j,@hsv_to_rgb(hue,255-j,brightness)); |
bar->line(0,j+1,29,j+1,@hsv_to_rgb(hue,255-j,brightness)); |
} |
|
where = 255-where; |
bar->line(0,where,29,where, 255,255,255); |
|
return bar->togif(255,255,255); |
} |
|
|
|
|
private mapping internal_roxen_image(string from) |
{ |
sscanf(from, "%s.gif", from); |
sscanf(from, "%s.jpg", from); |
|
|
|
|
|
|
from -= "."; |
|
|
|
|
int hue,bright,w; |
if(sscanf(from, "%*s:%d,%d,%d", hue, bright,w)==4) |
return http_string_answer(draw_saturation_bar(hue,bright,w),"image/gif"); |
|
if(object f=open("roxen-images/"+from+".gif", "r")) |
return (["file":f,"type":"image/gif"]); |
else |
return (["file":open("roxen-images/"+from+".jpg", "r"),"type":"image/jpeg"]); |
} |
|
|
|
|
|
mapping (mixed:function|int) locks = ([]); |
|
#ifdef THREADS |
|
|
mapping locked = ([]), thread_safe = ([]); |
|
object _lock(object|function f) |
{ |
object key; |
function|int l; |
|
if (functionp(f)) { |
f = function_object(f); |
} |
if (l = locks[f]) |
{ |
if (l != -1) |
{ |
|
catch{ |
|
locked[f]++; |
key = l(); |
}; |
} else |
thread_safe[f]++; |
} else if (f->thread_safe) { |
locks[f]=-1; |
thread_safe[f]++; |
} else { |
if (!locks[f]) |
{ |
|
l = Thread.Mutex()->lock; |
if (!locks[f]) { |
locks[f]=l; |
} |
} |
|
locked[f]++; |
key = l(); |
} |
return key; |
} |
|
#define LOCK(X) key=_lock(X) |
#define UNLOCK() do{key=0;}while(0) |
#else |
#define LOCK(X) |
#define UNLOCK() |
#endif |
|
|
#define TRACE_ENTER(A,B) do{if(id->misc->trace_enter)id->misc->trace_enter((A),(B));}while(0) |
#define TRACE_LEAVE(A) do{if(id->misc->trace_leave)id->misc->trace_leave((A));}while(0) |
|
string examine_return_mapping(mapping m) |
{ |
string res; |
|
if (m->extra_heads) |
m->extra_heads=mkmapping(Array.map(indices(m->extra_heads), |
lower_case), |
values(m->extra_heads)); |
else |
m->extra_heads=([]); |
|
switch (m->error||200) |
{ |
case 302: |
if (m->extra_heads && |
(m->extra_heads->location)) |
res = LOCALE->returned_redirect_to(m->extra_heads->location); |
else |
res = LOCALE->returned_redirect_no_location(); |
break; |
|
case 401: |
if (m->extra_heads["www-authenticate"]) |
res = LOCALE-> |
returned_authenticate(m->extra_heads["www-authenticate"]); |
else |
res = LOCALE->returned_auth_failed(); |
break; |
|
case 200: |
res = LOCALE->returned_ok(); |
break; |
|
default: |
res = LOCALE->returned_error(m->error); |
} |
|
if (!zero_type(m->len)) |
if (m->len<0) |
res += LOCALE->returned_no_data(); |
else |
res += LOCALE->returned_bytes(m->len); |
else if (stringp(m->data)) |
res += LOCALE->returned_bytes(strlen(m->data)); |
else if (objectp(m->file)) |
if (catch { |
array a=m->file->stat(); |
res += LOCALE->returned_bytes(a[1]-m->file->tell()); |
}) |
res += LOCALE->returned_unknown_bytes(); |
|
if (m->data) res += LOCALE->returned_static_data(); |
else if (m->file) res += LOCALE->returned_open_file(); |
|
if (stringp(m->extra_heads["http-content-type"]) || |
stringp(m->type)) { |
res += LOCALE->returned_type(m->type); |
} |
|
res+="<br>"; |
|
return res; |
} |
mapping|int low_get_file(object id, int|void no_magic) |
{ |
#ifdef MODULE_LEVEL_SECURITY |
int slevel; |
#endif |
|
#ifdef THREADS |
object key; |
#endif |
TRACE_ENTER(LOCALE->request_for(id->not_query), 0); |
|
string file=id->not_query; |
string loc; |
function funp; |
mixed tmp, tmp2; |
mapping|object fid; |
|
|
if(!no_magic) |
{ |
#ifndef NO_INTERNAL_HACK |
|
|
if(sizeof(file) && (file[0] == '/') && |
sscanf(file, "%*s/internal-%s", loc)) |
{ |
if(sscanf(loc, "gopher-%[^/]", loc)) |
{ |
TRACE_LEAVE(LOCALE->magic_internal_gopher()); |
return internal_gopher_image(loc); |
} |
if(sscanf(loc, "spinner-%[^/]", loc) |
||sscanf(loc, "roxen-%[^/]", loc)) |
{ |
TRACE_LEAVE(LOCALE->magic_internal_roxen()); |
return internal_roxen_image(loc); |
} |
} |
#endif |
|
if(id->prestate->diract && dir_module) |
{ |
LOCK(dir_module); |
TRACE_ENTER(LOCALE->directory_module(), dir_module); |
tmp = dir_module->parse_directory(id); |
UNLOCK(); |
if(mappingp(tmp)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
TRACE_LEAVE(""); |
} |
|
if(!search(file, QUERY(InternalLoc))) |
{ |
TRACE_ENTER(LOCALE->magic_internal_module_location(), 0); |
object module; |
string name, rest; |
function find_internal; |
if(2==sscanf(file[strlen(QUERY(InternalLoc))..], "%s/%s", name, rest) && |
(module = find_module(replace(name, "!", "#"))) && |
(find_internal = module->find_internal)) |
{ |
#ifdef MODULE_LEVEL_SECURITY |
if(tmp2 = check_security(find_internal, id, slevel)) |
if(intp(tmp2)) |
{ |
TRACE_LEAVE(LOCALE->module_access_denied()); |
find_internal = 0; |
} else { |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->request_denied()); |
return tmp2; |
} |
if(find_internal) |
#endif |
{ |
TRACE_ENTER(LOCALE->calling_find_internal(), find_internal); |
LOCK(find_internal); |
fid=find_internal( rest, id ); |
UNLOCK(); |
TRACE_LEAVE(LOCALE->find_internal_returned(fid)); |
if(fid) |
{ |
if(mappingp(fid)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(examine_return_mapping(fid)); |
return fid; |
} |
else |
{ |
#ifdef MODULE_LEVEL_SECURITY |
int oslevel = slevel; |
slevel = misc_cache[ find_internal ][1]; |
|
|
id->misc->seclevel = slevel; |
#endif |
if(objectp(fid)) |
TRACE_LEAVE(LOCALE->returned_fd() |
#ifdef MODULE_LEVEL_SECURITY |
+(slevel != oslevel? |
LOCALE->seclevel_is_now(slevel):"") |
#endif |
+"."); |
else |
TRACE_LEAVE(LOCALE->returned_directory_indicator() |
#ifdef MODULE_LEVEL_SECURITY |
+(oslevel != slevel? |
LOCALE->seclevel_is_now(slevel):"") |
#endif |
); |
} |
} else |
TRACE_LEAVE(""); |
} else |
TRACE_LEAVE(""); |
} else |
TRACE_LEAVE(""); |
} |
} |
|
|
|
if(!fid) |
{ |
#ifdef URL_MODULES |
|
foreach(url_modules(id), funp) |
{ |
LOCK(funp); |
TRACE_ENTER(LOCALE->url_module(), funp); |
tmp=funp( id, file ); |
UNLOCK(); |
|
if(mappingp(tmp)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
if(objectp( tmp )) |
{ |
array err; |
|
nest ++; |
err = catch { |
if( nest < 20 ) |
tmp = (id->conf || this_object())->low_get_file( tmp, no_magic ); |
else |
{ |
TRACE_LEAVE(LOCALE->too_deep_recursion()); |
error("Too deep recursion in roxen::get_file() while mapping " |
+file+".\n"); |
} |
}; |
nest = 0; |
if(err) throw(err); |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
TRACE_LEAVE(""); |
} |
#endif |
#ifdef EXTENSION_MODULES |
if(tmp=extension_modules(loc=extension(file), id)) |
{ |
foreach(tmp, funp) |
{ |
TRACE_ENTER(LOCALE->extension_module(loc), funp); |
LOCK(funp); |
tmp=funp(loc, id); |
UNLOCK(); |
if(tmp) |
{ |
if(!objectp(tmp)) |
{ |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
fid = tmp; |
#ifdef MODULE_LEVEL_SECURITY |
slevel = function_object(funp)->query("_seclvl"); |
#endif |
TRACE_LEAVE(LOCALE->returned_fd() |
#ifdef MODULE_LEVEL_SECURITY |
+(slevel != id->misc->seclevel? |
LOCALE->seclevel_is_now(slevel):"") |
#endif |
); |
#ifdef MODULE_LEVEL_SECURITY |
id->misc->seclevel = slevel; |
#endif |
break; |
} else |
TRACE_LEAVE(""); |
} |
} |
#endif |
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
if(!search(file, loc)) |
{ |
TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); |
#ifdef MODULE_LEVEL_SECURITY |
if(tmp2 = check_security(tmp[1], id, slevel)) |
if(intp(tmp2)) |
{ |
TRACE_LEAVE(LOCALE->module_access_denied()); |
continue; |
} else { |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->request_denied()); |
return tmp2; |
} |
#endif |
TRACE_ENTER(LOCALE->calling_find_file(), 0); |
LOCK(tmp[1]); |
fid=tmp[1]( file[ strlen(loc) .. ] + id->extra_extension, id); |
UNLOCK(); |
TRACE_LEAVE(LOCALE->find_file_returned(fid)); |
if(fid) |
{ |
id->virtfile = loc; |
|
if(mappingp(fid)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(examine_return_mapping(fid)); |
return fid; |
} |
else |
{ |
#ifdef MODULE_LEVEL_SECURITY |
int oslevel = slevel; |
slevel = misc_cache[ tmp[1] ][1]; |
|
|
id->misc->seclevel = slevel; |
#endif |
if(objectp(fid)) |
TRACE_LEAVE(LOCALE->returned_fd() |
#ifdef MODULE_LEVEL_SECURITY |
+(slevel != oslevel? |
LOCALE->seclevel_is_now(slevel):"") |
#endif |
|
+"."); |
else |
TRACE_LEAVE(LOCALE->returned_directory_indicator() |
#ifdef MODULE_LEVEL_SECURITY |
+(oslevel != slevel? |
LOCALE->seclevel_is_now(slevel):"") |
#endif |
); |
break; |
} |
} else |
TRACE_LEAVE(""); |
} else if(strlen(loc)-1==strlen(file)) { |
|
|
if(file+"/" == loc) |
{ |
TRACE_ENTER(LOCALE->automatic_redirect_to_location(), tmp[1]); |
TRACE_LEAVE(LOCALE->returning_data()); |
|
|
|
|
|
string new_query = http_encode_string(id->not_query) + "/" + |
(id->query?("?"+id->query):""); |
|
return http_redirect(new_query, id); |
} |
} |
} |
} |
|
if(fid == -1) |
{ |
if(no_magic) |
{ |
TRACE_LEAVE(LOCALE->no_magic()); |
return -1; |
} |
if(dir_module) |
{ |
LOCK(dir_module); |
TRACE_ENTER(LOCALE->directory_module(), dir_module); |
fid = dir_module->parse_directory(id); |
UNLOCK(); |
} |
else |
{ |
TRACE_LEAVE(LOCALE->no_directory_module()); |
return 0; |
} |
if(mappingp(fid)) |
{ |
TRACE_LEAVE(LOCALE->returning_data()); |
return (mapping)fid; |
} |
} |
|
|
if(objectp(fid)&& |
(tmp=file_extension_modules(loc=extension(id->not_query), id))) |
foreach(tmp, funp) |
{ |
TRACE_ENTER(LOCALE->extension_module(loc), funp); |
#ifdef MODULE_LEVEL_SECURITY |
if(tmp=check_security(funp, id, slevel)) |
if(intp(tmp)) |
{ |
TRACE_LEAVE(LOCALE->module_access_denied()); |
continue; |
} |
else |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->permission_denied()); |
return tmp; |
} |
#endif |
LOCK(funp); |
tmp=funp(fid, loc, id); |
UNLOCK(); |
if(tmp) |
{ |
if(!objectp(tmp)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
if(fid) |
destruct(fid); |
TRACE_LEAVE(LOCALE->returned_new_open_file()); |
fid = tmp; |
break; |
} else |
TRACE_LEAVE(""); |
} |
|
if(objectp(fid)) |
{ |
if(stringp(id->extension)) |
id->not_query += id->extension; |
|
|
TRACE_ENTER(LOCALE->content_type_module(), types_module); |
tmp=type_from_filename(id->not_query, 1); |
TRACE_LEAVE(tmp?LOCALE->returned_mime_type(tmp[0],tmp[1]): |
LOCALE->missing_type()); |
if(tmp) |
{ |
TRACE_LEAVE(""); |
return ([ "file":fid, "type":tmp[0], "encoding":tmp[1] ]); |
} |
TRACE_LEAVE(""); |
return ([ "file":fid, ]); |
} |
if(!fid) |
{ |
TRACE_LEAVE(LOCALE->returned_not_found()); |
} |
else |
TRACE_LEAVE(LOCALE->returning_data()); |
return fid; |
} |
|
|
mixed handle_request( object id ) |
{ |
function funp; |
mixed file; |
|
#ifdef REQUEST_DEBUG |
werror("CONFIG: handle_request()\n"); |
#endif /* REQUEST_DEBUG */ |
|
if(roxen->find_site_for( id ) != this_object()) { |
#ifdef REQUEST_DEBUG |
werror("CONFIG: handle_request(): Redirected (1)\n"); |
#endif /* REQUEST_DEBUG */ |
return id->conf->handle_request(id); |
} |
foreach(first_modules(id), funp) |
{ |
if(file = funp( id )) |
break; |
if(id->conf != this_object()) { |
#ifdef REQUEST_DEBUG |
werror("CONFIG: handle_request(): Redirected (2)\n"); |
#endif /* REQUEST_DEBUG */ |
return id->conf->handle_request(id); |
} |
} |
|
file = get_file(id); |
|
if(!mappingp(file)) |
{ |
mixed ret; |
foreach(last_modules(id), funp) if(ret = funp(id)) break; |
if (ret == 1) { |
#ifdef REQUEST_DEBUG |
werror("CONFIG: handle_request(): Recurse\n"); |
#endif /* REQUEST_DEBUG */ |
return handle_request(id); |
} |
file = ret; |
} |
#ifdef REQUEST_DEBUG |
werror("CONFIG: handle_request(): Done\n"); |
#endif /* REQUEST_DEBUG */ |
return file; |
} |
|
mixed get_file(object id, int|void no_magic) |
{ |
mixed res, res2; |
function tmp; |
res = low_get_file(id, no_magic); |
|
|
|
foreach(filter_modules(id), tmp) |
{ |
TRACE_ENTER(LOCALE->filter_module(), tmp); |
if(res2=tmp(res,id)) |
{ |
if(res && res->file && (res2->file != res->file)) |
destruct(res->file); |
TRACE_LEAVE(LOCALE->rewrote_result()); |
res=res2; |
} else |
TRACE_LEAVE(""); |
} |
return res; |
} |
|
public array find_dir(string file, object id) |
{ |
string loc; |
array dir = ({ }), tmp; |
array | mapping d; |
|
|
TRACE_ENTER(LOCALE->list_directory(file), 0); |
|
|
if(file[0] != '/') |
file = "/" + file; |
|
#ifdef URL_MODULES |
#ifdef THREADS |
object key; |
#endif |
|
foreach(url_modules(id), function funp) |
{ |
string of = id->not_query; |
id->not_query = file; |
LOCK(funp); |
TRACE_ENTER(LOCALE->url_module(), funp); |
tmp=funp( id, file ); |
UNLOCK(); |
|
if(mappingp( tmp )) |
{ |
id->not_query=of; |
TRACE_LEAVE(LOCALE->returned_no_thanks()); |
TRACE_LEAVE(""); |
return 0; |
} |
if(objectp( tmp )) |
{ |
array err; |
nest ++; |
|
TRACE_LEAVE(LOCALE->recursing()); |
file = id->not_query; |
err = catch { |
if( nest < 20 ) |
tmp = (id->conf || this_object())->find_dir( file, id ); |
else |
error("Too deep recursion in roxen::find_dir() while mapping " |
+file+".\n"); |
}; |
nest = 0; |
TRACE_LEAVE(""); |
if(err) |
throw(err); |
return tmp; |
} |
id->not_query=of; |
} |
#endif /* URL_MODULES */ |
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
if(!search(file, loc)) { |
|
TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); |
#ifdef MODULE_LEVEL_SECURITY |
if(check_security(tmp[1], id)) { |
TRACE_LEAVE(LOCALE->permission_denied()); |
continue; |
} |
#endif |
if(d=function_object(tmp[1])->find_dir(file[strlen(loc)..], id)) |
{ |
if(mappingp(d)) |
{ |
if(d->files) { |
dir |= d->files; |
TRACE_LEAVE(LOCALE->got_exclusive_dir()); |
TRACE_LEAVE(LOCALE->returning_file_list(sizeof(dir))); |
return dir; |
} else |
TRACE_LEAVE(""); |
} else { |
TRACE_LEAVE(LOCALE->got_files()); |
dir |= d; |
} |
} else |
TRACE_LEAVE(""); |
} else if((search(loc, file)==0) && (loc[strlen(file)-1]=='/') && |
(loc[0]==loc[-1]) && (loc[-1]=='/') && |
(function_object(tmp[1])->stat_file(".", id))) { |
|
|
|
TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); |
loc=loc[strlen(file)..]; |
sscanf(loc, "%s/", loc); |
dir += ({ loc }); |
TRACE_LEAVE(LOCALE->added_module_mountpoint()); |
} |
} |
if(sizeof(dir)) |
{ |
TRACE_LEAVE(LOCALE->returning_file_list(sizeof(dir))); |
return dir; |
} |
TRACE_LEAVE(LOCALE->returning_no_dir()); |
} |
|
|
|
public array stat_file(string file, object id) |
{ |
string loc; |
array s, tmp; |
TRACE_ENTER(LOCALE->stat_file(file), 0); |
|
file=replace(file, "//", "/"); |
|
#ifdef URL_MODULES |
#ifdef THREADS |
object key; |
#endif |
|
foreach(url_modules(id), function funp) |
{ |
string of = id->not_query; |
id->not_query = file; |
|
TRACE_ENTER(LOCALE->url_module(), funp); |
LOCK(funp); |
tmp=funp( id, file ); |
UNLOCK(); |
|
if(mappingp( tmp )) { |
id->not_query = of; |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returned_no_thanks()); |
return 0; |
} |
if(objectp( tmp )) |
{ |
file = id->not_query; |
|
array err; |
nest ++; |
TRACE_LEAVE(LOCALE->recursing()); |
err = catch { |
if( nest < 20 ) |
tmp = (id->conf || this_object())->stat_file( file, id ); |
else |
error("Too deep recursion in roxen::stat_file() while mapping " |
+file+".\n"); |
}; |
nest = 0; |
if(err) |
throw(err); |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->returning_data()); |
return tmp; |
} |
TRACE_LEAVE(""); |
id->not_query = of; |
} |
#endif |
|
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
if((file == loc) || ((file+"/")==loc)) |
{ |
TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); |
TRACE_LEAVE(LOCALE->exact_match()); |
TRACE_LEAVE(""); |
return ({ 0775, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); |
} |
if(!search(file, loc)) |
{ |
TRACE_ENTER(LOCALE->location_module(loc), tmp[1]); |
#ifdef MODULE_LEVEL_SECURITY |
if(check_security(tmp[1], id)) { |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->permission_denied()); |
continue; |
} |
#endif |
if(s=function_object(tmp[1])->stat_file(file[strlen(loc)..], id)) |
{ |
TRACE_LEAVE(""); |
TRACE_LEAVE(LOCALE->stat_ok()); |
return s; |
} |
TRACE_LEAVE(""); |
} |
} |
TRACE_LEAVE(LOCALE->returned_not_found()); |
} |
|
class StringFile |
{ |
string data; |
int offset; |
|
string read(int nbytes) |
{ |
if(!nbytes) |
{ |
offset = strlen(data); |
return data; |
} |
string d = data[offset..offset+nbytes-1]; |
offset += strlen(d); |
return d; |
} |
|
void write(mixed ... args) |
{ |
throw( ({ "File not open for write", backtrace() }) ); |
} |
|
void seek(int to) |
{ |
offset = to; |
} |
|
void create(string d) |
{ |
data = d; |
} |
|
} |
|
|
|
public array open_file(string fname, string mode, object id) |
{ |
object oc = id->conf; |
string oq = id->not_query; |
function funp; |
mapping file; |
|
if(roxen->find_site_for( id ) != this_object()) |
return id->open_file( fname, mode, id ); |
|
id->not_query = fname; |
|
foreach(oc->first_modules(), funp) |
if(file = funp( id )) |
break; |
else if(id->conf != oc) |
{ |
return open_file(fname, mode,id); |
} |
fname = id->not_query; |
|
if(search(mode, "R")!=-1) |
{ |
string f; |
mode -= "R"; |
if(f = real_file(fname, id)) |
{ |
|
return ({ open(f, mode), ([]) }); |
} |
|
} |
|
if(mode=="r") |
{ |
if(!file) |
{ |
file = oc->get_file( id ); |
if(!file) { |
foreach(oc->last_modules(), funp) if(file = funp( id )) |
break; |
if (file == 1) { |
|
return open_file(id->not_query, mode, id); |
} |
} |
} |
|
if(!mappingp(file)) |
{ |
if(id->misc->error_code) |
file = http_low_answer(id->misc->error_code, "Failed" ); |
else if(id->method!="GET"&&id->method != "HEAD"&&id->method!="POST") |
file = http_low_answer(501, "Not implemented."); |
else |
file=http_low_answer(404,replace(parse_rxml(query("ZNoSuchFile"),id), |
({"$File", "$Me"}), |
({fname,query("MyWorldLocation")}))); |
|
id->not_query = oq; |
|
return ({ 0, file }); |
} |
|
if(file->data) |
{ |
file->file = StringFile(file->data); |
m_delete(file, "data"); |
} |
id->not_query = oq; |
return ({ file->file, file }); |
} |
id->not_query = oq; |
return ({ 0, (["error":501, "data":"Not implemented"]) }); |
} |
|
|
public mapping(string:array(mixed)) find_dir_stat(string file, object id) |
{ |
string loc; |
mapping(string:array(mixed)) dir = ([]); |
mixed d, tmp; |
|
|
if(roxen->find_site_for( id ) != this_object()) |
return id->find_dir_stat( file, id ); |
|
file=replace(file, "//", "/"); |
|
if(file[0] != '/') |
file = "/" + file; |
|
|
|
TRACE_ENTER(LOCALE->find_dir_stat(file), 0); |
|
#ifdef URL_MODULES |
#ifdef THREADS |
object key; |
#endif |
|
foreach(url_modules(id), function funp) |
{ |
string of = id->not_query; |
id->not_query = file; |
LOCK(funp); |
TRACE_ENTER(LOCALE->url_module(), funp); |
tmp=funp( id, file ); |
UNLOCK(); |
|
if(mappingp( tmp )) |
{ |
id->not_query=of; |
#ifdef MODULE_DEBUG |
roxen_perror(sprintf("conf->find_dir_stat(\"%s\"): url_module returned mapping:%O\n", |
file, tmp)); |
#endif /* MODULE_DEBUG */ |
TRACE_LEAVE(LOCALE->returned_mapping()); |
TRACE_LEAVE(LOCALE->empty_dir()); |
return 0; |
} |
if(objectp( tmp )) |
{ |
array err; |
nest ++; |
|
file = id->not_query; |
err = catch { |
if( nest < 20 ) |
tmp = (id->conf || this_object())->find_dir_stat( file, id ); |
else { |
TRACE_LEAVE(LOCALE->too_deep_recursion()); |
error("Too deep recursion in roxen::find_dir_stat() while mapping " |
+file+".\n"); |
} |
}; |
nest = 0; |
if(err) |
throw(err); |
#ifdef MODULE_DEBUG |
roxen_perror(sprintf("conf->find_dir_stat(\"%s\"): url_module returned object:\n", |
file)); |
#endif /* MODULE_DEBUG */ |
TRACE_LEAVE(LOCALE->returned_object()); |
TRACE_LEAVE(LOCALE->returning_it()); |
return tmp; |
} |
id->not_query=of; |
TRACE_LEAVE(""); |
} |
#endif /* URL_MODULES */ |
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
|
TRACE_ENTER(LOCALE->location_module(loc), 0); |
|
if(!search(file, loc)) |
{ |
|
#ifdef MODULE_LEVEL_SECURITY |
if(check_security(tmp[1], id)) continue; |
#endif |
object c = function_object(tmp[1]); |
string f = file[strlen(loc)..]; |
if (c->find_dir_stat) { |
TRACE_ENTER(LOCALE->has_find_dir_stat(), 0); |
if (d = c->find_dir_stat(f, id)) { |
TRACE_ENTER(LOCALE->returned_mapping(), 0); |
dir = d | dir; |
TRACE_LEAVE(""); |
} |
TRACE_LEAVE(""); |
} else if(d = c->find_dir(f, id)) { |
TRACE_ENTER(LOCALE->returned_array(), 0); |
dir = mkmapping(d, Array.map(d, lambda(string f, string base, |
object c, object id) { |
return(c->stat_file(base + f, id)); |
}, f, c, id)) | dir; |
TRACE_LEAVE(""); |
} |
} else if(search(loc, file)==0 && loc[strlen(file)-1]=='/' && |
(loc[0]==loc[-1]) && loc[-1]=='/' && |
(function_object(tmp[1])->stat_file(".", id))) { |
|
|
|
TRACE_ENTER(LOCALE->file_on_mountpoint_path(file, loc), 0); |
loc=loc[strlen(file)..]; |
sscanf(loc, "%s/", loc); |
if (!dir[loc]) { |
dir[loc] = ({ 0775, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); |
} |
TRACE_LEAVE(""); |
} |
TRACE_LEAVE(""); |
} |
if(sizeof(dir)) |
return dir; |
} |
|
|
|
|
public array access(string file, object id) |
{ |
string loc; |
array s, tmp; |
|
file=replace(file, "//", "/"); |
|
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
if((file+"/")==loc) |
return file+="/"; |
if(!search(file, loc)) |
{ |
#ifdef MODULE_LEVEL_SECURITY |
if(check_security(tmp[1], id)) continue; |
#endif |
if(s=function_object(tmp[1])->access(file[strlen(loc)..], id)) |
return s; |
} |
} |
} |
|
|
|
public string real_file(string file, object id) |
{ |
string loc; |
string s; |
array tmp; |
file=replace(file, "//", "/"); |
|
if(!id) error("No id passed to real_file"); |
|
|
foreach(location_modules(id), tmp) |
{ |
loc = tmp[0]; |
if(!search(file, loc)) |
{ |
#ifdef MODULE_LEVEL_SECURITY |
if(check_security(tmp[1], id)) continue; |
#endif |
|
|
if(s=function_object(tmp[1])->real_file(file[strlen(loc)..1000000], id)) |
return s; |
} |
} |
} |
|
|
|
|
|
|
|
public mixed try_get_file(string s, object id, int|void status, int|void nocache) |
{ |
string res, q; |
object fake_id; |
mapping m; |
|
|
if(objectp(id)) { |
|
|
if ( !id->misc ) |
id->misc = ([]); |
if ( !id->misc->common ) |
id->misc->common = ([]); |
|
fake_id = id->clone_me(); |
|
fake_id->misc->common = id->misc->common; |
} else |
error("No ID passed to 'try_get_file'\n"); |
|
if(!id->pragma["no-cache"] && !nocache) |
if(res = cache_lookup("file:"+id->conf->name, s)) |
return res; |
|
if(sscanf(s, "%s?%s", s, q)) |
{ |
string v, name, value; |
foreach(q/"&", v) |
if(sscanf(v, "%s=%s", name, value)) |
fake_id->variables[http_decode_string(name)]=value; |
fake_id->query=q; |
} |
|
fake_id->raw_url=s; |
fake_id->not_query=s; |
fake_id->misc->internal_get=1; |
|
if(!(m = get_file(fake_id))) |
{ |
fake_id->end(); |
return 0; |
} |
fake_id->end(); |
|
if (!(< 0, 200, 201, 202, 203 >)[m->error]) return 0; |
|
if(status) return 1; |
|
#ifdef COMPAT |
if(m["string"]) res = m["string"]; |
else |
#endif |
if(m->data) res = m->data; |
else res=""; |
m->data = 0; |
|
if(m->file) |
{ |
res += m->file->read(); |
destruct(m->file); |
m->file = 0; |
} |
|
if(m->raw) |
{ |
res -= "\r"; |
if(!sscanf(res, "%*s\n\n%s", res)) |
sscanf(res, "%*s\n%s", res); |
} |
cache_set("file:"+id->conf->name, s, res); |
return res; |
} |
|
|
public int is_file(string what, object id) |
{ |
return !!stat_file(what, id); |
} |
|
string MKPORTKEY(array(string) p) |
{ |
if (sizeof(p[3])) { |
return(sprintf("%s://%s:%s/(%s)", |
p[1], p[2], (string)p[0], |
replace(p[3], ({"\n", "\r"}), ({ " ", " " })))); |
} else { |
return(sprintf("%s://%s:%s/", |
p[1], p[2], (string)p[0])); |
} |
} |
|
mapping(string:object) server_ports = ([]); |
|
int ports_changed = 1; |
void start(int num) |
{ |
string server_name = query_name(); |
array port; |
int err=0; |
object lf; |
mapping new=([]), o2; |
|
parse_log_formats(); |
init_log_file(); |
|
#if 0 |
|
|
if (!ports_changed) { |
return; |
} |
#endif /* 0 */ |
|
ports_changed = 0; |
|
|
mapping(string:array(string)) new_ports = ([]); |
foreach(query("Ports"), port) { |
if ((< "ssl", "ssleay", "ssl3" >)[port[1]]) { |
|
report_warning(server_name + ": " + LOCALE->obsolete_ssl(port[1])); |
|
port[1] = "https"; |
|
} |
string key = MKPORTKEY(port); |
if (!server_ports[key]) { |
report_notice(LOCALE->new_port(server_name, key)); |
new_ports[key] = port; |
} else { |
|
new_ports[key] = 0; |
} |
} |
|
|
foreach(indices(server_ports), string key) { |
if (zero_type(new_ports[key])) { |
report_notice(LOCALE->disabling_port(server_name, key)); |
object o = server_ports[key]; |
m_delete(server_ports, key); |
mixed err; |
if (err = catch{ |
destruct(o); |
}) { |
report_warning(LOCALE->error_disabling_port(server_name, key, |
describe_backtrace(err))); |
} |
o = 0; |
} |
} |
|
|
roxen_perror(LOCALE->opening_ports(server_name)); |
foreach(indices(new_ports), string key) { |
port = new_ports[key]; |
if (port) { |
array old = port; |
mixed erro; |
erro = catch { |
program requestprogram = (program)(getcwd()+"/protocols/"+port[1]); |
function rp; |
array tmp; |
if(!requestprogram) { |
report_error(server_name + ": " + |
LOCALE->no_request_program(port[1])); |
continue; |
} |
if(rp = requestprogram()->real_port) |
if(tmp = rp(port, this_object())) |
port = tmp; |
|
|
|
object privs; |
if(port[0] < 1024) |
privs = Privs(LOCALE->opening_low_port()); |
|
object o; |
if(o=create_listen_socket(port[0], this_object(), port[2], |
requestprogram, port)) { |
report_notice(LOCALE->opening_port(server_name, key)); |
server_ports[key] = o; |
} else { |
report_error(LOCALE->could_not_open_port(server_name, key)); |
} |
if (privs) { |
destruct(privs); |
} |
}; |
if (erro) { |
report_error(LOCALE->failed_to_open_port(server_name, key, |
(stringp(erro)?erro: |
describe_backtrace(erro)))); |
} |
} |
} |
if (sizeof(query("Ports")) && !sizeof(server_ports)) { |
string port_list = Array.map(query("Ports"), |
lambda(array p) { |
return sprintf("%5d %-10s %-20s\n", @p); |
})*""; |
report_error(LOCALE->no_ports_available_tried(name, port_list)); |
} |
} |
|
|
|
|
|
void save(int|void all) |
{ |
mapping mod; |
if(all) |
{ |
store("spider.lpc#0", variables, 0, this); |
start(2); |
} |
|
foreach(values(modules), mod) |
{ |
if(mod->enabled) |
{ |
store(mod->sname+"#0", mod->master->query(), 0, this); |
mod->enabled->start(2, this); |
} else if(mod->copies) { |
int i; |
foreach(indices(mod->copies), i) |
{ |
store(mod->sname+"#"+i, mod->copies[i]->query(), 0, this); |
mod->copies[i]->start(2, this); |
} |
} |
} |
invalidate_cache(); |
} |
|
|
int save_one( object o ) |
{ |
mapping mod; |
if(!o) |
{ |
store("spider#0", variables, 0, this); |
start(2); |
return 1; |
} |
foreach(values(modules), mod) |
{ |
if( mod->enabled == o) |
{ |
store(mod->sname+"#0", o->query(), 0, this); |
o->start(2, this); |
invalidate_cache(); |
return 1; |
} else if(mod->copies) { |
int i; |
foreach(indices(mod->copies), i) |
{ |
if(mod->copies[i] == o) |
{ |
store(mod->sname+"#"+i, o->query(), 0, this); |
o->start(2, this); |
invalidate_cache(); |
return 1; |
} |
} |
} |
} |
} |
|
mapping _hooks=([ ]); |
|
|
void hooks_for( string modname, object mod ) |
{ |
array hook; |
if(_hooks[modname]) |
{ |
#ifdef MODULE_DEBUG |
perror("Module hooks..."); |
#endif |
foreach(_hooks[modname], hook) |
hook[0]( @hook[1], mod ); |
} |
} |
|
|
int unload_module( string modname ); |
int load_module( string modname ); |
|
object enable_module( string modname ) |
{ |
string id; |
mapping module; |
mapping enabled_modules; |
modname = replace(modname, ".lpc#","#"); |
|
sscanf(modname, "%s#%s", modname, id ); |
|
module = modules[ modname ]; |
if(!module) |
{ |
load_module(modname); |
module = modules[ modname ]; |
} |
|
#if constant(gethrtime) |
int start_time = gethrtime(); |
#endif |
if (!module) { |
return 0; |
} |
|
object me; |
mapping tmp; |
int pr; |
array err; |
|
#ifdef MODULE_DEBUG |
perror("Enabling "+module->name+" # "+id+" ... "); |
#endif |
|
if(module->copies) |
{ |
if (err = catch(me = module["program"](this_object()))) { |
report_error(LOCALE->could_not_clone_module(module->name, |
describe_backtrace(err))); |
if (module->copies[id]) { |
#ifdef MODULE_DEBUG |
perror("Keeping old copy\n"); |
#endif |
} |
return(module->copies[id]); |
} |
if(module->copies[id]) { |
#ifdef MODULE_DEBUG |
perror("Disabling old copy ... "); |
#endif |
if (err = catch{ |
module->copies[id]->stop(); |
}) { |
report_error(LOCALE->error_disabling_module(module->name, |
describe_backtrace(err))); |
} |
destruct(module->copies[id]); |
} |
} else { |
if(objectp(module->master)) { |
me = module->master; |
} else { |
if (err = catch(me = module["program"](this_object()))) { |
report_error(LOCALE->could_not_clone_module(module->name, |
describe_backtrace(err))); |
return(0); |
} |
} |
} |
|
me->set_configuration(this_object()); |
#ifdef MODULE_DEBUG |
|
#endif |
if (module->type & (MODULE_LOCATION | MODULE_EXTENSION | |
MODULE_CONFIG| MODULE_FILE_EXTENSION | MODULE_LOGGER | |
MODULE_URL | MODULE_LAST | MODULE_PROVIDER | |
MODULE_FILTER | MODULE_PARSER | MODULE_FIRST)) |
{ |
if(module->type != MODULE_CONFIG) |
{ |
me->defvar("_priority", 5, "Priority", TYPE_INT_LIST, |
"The priority of the module. 9 is highest and 0 is lowest." |
" Modules with the same priority can be assumed to be " |
"called in random order", |
({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); |
|
me->deflocaledoc("svenska", "_priority", "Prioritet", |
"Modulens prioritet, 9 är högst och 0 är" |
" lägst. Moduler med samma prioritet anropas i " |
"mer eller mindre slumpmässig ordning."); |
} |
|
if(module->type != MODULE_LOGGER && |
module->type != MODULE_PROVIDER) |
{ |
if(!(module->type & MODULE_PROXY)) |
{ |
me->defvar("_sec_group", "user", "Security: Realm", TYPE_STRING, |
"The realm to use when requesting password from the " |
"client. Usually used as an informative message to the " |
"user."); |
|
me->deflocaledoc("svenska", "_sec_group", "Säkerhet: Grupp", |
"Gruppnamnet som används när klienten bes" |
" ange lösenord. I de flesta klienter visas den " |
" här informationen för användaren i" |
" lösenordsdialogen."); |
|
|
me->defvar("_seclvl", 0, "Security: Security level", TYPE_INT, |
"The modules security level is used to determine if a " |
" request should be handled by the module." |
"\n<p><h2>Security level vs Trust level</h2>" |
" Each module has a configurable <i>security level</i>." |
" Each request has an assigned trust level. Higher" |
" <i>trust levels</i> grants access to modules with higher" |
" <i>security levels</i>." |
"\n<p><h2>Definitions</h2><ul>" |
" <li>A requests initial Trust level is infinitely high." |
" <li> A request will only be handled by a module if its" |
" <i>trust level</i> is higher or equal to the" |
" <i>security level</i> of the module." |
" <li> Each time the request is handled by a module the" |
" <i>trust level</i> of the module will be set to the" |
" lower of its <i>trust level</i> and the modules" |
" <i>security level</i>." |
" </ul>" |
"\n<p><h2>Example</h2>" |
" Modules:<ul>" |
" <li> User filesystem, <i>security level</i> 1" |
" <li> Filesystem module, <i>security level</i> 3" |
" <li> CGI module, <i>security level</i> 2" |
" </ul>" |
"\n<p>A request handled by \"User filesystem\" is assigned" |
" a <i>trust level</i> of one after the <i>security" |
" level</i> of that module. That request can then not be" |
" handled by the \"CGI module\" since that module has a" |
" higher <i>security level</i> than the requests trust" |
" level." |
"\n<p>On the other hand, a request handled by the the" |
" \"Filsystem module\" could later be handled by the" |
" \"CGI module\"."); |
me->deflocaledoc("svenska", "_seclvl", "Säkerhet: Säkerhetsnivå", |
"Modulens säkerhetsnivå används för att avgöra om " |
" en specifik request ska få hanteras av modulen. " |
"\n<p><h2>Säkerhetsnivå och pålitlighetsnivå</h2>" |
" Varje modul har en konfigurerbar " |
"<i>säkerhtesnivå</i>. " |
"Varje request har en <i>pålitlighetsnivå</i>.<p>" |
"Högre <i>pålitlighetsnivåer</i> ger " |
" requesten tillgång till moduler med högre " |
"<i>säkerhetsnivå</i>. <p>\n" |
"\n<p><h2>Defenitioner</h2><ul>" |
" <li>En requests initialpålitlighetsnivå är " |
" oändligt hög." |
" <li> En request hanteras bara av moduler om " |
"dess <i>pålitlighetsnivå</i> är högre eller " |
" lika hög som modulens <i>säkerhetsnivå</i>" |
" <li> Varje gång en request hanteras av en" |
" modul så sätts dess <i>pålitlighetsnivå</i> " |
"till modulens <i>säkerhetsnivå</i> om " |
" modulen har en <i>säkerhetsnivå</i> som är " |
"skiljd from noll. " |
" </ul>" |
"\n<p><h2>Ett exempel</h2>" |
" Moduler:<ul>" |
" <li> Användarfilsystem, <i>säkerhetsnivå</i> 1" |
" <li> Filesystem, <i>säkerhetsnivå</i> 3" |
" <li> CGI modul, <i>säkerhetsnivå</i> 2" |
" </ul>" |
"\n<p>En request hanterad av " |
" <i>Användarfilsystemet</i> får ett " |
"som <i>pålitlighetsnivå</i>. Den här" |
" requesten kan därför inte skickas vidare " |
"till <i>CGI modulen</i> eftersom den har" |
" en <i>säkerhetsnivå</i> som är högre än" |
" requestens <i>pålitlighetsnivå</i>.<p>" |
" Å andra sidan så kan en request som " |
" hanteras av <i>Filsystem</i> modulen " |
" skickas vidare till <i>CGI modulen</i>."); |
|
|
|
|
me->defvar("_seclevels", "", "Security: Patterns", TYPE_TEXT_FIELD, |
"This is the 'security level=value' list.<br>" |
"Each security level can be any or more from this list:" |
"<hr noshade>" |
"allow ip=<i>IP</i>/<i>bits</i><br>" |
"allow ip=<i>IP</i>:<i>mask</i><br>" |
"allow ip=<i>pattern</i><br>" |
"allow user=<i>username</i>,...<br>" |
"deny ip=<i>IP</i>/<i>bits</i><br>" |
"deny ip=<i>IP</i>:<i>mask</i><br>" |
"deny ip=<i>pattern</i><br>" |
"<hr noshade>" |
"In patterns: * matches one or more characters, " |
"and ? matches one character.<p>" |
"In username: 'any' stands for any valid account " |
"(from .htaccess" |
" or auth-module. The default (used when _no_ " |
"entries are present) is 'allow ip=*', allowing" |
" everyone to access the module"); |
|
me->deflocaledoc("svenska", "_seclevels", |
"Säkerhet: Behörighetsregler", |
"Det här är en lista av behörighetsregler.<p>" |
"Varje behörighetsregler måste följa någon av de " |
" här mönstren: " |
"<hr noshade>" |
"allow ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" |
"allow ip=<i>IP-nummer</i>:<i>nätmask</i><br>" |
"allow ip=<i>globmönster</i><br>" |
"allow user=<i>användarnamn</i>,...<br>" |
"deny ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" |
"deny ip=<i>IP-nummer</i>:<i>nätmask</i><br>" |
"deny ip=<i>globmönster</i><br>" |
"<hr noshade>" |
"I globmänster betyer '*' ett eller flera " |
"godtyckliga tecken, och '?' betyder exekt " |
"ett godtyckligt tecken.<p> " |
"Användnamnet 'any' kan användas för att ange " |
"att vilken giltig användare som helst ska " |
" kunna få använda modulen."); |
|
|
} else { |
me->definvisvar("_seclvl", -10, TYPE_INT); |
|
me->defvar("_sec_group", "user", "Proxy Security: Realm", TYPE_STRING, |
"The realm to use when requesting password from the " |
"client. Usually used as an informative message to the " |
"user."); |
me->deflocaledoc("svenska", "_sec_group", "Säkerhet: Grupp", |
"Gruppnamnet som används när klienten bes" |
" ange lösenord. I de flesta klienter visas den " |
" här informationen för användaren i" |
"lösenordsdialogen."); |
|
|
|
me->defvar("_seclevels", "", "Proxy security: Patterns", |
TYPE_TEXT_FIELD, |
"This is the 'security level=value' list.<br>" |
"Each security level can be any or more from " |
"this list:<br>" |
"<hr noshade>" |
"allow ip=pattern<br>" |
"allow user=username,...<br>" |
"deny ip=pattern<br>" |
"<hr noshade>" |
"In patterns: * is on or more characters, ? is one " |
" character.<p>" |
"In username: 'any' stands for any valid account" |
" (from .htaccess" |
" or auth-module. The default is 'deny ip=*'"); |
|
me->deflocaledoc("svenska", "_seclevels", |
"Säkerhet: Behörighetsregler", |
"Det här är en lista av behörighetsregler.<p>" |
"Varje behörighetsregler måste följa någon av de " |
" här mönstren: " |
"<hr noshade>" |
"allow ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" |
"allow ip=<i>IP-nummer</i>:<i>nätmask</i><br>" |
"allow ip=<i>globmönster</i><br>" |
"allow user=<i>användarnamn</i>,...<br>" |
"deny ip=<i>IP-nummer</i>/<i>antal nätmaskbittar</i><br>" |
"deny ip=<i>IP-nummer</i>:<i>nätmask</i><br>" |
"deny ip=<i>globmönster</i><br>" |
"<hr noshade>" |
"I globmänster betyer '*' ett eller flera " |
"godtyckliga tecken, och '?' betyder exekt " |
"ett godtyckligt tecken.<p> " |
"Användnamnet 'any' kan användas för att ange " |
"att vilken giltig användare som helst ska " |
" kunna få använda modulen."); |
|
|
} |
} |
} else { |
me->defvar("_priority", 0, "", TYPE_INT, "", 0, 1); |
} |
|
me->defvar("_comment", "", " Comment", TYPE_TEXT_FIELD|VAR_MORE, |
"An optional comment. This has no effect on the module, it " |
"is only a text field for comments that the administrator " |
"might have (why the module are here, etc.)"); |
|
me->deflocaledoc("svenska", "_comment", |
"Kommentar", |
"En kommentar. Den här kommentaren påverkar inte " |
" funktionaliteten hos modulen på något sätt, den " |
" syns bara i konfigurationsinterfacet."); |
|
|
|
me->defvar("_name", "", " Module name", TYPE_STRING|VAR_MORE, |
"An optional name. You can set it to something to remaind you what " |
"the module really does."); |
|
me->deflocaledoc("svenska", "_name", "Namn", |
"Modulens namn. Om den här variablen är satt så " |
"används dess värde istället för modulens riktiga namn " |
"i konfigurationsinterfacet."); |
|
me->setvars(retrieve(modname + "#" + id, this)); |
|
if(module->copies) |
module->copies[(int)id] = me; |
else |
module->enabled = me; |
|
otomod[ me ] = modname; |
|
mixed err; |
if((me->start) && (err = catch{ |
me->start(0, this); |
})) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
|
|
m_delete(otomod, me); |
|
if(module->copies) |
m_delete(module->copies, (int)id); |
else |
m_delete(module, "enabled"); |
|
destruct(me); |
|
return 0; |
} |
|
if (err = catch(pr = me->query("_priority"))) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
pr = 3; |
} |
|
api_module_cache |= me->api_functions(); |
|
if(module->type & MODULE_EXTENSION) { |
if (err = catch { |
array arr = me->query_extensions(); |
if (arrayp(arr)) { |
string foo; |
foreach( arr, foo ) |
if(pri[pr]->extension_modules[ foo ]) |
pri[pr]->extension_modules[foo] += ({ me }); |
else |
pri[pr]->extension_modules[foo] = ({ me }); |
} |
}) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
} |
} |
|
if(module->type & MODULE_FILE_EXTENSION) { |
if (err = catch { |
array arr = me->query_file_extensions(); |
if (arrayp(arr)) { |
string foo; |
foreach( me->query_file_extensions(), foo ) |
if(pri[pr]->file_extension_modules[foo] ) |
pri[pr]->file_extension_modules[foo]+=({me}); |
else |
pri[pr]->file_extension_modules[foo]=({me}); |
} |
}) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
} |
} |
|
if(module->type & MODULE_PROVIDER) { |
if (err = catch { |
mixed provs = me->query_provides(); |
if(stringp(provs)) |
provs = (< provs >); |
if(arrayp(provs)) |
provs = mkmultiset(provs); |
if (multisetp(provs)) { |
pri[pr]->provider_modules [ me ] = provs; |
} |
}) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
} |
} |
|
if(module->type & MODULE_TYPES) |
{ |
types_module = me; |
types_fun = me->type_from_extension; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(module->type & MODULE_PARSER) |
{ |
if(parse_module) { |
if (err = catch { |
add_parse_module( me ); |
}) { |
report_error(LOCALE-> |
error_initializing_module_copy(module->name, |
describe_backtrace(err))); |
} |
} |
|
} |
|
if(module->type & MODULE_AUTH) |
{ |
auth_module = me; |
auth_fun = me->auth; |
} |
|
if(module->type & MODULE_DIRECTORIES) |
dir_module = me; |
|
if(module->type & MODULE_LOCATION) |
pri[pr]->location_modules += ({ me }); |
|
if(module->type & MODULE_LOGGER) |
pri[pr]->logger_modules += ({ me }); |
|
if(module->type & MODULE_URL) |
pri[pr]->url_modules += ({ me }); |
|
if(module->type & MODULE_LAST) |
pri[pr]->last_modules += ({ me }); |
|
if(module->type & MODULE_FILTER) |
pri[pr]->filter_modules += ({ me }); |
|
if(module->type & MODULE_FIRST) { |
pri[pr]->first_modules += ({ me }); |
} |
|
hooks_for(module->sname+"#"+id, me); |
|
enabled_modules=retrieve("EnabledModules", this); |
|
if(!enabled_modules[modname+"#"+id]) |
{ |
#ifdef MODULE_DEBUG |
perror("New module..."); |
#endif |
enabled_modules[modname+"#"+id] = 1; |
store( "EnabledModules", enabled_modules, 1, this); |
} |
invalidate_cache(); |
#ifdef MODULE_DEBUG |
#if constant(gethrtime) |
perror(" Done (%3.3f seconds).\n", (gethrtime()-start_time)/1000000.0); |
#else |
perror(" Done.\n"); |
#endif |
#endif |
return me; |
} |
|
|
string check_variable(string name, string value) |
{ |
switch(name) |
{ |
case "Ports": |
ports_changed=1; |
return 0; |
case "MyWorldLocation": |
if(strlen(value)<7 || value[-1] != '/' || |
!(sscanf(value,"%*s://%*s/")==2)) |
return LOCALE->url_format(); |
return 0; |
} |
} |
|
|
|
|
|
|
|
|
|
|
#define perr(X) do { report += X; perror(X); } while(0) |
|
|
|
int log_is_not_enabled() |
{ |
return !query("Log"); |
} |
|
|
|
|
|
private string get_domain(int|void l) |
{ |
array f; |
string t, s; |
|
|
if (!l) { |
f = (roxen->QUERY(ConfigurationURL)/"://"); |
if (sizeof(f) > 1) { |
t = (replace(f[1], ({ ":", "/" }), ({ "\0", "\0" }))/"\0")[0]; |
f = t/"."; |
if (sizeof(f) > 1) { |
s = f[1..]*"."; |
} |
} |
} |
#if efun(gethostbyname) |
#if efun(gethostname) |
if(!s) { |
f = gethostbyname(gethostname()); |
if(f) |
foreach(f, f) { |
if (arrayp(f)) { |
foreach(f, t) { |
f = t/"."; |
if ((sizeof(f) > 1) && |
(replace(t, ({ "0", "1", "2", "3", "4", "5", |
"6", "7", "8", "9", "." }), |
({ "","","","","","","","","","","" })) != "")) { |
t = f[1..]*"."; |
if(!s || strlen(s) < strlen(t)) |
s=t; |
} |
} |
} |
} |
} |
#endif |
#endif |
if(!s) { |
t = Stdio.read_bytes("/etc/resolv.conf"); |
if(t) { |
if(!sscanf(t, "domain %s\n", s)) |
if(!sscanf(t, "search %s%*[ \t\n]", s)) |
s="nowhere"; |
} else { |
s="nowhere"; |
} |
} |
if(s && strlen(s)) |
{ |
if(s[-1] == '.') s=s[..strlen(s)-2]; |
if(s[0] == '.') s=s[1..]; |
} else { |
s="unknown"; |
} |
return s; |
} |
|
int disable_module( string modname ) |
{ |
mapping module; |
mapping enabled_modules; |
object me; |
int pr; |
int id; |
|
sscanf(modname, "%s#%d", modname, id ); |
|
module = modules[ modname ]; |
|
if(!module) |
{ |
report_error(LOCALE->disable_nonexistant_module(modname)); |
return 0; |
} |
|
if(module->copies) |
{ |
me = module->copies[id]; |
m_delete(module->copies, id); |
if(!sizeof(module->copies)) |
unload_module(modname); |
} else { |
me = module->enabled || module->master; |
module->enabled=module->master = 0; |
unload_module(modname); |
} |
|
invalidate_cache(); |
|
if(!me) |
{ |
report_error(LOCALE->disable_module_failed(module->name+" # "+id)); |
return 0; |
} |
|
if(me->stop) me->stop(); |
|
#ifdef MODULE_DEBUG |
perror("Disabling "+module->name+" # "+id+"\n"); |
#endif |
|
if(module["type"] & MODULE_EXTENSION |
&& arrayp( me -> query_extensions())) |
{ |
string foo; |
foreach( me -> query_extensions(), foo ) |
for(pr=0; pr<10; pr++) |
if( pri[pr]->extension_modules[ foo ] ) |
pri[pr]->extension_modules[ foo ]-= ({ me }); |
} |
|
if(module["type"] & MODULE_FILE_EXTENSION |
&& arrayp( me -> query_file_extensions())) |
{ |
string foo; |
foreach( me -> query_file_extensions(), foo ) |
for(pr=0; pr<10; pr++) |
if(pri[pr]->file_extension_modules[ foo ] ) |
pri[pr]->file_extension_modules[foo]-=({me}); |
} |
|
if(module->type & MODULE_PROVIDER) { |
for(pr=0; pr<10; pr++) |
m_delete(pri[pr]->provider_modules, me); |
} |
|
if(module["type"] & MODULE_TYPES) |
{ |
types_module = 0; |
types_fun = 0; |
} |
|
|
|
|
if(module->type & MODULE_PARSER) |
remove_parse_module( me ); |
|
if( module->type & MODULE_AUTH ) |
{ |
auth_module = 0; |
auth_fun = 0; |
} |
|
if( module->type & MODULE_DIRECTORIES ) |
dir_module = 0; |
|
|
if( module->type & MODULE_LOCATION ) |
for(pr=0; pr<10; pr++) |
pri[pr]->location_modules -= ({ me }); |
|
if( module->type & MODULE_URL ) |
for(pr=0; pr<10; pr++) |
pri[pr]->url_modules -= ({ me }); |
|
if( module->type & MODULE_LAST ) |
for(pr=0; pr<10; pr++) |
pri[pr]->last_modules -= ({ me }); |
|
if( module->type & MODULE_FILTER ) |
for(pr=0; pr<10; pr++) |
pri[pr]->filter_modules -= ({ me }); |
|
if( module->type & MODULE_FIRST ) { |
for(pr=0; pr<10; pr++) |
pri[pr]->first_modules -= ({ me }); |
} |
|
if( module->type & MODULE_LOGGER ) |
for(pr=0; pr<10; pr++) |
pri[pr]->logger_modules -= ({ me }); |
|
enabled_modules=retrieve("EnabledModules", this); |
|
if(enabled_modules[modname+"#"+id]) |
{ |
m_delete( enabled_modules, modname + "#" + id ); |
store( "EnabledModules",enabled_modules, 1, this); |
} |
destruct(me); |
return 1; |
} |
|
object|string find_module(string name) |
{ |
int id; |
sscanf(name, "%s#%d", name, id); |
if(modules[name]) |
{ |
if(modules[name]->copies) |
return modules[name]->copies[id]; |
else |
if(modules[name]->enabled) |
return modules[name]->enabled; |
} |
return 0; |
} |
|
void register_module_load_hook( string modname, function fun, mixed ... args ) |
{ |
object o; |
#ifdef MODULE_DEBUG |
perror("Registering a hook for the module "+modname+"\n"); |
#endif |
if(o=find_module(modname)) |
{ |
#ifdef MODULE_DEBUG |
perror("Already there!\n"); |
#endif |
fun( @args, o ); |
} else |
if(!_hooks[modname]) |
_hooks[modname] = ({ ({ fun, args }) }); |
else |
_hooks[modname] += ({ ({ fun, args }) }); |
} |
|
int load_module(string module_file) |
{ |
int foo, disablep; |
mixed err; |
mixed *module_data; |
mapping loaded_modules; |
object obj; |
program prog; |
#if efun(gethrtime) |
int start_time = gethrtime(); |
#endif |
|
#ifdef MODULE_DEBUG |
perror("\nLoading " + module_file + "... "); |
#endif |
|
if(prog=cache_lookup("modules", module_file)) { |
err = catch { |
obj = prog(this_object()); |
}; |
} else { |
string dir; |
object e; |
master()->set_inhibit_compile_errors((e = ErrorContainer())->got_error); |
err = catch { |
obj = roxen->load_from_dirs(roxen->QUERY(ModuleDirs), module_file, |
this_object()); |
}; |
master()->set_inhibit_compile_errors(0); |
|
if (sizeof(e->get())) { |
|
report_error(LOCALE->module_compilation_errors(module_file, e->get())); |
return(0); |
} |
prog = roxen->last_loaded(); |
} |
|
if (err) { |
report_error(LOCALE->error_enabling_module(module_file, |
describe_backtrace(err))); |
return(0); |
} |
|
if(!obj) |
{ |
report_error(LOCALE->module_load_failed(module_file)); |
return 0; |
} |
|
obj->set_configuration(this_object()); |
if (err = catch (module_data = obj->register_module(this_object()))) { |
#ifdef MODULE_DEBUG |
perror("FAILED\n" + describe_backtrace( err )); |
#endif |
report_error(LOCALE-> |
module_loaded_register_module_failed(module_file, |
describe_backtrace(err))); |
return 0; |
} |
|
err = ""; |
if (!arrayp( module_data )) |
err = LOCALE->bad_register_module_result(); |
else |
switch (sizeof( module_data )) |
{ |
case 5: |
foo=module_data[4]; |
module_data=module_data[0..3]; |
case 4: |
if (module_data[3] && !arrayp( module_data[3] )) |
err = LOCALE->bad_register_module4() + err; |
case 3: |
if (!stringp( module_data[2] ) && !mappingp(module_data[2])) |
err = LOCALE->bad_register_module3() + err; |
if (!stringp( module_data[1] ) && !mappingp(module_data[1])) |
err = LOCALE->bad_register_module2() + err; |
if (!intp( module_data[0] )) |
err = LOCALE->bad_register_module1() + err; |
break; |
|
default: |
err = LOCALE->bad_register_module_other(); |
} |
if (err != "") |
{ |
#ifdef MODULE_DEBUG |
perror("FAILED\n"); |
#endif |
report_error(LOCALE->tried_loading_module(module_file, err)); |
if(obj) |
destruct( obj ); |
return 0; |
} |
|
if (sizeof(module_data) == 3) |
module_data += ({ 0 }); |
|
if(!foo) |
{ |
destruct(obj); |
obj=0; |
} else { |
otomod[obj] = module_file; |
} |
|
if(!modules[ module_file ]) |
modules[ module_file ] = ([]); |
mapping tmpp = modules[ module_file ]; |
|
tmpp->type=module_data[0]; |
if(mappingp(module_data[1])) |
{ |
tmpp->names=module_data[1]; |
tmpp->name=module_data[1]->standard; |
} |
else |
{ |
tmpp->name=module_data[1]; |
tmpp->names=([ "standard":module_data[1] ]); |
} |
|
if(mappingp(module_data[2])) |
{ |
tmpp->doc=module_data[2]->standard; |
tmpp->docs=module_data[2]; |
} else { |
tmpp->doc = module_data[2]; |
tmpp->docs = ([ "standard":module_data[2] ]); |
} |
tmpp->extra=module_data[3]; |
tmpp["program"]=prog; |
tmpp->master=obj; |
tmpp->copies=(foo ? 0 : (tmpp->copies||([]))); |
tmpp->sname=module_file; |
|
roxen->somemodules[module_file]= |
({ tmpp->name, tmpp->doc, module_data[0] }); |
#ifdef MODULE_DEBUG |
#if efun(gethrtime) |
perror(" Done (%3.3f seconds).\n", (gethrtime()-start_time)/1000000.0); |
#else |
perror(" Done.\n"); |
#endif |
#endif |
cache_set("modules", module_file, modules[module_file]["program"]); |
|
|
return 1; |
} |
|
int unload_module(string module_file) |
{ |
mapping module; |
int id; |
|
module = modules[ module_file ]; |
|
if(!module) |
return 0; |
|
if(objectp(module->master)) |
destruct(module->master); |
|
cache_remove("modules", module_file); |
|
m_delete(modules, module_file); |
|
return 1; |
} |
|
int port_open(array prt) |
{ |
return(server_ports[MKPORTKEY(prt)] != 0); |
} |
|
|
string desc() |
{ |
string res=""; |
array (string|int) port; |
|
if(!sizeof(QUERY(Ports))) |
{ |
|
|
|
|
|
|
|
|
array handlers = ({}); |
foreach(roxen->configurations, object c) |
if(c->modules["ip-less_hosts"]) |
handlers+=({({http_encode_string("/Configurations/"+c->name), |
strlen(c->query("name"))?c->query("name"):c->name})}); |
|
|
if(sizeof(handlers)==1) |
{ |
res = LOCALE->server_ports_handled_by_one(handlers[0][0], |
handlers[0][1]); |
} else if(sizeof(handlers)) { |
string serverlist = ""; |
|
foreach(handlers, array h) |
serverlist += "<a href=\""+h[0]+"\">"+h[1]+"</a><br>\n"; |
|
res = LOCALE->server_ports_handled_by_multiple(serverlist); |
} else |
res = LOCALE->server_ports_handled_by_none(); |
} |
|
foreach(QUERY(Ports), port) |
{ |
string prt; |
|
switch(port[1][0..2]) |
{ |
case "ssl": |
prt = "https://"; |
break; |
case "ftp": |
prt = "ftp://"; |
break; |
|
default: |
prt = port[1]+"://"; |
} |
if(port[2] && port[2]!="ANY") |
prt += port[2]; |
else |
#if efun(gethostname) |
prt += (gethostname()/".")[0] + "." + QUERY(Domain); |
#else |
; |
#endif |
prt += ":"+port[0]+"/"; |
if(port_open( port )) |
res += LOCALE->server_port_open(prt); |
else |
res += LOCALE->server_port_not_open(prt); |
} |
return (res + LOCALE->server_url(query("MyWorldLocation")) + "<p>"); |
} |
|
|
|
|
mapping(string:string) sql_urls = ([]); |
|
mapping sql_cache = ([]); |
|
object sql_cache_get(string what) |
{ |
#ifdef THREADS |
#if !constant(this_thread) |
return Sql.sql( what ); |
#else |
if(sql_cache[what] && sql_cache[what][this_thread()]) |
return sql_cache[what][this_thread()]; |
if(!sql_cache[what]) |
sql_cache[what] = ([ this_thread():Sql.sql( what ) ]); |
else |
sql_cache[what][ this_thread() ] = Sql.sql( what ); |
return sql_cache[what][ this_thread() ]; |
#endif /* !this_thread */ |
#else /* !THREADS */ |
if(!sql_cache[what]) |
sql_cache[what] = Sql.sql( what ); |
return sql_cache[what]; |
#endif |
} |
|
object sql_connect(string db) |
{ |
if (sql_urls[db]) { |
return(sql_cache_get(sql_urls[db])); |
} else { |
return(sql_cache_get(db)); |
} |
} |
|
|
|
|
|
private string get_my_url() |
{ |
string s; |
#if efun(gethostname) |
s = (gethostname()/".")[0] + "." + query("Domain"); |
s -= "\n"; |
#else |
s = "localhost"; |
#endif |
return "http://" + s + "/"; |
} |
|
void enable_all_modules() |
{ |
#if efun(gethrtime) |
int start_time = gethrtime(); |
#endif |
array modules_to_process=sort(indices(retrieve("EnabledModules",this))); |
string tmp_string; |
perror("\nEnabling all modules for "+query_name()+"... \n"); |
|
#if constant(_compiler_trace) |
|
#endif /* !constant(_compiler_trace) */ |
|
|
if(search(modules_to_process, "userdb#0")>-1) |
modules_to_process = (({"userdb#0"})+(modules_to_process-({"userdb#0"}))); |
|
|
array err; |
foreach( modules_to_process, tmp_string ) |
if(err = catch( enable_module( tmp_string ) )) |
report_error(LOCALE->enable_module_failed(tmp_string, |
describe_backtrace(err))); |
#if efun(gethrtime) |
perror("\nAll modules for %s enabled in %4.3f seconds\n\n", query_name(), |
(gethrtime()-start_time)/1000000.0); |
#endif |
} |
|
void create(string config) |
{ |
name=config; |
|
perror("Creating virtual server '"+config+"'\n"); |
|
|
|
defvar("ZNoSuchFile", "<title>Sorry. I cannot find this resource</title>\n" |
"<body bgcolor='#ffffff' text='#000000' alink='#ff0000' " |
"vlink='#00007f' link='#0000ff'>\n" |
"<h2 align=center><configimage src=roxen.gif alt=\"File not found\">\n" |
"<p><hr noshade>" |
"\n<i>Sorry</i></h2>\n" |
"<br clear>\n<font size=\"+2\">The resource requested " |
"<i>$File</i>\ncannot be found.<p>\n\nIf you feel that this is a " |
"configuration error, please contact " |
"the administrators or the author of the\n" |
"<if referrer>" |
"<a href=\"<referrer>\">referring</a>" |
"</if>\n" |
"<else>referring</else>\n" |
"page." |
"<p>\n</font>\n" |
"<hr noshade>" |
"<version>, at <a href=\"$Me\">$Me</a>.\n" |
"</body>\n", |
|
"Messages: No such file", TYPE_TEXT_FIELD, |
"What to return when there is no resource or file available " |
"at a certain location. $File will be replaced with the name " |
"of the resource requested, and $Me with the URL of this server "); |
deflocaledoc("svenska", "ZNoSuchFile", |
"Meddelanden: Filen finns inte", |
#"Det här meddelandet returneras om en användare frågar efter en |
resurs som inte finns. '$File' byts ut mot den efterfrågade |
resursen, och '$Me' med serverns URL"); |
|
defvar("comment", "", "Virtual server comment", |
TYPE_TEXT_FIELD|VAR_MORE, |
"This text will be visible in the configuration interface, it " |
" can be quite useful to use as a memory helper."); |
|
deflocaledoc("svenska", "comment", "Kommentar", |
"En kommentar som syns i konfigurationsinterfacet"); |
|
defvar("name", "", "Virtual server name", |
TYPE_STRING|VAR_MORE, |
"This is the name that will be used in the configuration " |
"interface. If this is left empty, the actual name of the " |
"virtual server will be used"); |
deflocaledoc("svenska", "name", "Serverns namn", |
#"Det här är namnet som kommer att synas i |
konfigurationsgränssnittet. Om du lämnar det här fältet tomt kommer |
serverns ursprungliga namn (det du skrev in när du skapade servern) |
att användas."); |
|
defvar("LogFormat", |
"404: $host $referer - [$cern_date] \"$method $resource $protocol\" 404 -\n" |
"500: $host $referer ERROR [$cern_date] \"$method $resource $protocol\" 500 -\n" |
"*: $host - - [$cern_date] \"$method $resource $protocol\" $response $length" |
, |
|
"Logging: Format", |
TYPE_TEXT_FIELD|VAR_MORE, |
|
"What format to use for logging. The syntax is:\n" |
"<pre>" |
"response-code or *: Log format for that response acode\n\n" |
"Log format is normal characters, or one or more of the " |
"variables below:\n" |
"\n" |
"\\n \\t \\r -- As in C, newline, tab and linefeed\n" |
"$char(int) -- Insert the (1 byte) character specified by the integer.\n" |
"$wchar(int) -- Insert the (2 byte) word specified by the integer.\n" |
"$int(int) -- Insert the (4 byte) word specified by the integer.\n" |
"$^ -- Supress newline at the end of the logentry\n" |
"$host -- The remote host name, or ip number.\n" |
"$ip_number -- The remote ip number.\n" |
"$bin-ip_number -- The remote host id as a binary integer number.\n" |
"\n" |
"$cern_date -- Cern Common Log file format date.\n" |
"$bin-date -- Time, but as an 32 bit iteger in network byteorder\n" |
"\n" |
"$method -- Request method\n" |
"$resource -- Resource identifier\n" |
"$protocol -- The protocol used (normally HTTP/1.0)\n" |
"$response -- The response code sent\n" |
"$bin-response -- The response code sent as a binary short number\n" |
"$length -- The length of the data section of the reply\n" |
"$bin-length -- Same, but as an 32 bit iteger in network byteorder\n" |
"$request-time -- The time the request took (seconds)\n" |
"$referer -- the header 'referer' from the request, or '-'.\n" |
"$user_agent -- the header 'User-Agent' from the request, or '-'.\n\n" |
"$user -- the name of the auth user used, if any\n" |
"$user_id -- A unique user ID, if cookies are supported,\n" |
" by the client, otherwise '0'\n" |
"</pre>", 0, log_is_not_enabled); |
deflocaledoc("svenska", "LogFormat", "Loggning: Loggningsformat", |
#"Vilket format som ska användas för att logga |
<pre> |
svarskod eller *: Loggformat för svarskoden (eller alla koder som inte |
har något annat format specifierat om du använder '*') |
|
loggformatet är normala tecken, och en eller flera av koderna nedan. |
|
\\n \\t \\r -- Precis som i C, ny rad, tab och carriage return |
$char(int) -- Stoppa in det tecken vars teckenkod är det angivna nummret. |
$wchar(int) -- Stoppa in det tvåocktetstecken vars teckenkod är det |
angivna nummret. |
$int(int) -- Stoppa in det fyraocktetstecken vars teckenkod är det |
angivna nummret. |
$^ -- Stoppa <b>inte</b> in en vagnretur på slutet av |
varje loggrad |
$host -- DNS namnet för datorn som gjorde förfrågan |
$ip_number -- IP-nummret för datorn som gjorde förfrågan |
$bin-ip_number -- IP-nummret för datorn som gjorde förfrågan som |
binärdata i nätverksoktettordning |
|
$cern_date -- Ett datum som det ska vara enligt Cern Common Log |
file specifikationen |
$bin-date -- Tiden för requesten som sekunder sedan 1970, binärt |
i nätverksoktettordning. |
|
$method -- Förfrågningsmetoden (GET, POST etc) |
$resource -- Resursidentifieraren (filnamnet) |
$protocol -- Protokollet som användes för att fråga efter filen |
$response -- Den skickade svarskoden |
$bin-response -- Den skickade svarskoden som ett binärt ord (2 |
oktetter) i nätverksoktettordning |
$length -- Längden av datan som skickades som svar till klienten |
$bin-length -- Samma sak, men som ett 4 oktetters ord i |
nätverksoktettordning. |
$request-time -- Tiden som requeten tog i sekunder |
$referer -- Headern 'referer' från förfrågan eller '-'. |
$user_agent -- Headern 'User-Agent' från förfrågan eller '-'. |
$user -- Den autentifierade användarens namn, eller '-' |
$user_id -- Ett unikt användarid. Tas från kakan RoxenUserID, du |
måste slå på kaksättningsfunktionaliteten i de |
globala inställningarna. '0' används för de |
förfrågningar som inte har kakan. |
</pre>"); |
|
|
defvar("Log", 1, "Logging: Enabled", TYPE_FLAG, "Log requests"); |
deflocaledoc("svenska", "Log", "Loggning: På", |
"Ska roxen logga alla förfrågningar till en logfil?"); |
|
defvar("LogFile", roxen->QUERY(logdirprefix)+ |
short_name(name)+"/Log", |
|
"Logging: Log file", TYPE_FILE, "The log file. " |
"" |
"A file name. May be relative to "+getcwd()+"." |
" Some substitutions will be done:" |
"<pre>" |
"%y Year (e.g. '1997')\n" |
"%m Month (e.g. '08')\n" |
"%d Date (e.g. '10' for the tenth)\n" |
"%h Hour (e.g. '00')\n</pre>" |
,0, log_is_not_enabled); |
deflocaledoc("svenska", "LogFile", |
"Loggning: Loggfil", |
"Filen som roxen loggar i. Filnamnet kan vara relativt " |
+getcwd()+ |
#". Du kan använda några kontrollkoder för att få flera loggfiler och |
automatisk loggrotation: |
<pre> |
%y År (t.ex. '1997') |
%m Månad (t.ex. '08') |
%d Datum (t.ex. '10') |
%h Timme (t.ex. '00') |
</pre>"); |
|
|
defvar("NoLog", ({ }), |
"Logging: No Logging for", TYPE_STRING_LIST|VAR_MORE, |
"Don't log requests from hosts with an IP number which matches any " |
"of the patterns in this list. This also affects the access counter " |
"log.\n",0, log_is_not_enabled); |
deflocaledoc("svenska", "NoLog", |
"Loggning: Logga inte för", |
#"Logga inte några förfrågningar vars IP-nummer matchar |
något av de mönster som står i den här listan. Den här variabeln |
påverkar även <accessed> RXML-styrkoden."); |
|
defvar("Domain", get_domain(), "Domain", TYPE_STRING, |
"The domainname of the server. The domainname is used " |
" to generate default URLs, and to gererate email addresses"); |
deflocaledoc( "svenska", "Domain", |
"DNS Domän", |
|
#"Serverns domännamn. Det av en del RXML styrkoder för att generara |
epostadresser, samt för att generera skönskvärdet för serverurl variablen."); |
|
|
defvar("Ports", ({ }), |
"Ports", TYPE_PORTS, |
"The ports this virtual instance of Roxen will bind to.\n"); |
deflocaledoc("svenska", "Ports", |
"Portar", |
#"Portarna som den här virtuella instansen av roxen |
kommer att öppna och lyssna på förfrågningar till"); |
|
|
defvar("MyWorldLocation", get_my_url(), |
"Server URL", TYPE_STRING, |
"This is where your start page is located."); |
deflocaledoc( "svenska", "MyWorldLocation", |
"Serverns URL", |
#"Det här är URLen till din startsida. Den används av rätt många |
moduler för att bygga upp absoluta URLer från en relativ URL."); |
|
|
defvar("FTPWelcome", |
" +-------------------------------------------------\n" |
" +-- Welcome to the Roxen Challenger FTP server ---\n" |
" +-------------------------------------------------\n", |
"FTP: FTP Welcome", |
TYPE_TEXT_FIELD|VAR_MORE, |
"FTP Welcome answer; transmitted to new FTP connections if the file " |
"<i>/welcome.msg</i> doesn't exist.\n"); |
deflocaledoc("svenska", "FTPWelcome", |
"FTP: Välkomstmeddelande", |
#"Det här meddelanden skickas till alla FTP klienter så |
fort de kopplar upp sig till servern"); |
|
defvar("named_ftp", 0, "FTP: Allow named FTP", TYPE_FLAG|VAR_MORE, |
"Allow ftp to normal user-accounts (requires auth-module).\n"); |
deflocaledoc("svenska", "named_ftp", "FTP: Tillåt icke-anonym FTP", |
"Tillåt FTP med loginnamn och lösenord. Du måste ha en " |
" authentifikationsmodul för att kunna " |
"använda icke-anonym FTP."); |
defvar("anonymous_ftp", 1, "FTP: Allow anonymous FTP", TYPE_FLAG|VAR_MORE, |
"Allows anonymous ftp.\n"); |
deflocaledoc("svenska", "anonymous_ftp", "FTP: Tillåt anonym FTP", |
"Tillåt anonym FTP"); |
|
defvar("guest_ftp", 0, "FTP: Allow FTP guest users", TYPE_FLAG|VAR_MORE, |
"Allows FTP guest users.\n"); |
deflocaledoc( "svenska", "guest_ftp", |
"FTP: Tillåt FTPgästanvändare", |
"Tillåt FTPgästanvändare"); |
|
defvar("ftp_user_session_limit", 0, |
"FTP: User session limit", TYPE_INT|VAR_MORE, |
"Limit of concurrent sessions a FTP user may have. 0 = unlimited.\n"); |
|
deflocaledoc( "svenska", "ftp_user_session_limit", |
"FTP: Maximalt antal samtidiga användarsessioner", |
"0=obegränsat antal"); |
|
defvar("shells", "/etc/shells", "FTP: Shell database", TYPE_FILE|VAR_MORE, |
"File which contains a list of all valid shells\n" |
"(usually /etc/shells). Used for named ftp.\n" |
"Specify the empty string to disable shell database lookup.\n"); |
deflocaledoc( "svenska", "shells", |
"FTP: Skaldatabas", |
#"En fil som innehåller en lista på alla tillåtna |
skal. (normalt sett /etc/shells). Används för icke-anonym ftp. Ange |
tomma strängen för att stänga av verifieringen av användarskal"); |
|
defvar("InternalLoc", "/_internal/", |
"Internal module resource mountpoint", TYPE_LOCATION|VAR_MORE, |
"Some modules may want to create links to internal resources. " |
"This setting configures an internally handled location that can " |
"be used for such purposes. Simply select a location that you are " |
"not likely to use for regular resources."); |
deflocaledoc("svenska", "InternalLoc", |
"Intern modulresursmountpoint", |
#"Somliga moduler kan vilja skapa länkar till interna resurser. |
Denna inställning konfigurerar en internt hanterad location som kan användas |
för sådana ändamål. Välj bara en location som du förmodligen inte kommer |
behöva för vanliga resurser."); |
|
setvars(retrieve("spider#0", this)); |
} |
|
|
|
|
|
|