diff --git a/commandline.c b/commandline.c index 21e37b7f..a98ef988 100644 --- a/commandline.c +++ b/commandline.c @@ -1818,25 +1818,94 @@ int app_rhizome_list(const struct cli_parsed *parsed, struct cli_context *contex { if (config.debug.verbose) DEBUG_cli_parsed(parsed); - const char *service, *name, *sender_sid, *recipient_sid, *offset, *limit; + const char *service = NULL, *name = NULL, *sender_hex = NULL, *recipient_hex = NULL, *offset_ascii = NULL, *limit_ascii = NULL; cli_arg(parsed, "service", &service, NULL, ""); cli_arg(parsed, "name", &name, NULL, ""); - cli_arg(parsed, "sender_sid", &sender_sid, cli_optional_sid, ""); - cli_arg(parsed, "recipient_sid", &recipient_sid, cli_optional_sid, ""); - cli_arg(parsed, "offset", &offset, cli_uint, "0"); - cli_arg(parsed, "limit", &limit, cli_uint, "0"); + cli_arg(parsed, "sender_sid", &sender_hex, cli_optional_sid, ""); + cli_arg(parsed, "recipient_sid", &recipient_hex, cli_optional_sid, ""); + cli_arg(parsed, "offset", &offset_ascii, cli_uint, "0"); + cli_arg(parsed, "limit", &limit_ascii, cli_uint, "0"); /* Create the instance directory if it does not yet exist */ if (create_serval_instance_dir() == -1) return -1; if (!(keyring = keyring_open_instance_cli(parsed))) return -1; - - int r=-1; - if (rhizome_opendb() != -1){ - r=rhizome_list_manifests(context, service, name, sender_sid, recipient_sid, atoi(offset), atoi(limit), 0); + if (rhizome_opendb() == -1) { + keyring_free(keyring); + return -1; } + size_t rowlimit = atoi(limit_ascii); + size_t rowoffset = atoi(offset_ascii); + struct rhizome_list_cursor cursor; + bzero(&cursor, sizeof cursor); + cursor.service = service && service[0] ? service : NULL; + cursor.name = name && name[0] ? name : NULL; + if (sender_hex && sender_hex[0]) { + if (str_to_sid_t(&cursor.sender, sender_hex) == -1) + return WHYF("Invalid : %s", sender_hex); + cursor.is_sender_set = 1; + } + if (recipient_hex && recipient_hex[0]) { + if (str_to_sid_t(&cursor.recipient, recipient_hex) == -1) + return WHYF("Invalid filesize != RHIZOME_SIZE_UNSET); + if (cursor.rowcount < rowoffset) + continue; + if (rowlimit != 0 && cursor.rowcount > rowlimit) + break; + rhizome_lookup_author(m); + cli_put_long(context, cursor.rowid, ":"); + cli_put_string(context, m->service, ":"); + cli_put_hexvalue(context, m->cryptoSignPublic.binary, sizeof m->cryptoSignPublic.binary, ":"); + cli_put_long(context, m->version, ":"); + cli_put_long(context, m->has_date ? m->date : 0, ":"); + cli_put_long(context, m->inserttime, ":"); + switch (m->authorship) { + case AUTHOR_LOCAL: + case AUTHOR_AUTHENTIC: + cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":"); + cli_put_long(context, 1, ":"); + break; + default: + cli_put_string(context, NULL, ":"); + cli_put_long(context, 0, ":"); + break; + } + cli_put_long(context, m->filesize, ":"); + cli_put_hexvalue(context, m->filesize ? m->filehash.binary : NULL, sizeof m->filehash.binary, ":"); + cli_put_hexvalue(context, m->has_sender ? m->sender.binary : NULL, sizeof m->sender.binary, ":"); + cli_put_hexvalue(context, m->has_recipient ? m->recipient.binary : NULL, sizeof m->recipient.binary, ":"); + cli_put_string(context, m->name, "\n"); + } + rhizome_list_release(&cursor); + cli_row_count(context, cursor.rowcount); keyring_free(keyring); - return r; + return 0; } int app_keyring_create(const struct cli_parsed *parsed, struct cli_context *context) diff --git a/rhizome.h b/rhizome.h index 93981aab..ea712679 100644 --- a/rhizome.h +++ b/rhizome.h @@ -564,9 +564,6 @@ int64_t rhizome_bar_version(const unsigned char *bar); uint64_t rhizome_bar_bidprefix_ll(unsigned char *bar); int rhizome_is_bar_interesting(unsigned char *bar); int rhizome_is_manifest_interesting(rhizome_manifest *m); -int rhizome_list_manifests(struct cli_context *context, const char *service, const char *name, - const char *sender_sid, const char *recipient_sid, - size_t rowlimit, size_t rowoffset, char count_rows); int rhizome_retrieve_manifest(const rhizome_bid_t *bid, rhizome_manifest *m); int rhizome_retrieve_manifest_by_prefix(const unsigned char *prefix, unsigned prefix_len, rhizome_manifest *m); int rhizome_advertise_manifest(struct subscriber *dest, rhizome_manifest *m); @@ -613,6 +610,29 @@ int rhizome_verify_bundle_privatekey(const unsigned char *sk, const unsigned cha int rhizome_queue_ignore_manifest(unsigned char *bid_prefix, int prefix_len, int timeout); int rhizome_ignore_manifest_check(unsigned char *bid_prefix, int prefix_len); +/* Rhizome list cursor for iterating over all or a subset of manifests in the store. + */ +struct rhizome_list_cursor { + // Query parameters that narrow the set of listed bundles. + const char *service; + const char *name; + bool_t is_sender_set; + bool_t is_recipient_set; + sid_t sender; + sid_t recipient; + // Set by calling the next() function. + int64_t rowid; + rhizome_manifest *manifest; + size_t rowcount; + // Private state. + sqlite3_stmt *_statement; + unsigned _offset; +}; + +int rhizome_list_open(sqlite_retry_state *, struct rhizome_list_cursor *); +int rhizome_list_next(sqlite_retry_state *, struct rhizome_list_cursor *); +void rhizome_list_release(struct rhizome_list_cursor *); + /* one manifest is required per candidate, plus a few spare. so MAX_RHIZOME_MANIFESTS must be > MAX_CANDIDATES. */ diff --git a/rhizome_database.c b/rhizome_database.c index f6791e30..4005b312 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1407,27 +1407,12 @@ rollback: return -1; } -struct rhizome_list_cursor { - // Query parameters that narrow the set of listed bundles. - const char *service; - const char *name; - sid_t sender; - sid_t recipient; - // Set by calling the next() function. - int64_t rowid; - rhizome_manifest *manifest; - size_t rowcount; - // Private state. - sqlite3_stmt *_statement; - unsigned _offset; -}; - /* The cursor struct must be zerofilled and the query parameters optionally filled in prior to * calling this function. * * @author Andrew Bettison */ -static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor) +int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor) { IN(); strbuf b = strbuf_alloca(1024); @@ -1436,9 +1421,9 @@ static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_curs strbuf_puts(b, " AND service = @service"); if (cursor->name) strbuf_puts(b, " AND name like @name"); - if (!is_sid_t_any(cursor->sender)) + if (cursor->is_sender_set) strbuf_puts(b, " AND sender = @sender"); - if (!is_sid_t_any(cursor->recipient)) + if (cursor->is_recipient_set) strbuf_puts(b, " AND recipient = @recipient"); strbuf_puts(b, " ORDER BY inserttime DESC LIMIT -1 OFFSET @offset"); if (strbuf_overrun(b)) @@ -1452,9 +1437,9 @@ static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_curs goto failure; if (cursor->name && sqlite_bind(retry, cursor->_statement, NAMED|STATIC_TEXT, "@name", cursor->name, END) == -1) goto failure; - if (!is_sid_t_any(cursor->sender) && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@sender", &cursor->sender, END) == -1) + if (cursor->is_sender_set && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@sender", &cursor->sender, END) == -1) goto failure; - if (!is_sid_t_any(cursor->recipient) && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@recipient", &cursor->recipient, END) == -1) + if (cursor->is_recipient_set && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@recipient", &cursor->recipient, END) == -1) goto failure; cursor->manifest = NULL; RETURN(0); @@ -1466,7 +1451,7 @@ failure: OUT(); } -static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor) +int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor) { IN(); if (cursor->_statement == NULL && rhizome_list_open(retry, cursor) == -1) @@ -1516,9 +1501,9 @@ static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_curs rhizome_manifest_set_inserttime(m, q_inserttime); if (cursor->service && !(m->service && strcasecmp(cursor->service, m->service) == 0)) continue; - if (!is_sid_t_any(cursor->sender) && !(m->has_sender && cmp_sid_t(&cursor->sender, &m->sender) == 0)) + if (cursor->is_sender_set && !(m->has_sender && cmp_sid_t(&cursor->sender, &m->sender) == 0)) continue; - if (!is_sid_t_any(cursor->recipient) && !(m->has_recipient && cmp_sid_t(&cursor->recipient, &m->recipient) == 0)) + if (cursor->is_recipient_set && !(m->has_recipient && cmp_sid_t(&cursor->recipient, &m->recipient) == 0)) continue; // Don't do rhizome_verify_author(m); too CPU expensive for a listing. Save that for when // the bundle is extracted or exported. @@ -1529,7 +1514,7 @@ static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_curs OUT(); } -static void rhizome_list_release(struct rhizome_list_cursor *cursor) +void rhizome_list_release(struct rhizome_list_cursor *cursor) { if (cursor->manifest) { rhizome_manifest_free(cursor->manifest); @@ -1541,76 +1526,6 @@ static void rhizome_list_release(struct rhizome_list_cursor *cursor) } } -int rhizome_list_manifests(struct cli_context *context, const char *service, const char *name, - const char *sender_hex, const char *recipient_hex, - size_t rowlimit, size_t rowoffset, char count_rows) -{ - IN(); - struct rhizome_list_cursor cursor; - bzero(&cursor, sizeof cursor); - cursor.service = service && service[0] ? service : NULL; - cursor.name = name && name[0] ? name : NULL; - if (sender_hex && *sender_hex && str_to_sid_t(&cursor.sender, sender_hex) == -1) - RETURN(WHYF("Invalid sender SID: %s", sender_hex)); - if (recipient_hex && *recipient_hex && str_to_sid_t(&cursor.recipient, recipient_hex) == -1) - RETURN(WHYF("Invalid recipient SID: %s", recipient_hex)); - sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; - if (rhizome_list_open(&retry, &cursor) == -1) - RETURN(-1); - const char *names[]={ - "_id", - "service", - "id", - "version", - "date", - ".inserttime", - ".author", - ".fromhere", - "filesize", - "filehash", - "sender", - "recipient", - "name" - }; - cli_columns(context, NELS(names), names); - while (rhizome_list_next(&retry, &cursor) == 1) { - rhizome_manifest *m = cursor.manifest; - assert(m->filesize != RHIZOME_SIZE_UNSET); - if (cursor.rowcount < rowoffset) - continue; - if (rowlimit == 0 || cursor.rowcount <= rowlimit) { - rhizome_lookup_author(m); - cli_put_long(context, cursor.rowid, ":"); - cli_put_string(context, m->service, ":"); - cli_put_hexvalue(context, m->cryptoSignPublic.binary, sizeof m->cryptoSignPublic.binary, ":"); - cli_put_long(context, m->version, ":"); - cli_put_long(context, m->has_date ? m->date : 0, ":"); - cli_put_long(context, m->inserttime, ":"); - switch (m->authorship) { - case AUTHOR_LOCAL: - case AUTHOR_AUTHENTIC: - cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":"); - cli_put_long(context, 1, ":"); - break; - default: - cli_put_string(context, NULL, ":"); - cli_put_long(context, 0, ":"); - break; - } - cli_put_long(context, m->filesize, ":"); - cli_put_hexvalue(context, m->filesize ? m->filehash.binary : NULL, sizeof m->filehash.binary, ":"); - cli_put_hexvalue(context, m->has_sender ? m->sender.binary : NULL, sizeof m->sender.binary, ":"); - cli_put_hexvalue(context, m->has_recipient ? m->recipient.binary : NULL, sizeof m->recipient.binary, ":"); - cli_put_string(context, m->name, "\n"); - } else if (!count_rows) - break; - } - rhizome_list_release(&cursor); - cli_row_count(context, cursor.rowcount); - RETURN(0); - OUT(); -} - void rhizome_bytes_to_hex_upper(unsigned const char *in, char *out, int byteCount) { (void) tohex(out, byteCount * 2, in);