2d5b1e2000-03-07Henrik Grubbström (Grubba) /*
0917d32013-03-04Anders Johansson  * $Id$
2d5b1e2000-03-07Henrik Grubbström (Grubba)  *
4ce9102000-03-28Henrik Grubbström (Grubba)  * Create an initial administration interface server.
2d5b1e2000-03-07Henrik Grubbström (Grubba)  */
cd03b41999-11-22Per Hedbor int mkdirhier(string from) { string a, b; array f; f=(from/"/"); b=""; foreach(f[0..sizeof(f)-2], a) { mkdir(b+a); b+=a+"/"; } }
de61f22000-08-29Fredrik Noring class Readline { inherit Stdio.Readline; void trap_signal(int n) { werror("Interrupted, exit.\r\n"); destruct(this_object()); exit(1); } void destroy() { get_input_controller()->dumb = 0; ::destroy(); signal(signum("SIGINT")); }
bdf9822000-08-29Fredrik Noring  private string safe_value(string r)
de61f22000-08-29Fredrik Noring  {
bdf9822000-08-29Fredrik Noring  if(!r) { /* C-d? */ werror("\nTerminal closed, exit.\n"); destruct(this_object()); exit(1); } return r;
de61f22000-08-29Fredrik Noring  }
bdf9822000-08-29Fredrik Noring  string read(mixed ... args) { return safe_value(::read(@args));
de61f22000-08-29Fredrik Noring  } string edit(mixed ... args) {
bdf9822000-08-29Fredrik Noring  return safe_value(::edit(@args));
de61f22000-08-29Fredrik Noring  } void create(mixed ... args) { signal(signum("SIGINT"), trap_signal); ::create(@args); } }
829fea2017-09-27Henrik Grubbström (Grubba) mapping(string:string) batch; string read_string(Readline rl, string prompt, string|void batch_symbol, string|void def)
0b7c642000-08-28Marcus Comstedt {
829fea2017-09-27Henrik Grubbström (Grubba)  string res; if (batch && batch_symbol) { res = batch[batch_symbol] || def; if (res) return res; } res = rl->edit(def || "", prompt+" ", ({ "bold" }));
0b7c642000-08-28Marcus Comstedt  if( def && !strlen(res-" ") ) res = def; return res; }
cd03b41999-11-22Per Hedbor 
0d0a042013-03-11Henrik Grubbström (Grubba) #if constant(Crypto.Password) constant hash_password = Crypto.Password.hash; #else constant hash_password = Crypto.make_crypt_md5; #endif
cd03b41999-11-22Per Hedbor int main(int argc, array argv) {
de61f22000-08-29Fredrik Noring  Readline rl = Readline();
5e323e2017-09-28Henrik Grubbström (Grubba)  string name = "Administration Interface"; string user = "administrator"; string password, configdir, port;
cd03b41999-11-22Per Hedbor  string passwd2;
7f1f652002-03-20Henrik Grubbström (Grubba) #if constant( SSL )
cd03b41999-11-22Per Hedbor  string def_port = "https://*:"+(random(20000)+10000)+"/"; #else string def_port = "http://*:"+(random(20000)+10000)+"/"; #endif
22c3652001-11-07Henrik Grubbström (Grubba)  //werror("Argv: ({%{%O, %}})\n", argv);
f1b6592001-10-16Martin Nilsson  if(has_value(argv, "--help")) { write(#" Creates and initializes a Roxen WebServer configuration interface. Arguments: -d dir The location of the configuration interface. Defaults to \"../configurations\". -a Only create a new administration user.
829fea2017-09-27Henrik Grubbström (Grubba)  Useful when the administration password is lost.
f1b6592001-10-16Martin Nilsson  --help Displays this text. --batch Create a configuration interface in batch mode.
09c8f02017-09-28Henrik Grubbström (Grubba)  The --batch argument should be followed by an optional list of value pairs, each pair representing the name of a question field and the value to be filled in. Available fields:
f1b6592001-10-16Martin Nilsson  server_name The name of the server. Defaults to \"Administration Interface\".
829fea2017-09-27Henrik Grubbström (Grubba)  server_url The server url, e.g. \"http://*:1234/\". Defaults to \"https://*:22202/\" in batch mode.
f1b6592001-10-16Martin Nilsson  user The name of the administrator. Defaults to \"administrator\". password The administrator password.
92a8d22017-09-28Henrik Grubbström (Grubba)  NB: No default; if not specified, no administration user will be created.
829fea2017-09-27Henrik Grubbström (Grubba)  ok Require interactive user confirmation of the above information with the value pair \"ok n\".
f1b6592001-10-16Martin Nilsson 
829fea2017-09-27Henrik Grubbström (Grubba) Example of batch installation with interactive password entry:
f1b6592001-10-16Martin Nilsson 
829fea2017-09-27Henrik Grubbström (Grubba)  ./create_configinterface --batch server_name Admin server_url \\ http://*:8080/ ok y user admin
f1b6592001-10-16Martin Nilsson  "); return 0; }
cd03b41999-11-22Per Hedbor  configdir = Getopt.find_option(argv, "d",({"config-dir","configuration-directory" }),
62d9572000-02-04Per Hedbor  ({ "ROXEN_CONFIGDIR", "CONFIGURATIONS" }),
cd03b41999-11-22Per Hedbor  "../configurations");
cbc7ea2000-02-19Martin Nilsson  int admin = has_value(argv, "-a");
cd03b41999-11-22Per Hedbor 
e650a92001-12-17Anders Johansson // werror("Admin mode: %O\n" // "Argv: ({%{%O, %}})\n", admin, argv);
22c3652001-11-07Henrik Grubbström (Grubba) 
0b7c642000-08-28Marcus Comstedt  int batch_args = search(argv, "--batch"); if(batch_args>=0)
09c8f02017-09-28Henrik Grubbström (Grubba)  batch = (mapping)(argv[batch_args+1..]/2);
0b7c642000-08-28Marcus Comstedt 
829fea2017-09-27Henrik Grubbström (Grubba)  if (batch) { if (!batch->server_url) { batch->server_url = "https://*:22202/"; } if (batch["__semicolon_separated__"]) { // Used by Win32Installer.vbs:CreateConfigInterface(). array(string) sections = batch["__semicolon_separated__"]/";"; if (sizeof(sections) < 6) { error("Too few sections in __semicolon_separated__: %O.\n", batch["__semicolon_separated__"]); } cd(sections[0]); // SERVERDIR batch->server_name = sections[1]; // SERVER_NAME batch->server_url = sprintf("%s://*:%s/", sections[2], // SERVER_PROTOCOL sections[3]); // SERVER_PORT batch->user = sections[4]; // ADM_USER batch->password = sections[5..]*";"; // ADM_PASS1
ff1f9e2005-02-25Henrik Grubbström (Grubba)  } }
88ee352000-03-27Per Hedbor  foreach( get_dir( configdir )||({}), string cf ) catch {
440cf82000-03-31Martin Nilsson  if( cf[-1]!='~' && search( Stdio.read_file( configdir+"/"+cf ),
88ee352000-03-27Per Hedbor  "'config_filesystem#0'" ) != -1 ) {
89f8112001-08-31Fredrik Noring  string server_version = Stdio.read_file("VERSION"); if(server_version) Stdio.write_file(configdir+"/server_version","server-"+server_version);
de61f22000-08-29Fredrik Noring  werror(" There is already an administration interface present in " "this\n server. A new one will not be created.\n");
c9b3b32017-09-28Henrik Grubbström (Grubba)  if(!admin++) exit( 1 );
88ee352000-03-27Per Hedbor  } };
c9b3b32017-09-28Henrik Grubbström (Grubba)  if(admin==1) {
de61f22000-08-29Fredrik Noring  werror(" No administration interface was found. A new one will be created.\n");
c9b3b32017-09-28Henrik Grubbström (Grubba)  admin = 0; }
cbc7ea2000-02-19Martin Nilsson  if(configdir[-1] != '/')
46132e1999-11-26Honza Petrous  configdir+="/";
cbc7ea2000-02-19Martin Nilsson  if(admin)
de61f22000-08-29Fredrik Noring  write( " Creating an administrator user.\n\n" );
cbc7ea2000-02-19Martin Nilsson  else
eed5792000-08-31Fredrik Noring  write( " Creating an administration interface server in\n"+ " "+combine_path(getcwd(), configdir)+".\n");
cd03b41999-11-22Per Hedbor 
62d9572000-02-04Per Hedbor  do
cd03b41999-11-22Per Hedbor  {
1e8c602000-09-06Fredrik Noring  password = passwd2 = 0;
b1f3e92000-04-03Per Hedbor  if(!admin) {
de61f22000-08-29Fredrik Noring  write("\n");
5e323e2017-09-28Henrik Grubbström (Grubba)  do { if (!sizeof(name)) name = "Administration Interface"; name = read_string(rl, "Server name:", "server_name", name); if (batch) m_delete(batch, "server_name"); } while (!sizeof(name));
cd03b41999-11-22Per Hedbor 
b1f3e92000-04-03Per Hedbor  int port_ok; while( !port_ok ) {
5e323e2017-09-28Henrik Grubbström (Grubba)  string protocol = "https"; string host, path;
b1f3e92000-04-03Per Hedbor 
829fea2017-09-27Henrik Grubbström (Grubba)  port = read_string(rl, "Port URL:", "server_url", def_port);
0b7c642000-08-28Marcus Comstedt  if( port == def_port ) ;
b1f3e92000-04-03Per Hedbor  else if( (int)port ) { int ok; while( !ok ) {
5e323e2017-09-28Henrik Grubbström (Grubba)  switch( protocol = lower_case(read_string(rl, "Protocol:", "protocol", protocol)))
b1f3e92000-04-03Per Hedbor  { case "":
829fea2017-09-27Henrik Grubbström (Grubba)  protocol = "https";
b1f3e92000-04-03Per Hedbor  case "http": case "https": port = protocol+"://*:"+port+"/"; ok=1; break; default:
de61f22000-08-29Fredrik Noring  write("\n Only http and https are supported for the " "configuration interface.\n");
829fea2017-09-27Henrik Grubbström (Grubba)  if (batch) m_delete(batch, "protocol");
b1f3e92000-04-03Per Hedbor  break; } } } if( sscanf( port, "%[^:]://%[^/]%s", protocol, host, path ) == 3) {
bd5f832000-04-03Per Hedbor  if( path == "" ) path = "/";
b1f3e92000-04-03Per Hedbor  switch( lower_case(protocol) ) { case "http": case "https": // Verify hostname here... port = lower_case( protocol )+"://"+host+path; port_ok = 1; break; default:
de61f22000-08-29Fredrik Noring  write("\n Only http and https are supported for the " "configuration interface.\n\n");
829fea2017-09-27Henrik Grubbström (Grubba)  if (batch) m_delete(batch, "server_url");
b1f3e92000-04-03Per Hedbor  break; } } }
cbc7ea2000-02-19Martin Nilsson  }
cd03b41999-11-22Per Hedbor 
92a8d22017-09-28Henrik Grubbström (Grubba)  // NB: Don't create a user if batch mode and no password. if (!batch || batch->password) { do { user = read_string(rl, "Administrator user name:", "user", user); if (batch) m_delete(batch, "user"); } while(((search(user, "/") != -1) || (search(user, "\\") != -1)) && write("User name may not contain slashes.\n"));
cd03b41999-11-22Per Hedbor 
92a8d22017-09-28Henrik Grubbström (Grubba)  do { if(passwd2 && password) write("\n Please select a password with one or more characters. " "You will\n be asked to type the password twice for " "verification.\n\n"); rl->get_input_controller()->dumb=1; password = read_string(rl, "Administrator password:", "password"); passwd2 = read_string(rl, "Administrator password (again):", "password"); rl->get_input_controller()->dumb=0; if(batch) m_delete(batch, "password"); else write("\n"); } while(!strlen(password) || (password != passwd2)); }
829fea2017-09-27Henrik Grubbström (Grubba) 
336da52017-09-28Henrik Grubbström (Grubba)  if (!batch || has_prefix(lower_case(batch->ok || ""), "n")) {
829fea2017-09-27Henrik Grubbström (Grubba)  passwd2 = read_string(rl, "Are the settings above correct [Y/n]?", 0, ""); if (has_prefix(lower_case(passwd2), "n")) {
336da52017-09-28Henrik Grubbström (Grubba)  // Exit batch mode and retry interactively. batch = 0;
829fea2017-09-27Henrik Grubbström (Grubba)  continue; } } break; } while(1);
cd03b41999-11-22Per Hedbor 
b1f3e92000-04-03Per Hedbor  if( !admin ) { mkdirhier( configdir );
167aa62001-03-23Fredrik Noring  string server_version = Stdio.read_file("VERSION"); if(server_version)
89f8112001-08-31Fredrik Noring  Stdio.write_file(configdir+"/server_version", "server-"+server_version);
b1f3e92000-04-03Per Hedbor  Stdio.write_file( configdir+replace( name, " ", "_" ), replace(
cd03b41999-11-22Per Hedbor #" <!-- -*- html -*- --> <?XML version=\"1.0\"?>
1a09182008-12-09Jonas Wallden <roxen-config>
cd03b41999-11-22Per Hedbor  <region name='EnabledModules'> <var name='config_filesystem#0'> <int>1</int> </var> <!-- Configration Filesystem --> </region>
740cec2000-03-07Henrik Grubbström (Grubba) <region name='pikescript#0'> <var name='trusted'><int>1</int></var> </region>
84fda12000-09-19Martin Nilsson <region name='graphic_text#0'> <var name='colorparse'> <int>1</int> </var> </region>
93b9f22000-04-05Johan Schön <region name='contenttypes#0'> <var name='_priority'> <int>0</int> </var> <var name='default'> <str>application/octet-stream</str> </var> <var name='exts'><str># This will include the defaults from a file. # Feel free to add to this, but do it after the #include line if # you want to override any defaults #include %3cetc/extensions%3e tag text/html xml text/html
898a9a2000-04-09Henrik Grubbström (Grubba) rad text/html ent text/html
93b9f22000-04-05Johan Schön </str></var> </region>
cd03b41999-11-22Per Hedbor <region name='spider#0'> <var name='Domain'> <str></str> </var> <var name='MyWorldLocation'><str></str></var>
22c3652001-11-07Henrik Grubbström (Grubba)  <var name='URLs'> <a> <str>$URL$#ip=;nobind=0;</str></a> </var>
cd03b41999-11-22Per Hedbor  <var name='comment'> <str>Automatically created by create_configuration</str> </var>
1a09182008-12-09Jonas Wallden  <var name='compat_level'>
6a1a022016-11-08Anders Johansson  <str>6.2</str>
1a09182008-12-09Jonas Wallden  </var>
cd03b41999-11-22Per Hedbor  <var name='name'> <str>$NAME$</str> </var>
1a09182008-12-09Jonas Wallden </region> </roxen-config>",
d752bf2004-09-14Fredrik Noring  ({ "$NAME$", "$URL$" }), ({ name, port }) ));
de61f22000-08-29Fredrik Noring  write("\n Administration interface created.\n");
b1f3e92000-04-03Per Hedbor  }
92a8d22017-09-28Henrik Grubbström (Grubba)  if (password) { string ufile=(configdir+"_configinterface/settings/" + user + "_uid"); mkdirhier( ufile ); Stdio.File( ufile, "wct", 0770 ) ->write(
a283de2017-09-27Henrik Grubbström (Grubba) string_to_utf8(#"<?xml version=\"1.0\" encoding=\"utf-8\"?>
b1f3e92000-04-03Per Hedbor <map> <str>permissions</str> : <a> <str>Everything</str> </a>
e48b912003-10-24Anders Johansson  <str>real_name</str> : <str>Administrator</str>
0d0a042013-03-11Henrik Grubbström (Grubba)  <str>password</str> : <str>" + hash_password(password) + #"</str>
a283de2017-09-27Henrik Grubbström (Grubba)  <str>name</str> : <str>" + user + #"</str> </map>\n" ));
cd03b41999-11-22Per Hedbor 
92a8d22017-09-28Henrik Grubbström (Grubba)  write("\n Administrator user \"" + user + "\" created.\n"); } else { write(#" NOTE: No administration user has been created. To create an administration user later; run create_configinterface -a\n"); }
cd03b41999-11-22Per Hedbor }