inherit "config/builders"; |
string cvs_version = "$Id: mainconfig.pike,v 1.42 1997/06/12 00:34:23 grubba Exp $"; |
inherit "roxenlib"; |
inherit "config/draw_things"; |
|
import Array; |
import Stdio; |
|
|
#define perror roxen_perror |
|
#include <confignode.h> |
#include <module.h> |
|
#define dR "00" |
#define dG "06" |
#define dB "30" |
|
#define bdR "00" |
#define bdG "50" |
#define bdB "90" |
|
|
#define BODY "<body "+(roxen->QUERY(BG)?"background=/image/background.gif ":"")+"bgcolor=#"+dR+dG+dB+" text=#ffffff link=#ffffaa vlink=#ffffaa alink=#f0e0f0>" |
|
#define TABLEP(x, y) (id->supports->tables ? x : y) |
#define PUSH(X) do{res+=({(X)});}while(0) |
|
int bar=time(1); |
|
class Node { |
inherit "struct/node"; |
|
import Simulate; |
|
mixed original; |
int changed, moredocs; |
|
int bar=time(); |
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+"\">\n" |
"<a href=\"/(unfold)" + name + "?"+(bar++)+ |
"\">\n<img border=0 align=baseline src=/auto/unfold" |
+(changed?"2":"")+" alt=\""+(changed?"*-":"--")+"\">" |
"</a>\n "+s+"\n"); |
else |
return ("<a name=\""+name+"\">\n" |
"<a href=\"/(fold)" + name + "?"+(bar++)+ |
"\">\n<img border=0 src=/auto/fold"+(changed?"2":"") |
+" alt="+(changed?"**":"\"\\/\"")+">" |
"</a>\n "+s+"\n"); |
} |
|
string describe(int i) |
{ |
array (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"); |
return 0; |
} |
#endif |
if(arrayp(tmp) && sizeof(tmp)) |
PUSH(tmp[0] + "<dt>" + (i?tmp[i]:show_me(tmp[1])) + "\n"); |
else if(stringp(tmp) && strlen(tmp)) |
PUSH("<dt>"+(i?tmp:show_me(tmp)) + "\n"); |
else if(!tmp) |
return ""; |
|
if(!folded) |
{ |
PUSH("<dl><dd>\n"); |
node = down; |
while(node) |
{ |
if(!objectp(node)) |
{ |
if(objectp(prevnode)) |
prevnode->next=0; |
node=0; |
break; |
} |
prevnode = node; |
node = node->next; |
PUSH(prevnode->describe()); |
} |
PUSH("</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); |
} |
|
#define BUTTON(ACTION,TEXT,ALIGN) do{PUSH("<a href=\"/(ACTION)"+(o?o->path(1):"/")+"?"+(bar++)+"\"><img border=0 hspacing=0 vspacing=0 src=/auto/button/"+(lm?"lm/":"")+replace(TEXT," ","%20")+" alt=\""+(lm?"/ ":" ")+TEXT+" /\""+(("ALIGN"-" ")=="left"?"":" align="+("ALIGN"-" "))+"></a>");lm=0;}while(0) |
|
inline string shutdown_restart(string save, int compact,void|object o) |
{ |
return ""; |
} |
|
string default_head(string h, string|void save) |
{ |
return ("<head><title>"+h+"</title></head>\n"+ BODY+"\n"); |
} |
|
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; |
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(); |
roxen->update_supports_from_roxen_com(); |
roxen->initiate_configuration_port( 0 ); |
} |
|
mapping stores( string s ) |
{ |
return |
([ |
"data":replace(s, "$docurl", roxen->docurl), |
"type":"text/html", |
"extra_heads": |
([ |
"Title":"Roxen Challenger maintenance", |
|
|
"Last-Modified":http_date(time(1)), |
]) |
]); |
} |
|
object find_module(string name, object in) |
{ |
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(in->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 = in->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_CUSTOM: |
return node->data[ VAR_MISC ][2]( var, type, node, allvars ); |
|
case TYPE_MODULE_LIST: |
return map(var/"\000", find_module); |
|
case TYPE_MODULE: |
return find_module(var, node->config()); |
|
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((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: |
array st; |
if (!strlen( var ) || !(st = file_stat( var )) || (st[1] != -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_FONT: |
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((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(default_head("")+ read_bytes("etc/newconfig.html"), |
({"$COPIES","$configurl"}), |
({configuration_list(),CONFIG_URL})) + |
"\n\n</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_AUTH) && (o=conf->auth_module)) |
|| ((type & MODULE_TYPES) && (o=conf->types_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++; |
orig = node->config()->enable_module(name+"#"+i); |
|
if(!orig) return http_string_answer("This module could not be enabled.\n"); |
|
module = node->config()->modules[name]; |
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); |
|
|
|
if(node) |
{ |
node->folded = 0; |
|
node->change(1); |
} |
return std_redirect(root, id); |
} |
|
mixed new_module_copy_copy(object node, object id) |
{ |
return new_module_copy(node, node->data->sname, id); |
} |
|
string new_module_form(object id, object node) |
{ |
int i; |
mixed a,b; |
string q; |
array mods; |
array (string) res; |
|
if(!roxen->allmodules || sizeof(id->pragma)) |
{ |
werror("CONFIG: Rescanning modules.\n"); |
roxen->current_configuration = node->config(); |
roxen->rescan_modules(); |
roxen->current_configuration = 0; |
werror("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")+"\n\n"+ |
"<h2>Select a module to add from the list below</h2>" }); |
|
foreach(mods, q) |
{ |
if(b = module_nomore(q, a[q][2], node->config())) |
{ |
if(b->sname != q) |
res += ({("<p>"+ |
(roxen->QUERY(BS)?"<h2>"+a[q][0]+"</h2>": |
"<img alt=\""+a[q][0]+"\" src=/auto/module/" + a[q][2]+"/"+ |
q+" height=24 width=500>")+ "<br><blockquote>" + a[q][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>" |
"\n<p><br><p></blockquote>")}); |
} else { |
res += ({"<p><a href=/(newmodule)"+node->path(1)+"?"+q+"=1>"+ |
(roxen->QUERY(BS)?"<h2>"+a[q][0]+"</h2>": |
"<img border=0 alt=\""+a[q][0]+"\" src=/auto/module/"+ |
a[q][2]+"/"+q+" height=24 width=500>")+ |
"</a><blockquote><br>"+a[q][1]+"<p><br><p></blockquote>"}); |
} |
} |
return res*""; |
} |
|
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: |
o=roxen->enable_configuration(name); |
break; |
|
case "standard": |
o = roxen->enable_configuration(name); |
o->enable_module("cgi#0"); |
o->enable_module("contenttypes#0"); |
o->enable_module("ismap#0"); |
o->enable_module("pikescript#0"); |
o->enable_module("htmlparse#0"); |
o->enable_module("directories#0"); |
o->enable_module("userdb#0"); |
o->enable_module("userfs#0"); |
o->enable_module("filesystem#0"); |
break; |
|
case "ipp": |
o=roxen->enable_configuration(name); |
o->enable_module("contenttypes#0"); |
o->enable_module("ismap#0"); |
o->enable_module("htmlparse#0"); |
o->enable_module("directories#0"); |
o->enable_module("filesystem#0"); |
break; |
|
case "proxy": |
o=roxen->enable_configuration(name); |
o->enable_module("proxy#0"); |
o->enable_module("gopher#0"); |
o->enable_module("ftpgateway#0"); |
o->enable_module("contenttypes#0"); |
o->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/"+roxenp()->short_name(name)+"/Log"; |
roxenp()->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")+ |
"<blockquote><h1>No configuration name?</h1>" |
"Either you entered no name, or your WWW-browser " |
"failed to include it in the request</blockquote>"); |
|
id->variables->name=(replace(id->variables->name,"\000"," ")/" "-({""}))*" "; |
if(!low_enable_configuration(id->variables->name, id->variables->type)) |
return stores(default_head("Bad luck") + |
"<blockquote><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</blockquote>"); |
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); |
|
root->save(); |
return std_redirect(root, id); |
} |
} |
|
res = default_head("Welcome to Roxen Challenger"); |
|
res += read_bytes("etc/welcome.html"); |
if(error && strlen(error)) |
res += "<blockquote>\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" |
|
|
|
" <input type=submit value=\"Use these values\">\n" |
"</form></font></pre></blockquote>"); |
|
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) |
{ |
if(!node) return ""; |
for(;node && (node->up!=root);node=node->up); |
if(!node) return ""; |
return node->path(1); |
} |
|
|
|
|
string tablist(array(string) nodes, array(string) links, int selected) |
{ |
array res = ({}); |
for(int i=0; i<sizeof(nodes); i++) |
if(i!=selected) |
PUSH("<a href=\""+links[i]+"\"><img alt=\"_/"+ |
nodes[i][1..strlen(nodes[i])-2]+"\\__\" src=/auto/unselected/"+ |
replace(nodes[i]," ","%20")+" border=0></a>"); |
else |
PUSH("<a href=\""+links[i]+"\"><b><img alt=\"_/"+ |
nodes[i][1..strlen(nodes[i])-2]+"\\__\" src=/auto/selected/"+ |
replace(nodes[i]," ","%20")+" border=0></b></a>"); |
|
return res*""; |
} |
|
mapping (string:string) selected_nodes = |
([ |
"Configurations":"/Configurations", |
"Globals":"/Globals", |
"Status":"/Status", |
"Errors":"/Errors", |
]); |
|
array tabs = ({ |
"Configurations", |
"Globals", |
"Status", |
"Errors", |
}); |
|
array tab_names = ({ |
" Virtual servers ", |
" Global variables ", |
" Status info ", |
" Error log ", |
}); |
|
|
string display_tabular_header(object node) |
{ |
string p, s; |
|
array links = ({ |
selected_nodes[tabs[0]]+"?"+(bar++), |
selected_nodes[tabs[1]]+"?"+(bar++), |
selected_nodes[tabs[2]]+"?"+(bar++), |
selected_nodes[tabs[3]]+"?"+(bar++), |
}); |
|
if(node != root) |
{ |
s = extract_almost_top(node) - "/"; |
selected_nodes[s] = node->path(1); |
|
links[search(tabs,s)]="/"+s+"/"+"?"+(bar++); |
} |
return tablist(tab_names, links, search(tabs,s)); |
} |
|
|
|
|
int nunfolded(object o) |
{ |
int i; |
if(o = o->down) |
do { i+=!o->folded; } while(o=o->next); |
return i; |
} |
|
|
object module_font = get_font("base_server/config/font",0,0,0,"left",1.0,1.0); |
object button_font = get_font("base_server/config/button_font",0,0,0,"left",1.0,1.0); |
|
mapping auto_image(string in, object id) |
{ |
string key, value; |
array trans = ({ (int)("0x"+dR),(int)("0x"+dG),(int)("0x"+dB) }); |
mapping r; |
mixed e; |
object i; |
|
string img_key = "auto/"+replace(in,"/","_")+".gif"-" "; |
|
if(e=file_image(img_key)) |
return e; |
|
if(!sscanf(in, "%s/%s", key, value)) key=in; |
|
switch(key) |
{ |
case "module": |
sscanf(value, "%*d/%s", value); |
i = draw_module_header(roxen->allmodules[value][0], |
roxen->allmodules[value][2], |
module_font); |
break; |
|
case "button": |
int lm,rm; |
if(sscanf(value, "lm/%s", value)) lm=1; |
if(sscanf(value, "rm/%s", value)) rm=1; |
i=draw_config_button(value,button_font,lm,rm); |
break; |
|
case "fold": |
case "fold2": |
i = draw_fold((int)reverse(key)); |
break; |
|
case "unfold": |
case "unfold2": |
i = draw_unfold((int)reverse(key)); |
break; |
|
case "back": |
i = draw_back((int)reverse(key)); |
break; |
|
case "selected": |
i=draw_selected_button(value,button_font); |
break; |
|
case "unselected": |
i=draw_unselected_button(value,button_font); |
break; |
} |
if(i) |
{ |
object o = open("roxen-images/"+img_key,"wct"); |
e=i->map_closest(i->select_colors(64)+({trans}))->togif(@trans); |
i=0; |
if(o) { o->write(e); o=0; } |
#ifdef DEBUG |
else {perror("Cannot open file for "+in+"\n");} |
#endif |
return http_string_answer(e,"image/gif"); |
} |
return 0; |
} |
|
|
string remove_font(string t, mapping m, string c) |
{ |
return "<b>"+c+"</b>"; |
} |
|
|
int nfolded(object o) |
{ |
int i; |
if(o = o->down) |
do { i+=!!o->folded; } while(o=o->next); |
return i; |
} |
|
int nfoldedr(object o) |
{ |
object node; |
int i; |
i = o->folded; |
node=o->down; |
while(node) |
{ |
i+=nfoldedr(node); |
node=node->next; |
} |
return i; |
} |
|
|
mapping configuration_parse(object id) |
{ |
array (string) res=({}); |
string tmp; |
|
if(sscanf(id->not_query, "/image/%s", tmp)) |
return file_image(tmp) || (["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 = ([ ]); |
} |
|
|
if(sscanf(id->not_query, "/auto/%s", tmp)) |
return auto_image(tmp,id) || (["data":"No such image"]); |
|
o = find_node(id->not_query); |
|
if(!o) |
{ |
id->referer = ({ }); |
return std_redirect(0, id); |
} else if(o == root) { |
|
|
|
return http_string_answer(default_head("Roxen Challenger")+ |
display_tabular_header(root)+ |
read_bytes("etc/config.html"),"text/html"); |
} |
|
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 "moredocs": o->moredocs=1; break; |
case "lessdocs": o->moredocs=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 "unfoldlevel": |
object node; |
node=o->down; |
while(node) |
{ |
node->folded=0; |
node = node->next; |
} |
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, o->config()); |
if(!name) |
error("This module cannot be updated"); |
sscanf(name, "%s#%*s", modname); |
|
if(!(cmod = o->config()->modules[ modname ])) |
error("This module cannot be updated"); |
|
o->save(); |
cache_remove("modules", modname); |
|
|
|
|
if(!o->config()->load_module(modname)) |
{ |
mapping rep; |
rep = http_string_answer("The reload of this module failed.\n" |
"This is (probably) the reason:\n<pre>" |
+ roxen->last_error + "</pre>" ); |
|
return rep; |
} |
|
object mod; |
if(!o->config()->disable_module(name))error("Failed to disable module.\n"); |
if(!(mod=o->config()->enable_module(name)))error("Failed to enable module.\n"); |
|
o->clear(); |
|
|
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": |
PUSH(default_head("Roxen Configuration")); |
|
|
switch(o->type) |
{ |
case NODE_CONFIGURATION: |
PUSH("<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: |
PUSH("<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: |
PUSH("<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"); |
} |
PUSH("<blockquote><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></blockquote>"); |
|
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(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, o->config()); |
o->config()->disable_module(name); |
|
roxen->remove(name, o->config()); |
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--) |
{ |
o->config()->disable_module(name+"#"+a[i]); |
roxen->remove(name+"#"+a[i], o->config()); |
} |
} else if(o->data->master) { |
name=o->config()->otomod[o->data->enabled]; |
} |
} else if(o->data->enabled) { |
name=o->config()->otomod[o->data->enabled]; |
o->config()->disable_module(name+"#0"); |
roxen->remove(name+"#0", o->config()); |
} |
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); |
} |
|
PUSH(default_head("Roxen server configuration", root->changed?o->path(1):0)); |
PUSH("<dl>\n"); |
PUSH("\n"+display_tabular_header( o )+"\n"); |
PUSH("<p>"); |
if(o->up != root && o->up) |
PUSH("<a href=\""+ o->up->path(1)+"?"+(bar++)+"\">" |
"<img src=/auto/back alt='[Up]' align=left hspace=0 border=0></a>\n"); |
|
if(i=o->folded) o->folded=0; |
string tmp = o->describe(1); |
if(!id->supports->font) |
tmp = parse_html(tmp, ([]),(["font":remove_font, ])); |
PUSH(tmp); |
o->folded=i; |
|
PUSH("</dl>"); |
PUSH("<p><br clear=all> \n"); |
|
int lm=1; |
|
if(o->type == NODE_CONFIGURATIONS) |
BUTTON(newconfig, "New virtual server", left); |
|
if(o->type == NODE_CONFIGURATION) |
BUTTON(newmodule, "New module", left); |
|
if(o->type == NODE_MODULE) |
{ |
BUTTON(delete, "Delete module", left); |
if(o->data->copies) |
BUTTON(newmodulecopy, "Copy module", left); |
} |
|
i=0; |
if(o->type == NODE_MODULE_MASTER_COPY || o->type == NODE_MODULE_COPY |
|| o->type == NODE_MODULE_COPY_VARIABLES) |
{ |
BUTTON(delete, "Delete module", left); |
BUTTON(refresh, "Reload module", left); |
} |
|
if(o->type == NODE_CONFIGURATION) |
BUTTON(delete,"Delete this server", left); |
|
if(nunfolded(o)) |
BUTTON(foldall, "Fold all",left); |
if(o->changed) |
BUTTON(unfoldmodified, "Unfold modified", left); |
|
if(nfolded(o)) |
BUTTON(unfoldlevel, "Unfold level", left); |
|
|
|
|
if(!lm) |
{ |
PUSH("<img border=0 alt=\"\" hspacing=0 vspacing=0 src=/auto/button/rm/%20>"); |
PUSH("</nobr><br clear=all>"); |
lm=1; |
} |
|
if((o->changed||root->changed)) |
{ |
BUTTON(save, "Save", left); |
PUSH("<img border=0 alt=\"\" hspacing=0 vspacing=0 src=/auto/button/%20%20%20%20%20%20>"); |
} |
BUTTON(restart, "Restart", left); |
BUTTON(shutdown,"Shutdown", left); |
|
PUSH("<img border=0 alt=\"\" hspacing=0 vspacing=0 src=/auto/button/rm/%20>"); |
PUSH("</nobr><br clear=all>"); |
|
PUSH("</body>\n"); |
return stores(res*""); |
} |
|
|
|
|
|
|
|