// // Enkel databas i en l}ng fil. // // Formatet f|r filen {r: // post \n\n post // Formatet f|r varje post {r: // f{lt \n f{lt \n f{lt ... s} m}nga som det nu {r... // inga f{lt f}r vara tomma. // #define DEBUG #define DATABASEFILE "/home/linus/.public/vemevem/data/DB" #define PASSWDFILE "/home/linus/.public/vemevem/data/passwd" #define SVMUDPLAYERS "/usr/svmud/lib/spelare/" #define ADMIN "linus" inherit "spiderlib"; array (array(string)) data = ({ }); void load_data() { data = map_array(explode(read_bytes(DATABASEFILE), "\n\n"), lambda(string record) { return explode(record, "\n") - ({ "", }); }) - ({ ({ }) }); } void save_data() { rm(DATABASEFILE + ".old"); mv(DATABASEFILE, DATABASEFILE + ".old"); write_file(DATABASEFILE, implode(map_array(data, lambda(array(string) record) { return implode(record,"\n"); }), "\n\n")); } void prepare_to_save() { remove_call_out(save_data); call_out(save_data, 1); } // These macros are used to find the correct record. #define RECORD_NAME(rec) (rec)[0] #define RECORD_PASSWORD(rec) (rec)[1] #define RECORD_REALNAME(rec) (rec)[2] #define RECORD_REALADDRESS(rec) (rec)[3] #define RECORD_PHONE(rec) (rec)[4] #define RECORD_EMAIL(rec) (rec)[5] #define RECORD_HOMEPAGE(rec) (rec)[6] #define RECORD_PICTURE(rec) (rec)[7] #define RECORD_ORIGINALLYFROM(rec) (rec)[8] #define RECORD_BECAMEWIZARD(rec) (rec)[9] #define RECORD_OTHER_INFO(rec) (rec)[10] #define RECORD_LAST_MODIFIED(rec) (rec)[11] #define VERIFY_ARRAY_SIZE(rec) while (sizeof(rec) < 12) { rec += ({ "" }); } // Removes all items with the name name from data. void remove_from_array(string name) { int i; for (i = 0; i < sizeof(data); i++) { if (RECORD_NAME(data[i]) == name) { data -= ({ data[i], }); i--; } } } void add_to_array(array(string) record) { int i; for(i = 0; i < sizeof(record); i++) if (record[i] == "") record[i] = "0"; data += ({ record }); } mapping data_index; // Resets the index void reset_index() { data_index = 0; } // Builds or rebuilds the index. void rebuild_index() { data_index = mkmapping(map_array(data, lambda(array(string) record) { return RECORD_NAME(record); }), data); } // Builds the index if not already built. void build_index() { if (mappingp(data_index)) return; rebuild_index(); } void create() { load_data(); reset_index(); } // This returns 0 if not found. array(string) get(string name) { build_index(); if (arrayp(data_index[name])) return map_array(data_index[name], lambda(string info) { if (info == "0") return ""; else return info; }); else return 0; } // Adds or modifies an entry. void put(array(string) record) { reset_index(); remove_from_array(RECORD_NAME(record)); add_to_array(record); prepare_to_save(); } void delete(string name) { reset_index(); remove_from_array(name); prepare_to_save(); } array(string) all_entries() { build_index(); return indices(data_index); } // End of database things string filename; string basename(string name) { array(string) a = explode(name,"/"); return filename = a[sizeof(a) - 1]; } // Things that help in the authentication // Generate a new record containing name and password for a user not in // the database. // First search in the passwd-format-like file. Then in the svmud data files. mapping passwd = 0; array(string) generate_new_passwd(string name) { name = lower_case(name); if (passwd == 0) { // Read the passwd-format file. passwd = sum(@map_array((explode(read_bytes(PASSWDFILE) || "", "\n")), lambda(string entry) { array(string) arr = explode(entry, ":"); if (sizeof(arr) < 2) return ([ ]); return ([arr[0]:arr[1]]); })); } if (passwd[name]) { return ({ name, passwd[name], }); } return 0; } array(string) generate_new_datafile(string name) { string pass; string filecont; name = lower_case(name); if ((filecont = read_bytes(SVMUDPLAYERS + name + ".o")) && sscanf(filecont, "%*s\npassword \"%s\"", pass)) { return ({ name, pass, }); } return 0; } // Convert an auth record to a name. string auth_to_name(array(string) arr) { return lower_case(arr[1]); } string auth_to_password(array(string) arr) { return arr[2]; } // Return true if the auth record identifies a user correctly // Actually it returns 1 if in the database, 2 if in the passwd-style file // and 3 if in the datafile. int auth_is_correct(array(string) arr) { array(string) record; if (!(arr && sizeof(arr) >= 3 && stringp(auth_to_name(arr)) && stringp(auth_to_password(arr)))) return 0; record = get(auth_to_name(arr)); if (record && sizeof(record) >= 2 && crypt(auth_to_password(arr), RECORD_PASSWORD(record))) return 1; record = generate_new_passwd(auth_to_name(arr)); if (record && sizeof(record) >= 2 && crypt(auth_to_password(arr), RECORD_PASSWORD(record))) return 2; record = generate_new_datafile(auth_to_name(arr)); if (record && sizeof(record) >= 2 && crypt(auth_to_password(arr), RECORD_PASSWORD(record))) return 3; return 0; } // Quote "dangerous" characters. string quote(string in) { return replace(in, ({ "\"", "<", ">", }), ({ """, "<", ">", })); } // Returns the info about one person. string info_about(string name, int with_pictures) { array(string) record = get(lower_case(name)); if (record) { VERIFY_ARRAY_SIZE(record); return (with_pictures && RECORD_PICTURE(record) != "" ? "" : "") + "

" + capitalize(name) + "

\n" + "
"
	    + quote(RECORD_REALNAME(record))
	    + "\n"
	    + implode(explode(quote(RECORD_REALADDRESS(record)),", "), "\n")
	    + "
" + "\n" + (RECORD_PHONE(record) != "" ? "Telefon: " + quote(RECORD_PHONE(record)) : "") + (RECORD_PHONE(record) != "" && RECORD_EMAIL(record) != "" ? ", " : "") + (RECORD_EMAIL(record) != "" ? "email: " + quote(RECORD_EMAIL(record)) + "" : "") + "

\n" + (RECORD_ORIGINALLYFROM(record) != "" ? capitalize(name) + " kommer ursprungligen från " + quote(RECORD_ORIGINALLYFROM(record)) + ".\n" : "") + "\n" + (RECORD_BECAMEWIZARD(record) != "" ? capitalize(name) + " blev magiker den " + quote(RECORD_BECAMEWIZARD(record)) + ".\n" : "") + "\n" + (RECORD_OTHER_INFO(record) != "" ? quote(RECORD_OTHER_INFO(record)) + ".\n" : "") + "\n" + (RECORD_HOMEPAGE(record) != "" ? capitalize(name) + " har en egen hemsida." : "") + (RECORD_LAST_MODIFIED(record) != "" ? "

\nInformationen om " + capitalize(name) + " ändrades senast " + RECORD_LAST_MODIFIED(record) : "") + "
\n"; } else { return "Ingen information finns i databasen om " + name + "\n"; } } #define LENKARNA "Ändra/lägg till din information "\ + "Utan bilder"\ : "?pictures=yes\">Med bilder") string the_entire_contents(int with_pictures) { return LENKARNA + "


\n" + implode(map_array(sort_array((array*)all_entries(), 0, 0), info_about, with_pictures), "\n\n") + "
\n" + LENKARNA; } // Funktionen returnerar det som administrat|ren har f|r att f} fram formul{r // f|r att editera andras information. string admin_knapp(string who) { return "

Administratörskommandon:

\n" + "
\n" + "\n" + "\n" + "\n" + "
\n" + "Annan:
\n" + "\n" + "\n" + "\n" + "
\n" + "
\n"; } // string form_for(string who, int is_admin, array(string) record, int first_time_around) { VERIFY_ARRAY_SIZE(record); return (is_admin ? admin_knapp(who) : "") + "

Informationen om " + capitalize(who) + " till SvenskMUDs vem är vem ser ut så här:

\n" + info_about(who, 1) + "
\n" + "
\n" + "

Här kan du ändra informationen

\n" + "
\n" + "\n" + "\n" + "
\n" + "
Riktigt namn:
\n" + "
Riktig adress:
\n" + "
Telefonnummer:
\n" + "
Email:
\n" + "
Hemsida:
\n" + "
Url:en till en bild:
\n" + "
Ursprungligen från:
\n" + "
Blev magiker:
\n" + "
Annat:
\n" + "
\n" + "Jag godkänner att informationen som jag nu skickar in blir " + "tillgänglig för alla på internet genom att trycka på" + "\n" + "
\n" + "
\n" + "\n" + "\n" + "Jag vill inte längre finnas med i registret och därför " + "vill jag" + "\n" + "
\n" + "
Du kan också gå tillbaka till hela listan" + (first_time_around ? "utan att spara informationen" : "") + ""; } // Funktioner som anropas n{r saker skall modifieras. string do_submit(string who, mapping vars, string new_password, int admin) { array(string) arr = get(who) || ({ who, }); VERIFY_ARRAY_SIZE(arr); if (new_password) RECORD_PASSWORD(arr) = new_password; RECORD_REALNAME(arr) = vars["realname"] || ""; RECORD_REALADDRESS(arr) = vars["realaddress"] || ""; RECORD_PHONE(arr) = vars["phone"] || ""; RECORD_EMAIL(arr) = vars["email"] || ""; RECORD_HOMEPAGE(arr) = vars["homepage"] || ""; RECORD_PICTURE(arr) = vars["picture"] || ""; RECORD_ORIGINALLYFROM(arr) = vars["originallyfrom"] || ""; RECORD_BECAMEWIZARD(arr) = vars["becamewizard"] || ""; RECORD_OTHER_INFO(arr) = vars["otherinfo"] || ""; RECORD_LAST_MODIFIED(arr) = ctime(time())[0..23] + (admin ? " av " + capitalize(ADMIN) : ""); put(copy_value(arr)); return "Informationen mottagen." + "
\n" + form_for(who, 0, arr, 0); } string do_remove(string who, mapping vars, string new_password) { array(string) arr = get(who); if (arr) { delete(who); } return "Informationen mottagen." + "
\n" + form_for(who, 0, ({ who, }), 0); } // This function simply adds the header and footer of all the requests. #define SURROUND(str, tag) "<" + tag + ">\n" + str + "\n\n" #define HEAD(str) SURROUND(str, "head") #define TITLE(str) SURROUND(str, "title") #define BODY(str) SURROUND(str, "body") #define H1(str) SURROUND(str, "h1") string add_decorations(string title, string data) { return HEAD(TITLE(title)) + BODY(H1(title) + "
\n" + data + "
\n" + "Det är Linus som sköter det här registret så hör av dig till honom om det är skumheter med det."); } // Alternatives for parse // - No special requests: // generate a list of the entire database // - op=update - no credentials // somebody pressed his update button, demand the credentials // - op=update - credentials // check the credentials if ok - show the form with contents. // if not ok - ask again. // - op=update - credentials - fields // update the fields. // - op=submit - enter the information // - op=remove - remove the information string|mapping parse(object request) { basename(request->realfile); if (request->variables["op"] != "update" && request->variables["op"] != "submit" && request->variables["op"] != "remove") { // We want the list return add_decorations("Vem är vem i SvenskMUD - hela listan", the_entire_contents(request->variables["pictures"] == "yes")); } else { int auth_type; if ((auth_type = auth_is_correct(request->auth))) { // We have credentials and they are correct. // Generate a form or handle the contents of a form. array(string) record = get(auth_to_name(request->auth)) || ({ auth_to_name(request->auth), }); array(string) new; if (auth_type == 2) new = generate_new_passwd(auth_to_name(request->auth)); if (auth_type == 3) new = generate_new_datafile(auth_to_name(request->auth)); if (request->variables["op"] == "submit") { if (RECORD_NAME(record) == ADMIN) { // The admin can update anything. return add_decorations("Vem är vem - Administratörsuppdateringens resultat.", do_submit(lower_case(request->variables["name"]), request->variables, new ? RECORD_PASSWORD(new) : 0, 1)); } else { return add_decorations("Vem är vem - Resultatet av uppdateringen.", do_submit(RECORD_NAME(record), request->variables, new ? RECORD_PASSWORD(new) : 0, 0)); } } else if (request->variables["op"] == "remove") { if (RECORD_NAME(record) == ADMIN) { // The admin can update anything. return add_decorations("Vem är vem - Administratörsuppdateringens resultat.", do_remove(lower_case(request->variables["name"]), request->variables, 0)); } else { return add_decorations("Vem är vem - Resultatet av uppdateringen.", do_remove(RECORD_NAME(record), request->variables, 0)); } } else { if (RECORD_NAME(record) == ADMIN && stringp(request->variables["name"])) { record = (get(lower_case(request->variables["name"])) || ({ lower_case(request->variables["name"]), })); return add_decorations("Vem är vem - Administratör fyll i information för " + RECORD_NAME(record), form_for(RECORD_NAME(record), 1, record, 1)); } else { return add_decorations("Vem är vem - Fyll i information för din karaktär: " + capitalize(RECORD_NAME(record)), form_for(RECORD_NAME(record), RECORD_NAME(record) == ADMIN, record, 1)); } } } else { // We don't have the credentials or they are incorrect. return http_auth_required("svenskmudplayer", add_decorations("Otillräcklig identifiering", "Du måste ge korrekt namn och lösenord för en existrerande svenskmuddare.

Ibland kanske inte ens det hjälper. Prova då att ange det lösenord du hade tidigare i Svenskmud eller om du är en ny spelare så finns du nog inte med. Tala då om problemet för Linus så kan han uppdatera lösenordsdatabasen." #ifdef DEBUG + sprintf("

\n%O\n
", passwd) + sprintf("
\n%O\n
", request->auth) #endif )); } } }