//
// 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) != ""
? ""
: "")
+ "
" + 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
+ "
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 )); } } }