// $Id: configure.c,v 1.59 2008/04/22 22:43:56 lynx Exp $ // vim:syntax=lpc // // web configurator interface. does a lot of cool things for you, // and it should always learn to do some more. if you don't need or // like it, simply don't load it (from init.ls, or by fetching the url). // #include #include #include #if HAS_PORT(HTTP_PORT, HTTP_PATH) || HAS_PORT(HTTPS_PORT, HTTP_PATH) #include #include #include inherit NET_PATH "sockets"; #ifdef WEB_CONFIGURE // should this use something else? # define CONFIGFILE CONFIG_PATH "local.h" volatile protected mapping description; void create() { sTextPath(0, 0, "html"); description = ([ // this has all moved into psyced.ini // "CHATNAME" : "Name of this Chat Community", // "DEFPLACE" : "Standard place unregistered users go to", // "ADMINISTRATORS" : "List of administrators (example: " // ""admin1", "admin2", " // ""admin3")", // "__DOMAIN_NAME__" : "Domain name of this server", // "SERVER_HOST" : "Address of this server", // "OSTYPE" : "Your Operating System", // "MACHTYPE" : "The flavour of your processor", // optimise on tunings, like this one? "MAX_VISIBLE_USERS" : "MAX_VISIBLE_USERS", // a bit absurd: specify a file on the fs instead of having a motd textarea "MOTD_FILE" : "The file that contains the IRC-MOTD", ]); } denyAccess(prot) { hterror(prot, 200, "You are not allowed to use the configure-page. " "You need to be from localhost to do that."); } parseConfig(fname) { mapping cv; int size; cv = ([ ]); if (file_size(fname) <= 0) { return ([ ]); } foreach(string line : explode(read_file(fname), "\n")) { mixed key, value; if (sscanf(line, "#define%t%s%t%s", key, value) || sscanf(line, "#define%t%s", key) || sscanf(line, "#%tdefine%t%s%t%s", key, value) || sscanf(line, "#%tdefine%t%s", key) ) { //if (dummy=="" && index(key, ' ')==-1 && index(key, '\t')==-1) // && (member(description, key) != -1)) cv[key] = value; } } return cv; } saveConfig(string fname, mapping config, mapping del) { string file, key, value, tail; int added; unless (mappingp(del)) { del = ([ ]); } if (file_size(fname) <= 0) { if (abbrev("place/", fname)) { file = w("_PAGES_configure_room_new"); } else { return; } } else { file = read_file(fname); } added = 0; foreach (key, value : config) { // re scheint keine + syntax zu beherrschen P2(("===> %O\n", value)) if (to_string(to_int(value)) != value && value != "") { unless (value[0] == '"') value = "\"" + value; unless (value[<1] == '"') value += "\""; } if (sizeof(regexp(({ file }), "#([ \t]*)define([ \t][ \t]*)"+key+ "([ \t][ \t]*)[^\n]*"))) { tail = "([ \t][ \t]*)[^\n]*"; } else if (sizeof(regexp(({ file }), "#([ \t]*)define([ \t][ \t]*)"+key))) { tail = ""; } else { // adden file = regreplace(file, "#include ", "#define "+key+" "+ (value != "" ? " "+value : "")+ "\n#include ", 0); added = 1; } unless (value == "" && added == 0) { file = regreplace(file, "#([ \t]*)define([ \t][ \t]*)"+key+tail, "#\\1define "+key+"\t"+value, 0); } else if (added == 0){ file = regreplace(file, "#([ \t]*)define([ \t][ \t]*)"+key+tail, "#\\1define "+key, 0); } // old ldmud requires 4th argument // if (t == file) printf("Could not change %s into %O\n", key, value); } foreach (key, value : del) { file = regreplace(file, "#([ \t]*)define([ \t][ \t]*)"+key+"[^\n]*\n", "", 0); } rm(fname); write_file(fname, file); return w("_PAGES_configure_advice_restart") + "
\n" +
	   "Congratulations, this is your new configuration file:\n" +
	   "
\n" + file; } htget(prot, query, headers, qs) { string s; // output buffer int trustworthy = legal_host(query_ip_number(), HTTP_PORT, "http", 0); if (trustworthy < 7) { denyAccess(prot); return 1; } if (file_size(CONFIGFILE) <= 0) { hterror(prot, 404, "You don't have any configfile, do you?"); return 1; } htok3(prot, "text/html", "Cache-Control: no-cache\n"); switch (query["option"]) { case "user_mgm": s = w("_PAGES_configure_user", ([ "_title" : "User Management" ])); break; case "list_users": write(w("_PAGES_configure_user_list", ([ "_title" : "User List" ]))); list_sockets(); return 1; case "block_modify": if (query["ip"] && query["ip"] != 0) { object ob; DAEMON_PATH "hosts"->modify(query["ip"]); foreach (ob : users()) { if (abbrev(query["ip"], query_ip_number(ob))) { log_file("BEHAVIOUR", "[%s] %O blocks %O (%s)\n", ctime(), ME, ob, query["ip"]); ob -> sanction("kill"); } } } case "list_blocks": write(w("_PAGES_configure_user_block_head", ([ "_title" : "Block Management", "_submit_value" : "Submit" ]))); DAEMON_PATH "hosts"->list(); return 1; case "user_password": s = w("_PAGES_configure_user_password", ([ "_title" : "Reset Password", "_submit_value" : "Edit" ])); break; case "user_password_edit": { object o; unless (o = find_person(query["nick"])) { unless (o = summon_person(query["nick"])) { s = w("_PAGES_configure_user_password_failure", ([ "_title" : "Reset Password" ])); break; } } if (o->isNewbie()) { destruct(o); s = w("_PAGES_configure_user_password_failure", ([ "_title" : "Reset Password" ])); break; } s = w("_PAGES_configure_user_password_edit", ([ "_title" : "Reset Password", "_submit_value" : "Reset Password", "_nick" : query["nick"] ])); break; } case "user_password_save": { object o; if (! query["password"] || strlen(query["password"]) <= 2) { s = w("_PAGES_configure_user_password_failure_bad", ([ "_title" : "Reset Password" ])); break; } unless (o = find_person(query["nick"])) { unless (o = summon_person(query["nick"])) { s = w("_PAGES_configure_user_password_failure", ([ "_title" : "Reset Password" ])); break; } } if (o->isNewbie()) { destruct(o); s = w("_PAGES_configure_user_password_failure", ([ "_title" : "Reset Password" ])); break; } o->vSet("password", query["password"]); o->save(); s = w("_PAGES_configure_user_password_save", ([ "_title" : "Reset Password", "_nick" : query["nick"], "_password" : query["password"] ])); break; } case "basic_mgm": s = w("_PAGES_configure_basic", ([ "_title" : "Basic Server Management" ])); break; case "restart": s = w("_PAGES_configure_head", ([ "_title" : "Restart" ])); s += "<b>Your chatserver is being restarted.</b>"; // write at the bottom wouldn't be called after shutdown, would it? write(s); server_shutdown("restart by web configuration", 1); return 1; case "list_udp": { mapping ports; string port; s = w("_PAGES_configure_basic_udp_head", ([ "_title" : "List UDP Ports" ])); ports = DAEMON_PATH "udp"->listPorts(1); foreach (port : m_indices(ports)) { s += w("_PAGES_configure_basic_udp_entry", ports[port]); } s += w("_PAGES_configure_basic_udp_tail"); break; } case "room_mgm": s = w("_PAGES_configure_room", ([ "_title" : "Room Management" ])); break; case "room_owned": s = w("_PAGES_configure_room_owned", ([ "_title" : "Manage Owned Rooms", "_submit_value" : "Edit / Add" ])); break; case "room_owned_save": { mapping del; del = ([ ]); m_delete(query, "option"); if (query["delete"]) { rm("place/" + lower_case(query["NAME"]) + ".c"); s = w("_PAGES_configure_room_deleted", ([ "_title" : "Room Deleted", "_name" : query["NAME"] ])); break; } if (query["ALLOW_EXTERNAL"]) { query["ALLOW_EXTERNAL"] = ""; } else { del += ([ "ALLOW_EXTERNAL" ]); } if (query["REGISTERED"]) { query["REGISTERED"] = ""; } else { del += ([ "REGISTERED" ]); } s = w("_PAGES_configure_head", ([ "_title" : "Owned Room Management" ])); s += saveConfig("place/" + lower_case(query["NAME"]) + ".c", query, del); break; } case "room_owned_edit": { mapping rs; string name; mixed t; rs = parseConfig("place/" + lower_case(query["NAME"]) + ".c"); P2(("===> %O\n", rs)) unless ((t = isRoomType("OWNED", rs)) == 1) { if (t != -1) { s = w("_PAGES_configure_room_error_type", ([ "_title" : "Manage Owned Rooms", "_name" : query["NAME"], "_expected" : "Owned", "_type" : t ])); } else { s = w("_PAGES_configure_room_error_type_undefined", ([ "_title" : "Manage Owned Rooms", "_name" : query["NAME"], "_expected" : "Owned" ])); } break; } if (rs["NAME"]) { name = replace(rs["NAME"], "\"", ""); } else { name = query["NAME"] || ""; } s = w("_PAGES_configure_room_owned_edit", ([ "_title" : "Manage Owned Rooms", "_submit_value" : "Save", "_name" : name, "_registered" : member(rs, "REGISTERED") ? " checked" : "", "_owned" : replace(rs["OWNED"] || "", "\"", "&quot;"), "_external" : member(rs, "ALLOW_EXTERNAL") ? " checked" : "" ])); break; } case "room_public": s = w("_PAGES_configure_room_public", ([ "_title" : "Manage Public Rooms", "_submit_value" : "Edit / Add" ])); break; case "room_public_save": { mapping del; del = ([ ]); m_delete(query, "option"); if (query["delete"]) { rm("place/" + lower_case(query["NAME"]) + ".c"); s = w("_PAGES_configure_room_deleted", ([ "_title" : "Room Deleted", "_name" : query["NAME"] ])); break; } if (query["HISTORY"]) { query["HISTORY"] = ""; } else { del += ([ "HISTORY" ]); } if (query["ALLOW_EXTERNAL"]) { query["ALLOW_EXTERNAL"] = ""; } else { del += ([ "ALLOW_EXTERNAL" ]); } if (query["REGISTERED"]) { query["REGISTERED"] = ""; } else { del += ([ "REGISTERED" ]); } s = w("_PAGES_configure_head", ([ "_title" : "Public Room Management" ])); s += saveConfig("place/" + lower_case(query["NAME"]) + ".c", query, del); break; } case "room_public_edit": { mapping rs; string name; mixed t; rs = parseConfig("place/" + lower_case(query["NAME"]) + ".c"); P2(("===> %O\n", rs)) unless (intp(t = isRoomType("PUBLIC", rs))) { s = w("_PAGES_configure_room_error_type", ([ "_title" : "Manage Public Rooms", "_name" : query["NAME"], "_expected" : "Public", "_type" : t ])); break; } if (rs["NAME"]) { name = replace(rs["NAME"], "\"", ""); } else { name = query["NAME"] || ""; } s = w("_PAGES_configure_room_public_edit", ([ "_title" : "Manage Public Rooms", "_submit_value" : "Save", "_name" : name, "_history" : member(rs, "HISTORY") ? " checked" : "", "_registered" : member(rs, "REGISTERED") ? " checked" : "", "_external" : member(rs, "ALLOW_EXTERNAL") ? " checked" : "" ])); break; } case "save_config": { s = w("_PAGES_configure_head", ([ "_title" : "Edit Config" ])); s += saveConfig(CONFIGFILE, query); break; } #if 0 // was um alles in der welt soll das? case "set": m_delete(query, "option"); break; // gehört da n break hin? #endif case "edit_config": { mapping cv; cv = parseConfig(CONFIGFILE); // sowas gehört in externe dateien.. am besten .fmt wegen // mehrsprachigkeit und layouting und template syntax und und.. s = w("_PAGES_configure_head", ([ "_title" : "Edit Config" ])); s += "<div align=\"center\" style=\"float:clear; text-align:center;\">\n" "<table bgcolor=\"#004411\" cellspacing=0 cellpadding=3>\n" "<form method=GET action=configure name=zero>\n" "<input type=hidden name=option value=\"save_config\">\n"; foreach(string key, string value : cv) { if (value) { value = replace(value, "\"", "&quot;"); s += "<tr><td style=\"border-left: 1px solid #f90; border-top: 1px solid #f90;\"><b>" + key + ":</b></td><td style=\"border-top: 1px solid #f90; border-right: 1px solid #f90;\"><input type=\"text\" value=\"" + value + "\" name=\"" + key + "\"></td></tr>\n" "<tr><td colspan=2 style=\"padding-left:10px; border-bottom: 1px solid #fc0; border-right: 1px solid #f90; border-left: 3px solid #fc0;\">" + (description[key] || "") + "</td></tr>\n" "<tr><td><span style=\"font-size:1px;\">&nbsp;</span></td></tr>\n"; } } s += "<tr><td colspan=2 align=center><p>&nbsp;</p>"; s += w("_PAGES_configure_submit", ([ "_submit_value" : "Save" ])); s += "</td></tr>\n" "</form></table>\n" "</div>\n"; break; } default: s = w("_PAGES_configure_menu", ([ "_title" : "Menu" ])); } write(s); } #else htget(prot, query, headers, qs) { hterror(prot, 501, "This server hasn't enabled webbased administration"); } #endif isRoomType(expected, mapping rs) { string type; unless (sizeof(rs)) { return 1; } foreach (type : filter(({ "OWNED", "MODERATED", "NEWSFEED_RSS", "SLAVE", "CONNECTED_IRC", "THREADS", "GAMESERV", "LINK", "PUBLIC" }), lambda( ({ 'x }), ({#'?, ({ #'!=, 'x, expected }) })) )) { if(member(rs, type)) return type[0..0] + lower_case(type[1..]); } if (member(rs, expected)) { return 1; } return -1; } w(mc, mixed vars, bla) { if (bla) { vars = bla; } if (mc == "_list_user_technical") { unless (mappingp(vars)) vars = ([ ]); write(psyctext(T(mc, ""), vars)); return; } unless (mappingp(vars)) { return T(mc, ""); } return psyctext(T(mc, ""), vars); } // only used for HOSTS_D pr(mc, text, vars) { string s, ip, reason; // we'll keep it this way, yet switch (mc) { case "_list_hosts_disabled": s = ""; foreach (ip, reason: vars) { s += w(mc, ([ "_ip" : ip, "_reason" : reason ])); } } write(s); } #endif