inherit "config/builders"; |
inherit "roxenlib"; |
|
#include <confignode.h> |
#include <module.h> |
|
#define BODY (roxen->variables->BG[VAR_VALUE]?"<body background=/image/background.jpg bgcolor=#f0e0a0 text=#000000 link=#0000f0 vlink=#0000f0 alink=#00f000>":"<body>") |
|
|
#define TABLEP(x, y) (id->supports->tables ? x : y) |
|
int bar=time(1); |
|
program Node = class { |
inherit "struct/node"; |
|
mixed original; |
int changed; |
|
int bar=previous_object()->bar; |
function saver = lambda(object o) { if(o->changed) o->change(-o->changed); }; |
|
string|array error; |
|
void change(int i) |
{ |
changed += i; |
if(up) up->change(i); |
} |
|
private string show_me(string s) |
{ |
string name=path(1); |
if(folded) |
return ("<a name=\""+name+"\">" |
"<a href=\"/(unfold)/" + name + "?"+(bar++)+ |
"\"><img border=0 src=/image/unfold" |
+(changed?"2":"")+".gif alt="+(changed?"*-":"--")+">" |
"</a> "+s); |
else |
return ("<a name=\""+name+"\">" |
"<a href=\"/(fold)/" + name + "?"+(bar++)+ |
"\"><img border=0 src=/image/fold"+(changed?"2":"") |
+".gif align=top alt="+(changed?"**":"\"\\/\"")+">" |
"</a> "+s); |
} |
|
string describe(int i) |
{ |
string res=""; |
object node,prevnode; |
mixed tmp; |
|
if(describer) |
tmp = describer(this_object()); |
#ifdef NODE_DEBUG |
else |
perror("No describer in node "+path(1)+"\n"); |
#endif |
if(arrayp(tmp) && sizeof(tmp)) |
res += tmp[0] + "<dt>" + (!i?show_me(tmp[1]):tmp[1]) + "\n\n"; |
else if(stringp(tmp) && strlen(tmp)) |
res += "<dt>" + (i?tmp:show_me(tmp)) + "\n\n"; |
else if(!tmp) |
return ""; |
|
if(!i && strlen(res)) |
res += "<dd>"; |
else if(strlen(res)) |
res += "<p>"; |
|
if(!folded) |
{ |
int sdl = 0; |
|
if(!i && strlen(res)) |
{ |
sdl = 1; |
res += "<dl>\n\n"; |
} |
node = down; |
while(node) |
{ |
if(!objectp(node)) |
{ |
if(objectp(prevnode)) |
prevnode->next=0; |
node=0; |
break; |
} |
prevnode = node; |
node = node->next; |
res += prevnode->describe(); |
} |
if(sdl) |
res += "</dl>\n\n"; |
} |
return res; |
} |
|
|
object config() |
{ |
object node; |
node=this_object(); |
while(node) |
if(node->type == NODE_CONFIGURATION) |
return node->data; |
else |
node=node->up; |
} |
|
void save() |
{ |
object node; |
node=down; |
|
|
while(node) |
{ |
if(node->changed) node->save(); |
node=node->next; |
} |
if(saver) saver(this_object()); |
} |
}; |
|
object root=Node(); |
int expert_mode; |
|
|
void create() |
{ |
build_root(root); |
init_ip_list(); |
call_out(init_ip_list, 0); |
} |
|
inline string shutdown_restart(string save, int compact) |
{ |
#define CBR (compact?"":"<br clear=right>\n") |
|
return |
("<a href=/(shutdown)/Configurations/?"+(bar++)+">" |
"<img src=/image/shutdown.gif alt=Kill hspace=0 border=0 align=right>" |
"</a>") |
+ CBR |
+ ("<a href=/(restart)/Configurations/?"+(bar++)+">" |
"<img src=/image/restart.gif alt=Restart hspace=0 border=0 align=right>" |
"</a>") |
+ CBR |
+ (save? |
("<a href=/(save)"+ save +"?"+(bar++)+ ">" |
"<img src=/image/save.gif alt=Save hspace=0 border=0 align=right>" |
"</a>"):""); |
} |
|
string default_head(string h, string|void save) |
{ |
return ("<title>"+h+"</title>" |
+ BODY |
+ (roxen->variables->BS[VAR_VALUE]? |
("<h2 align=center>"+shutdown_restart(save, 1)+h+"</h2>"): |
("<h1 align=center><img align=left alt=\"" |
+h+"\" src=/image/roxen.gif></h1>" |
+shutdown_restart(save, 0))) |
+ "<br clear=all>"); |
} |
|
object find_node(string l) |
{ |
array tmp = l/"/"-({""}); |
object o; |
if(!sizeof(tmp)) return root; |
for(o=root; sizeof(tmp) && (o=o->descend(tmp[0],1)); tmp=tmp[1..1000]); |
if(!o) return 0; |
roxen->current_configuration = o->config(); |
return o; |
} |
|
mapping file_image(string img) |
{ |
object o; |
o=open("roxen-images/"+img, "r"); |
if (!o) return 0; |
return ([ "file":o, "type":"image/" + ((img[-1]=='f')?"gif":"jpeg"), ]); |
} |
|
#define CONFIG_URL roxen->config_url() |
|
mapping save_it(object id, object o) |
{ |
id->referer = ({ CONFIG_URL + o->path(1) }); |
root->save(); |
if(roxen->do_fork_it()) |
{ |
roxen->update_supports_from_roxen_com(); |
roxen->initiate_configuration_port( 0 ); |
} |
else |
throw(-1); |
} |
|
mapping stores( string s ) |
{ |
return |
([ |
"data":replace(s, "$docurl", roxen->docurl), |
"type":"text/html", |
"extra_heads": |
([ |
"Title":"Roxen Challenger maintenance", |
"Expires":http_date(time(1)+2), |
"Pragma":"no-cache", |
"Last-Modified":http_date(time(1)), |
]) |
]); |
} |
|
object find_module(string name) |
{ |
mapping mod; |
object o; |
string s; |
int i; |
name = lower_case(name); |
if(!sscanf(name, "%s#%d", name, i)) |
{ |
#ifdef MODULE_DEBUG |
#if defined(DEBUG) && (DEBUG > 1000) |
perror("Modulename not in short form: "+name+"\n"); |
#endif |
#endif |
foreach(values(roxen->current_configuration->modules), mod) |
{ |
if(mod->copies) |
{ |
foreach(values(mod->copies), o) |
if(lower_case(s=name_of_module(o)) == name) |
return o; |
} else |
if(mod->enabled && (lower_case(s=name_of_module(mod->enabled))==name)) |
return mod->enabled; |
} |
} else { |
mapping modules; |
#ifdef MODULE_DEBUG |
#if defined(DEBUG) && (DEBUG > 1000) |
perror("Modulename in short form: "+name+"#"+i+"\n"); |
#endif |
#endif |
modules = roxen->current_configuration->modules; |
if(modules[name]) |
{ |
if(modules[name]->copies) |
return modules[name]->copies[i]; |
else |
if(modules[name]->enabled) |
return modules[name]->enabled; |
} |
} |
return 0; |
} |
|
mixed decode_form_result(string var, int type, object node, mapping allvars) |
{ |
switch(type) |
{ |
case TYPE_MODULE_LIST: |
return map_array(var/"\000", find_module); |
|
case TYPE_MODULE: |
return find_module(var); |
|
case TYPE_PORTS: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(allvars->new_port) |
return node->data[VAR_VALUE] + ({ ({ 80, "http", "ANY", "" }) }); |
|
array op = copy_value(node->data[VAR_VALUE]); |
int i; |
for(i = 0; i<sizeof(op); i++) |
{ |
if(!allvars["delete_"+i]) |
{ |
if(allvars["other_"+i] && (allvars["other_"+i] != op[i][2])) |
{ |
allvars["ip_number_"+i] = allvars["other_"+i]; |
ip_number_list += ({ allvars["other_"+i] }); |
} |
op[i][0] = (int)allvars["port_"+i]||op[i][0]; |
op[i][1] = allvars["protocol_"+i]||op[i][1]; |
op[i][2] = allvars["ip_number_"+i]||op[i][2]; |
op[i][3] = allvars["arguments_"+i]||op[i][3]; |
} else |
op[i]=0; |
} |
return op - ({ 0 }); |
|
case TYPE_DIR_LIST: |
array foo; |
foo=map_array((var-" ")/",", lambda(string var, object node) { |
if (!strlen( var ) || file_size( var ) != -2) |
{ |
if(node->error) |
node->error += ", " +var + " is not a directory"; |
else |
node->error = var + " is not a directory"; |
return 0; |
} |
if(var[-1] != '/') |
return var + "/"; |
return var; |
}, node); |
|
if(sizeof(foo-({0})) != sizeof(foo)) |
return 0; |
return foo; |
|
case TYPE_DIR: |
if (!strlen( var ) || file_size( var ) != -2) |
{ |
node->error = var + " is not a directory"; |
return 0; |
} |
if(var[-1] != '/') |
return var + "/"; |
return var; |
|
case TYPE_TEXT_FIELD: |
var -= "\r"; |
case TYPE_STRING: |
case TYPE_FILE: |
case TYPE_LOCATION: |
return var; |
|
case TYPE_PASSWORD: |
return crypt(var); |
|
case TYPE_FLAG: |
return lower_case(var) == "yes"; |
|
case TYPE_INT: |
int tmp; |
|
if (!sscanf( var, "%d", tmp )) |
{ |
node->error= var + " is not an integer"; |
return 0; |
} |
return tmp; |
|
case TYPE_FLOAT: |
float tmp; |
|
if (!sscanf( var, "%f", tmp )) |
{ |
node->error= var + " is not a arbitary precision floating point number"; |
return 0; |
} |
return tmp; |
|
case TYPE_INT_LIST: |
if(node->data[VAR_MISC]) |
return (int)var; |
else |
return map_array((var-" ")/",", lambda(string s){ |
return (int)s; |
}); |
|
|
case TYPE_STRING_LIST: |
if(node->data[VAR_MISC]) |
return var; |
else |
return (var-" ")/","; |
|
case TYPE_COLOR: |
int red, green, blue; |
|
if (sscanf( var, "%d:%d:%d", red, green, blue ) != 3 |
|| red < 0 || red > 255 || green < 0 || green > 255 |
|| blue < 0 || blue > 255) |
{ |
node->error = var + " is not a valid color specification"; |
return 0; |
} |
return (red << 16) + (green << 8) + blue; |
} |
error("Unknown type.\n"); |
} |
|
mapping std_redirect(object o, object id) |
{ |
string loc, l2; |
|
if(!o) o=root; |
|
if(id && sizeof(id->referer)) |
loc=((((((id->referer*" ")/"#")[0])/"?")[0])+"?"+(bar++) |
+"#"+o->path(1)); |
else |
loc = CONFIG_URL+o->path(1)[1..10000]+"?"+bar++; |
|
if(sscanf(loc, "%s/(%*s)%s",l2, loc) == 3) |
loc = l2 + loc; |
|
|
|
loc = replace(replace(replace(loc, "://", ""), "//", "/"), "", "://"); |
|
return http_redirect(http_decode_string(loc)); |
} |
|
string configuration_list() |
{ |
string res=""; |
object o; |
foreach(roxen->configurations, o) |
res += "<option>Copy of '"+o->name+"'"; |
return res; |
} |
|
string new_configuration_form() |
{ |
return replace(read_bytes("etc/newconfig.html"), ({"$COPIES","$configurl"}), |
({configuration_list(),CONFIG_URL})) + |
"\n\n<hr noshade><p align=right><a href=http://www.roxen.com/>"+ |
roxen->real_version +"</a></body>"; |
} |
|
mapping module_nomore(string name, int type, object conf) |
{ |
mapping module; |
object o; |
|
if((module = conf->modules[name]) |
&& (!module->copies && module->enabled)) |
return module; |
if(((type & MODULE_DIRECTORIES) && (o=conf->dir_module)) |
|
|
|| ((type & MODULE_MAIN_PARSER) && (o=conf->parse_module))) |
return conf->modules[conf->otomod[o]]; |
} |
|
mixed new_module_copy(object node, string name, object id) |
{ |
object orig; |
int i; |
mapping module; |
module = node->config()->modules[name]; |
switch(node->type) |
{ |
default: |
error("Foo? Illegal node in new_module_copy\n"); |
|
case NODE_MODULE_COPY: |
node=node->up; |
|
case NODE_MODULE_MASTER_COPY: |
case NODE_MODULE: |
node=node->up; |
|
case NODE_CONFIGURATION: |
} |
|
if(module) if(module->copies) while(module->copies[i]) i++; |
roxen->enable_module(name+"#"+i); |
module = node->config()->modules[name]; |
|
if(!module) return http_string_answer("This module could not be enabled.\n"); |
|
node = node->descend(module->name); |
|
|
node->data = module; |
node->describer = describe_module; |
node->type = NODE_MODULE; |
build_module(node); |
|
|
node->folded=0; |
|
|
if(module->copies) node = node->descend((string)i, 1); |
|
|
|
node->folded = 0; |
|
|
node->change(1); |
|
return std_redirect(root, id); |
} |
|
mixed new_module_copy_copy(object node, object id) |
{ |
roxen->current_configuration = node->config(); |
return new_module_copy(node, node->data->sname, id); |
} |
|
string new_module_form(object id, object node) |
{ |
int i; |
mixed a,b; |
array mods; |
string res; |
|
if(!roxen->allmodules || sizeof(id->pragma)) |
{ |
perror("CONFIG: Rescanning modules.\n"); |
roxen->rescan_modules(); |
perror("CONFIG: Done.\n"); |
} |
|
a=roxen->allmodules; |
mods=sort_array(indices(a), lambda(string a, string b, mapping m) { |
return m[a][0] > m[b][0]; |
}, a); |
|
res = default_head("Add a module")+ |
"<hr noshade><form>"+ TABLEP("<table>","<dl>")+"\n\n"; |
|
for(i=0; i<sizeof(mods); i++) |
if(!(b = module_nomore(mods[i], a[mods[i]][2], node->config()))) |
{ |
if(id->supports->tables) |
res += ("<tr><td><table><tr valign=top><td valign=top><input type=submit value=\"" + |
a[mods[i]][0] + "\" name=\"" + mods[i] + "\"><br></td><td>" + |
a[mods[i]][1]+"<p></td></tr>\n</table>" |
"<hr noshade size=1></td></tr>\n\n"); |
else |
res += ("<dt><input type=submit value=\"" + |
a[mods[i]][0] + "\" name=\"" + mods[i] + "\"><dd>" + |
a[mods[i]][1]+"<p><hr noshade size=1>\n\n"); |
} |
else |
{ |
if(b->sname != mods[i]) |
if(id->supports->tables) |
{ |
res += ("<tr><td><table><tr valign=top><td>"+a[mods[i]][0]+"<br></td><td>" + |
a[mods[i]][1] + "<p>" |
"<i>A module of the same type is already enabled (" |
+ b->name |
+ "). <a href=\"/(delete)" |
+ node->descend(b->name, 1)->path(1) + "?"+(bar++)+ |
"\">Disable that module</a> if you want this one insted</i>" |
"</td></tr></table><hr noshade size=1></td></tr>\n\n"); |
} |
else |
res += ("<dt>" + a[mods[i]][0] + mods[i] + "<dd>" + |
a[mods[i]][1] + "<p>" |
"<i>A module of the same type is already enabled (" |
+ b->name |
+ "). <a href=\"/(delete)" |
+ node->descend(b->name, 1)->path(1) + "?"+(bar++)+ |
"\">Disable that module</a> if you want this one insted</i>" |
"<hr noshade size=1>\n\n"); |
} |
return res + TABLEP("</table>", "</dl>") +"</form> "; |
} |
|
mapping new_module(object id, object node) |
{ |
string varname; |
|
if(!sizeof(id->variables)) |
return stores(new_module_form(id, node)); |
|
varname=indices(id->variables)[0]; |
|
return new_module_copy(node, varname, id); |
} |
|
int low_enable_configuration(string name, string type) |
{ |
object node; |
|
if(strlen(name) && name[-1] == '~') |
name = ""; |
|
if(search(name, "/")!= -1) |
return 0; |
|
foreach(roxen->configurations, node) |
if(node->name == name) |
return 0; |
|
switch(name) |
{ |
case "": |
case " ": |
case "\t": |
case "CVS": |
case "Global Variables": |
case "global variables": |
case "Global variables": |
return 0; |
break; |
|
default: |
object o, confnode; |
|
switch(lower_case((type/" ")[0])) |
{ |
default: |
roxen->enable_configuration(name); |
break; |
|
case "standard": |
roxen->enable_configuration(name); |
roxen->enable_module("cgi#0"); |
roxen->enable_module("contenttypes#0"); |
roxen->enable_module("ismap#0"); |
roxen->enable_module("lpcscript#0"); |
roxen->enable_module("htmlparse#0"); |
roxen->enable_module("directories#0"); |
roxen->enable_module("userdb#0"); |
roxen->enable_module("userfs#0"); |
roxen->enable_module("filesystem#0"); |
break; |
|
case "ipp": |
roxen->enable_configuration(name); |
roxen->enable_module("contenttypes#0"); |
roxen->enable_module("ismap#0"); |
roxen->enable_module("htmlparse#0"); |
roxen->enable_module("directories#0"); |
roxen->enable_module("filesystem#0"); |
break; |
|
case "proxy": |
roxen->enable_configuration(name); |
roxen->enable_module("proxy#0"); |
roxen->enable_module("gopher#0"); |
roxen->enable_module("ftpgateway#0"); |
roxen->enable_module("contenttypes#0"); |
roxen->enable_module("wais#0"); |
break; |
|
case "copy": |
string from; |
mapping tmp; |
sscanf(type, "%*s'%s'", from); |
tmp = roxen->copy_configuration(from, name); |
if(!tmp) error("No configuration to copy from!\n"); |
tmp["spider#0"]->LogFile = "../logs/" |
+roxen->short_name(name)+"/Log"; |
roxen->save_it(name); |
roxen->enable_configuration(name); |
} |
confnode = root->descend("Configurations"); |
node=confnode->descend(name); |
|
node->describer = describe_configuration; |
node->saver = save_configuration; |
node->data = roxen->configurations[-1]; |
node->type = NODE_CONFIGURATION; |
build_configuration(node); |
node->folded=0; |
node->change(1); |
|
if(o = node) |
{ |
if(o=o->descend( "Global", 1 )) |
{ |
o->folded = 0; |
if(o->descend( "Server URL", 1 )) |
{ |
o->descend( "Server URL" )->folded = 0; |
o->descend( "Server URL" )->change(1); |
} |
if(o->descend( "Listen ports", 1 )) |
{ |
o->descend( "Listen ports" )->folded = 0; |
o->descend( "Listen ports" )->change(1); |
} |
} |
} |
if(lower_case((type/" ")[0])=="standard" && (o=node)) |
{ |
if(o=o->descend( "Filesystem", 1 )) |
{ |
o->folded=0; |
if(o=o->descend( "0", 1)) |
{ |
o->folded=0; |
if(o=o->descend( "Search path", 1)) |
{ |
o->folded=0; |
o->change(1); |
} |
} |
} |
} |
} |
return 1; |
} |
|
mapping new_configuration(object id) |
{ |
if(!sizeof(id->variables)) |
return stores(new_configuration_form()); |
|
if(!id->variables->name) |
return stores(default_head("Bad luck")+ |
"<h1>No configuration name?</h1>" |
"Either you entered no name, or your WWW-browser " |
"failed to include it in the request"); |
|
id->variables->name=(replace(id->variables->name,"\000"," ")/" "-({""}))*" "; |
if(!low_enable_configuration(id->variables->name, id->variables->type)) |
return stores(default_head("Bad luck") + |
"<h1>Illegal configuration name</h1>" |
"The name of the configuration must contain characters" |
" other than space and tab, it should not end with " |
"~, and it must not be 'CVS', 'Global Variables' or " |
"'global variables', nor the name of an existing " |
"configuration, and the character '/' cannot be included"); |
return std_redirect(root->descend("Configurations"), id); |
} |
|
int conf_auth_ok(mixed auth) |
{ |
if(!(auth && sizeof(auth)>1)) |
return 0; |
|
if(sscanf(auth[1], "%s:%s", auth[0], auth[1]) < 2) |
return 0; |
|
if((auth[0] == roxen->QUERY(ConfigurationUser)) |
&& crypt(auth[1], roxen->QUERY(ConfigurationPassword))) |
return 1; |
} |
|
mapping initial_configuration(object id) |
{ |
object n2; |
string res, error; |
|
if(id->prestate->initial && id->variables->pass) |
{ |
error=""; |
if(id->variables->pass != id->variables->pass2) |
error = "You did not type the same password twice.\n"; |
if(!strlen(id->variables->pass)) |
error += "You must specify a password.\n"; |
if(!strlen(id->variables->user)) |
error += "You must specify a username.\n"; |
if(!strlen(error)) |
{ |
object node; |
|
|
|
node = find_node("/Globals"); |
node->folded=0; |
node->change(1); |
|
if(!node) |
return stores("Fatal configuration error, no 'Globals' node found.\n"); |
|
roxen->QUERY(ConfigurationPassword) = crypt(id->variables->pass); |
roxen->QUERY(ConfigurationUser) = id->variables->user; |
|
n2 = node->descend("Configuration interface", 1)->descend("Password", 1); |
n2->data[VAR_VALUE]=roxen->QUERY(ConfigurationPassword); |
n2->change(1); |
|
n2 = node->descend("Configuration interface", 1)->descend("User", 1); |
n2->data[VAR_VALUE] = roxen->QUERY(ConfigurationUser); |
n2->change(1); |
|
|
if(strlen(id->variables->pattern)) |
{ |
node = node->descend("Configuration interface", 1)->descend("IP-Pattern", 1); |
node->folded=0; |
node->data[VAR_VALUE] = id->variables->pattern; |
node->change(1); |
} |
root->save(); |
return std_redirect(root, id); |
} |
} |
|
res = default_head("Welcome to Roxen Challenger") + "<hr noshade>"; |
|
res += read_bytes("etc/welcome.html"); |
if(error && strlen(error)) |
res += "\n<p><b>"+error+"</b>"; |
|
res += ("<pre>" |
"<font size=+1>" |
"<form action=/(initial)/Globals/>" |
" User name <input name=user type=string>\n" |
" Password <input name=pass type=password>\n" |
" Again <input name=pass2 type=password>\n" |
"IP-pattern <input name=pattern type=string>\n" |
" <input type=submit value=\"Use these values\">\n" |
"</form></font></pre>"); |
|
return stores(res); |
} |
|
object module_of(object node) |
{ |
while(node) |
{ |
if(node->type == NODE_MODULE_COPY) |
return node->data; |
if(node->type == NODE_MODULE_MASTER_COPY) |
return node->data->master; |
node = node->up; |
} |
return roxen; |
} |
|
string extract_almost_top(object node) |
{ |
for(;node->up!=root;node=node->up); |
return node->path(1); |
} |
|
mapping (string:string) selected_nodes = |
([ |
"Configurations":"/Configurations", |
"Globals":"/Globals", |
"Status":"/Status", |
"Errors":"/Errors", |
]); |
|
array tabs = ({ |
({ "Configurations", read_bytes("etc/tablists/1.html") }), |
({ "Globals", read_bytes("etc/tablists/2.html") }), |
({ "Status", read_bytes("etc/tablists/3.html") }), |
({ "Errors", read_bytes("etc/tablists/4.html") }), |
}); |
|
|
|
string display_tabular_header(object node) |
{ |
string p, s; |
int i; |
|
s = extract_almost_top(node); |
s-="/"; |
string sel = root->descend(s, 1)->path(1)+"?"+(bar++); |
selected_nodes[s] = node->path(1); |
|
for(i=0;i<sizeof(tabs);i++) |
if(s==tabs[i][0]) |
return replace(tabs[i][1], |
({"@servers", "@globals", "@status", "@debug" }), |
({ |
(i==0?sel:selected_nodes["Configurations"]+"?"+bar++), |
(i==1?sel:selected_nodes["Globals"]+"?"+bar++), |
(i==2?sel:selected_nodes["Status"]+"?"+bar++), |
(i==3?sel:selected_nodes["Errors"]+"?"+bar++), |
})); |
return (""); |
} |
|
|
|
|
int nunfolded(object o) |
{ |
int i; |
if(o = o->down) |
do { i+=!o->folded; } while(o=o->next); |
return i; |
} |
|
mapping configuration_parse(object id) |
{ |
string res; |
|
if(sscanf(id->not_query, "/image/%s", res)) |
return file_image(res) || (["data":"No such image"]); |
|
object o; |
int i; |
|
id->since = 0; |
|
|
|
if(id->remoteaddr) |
if(strlen(roxen->QUERY(ConfigurationIPpattern)) && |
!glob(roxen->QUERY(ConfigurationIPpattern),id->remoteaddr)) |
return stores("Permission denied.\n"); |
|
|
if(!id->misc->read_allow) |
{ |
if(!(strlen(roxen->QUERY(ConfigurationPassword)) |
&& strlen(roxen->QUERY(ConfigurationUser)))) |
return initial_configuration(id); |
else if(!conf_auth_ok(id->auth)) |
return http_auth_failed("Roxen server maintenance"); |
} else { |
id->prestate = aggregate_multiset(@indices(id->prestate) |
&({"fold","unfold"})); |
|
if(sizeof(id->variables)) |
id->variables = ([ ]); |
} |
|
o = find_node(id->not_query); |
|
if(!o) |
{ |
id->referer = ({ }); |
return std_redirect(0, id); |
} else if(o == root) { |
|
|
|
return stores(replace(read_bytes("etc/config.html"),"rand()", |
(string)time())); |
} |
|
if(sizeof(id->prestate)) |
{ |
switch(indices(id->prestate)[0]) |
{ |
|
|
|
case "expert": expert_mode = 1; break; |
case "noexpert": expert_mode = 0; break; |
|
|
|
case "fold": o->folded=1; break; |
case "unfold": o->folded=0; break; |
|
case "foldall": |
o->map(lambda(object o) { o->folded=1; }); |
break; |
|
|
case "unfoldmodified": |
o->map(lambda(object o) { if(o->changed) o->folded=0; }); |
break; |
|
|
|
|
|
case "unfoldall": |
o->map(lambda(object o) { o->folded=0; }); |
break; |
|
|
|
|
|
|
|
case "refresh": |
case "reload": |
object mod; |
string name, modname; |
mapping cmod; |
|
mod = module_of(o); |
if(!mod || mod==roxen) |
error("This module cannot be updated.\n"); |
name = module_short_name(mod); |
if(!name) |
error("This module cannot be updated"); |
sscanf(name, "%s#%*s", modname); |
roxen->current_configuration = o->config(); |
if(!(cmod = o->config()->modules[ modname ])) |
error("This module cannot be updated"); |
|
o->save(); |
cache_remove("modules", modname); |
_master->set_inhibit_compile_errors(1); |
|
if(!roxen->load_module(modname)) |
{ |
mapping rep; |
rep = http_string_answer("The reload of this module failed.\n" |
"This is (probably) the reason:\n<pre>" |
+ _master->errors + "</pre>" ); |
_master->set_inhibit_compile_errors(0); |
return rep; |
} |
object mod; |
if(!roxen->disable_module(name)) error("Failed to disable module.\n"); |
if(!(mod=roxen->enable_module(name)))error("Failed to enable module.\n"); |
|
o->clear(); |
roxen->fork_it(); |
|
if(mappingp(o->data)) |
{ |
o->data = o->config()->modules[modname]; |
build_module(o); |
} else { |
object n = o->up; |
n->clear(); |
n->data = n->config()->modules[modname]; |
build_module(n); |
} |
break; |
|
|
case "shutdown": |
return roxen->shutdown(); |
|
|
case "restart": |
return roxen->restart(); |
|
|
case "rename": |
if(o->type == NODE_CONFIGURATION) |
{ |
mv("configurations/"+o->data->name, |
"configurations/"+id->variables->name); |
o->data->name=id->variables->name; |
} |
break; |
|
|
|
|
case "delete": |
res = default_head("Roxen Configuration")+ "<hr noshade>"; |
|
switch(o->type) |
{ |
case NODE_CONFIGURATION: |
res += ("<font size=+2>Do you really want to delete the configuration " |
+ o->data->name + ", all its modules and their copies?" |
"\n\n<p></font>"); |
break; |
|
case NODE_MODULE_MASTER_COPY: |
case NODE_MODULE: |
res += ("<font size=+2>Do you really want to delete the module " |
+ o->data->name + ", and its copies?" |
"\n\n<p></font>"); |
break; |
|
case NODE_MODULE_COPY_VARIABLES: |
|
case NODE_MODULE_COPY: |
res += ("<font size=+2>Do you really want to delete this copy " |
" of the module "+ o->up->data->name + "?\n\n<p></font>"); |
|
break; |
|
case NODE_CONFIGURATIONS: |
return stores("You don't want to do that...\n"); |
} |
res += ("<font size=+2><i>This action cannot be undone.\n\n<p></font>" |
+ TABLEP("<table>", "") +"<tr><td><form action="+ |
o->path(1)+">" |
"<input type=submit value=\"No, I do not want to delete it\"> " |
"</form></td><td><form action=/(really_delete)"+o->path(1) |
+ "><input type=submit value=\"Go ahead\"></form></td></tr> " |
"</table>"); |
|
return stores(res); |
break; |
|
|
|
|
|
|
|
|
case "really_delete": |
id->referer = ({ CONFIG_URL + o->up->path(1) }); |
|
switch(o->type) |
{ |
case NODE_CONFIGURATION: |
object oroot; |
|
for(i=0; i<sizeof(roxen->configurations); i++) |
if(roxen->configurations[i] == o->data) |
break; |
|
if(i==sizeof(roxen->configurations)) |
error("Configuration not found.\n"); |
|
roxen->remove_configuration(o->data->name); |
|
if(roxen->configurations[i]->ports_open) |
map_array(values(roxen->configurations[i]->ports_open), destruct); |
destruct(roxen->configurations[i]); |
|
roxen->configurations = |
roxen->configurations[..i-1] + roxen->configurations[i+1..]; |
|
o->change(-o->changed); |
o->dest(); |
break; |
|
case NODE_MODULE_COPY_VARIABLE: |
case NODE_MODULE_COPY_VARIABLES: |
|
o=o->up; |
|
case NODE_MODULE_COPY: |
string name; |
object n; |
|
name = module_short_name(o->data); |
roxen->disable_module(name); |
|
roxen->remove(name); |
o->change(-o->changed); |
n=o->up; |
o->dest(); |
|
if(!objectp(n)) |
{ |
o=root; |
|
} else { |
if(!sizeof(n->data->copies)) |
{ |
|
|
|
|
|
|
|
|
o=n->up; |
|
n->change(-n->changed); |
n->dest(); |
build_configuration(o); |
return std_redirect(o, 0); |
|
} else |
o = n; |
} |
break; |
|
case NODE_MODULE_MASTER_COPY: |
case NODE_MODULE: |
|
if(o->data->copies) |
{ |
if(sizeof(o->data->copies)) |
{ |
int i; |
array a,b; |
a=indices(o->data->copies); |
b=values(o->data->copies); |
name=o->config()->otomod[b[0]]; |
i=sizeof(a); |
while(i--) |
{ |
roxen->disable_module(name+"#"+a[i]); |
roxen->remove(name+"#"+a[i]); |
} |
} else if(o->data->master) { |
name=o->config()->otomod[o->data->enabled]; |
} |
} else if(o->data->enabled) { |
name=o->config()->otomod[o->data->enabled]; |
roxen->disable_module(name+"#0"); |
roxen->remove(name+"#0"); |
} |
o->change(-o->changed); |
o->dest(); |
break; |
} |
break; |
|
|
|
|
|
case "newconfig": |
id->referer = ({ CONFIG_URL + o->path(1) }); |
return new_configuration(id); |
|
|
|
|
case "save": |
if(save_it(id, o)) |
return 0; |
break; |
|
|
|
|
case "initial": |
case "changepass": |
return initial_configuration(id); |
|
|
|
case "new": |
o->new(); |
break; |
|
|
case "newmodule": |
id->referer = ({ CONFIG_URL + o->path(1) }); |
return new_module(id,o); |
|
|
|
case "newmodulecopy": |
id->referer = ({ CONFIG_URL + o->path(1) }); |
new_module_copy_copy(o, id); |
break; |
|
|
|
case "set": |
mixed tmp; |
o->error = 0; |
if(sizeof(id->variables)) |
tmp=decode_form_result(values(id->variables)[0], |
o->data[VAR_TYPE], o, id->variables); |
else |
tmp=0; |
if(!module_of(o)) perror("No module for this node.\n"); |
if(!o->error && module_of(o) |
&& module_of(o)->check_variable) |
o->error = module_of(o)->check_variable(o->data[VAR_SHORTNAME], tmp); |
|
if(!o->error) |
if(!equal(tmp, o->data[VAR_VALUE])) |
{ |
if(!o->original) |
o->original = o->data[VAR_VALUE]; |
o->data[VAR_VALUE]=tmp; |
if(equal(o->original, tmp)) |
o->change(-1); |
else if(!o->changed) |
o->change(1); |
} |
break; |
} |
return std_redirect(o, id); |
} |
|
res = (default_head("Roxen server configuration", |
root->changed?o->path(1):0) |
+ "\n" + display_tabular_header( o ) + "\n<br>\n" |
+ "<dl>\n"); |
|
if(o->up != root && o->up) |
res += ("<a href=\""+ o->up->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/up.gif alt='[Up]' align=left hspace=0 border=0></a> "); |
|
if(i=o->folded) o->folded=0; |
res += o->describe(1) ; |
o->folded=i; |
|
res += "</dl>\n\n<p>"; |
|
if(nunfolded(o)) |
res += ("<a href=\"/(foldall)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/foldall.gif align=left hspace=0 border=0" |
" height=19 alt=\"Close all\">" |
"</a>"); |
|
if(o->type == NODE_CONFIGURATIONS) |
res += ("<a href=/(newconfig)/Configurations?"+(bar++)+">" |
"<img src=/image/newconf.gif align=left hspace=0 border=0" |
" height=19 alt=\"Add virtual server\">" |
"</a>"); |
|
if(o->type == NODE_CONFIGURATION) |
res += ("<a href=\"/(newmodule)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/newmod.gif align=left hspace=0 border=0" |
" height=19 alt=\"Add a module\">" |
"</a>"); |
|
if(o->type == NODE_MODULE) |
{ |
res += ("<a href=\"/(delete)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/delmodcop.gif align=left hspace=0 border=0" |
" height=19 alt=\"Remove this module and it's copies\">" |
"</a>"); |
if(o->data->copies) |
{ |
res += ("<a href=\"/(newmodulecopy)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/newmod.gif align=left hspace=0 border=0" |
" height=19 alt=\"Add a new copy\">" |
"</a>"); |
} |
} |
|
i=0; |
if(o->type == NODE_MODULE_MASTER_COPY || o->type == NODE_MODULE_COPY |
|| o->type == NODE_MODULE_COPY_VARIABLES) |
{ |
res += ("<a href=\"/(delete)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/delmod.gif align=left hspace=0 border=0" |
" height=19 alt=\"Remove this module\">" |
"</a>") |
+ ("<a href=\"/(refresh)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/refresh.gif align=left hspace=0 border=0" |
" height=19 alt=\"Refresh\">" |
"</a>"); |
i++; |
} |
|
if(o->type == NODE_CONFIGURATION) |
{ |
res += ("<a href=\"/(delete)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/delconf.gif align=left hspace=0 border=0" |
" height=19 alt=\"Remove this configuration\">" |
"</a>"); |
i++; |
} |
|
if(o->changed) |
{ |
res += ("<a href=\"/(unfoldmodified)"+o->path(1)+"?"+(bar++)+"\">" |
"<img src=/image/unmod.gif align=right hspace=0 border=0" |
" height=19 alt=\"Open all modified\">" |
"</a>"); |
} |
|
if(i) |
res += ("<img src=/image/right.gif align=left height=19" |
" hspace=0 border=0 alt=\"\">"); |
|
res += "<hr noshade>"; |
return stores(res+"<p align=right><a href=$docurl>"+ |
roxen->real_version +"</a></body>"); |
} |
|
|
|
|
|
|
|