X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/fdca70eebfb07306ea5f57fa6787e86f913416d2..d8b957853160200fe6b00d8c0e8c61a3f62ecd7c:/lib/trackdb.c?ds=sidebyside diff --git a/lib/trackdb.c b/lib/trackdb.c index 7cc3719..718970a 100644 --- a/lib/trackdb.c +++ b/lib/trackdb.c @@ -23,15 +23,11 @@ * This file is getting in desparate need of splitting up... */ -#include -#include "types.h" +#include "common.h" -#include -#include #include #include #include -#include #include #include #include @@ -39,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -65,6 +60,7 @@ #include "unicode.h" #include "unidata.h" #include "base64.h" +#include "sendmail.h" #define RESCAN "disorder-rescan" #define DEADLOCK "disorder-deadlock" @@ -513,8 +509,13 @@ void trackdb_close(void) { /* generic db routines *******************************************************/ -/* fetch and decode a database entry. Returns 0, DB_NOTFOUND or - * DB_LOCK_DEADLOCK. */ +/** @brief Fetch and decode a database entry + * @param db Database + * @param track Track name + * @param kp Where to put decoded list (or NULL if you don't care) + * @param tid Owning transaction + * @return 0, @c DB_NOTFOUND or @c DB_LOCK_DEADLOCK + */ int trackdb_getdata(DB *db, const char *track, struct kvp **kp, @@ -525,10 +526,12 @@ int trackdb_getdata(DB *db, switch(err = db->get(db, tid, make_key(&key, track), prepare_data(&data), 0)) { case 0: - *kp = kvp_urldecode(data.data, data.size); + if(kp) + *kp = kvp_urldecode(data.data, data.size); return 0; case DB_NOTFOUND: - *kp = 0; + if(kp) + *kp = 0; return err; case DB_LOCK_DEADLOCK: error(0, "error querying database: %s", db_strerror(err)); @@ -1857,7 +1860,7 @@ static int do_list(struct vector *v, const char *dir, char *ptr; int err; size_t l, last_dir_len = 0; - char *last_dir = 0, *track, *alias; + char *last_dir = 0, *track; struct kvp *p; dl = strlen(dir); @@ -1890,12 +1893,35 @@ static int do_list(struct vector *v, const char *dir, if((err = trackdb_getdata(trackdb_prefsdb, track, &p, tid)) == DB_LOCK_DEADLOCK) goto deadlocked; + /* There's an awkward question here... + * + * If a track shares a directory with its alias then we could + * do one of three things: + * - report both. Looks ridiculuous in most UIs. + * - report just the alias. Remarkably inconvenient to write + * UI code for! + * - report just the real name. Ugly if the UI doesn't prettify + * names via the name parts. + */ +#if 1 + /* If this file is an alias for a track in the same directory then we + * skip it */ + struct kvp *t = kvp_urldecode(d.data, d.size); + const char *alias_target = kvp_get(t, "_alias_for"); + if(!(alias_target + && !strcmp(d_dirname(alias_target), + d_dirname(track)))) + if(track_matches(dl, k.data, k.size, re)) + vector_append(v, track); +#else /* if this file has an alias in the same directory then we skip it */ + char *alias; if((err = compute_alias(&alias, track, p, tid))) goto deadlocked; if(!(alias && !strcmp(d_dirname(alias), d_dirname(track)))) if(track_matches(dl, k.data, k.size, re)) vector_append(v, track); +#endif } } err = cursor->c_get(cursor, &k, &d, DB_NEXT); @@ -2209,7 +2235,7 @@ static int reap_rescan(ev_source attribute((unused)) *ev, eventlog("rescanned", (char *)0); /* Call rescanned callbacks */ while(rescanned_list) { - void (*rescanned)(void *u) = rescanned_list->rescanned; + void (*rescanned)(void *u_) = rescanned_list->rescanned; void *ru = rescanned_list->ru; rescanned_list = rescanned_list->next; @@ -2396,12 +2422,24 @@ static char **trackdb_new_tid(int *ntracksp, DBT k, d; int err = 0; struct vector tracks[1]; + hash *h = hash_new(1); vector_init(tracks); c = trackdb_opencursor(trackdb_noticeddb, tid); while((maxtracks <= 0 || tracks->nvec < maxtracks) - && !(err = c->c_get(c, prepare_data(&k), prepare_data(&d), DB_PREV))) - vector_append(tracks, xstrndup(d.data, d.size)); + && !(err = c->c_get(c, prepare_data(&k), prepare_data(&d), DB_PREV))) { + char *const track = xstrndup(d.data, d.size); + /* Don't add any track more than once */ + if(hash_add(h, track, "", HASH_INSERT)) + continue; + /* See if the track still exists */ + err = trackdb_getdata(trackdb_tracksdb, track, NULL/*kp*/, tid); + if(err == DB_NOTFOUND) + continue; /* It doesn't, skip it */ + if(err == DB_LOCK_DEADLOCK) + break; /* Doh */ + vector_append(tracks, track); + } switch(err) { case 0: /* hit maxtracks */ case DB_NOTFOUND: /* ran out of tracks */ @@ -2683,6 +2721,7 @@ int trackdb_adduser(const char *user, user, rights, email); else info("created user '%s' with rights '%s'", user, rights); + eventlog("user_add", user, (char *)0); return 0; } } @@ -2700,6 +2739,7 @@ int trackdb_deluser(const char *user) { return -1; } info("deleted user '%s'", user); + eventlog("user_delete", user, (char *)0); return 0; } @@ -2761,8 +2801,8 @@ int trackdb_edituserinfo(const char *user, } } else if(!strcmp(key, "email")) { if(*value) { - if(!strchr(value, '@')) { - error(0, "invalid email address '%s' for user '%s'", user, value); + if(!email_valid(value)) { + error(0, "invalid email address '%s' for user '%s'", value, user); return -1; } } else @@ -2779,8 +2819,10 @@ int trackdb_edituserinfo(const char *user, if(e) { error(0, "unknown user '%s'", user); return -1; - } else + } else { + eventlog("user_edit", user, key, (char *)0); return 0; + } } /** @brief List all users @@ -2846,6 +2888,7 @@ int trackdb_confirm(const char *user, const char *confirmation, switch(e) { case 0: info("registration confirmed for user '%s'", user); + eventlog("user_confirm", user, (char *)0); return 0; case DB_NOTFOUND: error(0, "confirmation for nonexistent user '%s'", user);