b1fca01996-11-12Per Hedbor inherit "config/builders";
88803f1998-04-07Peter Bortas string cvs_version = "$Id: mainconfig.pike,v 1.100 1998/04/07 01:10:33 peter Exp $";
953ca31997-08-18Per Hedbor //inherit "roxenlib";
a9d8af1997-11-07Mirar (Pontus Hagland) 
fd0b6f1996-12-02Per Hedbor inherit "config/draw_things";
b1fca01996-11-12Per Hedbor 
e5bad21998-02-10Per Hedbor // import Array; // import Stdio;
a9d8af1997-11-07Mirar (Pontus Hagland) 
38a83c1997-08-12Per Hedbor string status_row(object node); string display_tabular_header(object node);
799ed21997-08-13Per Hedbor object get_template(string t);
aaef2a1997-03-02Henrik Grubbström (Grubba) 
8c6b2e1997-08-14Henrik Grubbström (Grubba) /* Work-around for Simulate.perror */
19f5911997-03-03Henrik Grubbström (Grubba) #define perror roxen_perror
5e89211997-02-13Per Hedbor 
b1fca01996-11-12Per Hedbor #include <confignode.h> #include <module.h>
9b9f701997-08-12Per Hedbor #define dR "ff" #define dG "ff" #define dB "ff"
1e257d1996-12-03Per Hedbor  #define bdR "00"
2de6921996-12-03Per Hedbor #define bdG "50" #define bdB "90"
1e257d1996-12-03Per Hedbor 
1e5ee81997-08-21Per Hedbor #define BODY "<body bgcolor=white text=black link=darkblue vlink=black alink=red>"
b1fca01996-11-12Per Hedbor  #define TABLEP(x, y) (id->supports->tables ? x : y)
b2c3871996-12-04Per Hedbor #define PUSH(X) do{res+=({(X)});}while(0)
b1fca01996-11-12Per Hedbor  int bar=time(1);
c0863e1997-08-12David Hedbor multiset changed_port_servers;
b1fca01996-11-12Per Hedbor 
b2c3871996-12-04Per Hedbor class Node {
b1fca01996-11-12Per Hedbor  inherit "struct/node"; mixed original;
676c231996-12-06Per Hedbor  int changed, moredocs;
14179b1997-01-29Per Hedbor  int bar=time();
1e5ee81997-08-21Per Hedbor  function saver;
b1fca01996-11-12Per Hedbor  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)
45165f1997-08-13Peter Bortas  return ("<a name=\""+name+"\" href=\"/(unfold)" + name + "?"+(bar++)+
2adfdf1997-08-13Per Hedbor  "\">\n<img border=0 align=baseline src=/auto/unfold" +(changed?"2":"")+" alt=\""+(changed?"*-":"--")+"\">"
b2c3871996-12-04Per Hedbor  "</a>\n "+s+"\n");
b1fca01996-11-12Per Hedbor  else
1935451997-08-13Per Hedbor  return ("<a name=\""+name+"\" href=\"/(fold)" + name + "?"+(bar++)+
2adfdf1997-08-13Per Hedbor  "\">\n<img border=0 src=/auto/fold"+(changed?"2":"") +" alt="+(changed?"**":"\"\\/\"")+">"
b2c3871996-12-04Per Hedbor  "</a>\n "+s+"\n");
b1fca01996-11-12Per Hedbor  }
00aff81997-08-12Per Hedbor  mixed describe(int i, object id)
b1fca01996-11-12Per Hedbor  {
b2c3871996-12-04Per Hedbor  array (string) res=({""});
b1fca01996-11-12Per Hedbor  object node,prevnode; mixed tmp; if(describer)
00aff81997-08-12Per Hedbor  tmp = describer(this_object(), id);
b1fca01996-11-12Per Hedbor #ifdef NODE_DEBUG else
676c231996-12-06Per Hedbor  {
b1fca01996-11-12Per Hedbor  perror("No describer in node "+path(1)+"\n");
676c231996-12-06Per Hedbor  return 0; }
b1fca01996-11-12Per Hedbor #endif
00aff81997-08-12Per Hedbor  if(mappingp(tmp)) {
13ff621997-08-12Per Hedbor // werror("Got mapping.\n");
00aff81997-08-12Per Hedbor  return tmp; }
b1fca01996-11-12Per Hedbor  if(arrayp(tmp) && sizeof(tmp))
676c231996-12-06Per Hedbor  PUSH(tmp[0] + "<dt>" + (i?tmp[i]:show_me(tmp[1])) + "\n");
b1fca01996-11-12Per Hedbor  else if(stringp(tmp) && strlen(tmp))
676c231996-12-06Per Hedbor  PUSH("<dt>"+(i?tmp:show_me(tmp)) + "\n");
b1fca01996-11-12Per Hedbor  else if(!tmp) return ""; if(!folded) {
b2c3871996-12-04Per Hedbor  PUSH("<dl><dd>\n");
b1fca01996-11-12Per Hedbor  node = down;
2adfdf1997-08-13Per Hedbor  array node_desc = ({});
b1fca01996-11-12Per Hedbor  while(node) { if(!objectp(node)) // ERROR! Destructed node in tree! { if(objectp(prevnode)) prevnode->next=0; node=0; break; } prevnode = node; node = node->next;
2adfdf1997-08-13Per Hedbor  node_desc += ({ prevnode->describe() });
b1fca01996-11-12Per Hedbor  }
2adfdf1997-08-13Per Hedbor  PUSH(node_desc*"\n");
b2c3871996-12-04Per Hedbor  PUSH("</dl>\n\n");
b1fca01996-11-12Per Hedbor  }
b2c3871996-12-04Per Hedbor  return res*"";
b1fca01996-11-12Per Hedbor  } 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; // depth-first save. while(node) { if(node->changed) node->save(); node=node->next; }
c0863e1997-08-12David Hedbor  if(changed && type == NODE_MODULE_COPY_VARIABLE && data[VAR_TYPE] == TYPE_PORTS) { roxen->configuration_interface_obj->changed_port_servers[config()] = 1; // A port was changed in the current server... }
08df121997-08-19Henrik Grubbström (Grubba)  if(saver) saver(this_object(), config());
1e5ee81997-08-21Per Hedbor  else change(-changed);
b1fca01996-11-12Per Hedbor  }
b2c3871996-12-04Per Hedbor }
b1fca01996-11-12Per Hedbor 
0f28da1997-08-13Per Hedbor int restore_more_mode() { return !!file_stat(".more_mode"); }
5e4ede1996-11-12Per Hedbor object root=Node();
0f28da1997-08-13Per Hedbor int expert_mode, more_mode=restore_more_mode(); void save_more_mode() { if(more_mode) open(".more_mode", "wct"); else rm(".more_mode"); }
b1fca01996-11-12Per Hedbor  void create() { build_root(root); init_ip_list(); call_out(init_ip_list, 0); }
4814db1997-08-14Henrik Grubbström (Grubba) // Note stringification of ACTION and ALIGN #if 0
45165f1997-08-13Peter Bortas #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)
4814db1997-08-14Henrik Grubbström (Grubba) #else
d0f5b41998-01-20Henrik Grubbström (Grubba) #if constant(cpp) #define BUTTON(ACTION,TEXT,ALIGN) do{buttons += ({({"<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) #else /* !constant(cpp) */ #define BUTTON(ACTION,TEXT,ALIGN) do{buttons += ({({"<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) #endif /* constant(cpp) */
4814db1997-08-14Henrik Grubbström (Grubba) #define PUSH_BUTTONS(CLEAR) do{if(sizeof(buttons)){buttons[-1][0]+="rm/";res+=`+(@buttons);if(CLEAR){PUSH("<br clear=all>");}}lm=1;buttons=({});}while(0) #endif /* 0 */
fdee9d1996-12-02Per Hedbor 
b1fca01996-11-12Per Hedbor string default_head(string h, string|void save) {
2adfdf1997-08-13Per Hedbor  return ("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Draft//EN\">"
75562d1997-08-14Thomas Abrahamsson  "<head><title>"+h+"</title>\n<META HTTP-EQUIV=\"Expires\" CONTENT=\"0\">\n</head>\n"+ BODY+"\n");
b1fca01996-11-12Per Hedbor } object find_node(string l) { array tmp = l/"/"-({""}); object o; if(!sizeof(tmp)) return root;
62eac81997-10-03Henrik Grubbström (Grubba)  for(o=root; sizeof(tmp) && (o=o->descend(tmp[0],1)); tmp=tmp[1..]);
b1fca01996-11-12Per Hedbor  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"), ]); } mapping stores( string s ) { return ([ "data":replace(s, "$docurl", roxen->docurl), "type":"text/html", "extra_heads": ([ "Title":"Roxen Challenger maintenance",
9165e01996-12-06Per Hedbor // "Expires":http_date(time(1)+2), // "Pragma":"no-cache",
b1fca01996-11-12Per Hedbor  "Last-Modified":http_date(time(1)), ]) ]); }
c0863e1997-08-12David Hedbor #define CONFIG_URL roxen->config_url() mapping verify_changed_ports(object id, object o) { string res = default_head("Roxen Config: Setting Server URL") + ("<h1>Set the correct server URL</h1>" "As you have changed the open ports in one or more servers " "you might have to adjust the default server URL(s). Check the "
da42a51997-08-12David Hedbor  "correct URL(s) below and modify it as needed. The server URLs are among " "other things used for redirects. "
c0863e1997-08-12David Hedbor  "<form action=\"/(modify_server_url)"+o->path(1)+"\">"); foreach(indices(changed_port_servers), object server) {
da42a51997-08-12David Hedbor  int glob; string name; if(!server) { glob = 1; server = roxen; name="Global Variables"; #if 0 perror("Config Interface, URL %s, Ports %O\n", GLOBVAR(ConfigurationURL), GLOBVAR(ConfigPorts)); #endif } else { glob = 0; name = server->name; #if 0 perror("Server %s, URL %s, Ports %O\n", server->name, server->query("MyWorldLocation"), server->query("Ports")); #endif }
c0863e1997-08-12David Hedbor 
da42a51997-08-12David Hedbor  string def; if(glob) { def = GLOBVAR(ConfigurationURL); res += "<h3>Select Configuration Interface URL: </h3>\n<pre>"; } else { def = server->query("MyWorldLocation");
c0863e1997-08-12David Hedbor  res += sprintf("<h3>Select server URL for for %s: </h3>\n"
da42a51997-08-12David Hedbor  "<pre>", name); } foreach((glob ? GLOBVAR(ConfigPorts) : server->query("Ports")), array port) {
c0863e1997-08-12David Hedbor  string prt; if(port[1] == "tetris") continue; switch(port[1][0..2]) { case "ssl": prt = "https://"; break; default: prt = port[1]+"://"; } if(port[2] && port[2]!="ANY") prt += port[2];
c79b261998-02-05Johan Schön #if efun(gethostname)
c0863e1997-08-12David Hedbor  else
da42a51997-08-12David Hedbor  prt += (gethostname()/".")[0] + "." + (glob ? roxen->get_domain() : server->query("Domain"));
c79b261998-02-05Johan Schön #endif
c0863e1997-08-12David Hedbor  prt += ":"+port[0]+"/"; if(prt != def) res += sprintf(" <input type=radio name=\"%s\" value=\"%s\"> %s\n",
da42a51997-08-12David Hedbor  name, prt, prt);
c0863e1997-08-12David Hedbor  } res += sprintf(" <input type=radio checked value=own name=\"%s\"> " "<input size=70 name=\"%s->own\" " "value=\"%s\">\n</pre><p>",
da42a51997-08-12David Hedbor  name, name, def);
c0863e1997-08-12David Hedbor  }
00aff81997-08-12Per Hedbor  changed_port_servers = (<>);
c0863e1997-08-12David Hedbor  return stores(res+"<input type=submit value=\"Continue...\"></form>"); } mapping save_it(object id, object o) { changed_port_servers = (<>); root->save(); roxen->update_supports_from_roxen_com(); roxen->initiate_configuration_port( 0 );
da42a51997-08-12David Hedbor  id->referer = ({ CONFIG_URL + o->path(1) });
c0863e1997-08-12David Hedbor  if(sizeof(changed_port_servers)) return verify_changed_ports(id, o); }
14179b1997-01-29Per Hedbor object find_module(string name, object in)
b1fca01996-11-12Per Hedbor { 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
14179b1997-01-29Per Hedbor  foreach(values(in->modules), mod)
b1fca01996-11-12Per Hedbor  { 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
14179b1997-01-29Per Hedbor  modules = in->modules;
b1fca01996-11-12Per Hedbor  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) {
f6d62d1997-03-26Per Hedbor  case TYPE_CUSTOM: return node->data[ VAR_MISC ][2]( var, type, node, allvars );
b1fca01996-11-12Per Hedbor  case TYPE_MODULE_LIST:
e5bad21998-02-10Per Hedbor  return Array.map(var/"\000", find_module);
b1fca01996-11-12Per Hedbor  case TYPE_MODULE:
41d0f91998-02-20Per Hedbor  return find_module((var/"\000")[0], node->config());
b1fca01996-11-12Per Hedbor  case TYPE_PORTS: /* Encoded like this: new_port --> Add a new port ok[_<ID>] --> Save the value for all or one port delete_<ID> --> Delete a port ---- { A port is defined by: port_<ID> == INT protocol_<ID> == STRING ip_number_<ID> == STRING arguments_<ID> == STRING } ---- */ 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];
ae32d01998-03-23David Hedbor  string args = ""; if(allvars["key_"+i] && strlen(allvars["key_"+i])) args += "key-file "+allvars["key_"+i]+"\n"; if(allvars["cert_"+i] && strlen(allvars["cert_"+i])) args += "cert-file "+allvars["cert_"+i]+"\n"; if(strlen(args)) op[i][3] = args;
b1fca01996-11-12Per Hedbor  } else // Delete this port. op[i]=0; } return op - ({ 0 }); case TYPE_DIR_LIST: array foo;
e5bad21998-02-10Per Hedbor  foo=Array.map((var-" ")/",", lambda(string var, object node) { if (!strlen( var ) || Stdio.file_size( var ) != -2)
b1fca01996-11-12Per Hedbor  { 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:
48fa361997-04-05Per Hedbor  array st;
8e727d1997-03-11Per Hedbor  if (!strlen( var ) || !(st = file_stat( var )) || (st[1] != -2))
b1fca01996-11-12Per Hedbor  { node->error = var + " is not a directory"; return 0; } if(var[-1] != '/') return var + "/"; return var; case TYPE_TEXT_FIELD: var -= "\r";
8e727d1997-03-11Per Hedbor  case TYPE_FONT:
b1fca01996-11-12Per Hedbor  case TYPE_STRING: case TYPE_FILE: case TYPE_LOCATION:
41d0f91998-02-20Per Hedbor  return (var/"\000")[0];
b1fca01996-11-12Per Hedbor  case TYPE_PASSWORD:
41d0f91998-02-20Per Hedbor  return crypt((var/"\000")[0]);
b1fca01996-11-12Per Hedbor  case TYPE_FLAG:
41d0f91998-02-20Per Hedbor  return lower_case((var/"\000")[0]) == "yes";
b1fca01996-11-12Per Hedbor  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
e5bad21998-02-10Per Hedbor  return Array.map((var-" ")/",", lambda(string s){
b1fca01996-11-12Per Hedbor  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
62eac81997-10-03Henrik Grubbström (Grubba)  loc = CONFIG_URL+o->path(1)[1..]+"?"+bar++;
b1fca01996-11-12Per Hedbor  if(sscanf(loc, "%s/(%*s)%s",l2, loc) == 3) loc = l2 + loc; // Remove the prestate. // http://www:22020//Configuration/ -> http://www:22202/Configurations/ loc = replace(replace(replace(loc, "://", ""), "//", "/"), "", "://"); return http_redirect(http_decode_string(loc)); } string configuration_list() { string res="";
4f55ff1997-12-15Peter Bortas  /* FIXME
b1fca01996-11-12Per Hedbor  object o; foreach(roxen->configurations, o)
84b6331997-08-14Henrik Grubbström (Grubba)  res += "<option>Copy of '"+o->name+"'\n";
4f55ff1997-12-15Peter Bortas  */
b1fca01996-11-12Per Hedbor  return res; }
799ed21997-08-13Per Hedbor string configuration_types() { string res=""; foreach(get_dir("server_templates"), string c) {
39ff571997-08-14Henrik Grubbström (Grubba)  array err; if (err = catch {
6ebc281997-08-14Henrik Grubbström (Grubba)  if(c[-1]=='e' && c[0]!='#') {
39ff571997-08-14Henrik Grubbström (Grubba)  object o = get_template(c);
6ebc281997-08-14Henrik Grubbström (Grubba)  if (o) { res += sprintf("<option value=\"%s\"%s>%s\n", c, (o->selected?" selected":""), o->name); }
39ff571997-08-14Henrik Grubbström (Grubba)  } }) { report_error(sprintf("Error initializing server template \"%s\"\n" "%s\n", c, describe_backtrace(err))); }
799ed21997-08-13Per Hedbor  } return res; } string describe_config_modules(array mods) { string res = "This configuration template adds the following modules:<p><ul>"; if(!mods||!sizeof(mods)) return "This configuration template adds no modules"; foreach(mods, string mod) { sscanf(mod, "%s#", mod);
0a7a0c1997-12-15Peter Bortas  if(!roxen->allmodules) { werror("CONFIG: Rescanning modules (doc string).\n"); roxen->rescan_modules(); werror("CONFIG: Done.\n"); }
84b6331997-08-14Henrik Grubbström (Grubba)  if(!roxen->allmodules[mod]) res += "<li>The unknown modules '"+mod+"'\n";
799ed21997-08-13Per Hedbor  else res += "<li>"+roxen->allmodules[mod][0]+"\n"; } return res+"</ul>"; } string configuration_docs() {
0f28da1997-08-13Per Hedbor  string res="";
799ed21997-08-13Per Hedbor  foreach(get_dir("server_templates"), string c) {
cc005c1997-12-18Peter Bortas  if( c[-1]=='e' ) res += ("<dt><b>"+get_template(c)->name+"</b>\n"+ "<dd>"+get_template(c)->desc+"<br>\n"+ describe_config_modules(get_template(c)->modules) + "\n");
799ed21997-08-13Per Hedbor  } return res; }
b1fca01996-11-12Per Hedbor string new_configuration_form() {
799ed21997-08-13Per Hedbor  return (default_head("") + status_row(root) + "<h2>Add a new virtual server</h2>\n" "<table bgcolor=#000000><tr><td >\n" "<table cellpadding=3 cellspacing=1 bgcolor=lightblue><tr><td>\n" "<form>\n" "<tr><td>Server name:</td><td><input name=name size=40,1>" "</td></tr>\n" "<tr><td>Configuration type:</td><td><select name=type>"+ configuration_types()+configuration_list()+"</select></tr>" "</td>\n" "<tr><td colspan=2><table><tr><td align=left>" "<input type=submit name=ok value=\" Ok \"></td>" "<td align=right>"
84b6331997-08-14Henrik Grubbström (Grubba)  "<input type=submit name=no value=\" Cancel \"></td></tr>\n" "</table></td></tr></table></td></tr>\n</table>\n" +
799ed21997-08-13Per Hedbor  "<p>The only thing the type change is the initial "
84b6331997-08-14Henrik Grubbström (Grubba)  "configuration of the server.\n" "<p>The types are:<dl>\n" + configuration_docs() +
4f55ff1997-12-15Peter Bortas  /* FIXME
799ed21997-08-13Per Hedbor  "<dt><b>Copy of ...</b>:\n"
b6f43f1997-08-12David Hedbor  "<dd>Make an exact copy of the mentioned virtual server.\n"
84b6331997-08-14Henrik Grubbström (Grubba)  "You should change at least the listen ports.<p>\n"
799ed21997-08-13Per Hedbor  "This can be very useful, since you can make 'template' virtual " "servers (servers without any open ports), that you can copy later "
4f55ff1997-12-15Peter Bortas  "on.\n" */ "</dl>\n</body>\n");
b1fca01996-11-12Per Hedbor }
799ed21997-08-13Per Hedbor 
b1fca01996-11-12Per Hedbor mapping module_nomore(string name, int type, object conf) { mapping module; object o; // perror("Module: "+name+"\n"); if((module = conf->modules[name]) && (!module->copies && module->enabled)) return module; if(((type & MODULE_DIRECTORIES) && (o=conf->dir_module))
f2549a1997-06-09Henrik Grubbström (Grubba)  || ((type & MODULE_AUTH) && (o=conf->auth_module)) || ((type & MODULE_TYPES) && (o=conf->types_module))
b1fca01996-11-12Per Hedbor  || ((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++;
14179b1997-01-29Per Hedbor  orig = node->config()->enable_module(name+"#"+i);
a52cc61996-11-20Per Hedbor 
14179b1997-01-29Per Hedbor  if(!orig) return http_string_answer("This module could not be enabled.\n");
a52cc61996-11-20Per Hedbor 
14179b1997-01-29Per Hedbor  module = node->config()->modules[name];
b1fca01996-11-12Per Hedbor  node = node->descend(module->name); // Now it is the (probably unbuilt) module main node... node->data = module; node->describer = describe_module; node->type = NODE_MODULE; build_module(node); // We want to see the new module.. node->folded=0; // If the module have copies, select the actual copy added.. if(module->copies) node = node->descend((string)i, 1); // Now it is the module.. // We want to see this one immediately.
5b38191996-12-13Per Hedbor  if(node) { node->folded = 0; // Mark the node and all its parents as modified. node->change(1); }
b1fca01996-11-12Per Hedbor  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;
fd0b6f1996-12-02Per Hedbor  string q;
b1fca01996-11-12Per Hedbor  array mods;
fd0b6f1996-12-02Per Hedbor  array (string) res;
b1fca01996-11-12Per Hedbor  if(!roxen->allmodules || sizeof(id->pragma)) {
8e727d1997-03-11Per Hedbor  werror("CONFIG: Rescanning modules.\n"); roxen->current_configuration = node->config(); roxen->rescan_modules(); roxen->current_configuration = 0; werror("CONFIG: Done.\n");
b1fca01996-11-12Per Hedbor  } a=roxen->allmodules;
e5bad21998-02-10Per Hedbor  mods=Array.sort_array(indices(a), lambda(string a, string b, mapping m) {
b1fca01996-11-12Per Hedbor  return m[a][0] > m[b][0]; }, a);
fd0b6f1996-12-02Per Hedbor  res = ({default_head("Add a module")+"\n\n"+
4a83271997-08-12Per Hedbor  status_row(node)+
38a83c1997-08-12Per Hedbor // display_tabular_header(node)+
5aa6081997-08-12Peter Bortas  "<table><tr><td>&nbsp;<td><h2>Select a module to add"
4a83271997-08-12Per Hedbor  " from the list below, click on it's header to add it.</h2>" });
b1fca01996-11-12Per Hedbor 
fd0b6f1996-12-02Per Hedbor  foreach(mods, q) {
5f450a1996-12-02Per Hedbor  if(b = module_nomore(q, a[q][2], node->config()))
b1fca01996-11-12Per Hedbor  {
fd0b6f1996-12-02Per Hedbor  if(b->sname != q)
5aab841997-08-21Henrik Grubbström (Grubba)  res += ({("<p><img alt=\""+a[q][0]+"\" src=\"/auto/module/" + a[q][2] + "/"+ q+"\" height=24 width=500><br><blockquote>" + a[q][1] +
f92b7a1997-05-26Henrik Grubbström (Grubba)  "<p><i>A module of the same type is already enabled (" + b->name + "). <a href=\"/(delete)" + node->descend(b->name, 1)->path(1) + "?" + (bar++) +
6cf9271997-07-20Henrik Grubbström (Grubba)  "\">Disable that module</a> if you want this one instead</i>"
5b38191996-12-13Per Hedbor  "\n<p><br><p></blockquote>")});
fd0b6f1996-12-02Per Hedbor  } else {
5aab841997-08-21Henrik Grubbström (Grubba)  res += ({"<p><a href=\"/(addmodule)"+node->path(1)+"?"+q+"=1\">" "<img border=0 alt=\""+a[q][0]+"\" src=\"/auto/module/" + a[q][2]+"/"+q+"\" height=24 width=500>"
5b38191996-12-13Per Hedbor  "</a><blockquote><br>"+a[q][1]+"<p><br><p></blockquote>"});
b1fca01996-11-12Per Hedbor  }
fd0b6f1996-12-02Per Hedbor  }
9b9f701997-08-12Per Hedbor  return res*""+"</table>";
b1fca01996-11-12Per Hedbor } 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); }
799ed21997-08-13Per Hedbor string ot; object oT; object get_template(string t) {
931b581997-12-17Peter Bortas  t-=".pike";
799ed21997-08-13Per Hedbor  if(ot==t) return oT; ot=t;
931b581997-12-17Peter Bortas  return (oT = compile_file("server_templates/"+t+".pike")());
799ed21997-08-13Per Hedbor } int check_config_name(string name) { if(strlen(name) && name[-1] == '~') name = ""; if(search(name, "/")!= -1) return 1; foreach(roxen->configurations, object c) if(lower_case(c->name) == lower_case(name)) return 1; switch(name) { case " ": case "\t": case "CVS": case "Global Variables": case "global variables": case "Global variables": return 1; } return !strlen(name); }
b1fca01996-11-12Per Hedbor int low_enable_configuration(string name, string type) { object node;
799ed21997-08-13Per Hedbor  object o, o2, confnode; array(string) arr = replace(type,"."," ")/" ";
4814db1997-08-14Henrik Grubbström (Grubba)  object template;
b1fca01996-11-12Per Hedbor 
799ed21997-08-13Per Hedbor  if(check_config_name(name)) return 0;
b1fca01996-11-12Per Hedbor 
799ed21997-08-13Per Hedbor  if((type = lower_case(arr[0])) == "copy") { string from; mapping tmp; if ((sizeof(arr) > 1) && (sscanf(arr[1..]*" ", "%*s'%s'", from) == 2) && (tmp = roxen->copy_configuration(from, name))) {
4a04cc1997-12-13Henrik Grubbström (Grubba)  // FIXME: Should "../logs/" be hard-coded here?
799ed21997-08-13Per Hedbor  tmp["spider#0"]->LogFile = "../logs/" + roxenp()->short_name(name) + "/Log"; roxenp()->save_it(name); roxen->enable_configuration(name); } } else
4814db1997-08-14Henrik Grubbström (Grubba)  (template = get_template(type))->enable(roxen->enable_configuration(name));
b1fca01996-11-12Per Hedbor 
799ed21997-08-13Per Hedbor  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);
4814db1997-08-14Henrik Grubbström (Grubba)  if(template && template->post) template->post(node);
799ed21997-08-13Per Hedbor  if(o = node->descend( "Global", 1 )) { o->folded = 0; if(o2 = o->descend( "Listen ports", 1 )) { o2->folded = 0; o2->change(1); } } if(o = node->descend( "Filesystem", 1 )) { o->folded=0; if(o = o->descend( "0", 1)) { o->folded=0; if(o2 = o->descend( "Search path", 1)) { o2->folded=0; o2->change(1);
b1fca01996-11-12Per Hedbor  }
799ed21997-08-13Per Hedbor  if (o2 = o->descend("Handle the PUT method", 1)) {
ad63cc1997-07-06Henrik Grubbström (Grubba)  o2->folded = 0; o2->change(1); }
b1fca01996-11-12Per Hedbor  } } return 1; } mapping new_configuration(object id) { if(!sizeof(id->variables)) return stores(new_configuration_form());
0f28da1997-08-13Per Hedbor  if(id->variables->no) return http_redirect(roxen->config_url()+id->not_query[1..]+"?"+bar++);
b1fca01996-11-12Per Hedbor  if(!id->variables->name) return stores(default_head("Bad luck")+
38dca81996-12-10Per Hedbor  "<blockquote><h1>No configuration name?</h1>"
b1fca01996-11-12Per Hedbor  "Either you entered no name, or your WWW-browser "
19104e1996-12-07Per Hedbor  "failed to include it in the request</blockquote>");
b1fca01996-11-12Per Hedbor  id->variables->name=(replace(id->variables->name,"\000"," ")/" "-({""}))*" "; if(!low_enable_configuration(id->variables->name, id->variables->type)) return stores(default_head("Bad luck") +
38dca81996-12-10Per Hedbor  "<blockquote><h1>Illegal configuration name</h1>"
b1fca01996-11-12Per Hedbor  "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 "
19104e1996-12-07Per Hedbor  "configuration, and the character '/' cannot be included</blockquote>");
b1fca01996-11-12Per Hedbor  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;
953ca31997-08-18Per Hedbor  if(id->variables->nope) return std_redirect(root, id);
b1fca01996-11-12Per Hedbor  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; /* build_root(root);*/ // Should find the real node instead of assuming 'Globals'... 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); } }
5102f31998-03-08Henrik Grubbström (Grubba)  res = default_head("Welcome to Roxen Challenger " + roxen->__roxen_version__ + "." + roxen->__roxen_build__);
b1fca01996-11-12Per Hedbor 
e5bad21998-02-10Per Hedbor  res += Stdio.read_bytes("etc/welcome.html");
b1fca01996-11-12Per Hedbor  if(error && strlen(error))
38dca81996-12-10Per Hedbor  res += "<blockquote>\n<p><b>"+error+"</b>";
b1fca01996-11-12Per Hedbor 
953ca31997-08-18Per Hedbor  res += ("<table border=0 bgcolor=black><tr><td><table cellspacing=0 border=0 cellpadding=3 bgcolor=#e0e0ff>" "<tr><td colspan=2><center><h1>Please complete this form.</h1></center>" "</td></tr>"
2adfdf1997-08-13Per Hedbor  "<form action=\"/(initial)/Globals/\">"
953ca31997-08-18Per Hedbor  "<tr><td align=right>User name</td><td><input name=user type=string></td></tr>\n" "<tr><td align=right>Password</td><td><input name=pass type=password></td></tr>\n" "<tr><td align=right>Again</td><td><input name=pass2 type=password></td></tr>\n"
f92b7a1997-05-26Henrik Grubbström (Grubba) // Avoid this trap for people who like to shoot themselves in the foot.
c6d6a71996-12-02Peter Bortas // /Peter // "IP-pattern <input name=pattern type=string>\n"
953ca31997-08-18Per Hedbor  "<tr><td align=left><input type=submit value=\" Ok \">\n</td>" "<td align=right><input type=submit name=nope value=\" Cancel \"></td></tr>\n" "</form></table></table></blockquote>");
b1fca01996-11-12Per Hedbor  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) {
1e257d1996-12-03Per Hedbor  if(!node) return ""; for(;node && (node->up!=root);node=node->up); if(!node) return "";
b1fca01996-11-12Per Hedbor  return node->path(1); }
1e257d1996-12-03Per Hedbor  string tablist(array(string) nodes, array(string) links, int selected) { array res = ({}); for(int i=0; i<sizeof(nodes); i++) if(i!=selected)
f320281997-05-28Per Hedbor  PUSH("<a href=\""+links[i]+"\"><img alt=\"_/"+
2adfdf1997-08-13Per Hedbor  nodes[i][0..strlen(nodes[i])-1]+"\\__\" src=\"/auto/unselected/"+ replace(nodes[i]," ","%20")+"\" border=0></a>");
1e257d1996-12-03Per Hedbor  else
f320281997-05-28Per Hedbor  PUSH("<a href=\""+links[i]+"\"><b><img alt=\"_/"+
2adfdf1997-08-13Per Hedbor  nodes[i][0..strlen(nodes[i])-1]+"\\__\" src=\"/auto/selected/"+ replace(nodes[i]," ","%20")+"\" border=0></b></a>");
f320281997-05-28Per Hedbor //PUSH("<br>");
1e257d1996-12-03Per Hedbor  return res*""; }
b1fca01996-11-12Per Hedbor mapping (string:string) selected_nodes = ([ "Configurations":"/Configurations", "Globals":"/Globals", "Errors":"/Errors",
00aff81997-08-12Per Hedbor  "Actions":"/Actions",
1e257d1996-12-03Per Hedbor ]);
b1fca01996-11-12Per Hedbor 
5e89211997-02-13Per Hedbor array tabs = ({
1e257d1996-12-03Per Hedbor  "Configurations", "Globals", "Errors",
00aff81997-08-12Per Hedbor  "Actions",
b1fca01996-11-12Per Hedbor });
5e89211997-02-13Per Hedbor array tab_names = ({
00aff81997-08-12Per Hedbor  "Virtual Servers",
a150341997-08-12David Hedbor  "Global Variables", "Event Log",
00aff81997-08-12Per Hedbor  "Actions",
1e257d1996-12-03Per Hedbor });
b1fca01996-11-12Per Hedbor  string display_tabular_header(object node) { string p, s;
8885dd1997-08-24Peter Bortas  array links = Array.map(tabs, lambda(string q) { return selected_nodes[q]+"?"+(bar++);
1e257d1996-12-03Per Hedbor  });
f320281997-05-28Per Hedbor  if(node != root) { s = extract_almost_top(node) - "/"; selected_nodes[s] = node->path(1); links[search(tabs,s)]="/"+s+"/"+"?"+(bar++); }
1e257d1996-12-03Per Hedbor  return tablist(tab_names, links, search(tabs,s));
b1fca01996-11-12Per Hedbor } // Return the number of unfolded nodes on the level directly below the passed // node. int nunfolded(object o) { int i; if(o = o->down) do { i+=!o->folded; } while(o=o->next); return i; }
fd0b6f1996-12-02Per Hedbor 
5e89211997-02-13Per Hedbor 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);
a9d8af1997-11-07Mirar (Pontus Hagland) mapping(string:object) my_colortable = ([]);
fd0b6f1996-12-02Per Hedbor  mapping auto_image(string in, object id) { string key, value;
1e257d1996-12-03Per Hedbor  array trans = ({ (int)("0x"+dR),(int)("0x"+dG),(int)("0x"+dB) });
fd0b6f1996-12-02Per Hedbor  mapping r; mixed e;
1e257d1996-12-03Per Hedbor  object i;
f320281997-05-28Per Hedbor  string img_key = "auto/"+replace(in,"/","_")+".gif"-" "; if(e=file_image(img_key)) return e;
a6cdc51996-12-04Per Hedbor  if(!sscanf(in, "%s/%s", key, value)) key=in;
1e257d1996-12-03Per Hedbor 
fd0b6f1996-12-02Per Hedbor  switch(key) { case "module":
8691921997-06-12Henrik Grubbström (Grubba)  sscanf(value, "%*d/%s", value); i = draw_module_header(roxen->allmodules[value][0], roxen->allmodules[value][2], module_font); break;
1e257d1996-12-03Per Hedbor 
fdee9d1996-12-02Per Hedbor  case "button":
8691921997-06-12Henrik Grubbström (Grubba)  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;
1e257d1996-12-03Per Hedbor  case "fold": case "fold2":
8691921997-06-12Henrik Grubbström (Grubba)  i = draw_fold((int)reverse(key)); break;
1e257d1996-12-03Per Hedbor  case "unfold": case "unfold2":
8691921997-06-12Henrik Grubbström (Grubba)  i = draw_unfold((int)reverse(key)); break;
1e257d1996-12-03Per Hedbor  case "back":
8691921997-06-12Henrik Grubbström (Grubba)  i = draw_back((int)reverse(key)); break;
1e257d1996-12-03Per Hedbor  case "selected":
8691921997-06-12Henrik Grubbström (Grubba)  i=draw_selected_button(value,button_font); break;
fdee9d1996-12-02Per Hedbor 
1e257d1996-12-03Per Hedbor  case "unselected":
8691921997-06-12Henrik Grubbström (Grubba)  i=draw_unselected_button(value,button_font); break;
fd0b6f1996-12-02Per Hedbor  }
a9d8af1997-11-07Mirar (Pontus Hagland)  if (!i) return 0; object ct; if (!(ct=my_colortable[key]))
3d8e641998-02-05Henrik Grubbström (Grubba)  ct=my_colortable[key]=Image.colortable(i,256,4,4,4);
a9d8af1997-11-07Mirar (Pontus Hagland) // colortable(4,4,8, // ({0,0,0}),({255,255,0}),16, // ({0,0,0}),({170,170,255}),48, // ) object o = open("roxen-images/"+img_key,"wct");
3d8e641998-02-05Henrik Grubbström (Grubba)  e=Image.GIF.encode(i,ct);
a9d8af1997-11-07Mirar (Pontus Hagland)  i=0; if(o) { o->write(e); o=0; }
f320281997-05-28Per Hedbor #ifdef DEBUG
a9d8af1997-11-07Mirar (Pontus Hagland)  else {perror("Cannot open file for "+in+"\n");}
f320281997-05-28Per Hedbor #endif
a9d8af1997-11-07Mirar (Pontus Hagland)  return http_string_answer(e,"image/gif");
fd0b6f1996-12-02Per Hedbor }
fdee9d1996-12-02Per Hedbor 
b2c3871996-12-04Per Hedbor string remove_font(string t, mapping m, string c) { return "<b>"+c+"</b>"; }
ae32fc1996-12-05Per Hedbor 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; }
9b9f701997-08-12Per Hedbor string dn(object node) { if(!node) return "???";
2adfdf1997-08-13Per Hedbor  string s = sizeof(node->_path)?node->_path[-1]:" ";
9b9f701997-08-12Per Hedbor  if(((string)((int)s))==s) return "Instance "+s;
00aff81997-08-12Per Hedbor  switch(s) { case "Globals": return "Global Variables"; case "Configurations": return "Servers"; case "Errors":
a150341997-08-12David Hedbor  return "Event Log";
00aff81997-08-12Per Hedbor  }
9b9f701997-08-12Per Hedbor  return s; } string describe_node_path(object node) { string q="", res=""; int cnt; foreach(node->path(1)/"/", string p) { q+=p+"/";
00aff81997-08-12Per Hedbor  if(cnt>0)
9b9f701997-08-12Per Hedbor  { // werror("q="+q+"\n");
62d8c41997-10-16Per Hedbor  res += ("\n<b><a href=\""+q+"?"+bar+++"\">"+
2adfdf1997-08-13Per Hedbor  dn(find_node(http_decode_string(q[..strlen(q)-2])))+
62d8c41997-10-16Per Hedbor  "</a></b> -&gt;\n");
9b9f701997-08-12Per Hedbor  } else cnt++; } return res[0..strlen(res)-8]; } string status_row(object node) {
62d8c41997-10-16Per Hedbor  return ("<table width=\"100%\" border=0 cellpadding=0"
84b6331997-08-14Henrik Grubbström (Grubba)  " cellspacing=0>\n"
62d8c41997-10-16Per Hedbor  "<tr><td valign=bottom align=left><a href=\"$docurl"+
953ca31997-08-18Per Hedbor  node->path(1)+"\">" "<img border=0 src=\"/image/roxen-icon-gray.gif\" alt=\"\"></a>"
62d8c41997-10-16Per Hedbor  "</td>\n<td>&nbsp;</td><td width=100% height=39>" "<table cellpadding=0 cellspacing=0 width=100% border=0>\n" "<tr width=\"100%\">\n"
99af2a1997-10-18Henrik Grubbström (Grubba)  "<td width=\"100%\" align=right valigh=center height=28>"
62d8c41997-10-16Per Hedbor  +describe_node_path(node)+"</td>" "</tr><tr width=\"100%\">" "<td bgcolor=\"#003366\" align=right height=12 width=\"100%\">"
f6d0031998-02-21Fredrik Noring  "<font color=white size=-2>Administration Interface" "&nbsp;&nbsp;</font></td></tr></table></td>"
99af2a1997-10-18Henrik Grubbström (Grubba)  "\n</tr>\n</table><br>");
9b9f701997-08-12Per Hedbor }
00aff81997-08-12Per Hedbor mapping logged = ([ ]); void check_login(object id) {
92653c1997-10-12Henrik Grubbström (Grubba)  if(logged[id->remoteaddr] + 1000 < time()) { report_notice("Administrator logged on from " + roxen->blocking_ip_to_host(id->remoteaddr) + "."); } logged[id->remoteaddr] = time(1);
00aff81997-08-12Per Hedbor }
ae32fc1996-12-05Per Hedbor 
b1fca01996-11-12Per Hedbor mapping configuration_parse(object id) {
fdee9d1996-12-02Per Hedbor  array (string) res=({}); string tmp;
b1fca01996-11-12Per Hedbor  // Is it an image?
fdee9d1996-12-02Per Hedbor  if(sscanf(id->not_query, "/image/%s", tmp)) return file_image(tmp) || (["data":"No such image"]);
b1fca01996-11-12Per Hedbor  object o; int i; id->since = 0; // We do not want 'get-if-modified-since' to work here. // Permisson denied by address? if(id->remoteaddr) if(strlen(roxen->QUERY(ConfigurationIPpattern)) &&
5e4ede1996-11-12Per Hedbor  !glob(roxen->QUERY(ConfigurationIPpattern),id->remoteaddr))
b1fca01996-11-12Per Hedbor  return stores("Permission denied.\n"); // Permission denied by userid? if(!id->misc->read_allow) { if(!(strlen(roxen->QUERY(ConfigurationPassword)) && strlen(roxen->QUERY(ConfigurationUser)))) return initial_configuration(id); // Never configured before else if(!conf_auth_ok(id->auth)) return http_auth_failed("Roxen server maintenance"); // Denied } else {
5e4ede1996-11-12Per Hedbor  id->prestate = aggregate_multiset(@indices(id->prestate) &({"fold","unfold"}));
b1fca01996-11-12Per Hedbor  if(sizeof(id->variables)) // This is not 100% neccesary, really. id->variables = ([ ]); }
f320281997-05-28Per Hedbor  // Automatically generated image?
fdee9d1996-12-02Per Hedbor  if(sscanf(id->not_query, "/auto/%s", tmp)) return auto_image(tmp,id) || (["data":"No such image"]);
fd0b6f1996-12-02Per Hedbor 
b1fca01996-11-12Per Hedbor  o = find_node(id->not_query); // Find the requested node (from the filename) if(!o) // Bad node, perhaps an old bookmark or something. { id->referer = ({ }); return std_redirect(0, id); } else if(o == root) { // The URL is http://config-url/, not one of the top nodes, but // _above_ them. This is supposed to be some nice introductory // text about the configuration interface...
5f43491997-12-15Henrik Grubbström (Grubba)  // We also need to determine wether this is the full or the // lobotomized international version. int full_version=0; catch { if (sizeof(indices(master()->resolv("_Crypto")))) { full_version = 1; } };
5102f31998-03-08Henrik Grubbström (Grubba)  return http_string_answer(default_head("Roxen Challenger " + roxen->__roxen_version__ + "." + roxen->__roxen_build__)+
4a83271997-08-12Per Hedbor  status_row(root)+
5e89211997-02-13Per Hedbor  display_tabular_header(root)+
e5bad21998-02-10Per Hedbor  Stdio.read_bytes(full_version?"etc/config.html":
5f43491997-12-15Henrik Grubbström (Grubba)  "etc/config.int.html"), "text/html");
b1fca01996-11-12Per Hedbor  } if(sizeof(id->prestate)) { switch(indices(id->prestate)[0]) { // It is possible to mark variables as 'VAR_EXPERT', this // will make it impossible to configure them whithout the // 'expert' mode. It can be useful. case "expert": expert_mode = 1; break; case "noexpert": expert_mode = 0; break;
9b9f701997-08-12Per Hedbor 
0f28da1997-08-13Per Hedbor  case "morevars": more_mode = 1; save_more_mode(); break; case "nomorevars": more_mode = 0; save_more_mode(); break;
b1fca01996-11-12Per Hedbor  // Fold and unfold nodes, this is _very_ simple, once all the // supporting code was writte. case "fold": o->folded=1; break; case "unfold": o->folded=0; break;
676c231996-12-06Per Hedbor  case "moredocs": o->moredocs=1; break; case "lessdocs": o->moredocs=0; break;
b1fca01996-11-12Per Hedbor  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; // There is no button for this in the configuration interface, // the results are quite horrible, especially when applied to // one of the top nodes. case "unfoldall": o->map(lambda(object o) { o->folded=0; }); break;
ae32fc1996-12-05Per Hedbor  case "unfoldlevel": object node; node=o->down; while(node) { node->folded=0; node = node->next; } break;
b1fca01996-11-12Per Hedbor  // And now the actual actions.. // Re-read a module from disk // This is _not_ as easy as it sounds, since quite a lot of
17495a1997-06-02Henrik Grubbström (Grubba)  // caches and stuff have to be invalidated..
b1fca01996-11-12Per Hedbor  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");
14179b1997-01-29Per Hedbor  name = module_short_name(mod, o->config());
b1fca01996-11-12Per Hedbor  if(!name) error("This module cannot be updated"); sscanf(name, "%s#%*s", modname);
14179b1997-01-29Per Hedbor 
b1fca01996-11-12Per Hedbor  if(!(cmod = o->config()->modules[ modname ])) error("This module cannot be updated"); o->save();
f3edef1998-02-17Martin Stjernholm  program oldprg = cache_lookup ("modules", modname); mapping oldprgs = copy_value (master()->programs);
b1fca01996-11-12Per Hedbor  cache_remove("modules", modname);
f2549a1997-06-09Henrik Grubbström (Grubba) 
43191e1997-09-07Henrik Grubbström (Grubba)  // Not useful since load_module() also does it.
f2549a1997-06-09Henrik Grubbström (Grubba)  // _master->set_inhibit_compile_errors("");
b1fca01996-11-12Per Hedbor 
14179b1997-01-29Per Hedbor  if(!o->config()->load_module(modname))
b1fca01996-11-12Per Hedbor  { mapping rep; rep = http_string_answer("The reload of this module failed.\n" "This is (probably) the reason:\n<pre>"
f2549a1997-06-09Henrik Grubbström (Grubba)  + roxen->last_error + "</pre>" ); // _master->set_inhibit_compile_errors(0);
b1fca01996-11-12Per Hedbor  return rep; }
f3edef1998-02-17Martin Stjernholm  program newprg = cache_lookup ("modules", modname);
f2549a1997-06-09Henrik Grubbström (Grubba)  // _master->set_inhibit_compile_errors(0);
b1fca01996-11-12Per Hedbor  object mod;
f3edef1998-02-17Martin Stjernholm  if(!o->config()->disable_module(name)) { mapping rep; rep = http_string_answer("Failed to disable this module.\n" "This is (probably) the reason:\n<pre>" + roxen->last_error + "</pre>" ); return rep; } cache_set ("modules", modname, newprg); // Do not compile again in enable_module. if(!(mod=o->config()->enable_module(name))) { mapping rep; rep = http_string_answer("Failed to enable this module.\n" "This is (probably) the reason:\n<pre>" + roxen->last_error + "</pre>" ); // Recover.. master()->programs = oldprgs; cache_set ("modules", modname, oldprg); #ifdef MODULE_DEBUG perror ("Modules: Trying to re-enable the old module.\n"); #endif o->config()->enable_module(name); return rep; }
b1fca01996-11-12Per Hedbor  o->clear();
14179b1997-01-29Per Hedbor // roxen->fork_it();
b1fca01996-11-12Per Hedbor  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; /* Shutdown Roxen... */ case "shutdown": return roxen->shutdown(); /* Restart Roxen, somewhat more nice. */ case "restart": return roxen->restart(); /* Rename a configuration. Not Yet Used... */ case "rename": if(o->type == NODE_CONFIGURATION) { mv("configurations/"+o->data->name, "configurations/"+id->variables->name); o->data->name=id->variables->name; } break; /* This only asks "do you really want to...", it does not delete * the node */ case "delete":
4a83271997-08-12Per Hedbor  PUSH(default_head("Roxen Configuration")+
38a83c1997-08-12Per Hedbor  status_row(o));
1e257d1996-12-03Per Hedbor // PUSH("<hr noshade>");
38a83c1997-08-12Per Hedbor 
b1fca01996-11-12Per Hedbor  switch(o->type) { case NODE_CONFIGURATION:
2adfdf1997-08-13Per Hedbor  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>");
b1fca01996-11-12Per Hedbor  break; case NODE_MODULE_MASTER_COPY: case NODE_MODULE:
45165f1997-08-13Peter Bortas  PUSH("<font size=\"+2\">Do you really want to delete the module "+
fdee9d1996-12-02Per Hedbor  o->data->name + ", and its copies?\n\n<p></font>");
b1fca01996-11-12Per Hedbor  break; case NODE_MODULE_COPY_VARIABLES: case NODE_MODULE_COPY:
45165f1997-08-13Peter Bortas  PUSH("<font size=\"+2\">Do you really want to delete this copy "
fdee9d1996-12-02Per Hedbor  " of the module "+ o->up->data->name + "?\n\n<p></font>");
b1fca01996-11-12Per Hedbor  break; case NODE_CONFIGURATIONS: return stores("You don't want to do that...\n"); }
cb882f1997-08-13Peter Bortas  PUSH("<blockquote><font size=\"+2\"><i>This action cannot be" " undone.\n\n<p></font>"+ TABLEP("<table>", "")+ "<tr><td><form action=\""+ o->path(1)+"\">"
fdee9d1996-12-02Per Hedbor  "<input type=submit value=\"No, I do not want to delete it\"> "
cb882f1997-08-13Peter Bortas  "</form></td><td><form action=\"/(really_delete)"+ o->path(1)+
2adfdf1997-08-13Per Hedbor  "\"><input type=submit value=\"Go ahead\"></form></td></tr> "
19104e1996-12-07Per Hedbor  "</table></blockquote>");
b1fca01996-11-12Per Hedbor 
fdee9d1996-12-02Per Hedbor  return stores(res*"");
b1fca01996-11-12Per Hedbor  break; /* When this has been called, the node will be * _very_ deleted * The amount of work needed to delete a node does vary * depending on the node, since there is no 'zap' function in * the nodes at the moment. I will probably move this code into * function-pointers in the nodes. */ 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)
e5bad21998-02-10Per Hedbor  Array.map(values(roxen->configurations[i]->ports_open), destruct);
b1fca01996-11-12Per Hedbor  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: // Ehum? Lets zap the module instead of it's variables... o=o->up; case NODE_MODULE_COPY: string name; object n;
14179b1997-01-29Per Hedbor  name = module_short_name(o->data, o->config());
f2f72b1997-02-07Niels Möller  o->config()->disable_module(name);
b1fca01996-11-12Per Hedbor  // Remove the suitable part of the configuration file.
f2f72b1997-02-07Niels Möller  roxen->remove(name, o->config());
b1fca01996-11-12Per Hedbor  o->change(-o->changed); n=o->up; o->dest(); if(!objectp(n)) { o=root; // Error, really, no parent module for this module class. } else { if(!sizeof(n->data->copies)) { // No more instances in this module, let's zap the whole class. 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--) {
14179b1997-01-29Per Hedbor  o->config()->disable_module(name+"#"+a[i]); roxen->remove(name+"#"+a[i], o->config());
b1fca01996-11-12Per Hedbor  } } else if(o->data->master) { name=o->config()->otomod[o->data->enabled]; } } else if(o->data->enabled) { name=o->config()->otomod[o->data->enabled];
14179b1997-01-29Per Hedbor  o->config()->disable_module(name+"#0"); roxen->remove(name+"#0", o->config());
b1fca01996-11-12Per Hedbor  } o->change(-o->changed); o->dest(); break; } break; // Create a new configuration. All the work is done in another // function.. This _should_ be the case with some of the other // actions too. case "newconfig": id->referer = ({ CONFIG_URL + o->path(1) }); return new_configuration(id);
c0863e1997-08-12David Hedbor  // When a port has been changed the admin are prompted to // change the server URL. This is where we come when we are // done. case "modify_server_url": string srv, url; object thenode; foreach(indices(id->variables), string var) { if(sscanf(var, "%s->own", srv)) { url = id->variables[srv] == "own" ? id->variables[var] : id->variables[srv];
da42a51997-08-12David Hedbor  if(srv == "Global Variables") thenode = find_node("/Globals/Configuration interface/URL"); else thenode = find_node("/Configurations/"+srv+ "/Global/Server URL");
c0863e1997-08-12David Hedbor  if(thenode) { thenode->data[VAR_VALUE] = url; thenode->change(1); thenode->up->save();
da42a51997-08-12David Hedbor  }
c0863e1997-08-12David Hedbor  } }
da42a51997-08-12David Hedbor  id->referer = ({ CONFIG_URL + o->path(1) });
c0863e1997-08-12David Hedbor  break; // Save changes done to the node 'o'. Currently 'o' is the root // node most of the time, thus saving _everything_.
b1fca01996-11-12Per Hedbor  case "save":
c0863e1997-08-12David Hedbor  mapping cf; if(cf = save_it(id, o)) return cf;
b1fca01996-11-12Per Hedbor  break; // Set the password and username, the first time, or when // the action 'changepass' is requested. case "initial": case "changepass": return initial_configuration(id); // Hmm. No idea, really. Beats me :-) /Per case "new": o->new(); break; // Add a new module to the current configuration.
7090fb1997-08-04Henrik Grubbström (Grubba)  case "newmodule": // For backward compatibility case "addmodule":
b1fca01996-11-12Per Hedbor  id->referer = ({ CONFIG_URL + o->path(1) }); return new_module(id,o); // Add a new copy of the current module to the current configuration. case "newmodulecopy": id->referer = ({ CONFIG_URL + o->path(1) }); new_module_copy_copy(o, id); break; // Set a variable to a new (or back to an old..) value. 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); }
00aff81997-08-12Per Hedbor  check_login(id);
b1fca01996-11-12Per Hedbor 
9b9f701997-08-12Per Hedbor  PUSH(default_head("Roxen server configuration")); // PUSH("<table><tr><td>&nbsp;<td>"
2adfdf1997-08-13Per Hedbor  PUSH("<dl>\n");
9b9f701997-08-12Per Hedbor  PUSH("\n"+status_row(o)+"\n"+display_tabular_header( o )+"\n");
676c231996-12-06Per Hedbor  PUSH("<p>"); if(o->up != root && o->up)
fdee9d1996-12-02Per Hedbor  PUSH("<a href=\""+ o->up->path(1)+"?"+(bar++)+"\">"
2adfdf1997-08-13Per Hedbor  "<img src=/auto/back alt=\"[Up]\" align=left hspace=0 border=0></a>\n");
b1fca01996-11-12Per Hedbor  if(i=o->folded) o->folded=0;
00aff81997-08-12Per Hedbor  mixed tmp = o->describe(1,id); if(mappingp(tmp)) return tmp;
b2c3871996-12-04Per Hedbor  if(!id->supports->font) tmp = parse_html(tmp, ([]),(["font":remove_font, ]));
cb882f1997-08-13Peter Bortas  PUSH("<dl><dt>");
b2c3871996-12-04Per Hedbor  PUSH(tmp);
cb882f1997-08-13Peter Bortas  PUSH("</dl>");
b1fca01996-11-12Per Hedbor  o->folded=i;
e439c01996-12-10Per Hedbor  PUSH("<p><br clear=all>&nbsp;\n");
a6cdc51996-12-04Per Hedbor  int lm=1;
4814db1997-08-14Henrik Grubbström (Grubba)  array(mixed) buttons = ({});
b1fca01996-11-12Per Hedbor  if(o->type == NODE_CONFIGURATIONS)
fdee9d1996-12-02Per Hedbor  BUTTON(newconfig, "New virtual server", left);
b1fca01996-11-12Per Hedbor  if(o->type == NODE_CONFIGURATION)
7090fb1997-08-04Henrik Grubbström (Grubba)  BUTTON(addmodule, "Add module", left);
b1fca01996-11-12Per Hedbor  if(o->type == NODE_MODULE) {
5b38191996-12-13Per Hedbor  BUTTON(delete, "Delete module", left);
b1fca01996-11-12Per Hedbor  if(o->data->copies)
1e257d1996-12-03Per Hedbor  BUTTON(newmodulecopy, "Copy module", left);
b1fca01996-11-12Per Hedbor  } i=0; if(o->type == NODE_MODULE_MASTER_COPY || o->type == NODE_MODULE_COPY || o->type == NODE_MODULE_COPY_VARIABLES) {
5b38191996-12-13Per Hedbor  BUTTON(delete, "Delete module", left);
0f28da1997-08-13Per Hedbor  if(more_mode) BUTTON(refresh, "Reload module", left);
b1fca01996-11-12Per Hedbor  } if(o->type == NODE_CONFIGURATION)
a6cdc51996-12-04Per Hedbor  BUTTON(delete,"Delete this server", left);
b1fca01996-11-12Per Hedbor 
fdee9d1996-12-02Per Hedbor  if(nunfolded(o))
ae32fc1996-12-05Per Hedbor  BUTTON(foldall, "Fold all",left);
b1fca01996-11-12Per Hedbor  if(o->changed)
ae32fc1996-12-05Per Hedbor  BUTTON(unfoldmodified, "Unfold modified", left); if(nfolded(o)) BUTTON(unfoldlevel, "Unfold level", left);
38dca81996-12-10Per Hedbor // else if(nfoldedr(o)) // BUTTON(unfoldall, "Unfold all", left);
ae32fc1996-12-05Per Hedbor 
4814db1997-08-14Henrik Grubbström (Grubba)  PUSH_BUTTONS(1);
b1fca01996-11-12Per Hedbor 
4a83271997-08-12Per Hedbor  if(!more_mode)
13ff621997-08-12Per Hedbor  BUTTON(morevars, "More options", left);
4a83271997-08-12Per Hedbor  else
13ff621997-08-12Per Hedbor  BUTTON(nomorevars, "Fewer options", left);
4a83271997-08-12Per Hedbor 
1e257d1996-12-03Per Hedbor  if((o->changed||root->changed))
a6cdc51996-12-04Per Hedbor  BUTTON(save, "Save", left);
8662771997-08-12Per Hedbor // BUTTON(restart, "Restart", left); // BUTTON(shutdown,"Shutdown", left);
1e257d1996-12-03Per Hedbor 
4814db1997-08-14Henrik Grubbström (Grubba)  PUSH_BUTTONS(0);
0f28da1997-08-13Per Hedbor // PUSH("<br clear=all>");
45165f1997-08-13Peter Bortas // PUSH("<p align=right><font size=-1 color=blue><a href=\"$docurl\"><font color=blue>"+roxen->real_version +"</font></a></font></p>");
9b9f701997-08-12Per Hedbor // PUSH("</table>");
b2c3871996-12-04Per Hedbor  PUSH("</body>\n");
fdee9d1996-12-02Per Hedbor  return stores(res*"");
b1fca01996-11-12Per Hedbor }