]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - aft.c
Merge branch 'crypt' into next
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 6c7f66643f1077083ab8317365aed9b622d12907..e5409244c5a626204cb1e645ae52b903f2a49448 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -7,8 +7,11 @@
 /** \file aft.c Audio file table functions. */
 
 #include <dirent.h> /* readdir() */
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "string.h"
 #include <sys/mman.h>
 #include <fnmatch.h>
@@ -74,6 +77,8 @@ enum ls_flags {
        LS_FLAG_ADMISSIBLE_ONLY = 2,
        /** -r */
        LS_FLAG_REVERSE = 4,
+       /** -d */
+       LS_FLAG_UNIXDATE = 8,
 };
 
 /**
@@ -800,10 +805,15 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts,
                goto out;
        }
        get_attribute_bitmap(&afsi->attributes, att_buf);
-       ret = get_local_time(&afsi->last_played, last_played_time,
-               sizeof(last_played_time), current_time, opts->mode);
-       if (ret < 0)
-               goto out;
+       if (opts->flags & LS_FLAG_UNIXDATE)
+               sprintf(last_played_time, "%llu",
+                       (long long unsigned)afsi->last_played);
+       else {
+               ret = get_local_time(&afsi->last_played, last_played_time,
+                       sizeof(last_played_time), current_time, opts->mode);
+               if (ret < 0)
+                       goto out;
+       }
        get_duration_buf(afhi->seconds_total, duration_buf, opts);
        if (have_score) {
                if (opts->mode == LS_MODE_LONG)
@@ -980,16 +990,95 @@ void make_empty_status_items(char *buf)
        );
 }
 
-static int make_status_items(struct ls_data *d, struct para_buffer *pb)
+static void fixup_taginfo(char *begin, char *end)
+{
+       char *p = begin;
+
+       for (;;) {
+               p = strchr(p, '\n');
+               if (!p)
+                       break;
+               if (p >= end - 1)
+                       break;
+               *p = ' ';
+               p++;
+       }
+}
+
+/* crap, remove this ASAP. */
+static int fixup_info_string(char *info_string)
+{
+       char *t1, *t2, *end;
+
+       if (strncmp(info_string, "audio_file_info:", 16))
+               return -ERRNO_TO_PARA_ERROR(EINVAL);
+       t1 = strstr(info_string, "\ntaginfo1:");
+       if (!t1)
+               return -ERRNO_TO_PARA_ERROR(EINVAL);
+       t2 = strstr(info_string, "\ntaginfo2: ");
+       if (!t2)
+               return -ERRNO_TO_PARA_ERROR(EINVAL);
+
+       end = t2 + strlen(t2) + 1;
+       fixup_taginfo(info_string + 16, t1);
+       fixup_taginfo(t1 + 10, t2);
+       fixup_taginfo(t2 + 10, end);
+
+       if (t1 - info_string < 80 && t2 - t1 < 80 && end - t2 < 80)
+               return 0;
+       if (t1 - info_string >= 80) {
+               memmove(info_string + 80, t1, end - t1);
+               t1 = info_string + 80;
+               t2 -= t1 - info_string - 80;
+               end -= t1 - info_string - 80;
+       }
+       if (t2 - t1 >= 80) {
+               memmove(t1 + 80, t2, end - t2);
+               end -= t2 - t1 - 80;
+               t2 = t1 + 80;
+       }
+       if (end - t2 >= 80) {
+               t2[78] = '\n';
+               t2[79] = '\0';
+       }
+       return 1;
+}
+
+static int make_status_items(struct audio_file_data *afd,
+               struct afs_info *afsi, char *path, long score,
+               HASH_TYPE *hash)
 {
+       struct ls_data d = {
+               .afhi = afd->afhi,
+               .afsi = *afsi,
+               .path = path,
+               .score = score,
+               .hash = hash
+       };
        struct ls_options opts = {
                .flags = LS_FLAG_FULL_PATH | LS_FLAG_ADMISSIBLE_ONLY,
                .mode = LS_MODE_VERBOSE,
        };
+       struct para_buffer pb = {.max_size = VERBOSE_LS_OUTPUT_SIZE - 1};
        time_t current_time;
+       int ret;
 
+       ret = fixup_info_string(afd->afhi.info_string);
+       if (ret < 0) {
+               PARA_WARNING_LOG("ignoring invalid tag info\n");
+               afd->afhi.info_string[0] = '\0';
+       } else if (ret)
+               PARA_NOTICE_LOG("truncated overlong tag info\n");
        time(&current_time);
-       return print_list_item(d, &opts, pb, current_time);
+       ret = print_list_item(&d, &opts, &pb, current_time); /* frees info string */
+       afd->afhi.info_string = NULL;
+       if (ret < 0)
+               goto out;
+       strncpy(afd->verbose_ls_output, pb.buf, VERBOSE_LS_OUTPUT_SIZE);
+       afd->verbose_ls_output[VERBOSE_LS_OUTPUT_SIZE - 1] = '\0';
+out:
+       free(pb.buf);
+       return ret;
 }
 
 /**
@@ -1052,23 +1141,9 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
        save_afsi(&new_afsi, &afsi_obj); /* in-place update */
 
        load_chunk_table(&afd->afhi, chunk_table_obj.data);
-       {
-               struct ls_data d = {
-                       .afhi = afd->afhi, /* struct copy */
-                       .afsi = old_afsi,
-                       .path = path,
-                       .score = score,
-                       .hash = file_hash
-               };
-               struct para_buffer pb = {.max_size = VERBOSE_LS_OUTPUT_SIZE - 1};
-               ret = make_status_items(&d, &pb); /* frees info string */
-               afd->afhi.info_string = NULL;
-               if (ret < 0)
-                       goto err;
-               strncpy(afd->verbose_ls_output, pb.buf, VERBOSE_LS_OUTPUT_SIZE);
-               afd->verbose_ls_output[VERBOSE_LS_OUTPUT_SIZE - 1] = '\0';
-               free(pb.buf);
-       }
+       ret = make_status_items(afd, &old_afsi, path, score, file_hash);
+       if (ret < 0)
+               goto err;
        aced.aft_row = aft_row;
        aced.old_afsi = &old_afsi;
        afs_event(AFSI_CHANGE, NULL, &aced);
@@ -1337,7 +1412,7 @@ out:
 /*
  * TODO: flags -h (sort by hash)
  */
-int com_ls(int fd, int argc, char * const * const argv)
+int com_ls(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int i, ret;
        unsigned flags = 0;
@@ -1393,6 +1468,10 @@ int com_ls(int fd, int argc, char * const * const argv)
                        flags |= LS_FLAG_REVERSE;
                        continue;
                }
+               if (!strcmp(arg, "-d")) {
+                       flags |= LS_FLAG_UNIXDATE;
+                       continue;
+               }
                if (!strncmp(arg, "-s", 2)) {
                        if (!*(arg + 2) || *(arg + 3))
                                return -E_AFT_SYNTAX;
@@ -1442,7 +1521,7 @@ int com_ls(int fd, int argc, char * const * const argv)
        opts.mode = mode;
        opts.num_patterns = argc - i;
        ret = send_option_arg_callback_request(&query, opts.num_patterns,
-               argv + i, com_ls_callback, send_result, &fd);
+               argv + i, com_ls_callback, rc4_send_result, rc4c);
        return ret;
 }
 
@@ -1729,8 +1808,8 @@ out:
 
 /** Used by com_add(). */
 struct private_add_data {
-       /** The socket file descriptor. */
-       int fd;
+       /** The socket file descriptor, including rc4 keys. */
+       struct rc4_context *rc4c;
        /** The given add flags. */
        uint32_t flags;
 };
@@ -1785,7 +1864,8 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = send_va_buffer(pad->fd, "lazy-ignore: %s\n", path);
+                       send_ret = rc4_send_va_buffer(pad->rc4c,
+                               "lazy-ignore: %s\n", path);
                goto out_free;
        }
        /* We still want to add this file. Compute its hash. */
@@ -1805,7 +1885,7 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = send_va_buffer(pad->fd,
+                       send_ret = rc4_send_va_buffer(pad->rc4c,
                                "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
@@ -1823,13 +1903,13 @@ static int add_one_audio_file(const char *path, void *private_data)
        munmap(map.data, map.size);
        close(fd);
        if (pad->flags & ADD_FLAG_VERBOSE) {
-               send_ret = send_va_buffer(pad->fd, "adding %s\n", path);
+               send_ret = rc4_send_va_buffer(pad->rc4c, "adding %s\n", path);
                if (send_ret < 0)
                        goto out_free;
        }
        save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
        /* Ask afs to consider this entry for adding. */
-       ret = send_callback_request(com_add_callback, &obj, send_result, &pad->fd);
+       ret = send_callback_request(com_add_callback, &obj, rc4_send_result, pad->rc4c);
        goto out_free;
 
 out_unmap:
@@ -1837,8 +1917,8 @@ out_unmap:
        munmap(map.data, map.size);
 out_free:
        if (ret < 0 && send_ret >= 0)
-               send_ret = send_va_buffer(pad->fd, "failed to add %s (%s)\n", path,
-                       para_strerror(-ret));
+               send_ret = rc4_send_va_buffer(pad->rc4c,
+                       "failed to add %s (%s)\n", path, para_strerror(-ret));
        free(obj.data);
        if (afhi_ptr) {
                free(afhi_ptr->chunk_table);
@@ -1848,10 +1928,10 @@ out_free:
        return send_ret;
 }
 
-int com_add(int fd, int argc, char * const * const argv)
+int com_add(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int i, ret;
-       struct private_add_data pad = {.fd = fd, .flags = 0};
+       struct private_add_data pad = {.rc4c = rc4c, .flags = 0};
        struct stat statbuf;
 
        for (i = 1; i < argc; i++) {
@@ -1885,7 +1965,7 @@ int com_add(int fd, int argc, char * const * const argv)
                char *path;
                ret = verify_path(argv[i], &path);
                if (ret < 0) {
-                       ret = send_va_buffer(fd, "%s: %s\n", argv[i],
+                       ret = rc4_send_va_buffer(rc4c, "%s: %s\n", argv[i],
                                para_strerror(-ret));
                        if (ret < 0)
                                return ret;
@@ -1893,7 +1973,7 @@ int com_add(int fd, int argc, char * const * const argv)
                }
                ret = stat(path, &statbuf);
                if (ret < 0) {
-                       ret = send_va_buffer(fd, "failed to stat %s (%s)\n", path,
+                       ret = rc4_send_va_buffer(rc4c, "failed to stat %s (%s)\n", path,
                                strerror(errno));
                        free(path);
                        if (ret < 0)
@@ -1906,7 +1986,7 @@ int com_add(int fd, int argc, char * const * const argv)
                else
                        ret = add_one_audio_file(path, &pad);
                if (ret < 0) {
-                       send_va_buffer(fd, "%s: %s\n", path, para_strerror(-ret));
+                       rc4_send_va_buffer(rc4c, "%s: %s\n", path, para_strerror(-ret));
                        free(path);
                        return ret;
                }
@@ -2038,7 +2118,7 @@ static void com_touch_callback(int fd, const struct osl_object *query)
        free(tad.pb.buf);
 }
 
-int com_touch(int fd, int argc, char * const * const argv)
+int com_touch(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        struct com_touch_options cto = {
                .num_played = -1,
@@ -2106,9 +2186,9 @@ int com_touch(int fd, int argc, char * const * const argv)
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i,
-               argv + i, com_touch_callback, send_result, &fd);
+               argv + i, com_touch_callback, rc4_send_result, rc4c);
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -2190,7 +2270,7 @@ static void com_rm_callback(int fd, const struct osl_object *query)
 }
 
 /* TODO options: -r (recursive) */
-int com_rm(int fd, int argc,  char * const * const argv)
+int com_rm(struct rc4_context *rc4c, int argc,  char * const * const argv)
 {
        uint32_t flags = 0;
        struct osl_object query = {.data = &flags, .size = sizeof(flags)};
@@ -2221,9 +2301,9 @@ int com_rm(int fd, int argc,  char * const * const argv)
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i, argv + i,
-               com_rm_callback, send_result, &fd);
+               com_rm_callback, rc4_send_result, rc4c);
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
@@ -2338,7 +2418,7 @@ out:
        free(cad.pb.buf);
 }
 
-int com_cpsi(int fd, int argc,  char * const * const argv)
+int com_cpsi(struct rc4_context *rc4c, int argc,  char * const * const argv)
 {
        unsigned flags = 0;
        int i, ret;
@@ -2383,9 +2463,9 @@ int com_cpsi(int fd, int argc,  char * const * const argv)
        if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
                flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_cpsi_callback, send_result, &fd);
+               com_cpsi_callback, rc4_send_result, rc4c);
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }