/*
* This file is part of DisOrder.
- * Copyright (C) 2004, 2005, 2006 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2006, 2007 Richard Kettlewell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
+#include <pcre.h>
#include "log.h"
#include "mem.h"
#include "addr.h"
#include "authhash.h"
#include "client-common.h"
+#include "rights.h"
+#include "trackdb.h"
struct disorder_client {
FILE *fpin, *fpout;
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);
}
const char *username,
const char *password,
const char *ident) {
- int fd = -1, fd2 = -1;
+ int fd = -1, fd2 = -1, nrvec;
unsigned char *nonce;
size_t nl;
const char *res;
- char *r;
+ char *r, **rvec;
+ const char *protocol, *algorithm, *challenge;
if(!password) {
error(0, "no password found");
c->ident = xstrdup(ident);
if(disorder_simple(c, &r, 0, (const char *)0))
return -1;
- if(!(nonce = unhex(r, &nl)))
+ if(!(rvec = split(r, &nrvec, SPLIT_QUOTES, 0, 0)))
+ return -1;
+ if(nrvec != 3) {
+ error(0, "cannot parse server greeting %s", r);
+ return -1;
+ }
+ protocol = *rvec++;
+ if(strcmp(protocol, "2")) {
+ error(0, "unknown protocol version: %s", protocol);
+ return -1;
+ }
+ algorithm = *rvec++;
+ challenge = *rvec++;
+ if(!(nonce = unhex(challenge, &nl)))
return -1;
- if(!(res = authhash(nonce, nl, password))) 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);
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,
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,
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) {
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);
}
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) {
+ return disorder_simple(c, 0, "adduser", user, password, (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);
}
/*
comment-column:40
End:
*/
-/* arch-tag:3937adbfa9480384606631d8e0365885 */