chiark / gitweb /
client.c make-cookie support
[disorder] / lib / client.c
index b012841545798887667393be2b728e667c66b427..c18ca567c20a10b8fd6c3cd1dc419bdf2751f051 100644 (file)
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <netdb.h>
 #include <stdlib.h>
+#include <pcre.h>
 
 #include "log.h"
 #include "mem.h"
@@ -49,6 +50,8 @@
 #include "addr.h"
 #include "authhash.h"
 #include "client-common.h"
+#include "rights.h"
+#include "trackdb.h"
 
 struct disorder_client {
   FILE *fpin, *fpout;
@@ -154,22 +157,24 @@ static int connect_sock(void *vc,
                        const char *ident) {
   const char *username, *password;
   disorder_client *c = vc;
-  int n;
   
   if(!(username = config->username)) {
     error(0, "no username configured");
     return -1;
   }
-  if(!(password = config->password)) {
-    for(n = 0; (n < config->allow.n
-               && strcmp(config->allow.s[n].s[0], username)); ++n)
-      ;
-    if(n < config->allow.n)
-      password = config->allow.s[n].s[1];
-    else {
-      error(0, "no password configured");
-      return -1;
-    }
+  password = config->password;
+  if(!password) {
+    /* Maybe we can read the database */
+    /* TODO failure to open the database should not be fatal */
+    trackdb_init(TRACKDB_NO_RECOVER|TRACKDB_NO_UPGRADE);
+    trackdb_open(TRACKDB_READ_ONLY);
+    password = trackdb_get_password(username);
+    trackdb_close();
+  }
+  if(!password) {
+    /* Oh well */
+    error(0, "no password configured");
+    return -1;
   }
   return disorder_connect_sock(c, sa, len, username, password, ident);
 }
@@ -212,7 +217,7 @@ int disorder_connect_sock(disorder_client *c,
   size_t nl;
   const char *res;
   char *r, **rvec;
-  const char *algo = "SHA1";
+  const char *protocol, *algorithm, *challenge;
 
   if(!password) {
     error(0, "no password found");
@@ -246,15 +251,20 @@ int disorder_connect_sock(disorder_client *c,
     return -1;
   if(!(rvec = split(r, &nrvec, SPLIT_QUOTES, 0, 0)))
     return -1;
-  if(nrvec > 1) {
-    algo = *rvec++;
-    --nrvec;
+  if(nrvec != 3) {
+    error(0, "cannot parse server greeting %s", r);
+    return -1;
   }
-  if(!nrvec)
+  protocol = *rvec++;
+  if(strcmp(protocol, "2")) {
+    error(0, "unknown protocol version: %s", protocol);
     return -1;
-  if(!(nonce = unhex(*rvec, &nl)))
+  }
+  algorithm = *rvec++;
+  challenge = *rvec++;
+  if(!(nonce = unhex(challenge, &nl)))
     return -1;
-  if(!(res = authhash(nonce, nl, password, algo))) goto error;
+  if(!(res = authhash(nonce, nl, password, algorithm))) goto error;
   if(disorder_simple(c, 0, "user", username, res, (char *)0))
     return -1;
   c->user = xstrdup(username);
@@ -332,8 +342,20 @@ int disorder_rescan(disorder_client *c) {
   return disorder_simple(c, 0, "rescan", (char *)0);
 }
 
+static int dequote(int rc, char **rp) {
+  char **rr;
+  if(!rc){
+    if((rr = split(*rp, 0, SPLIT_QUOTES, 0, 0)) && *rr) {
+      *rp = *rr;
+      return 0;
+    }
+    error(0, "invalid reply: %s", *rp);
+  }
+  return -1;
+}
+
 int disorder_version(disorder_client *c, char **rp) {
-  return disorder_simple(c, rp, "version", (char *)0);
+  return dequote(disorder_simple(c, rp, "version", (char *)0), rp);
 }
 
 static void client_error(const char *msg,
@@ -457,7 +479,8 @@ int disorder_unset(disorder_client *c, const char *track,
 
 int disorder_get(disorder_client *c,
                 const char *track, const char *key, char **valuep) {
-  return disorder_simple(c, valuep, "get", track, key, (char *)0);
+  return dequote(disorder_simple(c, valuep, "get", track, key, (char *)0),
+                valuep);
 }
 
 static void pref_error_handler(const char *msg,
@@ -580,11 +603,13 @@ int disorder_log(disorder_client *c, struct sink *s) {
 
 int disorder_part(disorder_client *c, char **partp,
                  const char *track, const char *context, const char *part) {
-  return disorder_simple(c, partp, "part", track, context, part, (char *)0);
+  return dequote(disorder_simple(c, partp, "part",
+                                track, context, part, (char *)0), partp);
 }
 
 int disorder_resolve(disorder_client *c, char **trackp, const char *track) {
-  return disorder_simple(c, trackp, "resolve", track, (char *)0);
+  return dequote(disorder_simple(c, trackp, "resolve", track, (char *)0),
+                trackp);
 }
 
 int disorder_pause(disorder_client *c) {
@@ -600,6 +625,27 @@ int disorder_tags(disorder_client *c,
   return disorder_simple_list(c, vecp, nvecp, "tags", (char *)0);
 }
 
+int disorder_users(disorder_client *c,
+                  char ***vecp, int *nvecp) {
+  return disorder_simple_list(c, vecp, nvecp, "users", (char *)0);
+}
+
+/** @brief Get recentl added tracks
+ * @param c Client
+ * @param vecp Where to store pointer to list
+ * @param nvecp Where to store count
+ * @param max Maximum tracks to fetch, or 0 for all available
+ * @return 0 on success, non-0 on error
+ */
+int disorder_new_tracks(disorder_client *c,
+                       char ***vecp, int *nvecp,
+                       int max) {
+  char limit[32];
+
+  sprintf(limit, "%d", max);
+  return disorder_simple_list(c, vecp, nvecp, "new", limit, (char *)0);
+}
+
 int disorder_set_global(disorder_client *c,
                        const char *key, const char *value) {
   return disorder_simple(c, 0, "set-global", key, value, (char *)0);
@@ -610,7 +656,63 @@ int disorder_unset_global(disorder_client *c, const char *key) {
 }
 
 int disorder_get_global(disorder_client *c, const char *key, char **valuep) {
-  return disorder_simple(c, valuep, "get-global", key, (char *)0);
+  return dequote(disorder_simple(c, valuep, "get-global", key, (char *)0),
+                valuep);
+}
+
+int disorder_rtp_address(disorder_client *c, char **addressp, char **portp) {
+  char *r;
+  int rc, n;
+  char **vec;
+
+  if((rc = disorder_simple(c, &r, "rtp-address", (char *)0)))
+    return rc;
+  vec = split(r, &n, SPLIT_QUOTES, 0, 0);
+  if(n != 2) {
+    error(0, "malformed rtp-address reply");
+    return -1;
+  }
+  *addressp = vec[0];
+  *portp = vec[1];
+  return 0;
+}
+
+int disorder_adduser(disorder_client *c,
+                    const char *user, const char *password,
+                    const char *rights) {
+  return disorder_simple(c, 0, "adduser", user, password, rights, (char *)0);
+}
+
+int disorder_deluser(disorder_client *c, const char *user) {
+  return disorder_simple(c, 0, "deluser", user, (char *)0);
+}
+
+int disorder_userinfo(disorder_client *c, const char *user, const char *key,
+                     char **valuep) {
+  return dequote(disorder_simple(c, valuep, "userinfo", user, key, (char *)0),
+                valuep);
+}
+
+int disorder_edituser(disorder_client *c, const char *user,
+                     const char *key, const char *value) {
+  return disorder_simple(c, 0, "edituser", user, key, value, (char *)0);
+}
+
+int disorder_register(disorder_client *c, const char *user,
+                     const char *password, const char *email,
+                     char **confirmp) {
+  return dequote(disorder_simple(c, confirmp, "register",
+                                user, password, email, (char *)0),
+                confirmp);
+}
+
+int disorder_confirm(disorder_client *c, const char *confirm) {
+  return disorder_simple(c, 0, "confirm", confirm, (char *)0);
+}
+
+int disorder_make_cookie(disorder_client *c, char **cookiep) {
+  return dequote(disorder_simple(c, cookiep, "make-cookie", (char *)0),
+                cookiep);
 }
 
 /*