chiark / gitweb /
Fix mis-merged trackdb_open().
[disorder] / lib / trackdb-playlists.c
index 1492f8c4c13beebbf3ab34aac8655d471ff132a0..bef7107bf9c784976c78fcfaa80b876926616c94 100644 (file)
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "configuration.h"
 #include "vector.h"
+#include "eventlog.h"
 
 static int trackdb_playlist_get_tid(const char *name,
                                     const char *who,
@@ -81,7 +82,7 @@ int playlist_parse_name(const char *name,
     if(!valid_username(name))
       return -1;
     owner = 0;
-    share = "public";
+    share = "shared";
   }
   if(ownerp)
     *ownerp = owner;
@@ -100,7 +101,7 @@ static int playlist_may_read(const char *name,
                              const char *share) {
   char *owner;
   
-  if(!playlist_parse_name(name, &owner, 0))
+  if(playlist_parse_name(name, &owner, 0))
     return 0;
   /* Anyone can read shared playlists */
   if(!owner)
@@ -125,7 +126,7 @@ static int playlist_may_write(const char *name,
                               const char attribute((unused)) *share) {
   char *owner;
   
-  if(!playlist_parse_name(name, &owner, 0))
+  if(playlist_parse_name(name, &owner, 0))
     return 0;
   /* Anyone can modify shared playlists */
   if(!owner)
@@ -147,7 +148,7 @@ static int playlist_may_write(const char *name,
  *
  * Possible return values:
  * - @c 0 on success
- * - @c DB_NOTFOUND if the playlist doesn't exist
+ * - @c ENOENT if the playlist doesn't exist
  * - @c EINVAL if the playlist name is invalid
  * - @c EACCES if the playlist cannot be read by @p who
  */
@@ -158,13 +159,16 @@ int trackdb_playlist_get(const char *name,
                          char **sharep) {
   int e;
 
-  if(!playlist_parse_name(name, 0, 0)) {
+  if(playlist_parse_name(name, 0, 0)) {
     error(0, "invalid playlist name '%s'", name);
     return EINVAL;
   }
   WITH_TRANSACTION(trackdb_playlist_get_tid(name, who,
                                             tracksp, ntracksp, sharep,
                                             tid));
+  /* Don't expose libdb error codes too much */
+  if(e == DB_NOTFOUND)
+    e = ENOENT;
   return e;
 }
 
@@ -237,6 +241,10 @@ static int trackdb_playlist_get_tid(const char *name,
  * none, and the default sharing is private (if it is an owned one) or shared
  * (otherwise).
  *
+ * If neither @c tracks nor @c share are set then we only do an access check.
+ * The database is never modified (even to create the playlist) in this
+ * situation.
+ *
  * Possible return values:
  * - @c 0 on success
  * - @c EINVAL if the playlist name is invalid
@@ -250,7 +258,7 @@ int trackdb_playlist_set(const char *name,
   int e;
   char *owner;
   
-  if(!playlist_parse_name(name, &owner, 0)) {
+  if(playlist_parse_name(name, &owner, 0)) {
     error(0, "invalid playlist name '%s'", name);
     return EINVAL;
   }
@@ -286,6 +294,7 @@ static int trackdb_playlist_set_tid(const char *name,
   struct kvp *k;
   int e;
   const char *s;
+  const char *event = "playlist_modified";
 
   if((e = trackdb_getdata(trackdb_playlistsdb, name, &k, tid))
      && e != DB_NOTFOUND)
@@ -304,6 +313,7 @@ static int trackdb_playlist_set_tid(const char *name,
     k = 0;
     kvp_set(&k, "count", 0);
     kvp_set(&k, "sharing", defshare);
+    event = "playlist_created";
   }
   /* Check that the modification is allowed */
   if(!(s = kvp_get(k, "sharing"))) {
@@ -312,9 +322,12 @@ static int trackdb_playlist_set_tid(const char *name,
   }
   if(!playlist_may_write(name, who, s))
     return EACCES;
+  /* If no change was requested then don't even create */
+  if(!share && !tracks)
+    return 0;
   /* Set the new values */
   if(share)
-    kvp_set(&k, "share", share);
+    kvp_set(&k, "sharing", share);
   if(tracks) {
     char b[16];
     int oldcount, n;
@@ -344,7 +357,11 @@ static int trackdb_playlist_set_tid(const char *name,
     kvp_set(&k, "count", b);
   }
   /* Store the resulting record */
-  return trackdb_putdata(trackdb_playlistsdb, name, k, tid, 0);
+  e = trackdb_putdata(trackdb_playlistsdb, name, k, tid, 0);
+  /* Log the event */
+  if(!e)
+    eventlog(event, name, kvp_get(k, "sharing"), (char *)0);
+  return e;
 }
 
 /** @brief Get a list of playlists
@@ -376,13 +393,17 @@ static int trackdb_playlist_list_tid(const char *who,
   while(!(e = c->c_get(c, k, prepare_data(d), DB_NEXT))) {
     char *name = xstrndup(k->data, k->size), *owner;
     const char *share = kvp_get(kvp_urldecode(d->data, d->size),
-                                "share");
+                                "sharing");
 
     /* Extract owner; malformed names are skipped */
     if(playlist_parse_name(name, &owner, 0)) {
       error(0, "invalid playlist name '%s' found in database", name);
       continue;
     }
+    if(!share) {
+      error(0, "playlist '%s' has no 'sharing' key", name);
+      continue;
+    }
     /* Always list public and shared playlists
      * Only list private ones to their owner
      * Don't list anything else
@@ -393,6 +414,7 @@ static int trackdb_playlist_list_tid(const char *who,
            && owner && !strcmp(owner, who)))
       vector_append(v, name);
   }
+  trackdb_closecursor(c);
   switch(e) {
   case DB_NOTFOUND:
     break;
@@ -418,19 +440,21 @@ static int trackdb_playlist_list_tid(const char *who,
  * - @c 0 on success
  * - @c EINVAL if the playlist name is invalid
  * - @c EACCES if the playlist cannot be modified by @p who
- * - @c DB_NOTFOUND if the playlist doesn't exist
+ * - @c ENOENT if the playlist doesn't exist
  */
 int trackdb_playlist_delete(const char *name,
                             const char *who) {
   int e;
   char *owner;
   
-  if(!playlist_parse_name(name, &owner, 0)) {
+  if(playlist_parse_name(name, &owner, 0)) {
     error(0, "invalid playlist name '%s'", name);
     return EINVAL;
   }
   /* We've checked as much as we can for now, now go and attempt the change */
   WITH_TRANSACTION(trackdb_playlist_delete_tid(name, who, tid));
+  if(e == DB_NOTFOUND)
+    e = ENOENT;
   return e;
 }
 
@@ -451,7 +475,10 @@ static int trackdb_playlist_delete_tid(const char *name,
   if(!playlist_may_write(name, who, s))
     return EACCES;
   /* Delete the playlist */
-  return trackdb_delkey(trackdb_playlistsdb, name, tid);
+  e = trackdb_delkey(trackdb_playlistsdb, name, tid);
+  if(!e)
+    eventlog("playlist_deleted", name, 0);
+  return e;
 }
 
 /*