Issue #17, add AUTHOR column to Rhizome MANIFESTS table

Replace ".selfsigned" column with ".author" and ".fromhere" columns in
output of "rhizome list" command.  (Note that a "sender" column is
already present.)

Add 'author' field to struct rhizome_manifest.

Log all fully rendered SQL statements on DEBUG_RHIZOME.

Update 'rhizomeops' test cases and improve the assert_rhizome_list()
test function to be able to assert authorship of files.
This commit is contained in:
Andrew Bettison 2012-10-09 17:43:34 +10:30
parent 1de2bc8f23
commit 3678522872
8 changed files with 138 additions and 73 deletions

View File

@ -1030,8 +1030,13 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
}
/* Bind an ID to the manifest, and also bind the file. Then finalise the manifest.
But if the manifest already contains an ID, don't override it. */
if (authorSidHex[0]) {
if (debug & DEBUG_RHIZOME)
DEBUGF("author=%s", authorSidHex);
memcpy(m->author, authorSid, SID_SIZE);
}
if (rhizome_manifest_get(m, "id", NULL, 0) == NULL) {
if (rhizome_manifest_bind_id(m, authorSidHex[0] ? authorSid : NULL)) {
if (rhizome_manifest_bind_id(m) == -1) {
rhizome_manifest_free(m);
m = NULL;
return WHY("Could not bind manifest to an ID");
@ -1067,12 +1072,9 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
PGS @20121003 - Hang on, didn't we create the ID above? Presumably the
following does NOT in fact generate a bundle ID.
*/
rhizome_manifest *mout = NULL;
if (debug & DEBUG_RHIZOME) DEBUGF("rhizome_add_manifest(author='%s')", authorSidHex);
int ret=0;
if (rhizome_manifest_check_duplicate(m,&mout)==2)
{
rhizome_manifest *mout = NULL;
if (rhizome_manifest_check_duplicate(m, &mout) == 2) {
/* duplicate found -- verify it so that we can write it out later */
rhizome_manifest_verify(mout);
ret=2;
@ -1082,7 +1084,7 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
rhizome_manifest_free(m);
return WHY("Could not finalise manifest");
}
if (rhizome_add_manifest(m,255 /* TTL */)) {
if (rhizome_add_manifest(m, 255 /* TTL */)) {
rhizome_manifest_free(m);
return WHY("Manifest not added to Rhizome database");
}
@ -1090,7 +1092,7 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
/* If successfully added, overwrite the manifest file so that the Java component that is
invoking this command can read it to obtain feedback on the result. */
rhizome_manifest *mwritten=mout?mout:m;
rhizome_manifest *mwritten = mout ? mout : m;
if (manifestpath[0]
&& rhizome_write_manifest_file(mwritten, manifestpath) == -1)
ret = WHY("Could not overwrite manifest file.");

View File

@ -149,9 +149,10 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in)
by joining the parent group.
*/
int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *authorSid)
int rhizome_manifest_bind_id(rhizome_manifest *m_in)
{
rhizome_manifest_createid(m_in);
if (rhizome_manifest_createid(m_in) == -1)
return -1;
/* The ID is implicit in transit, but we need to store it in the file, so that reimporting
manifests on receiver nodes works easily. We might implement something that strips the id
variable out of the manifest when sending it, or some other scheme to avoid sending all the
@ -159,7 +160,7 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *author
char id[RHIZOME_MANIFEST_ID_STRLEN + 1];
rhizome_bytes_to_hex_upper(m_in->cryptoSignPublic, id, RHIZOME_MANIFEST_ID_BYTES);
rhizome_manifest_set(m_in, "id", id);
if (authorSid) {
if (!is_sid_any(m_in->author)) {
/* Set the BK using the provided authorship information.
Serval Security Framework defines BK as being:
BK = privateKey XOR sha512(RS##BID), where BID = cryptoSignPublic,
@ -168,7 +169,7 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *author
privateKey = BK XOR sha512(RS##BID), so the same function can be used
to encrypt and decrypt the BK field. */
unsigned char bkbytes[RHIZOME_BUNDLE_KEY_BYTES];
if (rhizome_bk_xor(authorSid, m_in->cryptoSignPublic, m_in->cryptoSignSecret, bkbytes) == 0) {
if (rhizome_bk_xor(m_in->author, m_in->cryptoSignPublic, m_in->cryptoSignSecret, bkbytes) == 0) {
char bkhex[RHIZOME_BUNDLE_KEY_STRLEN + 1];
(void) tohex(bkhex, bkbytes, RHIZOME_BUNDLE_KEY_BYTES);
if (debug&DEBUG_RHIZOME) DEBUGF("set BK=%s", bkhex);
@ -281,7 +282,7 @@ int rhizome_manifest_check_file(rhizome_manifest *m_in)
/* Check if a manifest is already stored for the same payload with the same details.
This catches the case of "dna rhizome add file <filename>" on the same file more than once.
(Debounce!) */
int rhizome_manifest_check_duplicate(rhizome_manifest *m_in,rhizome_manifest **m_out)
int rhizome_manifest_check_duplicate(rhizome_manifest *m_in, rhizome_manifest **m_out)
{
if (debug & DEBUG_RHIZOME) DEBUG("Checking for duplicate");
if (m_out) *m_out = NULL;

View File

@ -132,6 +132,11 @@ typedef struct rhizome_manifest {
int group_count;
char *groups[MAX_MANIFEST_VARS];
/* Author of the manifest. A reference to a local keyring entry. Manifests
* not authored locally will have the ANY author (all zeros).
*/
unsigned char author[SID_SIZE];
} rhizome_manifest;
/* Supported service identifiers. These go in the 'service' field of every
@ -222,7 +227,7 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in);
int rhizome_manifest_check_file(rhizome_manifest *m_in);
int rhizome_manifest_check_duplicate(rhizome_manifest *m_in,rhizome_manifest **m_out);
int rhizome_manifest_bind_id(rhizome_manifest *m_in, const unsigned char *authorSid);
int rhizome_manifest_bind_id(rhizome_manifest *m_in);
int rhizome_manifest_bind_file(rhizome_manifest *m_in,const char *filename,int encryptP);
int rhizome_manifest_finalise(rhizome_manifest *m);
int rhizome_add_manifest(rhizome_manifest *m_in,int ttl);

View File

@ -112,10 +112,14 @@ int rhizome_extract_privatekey(rhizome_manifest *m, const unsigned char *authorS
/*
Test to see if the given manifest was created (signed) by any unlocked identity currently in the
keyring.
Returns -1 if an error occurs, eg, the manifest contains an invalid BK field.
Return 0 if the manifest's BK field was produced by any currently unlocked SID.
Returns 1 if the manifest has no BK field.
Returns 2 otherwise.
- Returns -1 if an error occurs, eg, the manifest contains an invalid BK field.
- Return 0 if the manifest's BK field was produced by any currently unlocked SID.
- Returns 1 if the manifest has no BK field.
- Returns 2 otherwise.
Currently unused; was called from rhizome_list_manifests() to compute the now-defunct
".selfsigned" column, but that made the Rhizome List view too slow in the Serval Mesh app.
See issue servalproject/serval-dna#17.
@author Andrew Bettison <andrew@servalproject.com>
*/
int rhizome_is_self_signed(rhizome_manifest *m)
{

View File

@ -120,6 +120,12 @@ int rhizome_manifest_priority(sqlite_retry_state *retry, const char *id)
return (int) result;
}
static void sqlite_trace_callback(void *context, const char *rendered_sql)
{
if (debug & DEBUG_RHIZOME)
DEBUG(rendered_sql);
}
int rhizome_opendb()
{
if (rhizome_db) return 0;
@ -137,6 +143,7 @@ int rhizome_opendb()
if (sqlite3_open(dbpath,&rhizome_db)){
RETURN(WHYF("SQLite could not open database %s: %s", dbpath, sqlite3_errmsg(rhizome_db)));
}
sqlite3_trace(rhizome_db, sqlite_trace_callback, NULL);
int loglevel = (debug & DEBUG_RHIZOME) ? LOG_LEVEL_DEBUG : LOG_LEVEL_SILENT;
/* Read Rhizome configuration */
@ -149,7 +156,7 @@ int rhizome_opendb()
/* Create tables as required */
sqlite_exec_void_loglevel(loglevel, "PRAGMA auto_vacuum=2;");
if ( sqlite_exec_void("CREATE TABLE IF NOT EXISTS GROUPLIST(id text not null primary key, closed integer,ciphered integer,priority integer);") == -1
|| sqlite_exec_void("CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, manifest blob, version integer,inserttime integer, bar blob, filesize integer, filehash text);") == -1
|| sqlite_exec_void("CREATE TABLE IF NOT EXISTS MANIFESTS(id text not null primary key, manifest blob, version integer,inserttime integer, bar blob, filesize integer, filehash text, author text);") == -1
|| sqlite_exec_void("CREATE TABLE IF NOT EXISTS FILES(id text not null primary key, data blob, length integer, highestpriority integer, datavalid integer, inserttime integer);") == -1
|| sqlite_exec_void("DROP TABLE IF EXISTS FILEMANIFESTS;") == -1
|| sqlite_exec_void("CREATE TABLE IF NOT EXISTS GROUPMEMBERSHIPS(manifestid text not null, groupid text not null);") == -1
@ -159,7 +166,7 @@ int rhizome_opendb()
}
/* Create indexes if they don't already exist */
sqlite_exec_void_loglevel(LOG_LEVEL_WARN,"CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);");
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS bundlesizeindex ON manifests (filesize);");
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_HASH ON MANIFESTS(filehash);");
/* Clean out half-finished entries from the database */
@ -669,12 +676,14 @@ int rhizome_store_bundle(rhizome_manifest *m)
filehash[0] = '\0';
}
const char *author = is_sid_any(m->author) ? NULL : alloca_tohex_sid(m->author);
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
return -1;
sqlite3_stmt *stmt;
if ((stmt = sqlite_prepare(&retry, "INSERT OR REPLACE INTO MANIFESTS(id,manifest,version,inserttime,bar,filesize,filehash) VALUES(?,?,?,?,?,?,?);")) == NULL)
if ((stmt = sqlite_prepare(&retry, "INSERT OR REPLACE INTO MANIFESTS(id,manifest,version,inserttime,bar,filesize,filehash,author) VALUES(?,?,?,?,?,?,?,?);")) == NULL)
goto rollback;
if (!( sqlite_code_ok(sqlite3_bind_text(stmt, 1, manifestid, -1, SQLITE_TRANSIENT))
&& sqlite_code_ok(sqlite3_bind_blob(stmt, 2, m->manifestdata, m->manifest_bytes, SQLITE_TRANSIENT))
@ -683,6 +692,7 @@ int rhizome_store_bundle(rhizome_manifest *m)
&& sqlite_code_ok(sqlite3_bind_blob(stmt, 5, bar, RHIZOME_BAR_BYTES, SQLITE_TRANSIENT))
&& sqlite_code_ok(sqlite3_bind_int64(stmt, 6, m->fileLength))
&& sqlite_code_ok(sqlite3_bind_text(stmt, 7, filehash, -1, SQLITE_TRANSIENT))
&& sqlite_code_ok(sqlite3_bind_text(stmt, 8, author, -1, SQLITE_TRANSIENT))
)) {
WHYF("query failed, %s: %s", sqlite3_errmsg(rhizome_db), sqlite3_sql(stmt));
goto rollback;
@ -758,7 +768,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
{
IN();
strbuf b = strbuf_alloca(1024);
strbuf_sprintf(b, "SELECT id, manifest, version, inserttime FROM manifests ORDER BY inserttime DESC");
strbuf_sprintf(b, "SELECT id, manifest, version, inserttime, author FROM manifests ORDER BY inserttime DESC");
if (limit)
strbuf_sprintf(b, " LIMIT %u", limit);
if (offset)
@ -771,13 +781,14 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
return -1;
int ret = 0;
size_t rows = 0;
cli_puts("11"); cli_delim("\n"); // number of columns
cli_puts("12"); cli_delim("\n"); // number of columns
cli_puts("service"); cli_delim(":");
cli_puts("id"); cli_delim(":");
cli_puts("version"); cli_delim(":");
cli_puts("date"); cli_delim(":");
cli_puts(".inserttime"); cli_delim(":");
cli_puts(".selfsigned"); cli_delim(":");
cli_puts(".author"); cli_delim(":");
cli_puts(".fromhere"); cli_delim(":");
cli_puts("filesize"); cli_delim(":");
cli_puts("filehash"); cli_delim(":");
cli_puts("sender"); cli_delim(":");
@ -785,11 +796,14 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
cli_puts("name"); cli_delim("\n"); // should be last, because name may contain ':'
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
++rows;
if (!( sqlite3_column_count(statement) == 4
if (!( sqlite3_column_count(statement) == 5
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
&& sqlite3_column_type(statement, 3) == SQLITE_INTEGER
&& ( sqlite3_column_type(statement, 4) == SQLITE_TEXT
|| sqlite3_column_type(statement, 4) == SQLITE_NULL
)
)) {
ret = WHY("Incorrect statement column");
break;
@ -804,6 +818,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob()
long long q_version = sqlite3_column_int64(statement, 2);
long long q_inserttime = sqlite3_column_int64(statement, 3);
const char *q_author = (const char *) sqlite3_column_text(statement, 4);
if (rhizome_read_manifest_file(m, manifestblob, manifestblobsize) == -1) {
WARNF("MANIFESTS row id=%s has invalid manifest blob -- skipped", q_manifestid);
} else {
@ -829,14 +844,29 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
long long blob_date = rhizome_manifest_get_ll(m, "date");
const char *blob_filehash = rhizome_manifest_get(m, "filehash", NULL, 0);
long long blob_filesize = rhizome_manifest_get_ll(m, "filesize");
int self_signed = rhizome_is_self_signed(m) ? 0 : 1;
int from_here = 0;
if (q_author) {
DEBUGF("q_author=%s", alloca_str_toprint(q_author));
unsigned char authorSid[SID_SIZE];
stowSid(authorSid, 0, q_author);
int cn = 0, in = 0, kp = 0;
from_here = keyring_find_sid(keyring, &cn, &in, &kp, authorSid);
}
if (!from_here && blob_sender) {
DEBUGF("blob_sender=%s", alloca_str_toprint(blob_sender));
unsigned char senderSid[SID_SIZE];
stowSid(senderSid, 0, blob_sender);
int cn = 0, in = 0, kp = 0;
from_here = keyring_find_sid(keyring, &cn, &in, &kp, senderSid);
}
if (debug & DEBUG_RHIZOME) DEBUGF("manifest payload size = %lld", blob_filesize);
cli_puts(blob_service ? blob_service : ""); cli_delim(":");
cli_puts(q_manifestid); cli_delim(":");
cli_printf("%lld", blob_version); cli_delim(":");
cli_printf("%lld", blob_date); cli_delim(":");
cli_printf("%lld", q_inserttime); cli_delim(":");
cli_printf("%d", self_signed); cli_delim(":");
cli_puts(q_author ? q_author : ""); cli_delim(":");
cli_printf("%d", from_here); cli_delim(":");
cli_printf("%lld", blob_filesize); cli_delim(":");
cli_puts(blob_filehash ? blob_filehash : ""); cli_delim(":");
cli_puts(blob_sender ? blob_sender : ""); cli_delim(":");
@ -1104,7 +1134,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
}
char sqlcmd[1024];
strbuf b = strbuf_local(sqlcmd, sizeof sqlcmd);
strbuf_puts(b, "SELECT id, manifest, version FROM manifests WHERE ");
strbuf_puts(b, "SELECT id, manifest, version, author FROM manifests WHERE ");
if (m->fileLength != 0) {
if (!m->fileHashedP)
return WHY("Manifest payload is not hashed");
@ -1115,8 +1145,6 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
strbuf_puts(b, " AND version = ?");
if (strbuf_overrun(b))
return WHYF("SQL command too long: %s", strbuf_str(b));
if (debug & DEBUG_RHIZOME)
DEBUGF("sql query: %s", sqlcmd);
int ret = 0;
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
sqlite3_stmt *statement = sqlite_prepare(&retry, "%s", strbuf_str(b));
@ -1137,10 +1165,13 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
++rows;
if (debug & DEBUG_RHIZOME) DEBUGF("Row %d", rows);
if (!( sqlite3_column_count(statement) == 3
if (!( sqlite3_column_count(statement) == 4
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
&& ( sqlite3_column_type(statement, 3) == SQLITE_TEXT
|| sqlite3_column_type(statement, 3) == SQLITE_NULL
)
)) {
ret = WHY("Incorrect statement columns");
break;
@ -1220,7 +1251,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
strbuf_sprintf(b, " name=\"%s\"", blob_name);
ret = 1;
}
} else if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) {
} else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) {
const char *blob_sender = rhizome_manifest_get(blob_m, "sender", NULL, 0);
const char *blob_recipient = rhizome_manifest_get(blob_m, "recipient", NULL, 0);
if (blob_sender && !strcasecmp(blob_sender, sender) && blob_recipient && !strcasecmp(blob_recipient, recipient)) {
@ -1230,6 +1261,12 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
}
}
if (ret == 1) {
const char *q_author = (const char *) sqlite3_column_text(statement, 3);
if (q_author) {
if (debug & DEBUG_RHIZOME)
strbuf_sprintf(b, " .author=%s", q_author);
stowSid(blob_m->author, 0, q_author);
}
memcpy(blob_m->cryptoSignPublic, manifest_id, RHIZOME_MANIFEST_ID_BYTES);
memcpy(blob_m->fileHexHash, m->fileHexHash, RHIZOME_FILEHASH_STRLEN + 1);
blob_m->fileHashedP = 1;
@ -1237,7 +1274,7 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
blob_m->version = q_version;
*found = blob_m;
DEBUGF("Found duplicate payload: service=%s%s version=%llu hexhash=%s",
blob_service, strbuf_str(b), blob_m->version, blob_m->fileHexHash
blob_service, strbuf_str(b), blob_m->version, blob_m->fileHexHash, q_author ? q_author : ""
);
break;
}
@ -1263,7 +1300,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
if (fromhexstr(manifest_id, manifestid, RHIZOME_MANIFEST_ID_BYTES) == -1)
return WHY("Invalid manifest ID");
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, manifest, version, inserttime FROM manifests WHERE id = ?");
sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, manifest, version, inserttime, author FROM manifests WHERE id = ?");
if (!statement)
return -1;
char manifestIdUpper[RHIZOME_MANIFEST_ID_STRLEN + 1];
@ -1272,11 +1309,12 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
int ret = 0;
rhizome_manifest *m = NULL;
while (sqlite_step_retry(&retry, statement) == SQLITE_ROW) {
if (!( sqlite3_column_count(statement) == 4
if (!( sqlite3_column_count(statement) == 5
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
&& sqlite3_column_type(statement, 3) == SQLITE_INTEGER
&& sqlite3_column_type(statement, 4) == SQLITE_TEXT
)) {
ret = WHY("Incorrect statement column");
break;
@ -1323,6 +1361,7 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
else
m->version = blob_version;
if (ret == 1) {
const char *q_author = (const char *) sqlite3_column_text(statement, 4);
cli_puts("service"); cli_delim(":");
cli_puts(blob_service); cli_delim("\n");
cli_puts("manifestid"); cli_delim(":");
@ -1331,6 +1370,10 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
cli_printf("%lld", (long long) sqlite3_column_int64(statement, 2)); cli_delim("\n");
cli_puts("inserttime"); cli_delim(":");
cli_printf("%lld", (long long) sqlite3_column_int64(statement, 3)); cli_delim("\n");
if (q_author) {
cli_puts(".author"); cli_delim(":");
cli_puts(q_author); cli_delim("\n");
}
cli_puts("filesize"); cli_delim(":");
cli_printf("%lld", (long long) m->fileLength); cli_delim("\n");
if (m->fileLength != 0) {

View File

@ -251,18 +251,17 @@ int rhizome_direct_form_received(rhizome_http_request *r)
if (debug & DEBUG_RHIZOME) DEBUGF("manifest contains name=\"%s\"", name);
}
const char *senderhex
= rhizome_manifest_get(m, "sender", NULL, 0);
if (!senderhex) senderhex=confValueGet("rhizome.api.addfile.author",NULL);
unsigned char authorSid[SID_SIZE];
if (senderhex) fromhexstr(authorSid,senderhex,SID_SIZE);
const char *bskhex
=confValueGet("rhizome.api.addfile.bundlesecretkey", NULL);
const char *senderhex = rhizome_manifest_get(m, "sender", NULL, 0);
if (!senderhex)
senderhex = confValueGet("rhizome.api.addfile.author", NULL);
if (senderhex)
fromhexstr(m->author, senderhex, SID_SIZE);
const char *bskhex = confValueGet("rhizome.api.addfile.bundlesecretkey", NULL);
/* Bind an ID to the manifest, and also bind the file. Then finalise the
manifest. But if the manifest already contains an ID, don't override it. */
if (rhizome_manifest_get(m, "id", NULL, 0) == NULL) {
if (rhizome_manifest_bind_id(m, senderhex ? authorSid : NULL)) {
if (rhizome_manifest_bind_id(m)) {
rhizome_manifest_free(m);
m = NULL;
rhizome_direct_clear_temporary_files(r);

View File

@ -47,17 +47,22 @@ assert_manifest_complete() {
assert_rhizome_list() {
assertStdoutLineCount --stderr '==' $(($# + 2))
assertStdoutIs --stderr --line=1 -e '11\n'
assertStdoutIs --stderr --line=2 -e 'service:id:version:date:.inserttime:.selfsigned:filesize:filehash:sender:recipient:name\n'
assertStdoutIs --stderr --line=1 -e '12\n'
assertStdoutIs --stderr --line=2 -e 'service:id:version:date:.inserttime:.author:.fromhere:filesize:filehash:sender:recipient:name\n'
local filename
local re__author="\($rexp_sid\)\{0,1\}"
local re__fromhere
local re__inserttime="$rexp_date"
for filename; do
re__selfsigned=1
re__fromhere=1
case "$filename" in
*!) filename="${filename%!}"; re__selfsigned=0;;
*@*) re__author="${filename##*@}"; filename="${filename%@*}";;
esac
case "$filename" in
*!) re__fromhere=0; filename="${filename%!}";;
esac
unpack_manifest_for_grep "$filename"
assertStdoutGrep --stderr --matches=1 "^$re_service:$re_manifestid:$re_version:$re_date:$re__inserttime:$re__selfsigned:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$"
assertStdoutGrep --stderr --matches=1 "^$re_service:$re_manifestid:$re_version:$re_date:$re__inserttime:$re__author:$re__fromhere:$re_filesize:$re_filehash:$re_sender:$re_recipient:$re_name\$"
done
}
@ -110,6 +115,8 @@ unpack_manifest_for_grep() {
re_version="$rexp_version"
re_date="$rexp_date"
re_secret="$rexp_bundlesecret"
re_sender="\($rexp_sid\)\{0,1\}"
re_recipient="\($rexp_sid\)\{0,1\}"
re_name=$(escape_grep_basic "${filename##*/}")
local filesize=$($SED -n -e '/^filesize=/s///p' "$filename.manifest" 2>/dev/null)
if [ "$filesize" = 0 ]; then
@ -124,11 +131,11 @@ unpack_manifest_for_grep() {
# file, then use its file hash to check the rhizome list '' output.
local filehash=$($SED -n -e '/^filehash=/s///p' "$filename.manifest" 2>/dev/null)
if [ "$filehash" = "$re_filehash" ]; then
re_service=$($SED -n -e '/^service=/s///p' "$filename.manifest")
re_service=$(escape_grep_basic "$re_service")
re_manifestid=$($SED -n -e '/^id=/s///p' "$filename.manifest")
re_version=$($SED -n -e '/^version=/s///p' "$filename.manifest")
re_date=$($SED -n -e '/^date=/s///p' "$filename.manifest")
re_service=$($SED -n -e '/^service=/s///p' "$filename.manifest")
re_service=$(escape_grep_basic "$re_service")
re_sender=$($SED -n -e '/^sender=/s///p' "$filename.manifest")
re_recipient=$($SED -n -e '/^recipient=/s///p' "$filename.manifest")
case "$re_service" in
@ -138,6 +145,8 @@ unpack_manifest_for_grep() {
;;
*)
re_name=
re_sender="$rexp_sid"
re_recipient="$rexp_sid"
;;
esac
fi

View File

@ -141,7 +141,7 @@ test_AddEmpty() {
assertGrep .manifest '^name=$'
assertGrep .manifest '^filesize=0$'
executeOk_servald rhizome list ''
assert_rhizome_list ''
assert_rhizome_list @$SIDB1
}
doc_AddThenList="List contains one file after one add"
@ -157,11 +157,11 @@ test_AddThenList() {
# Add first file
executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest
executeOk_servald rhizome list ''
assert_rhizome_list file1
assert_rhizome_list file1@$SIDB1
# Add second file
executeOk_servald rhizome add file $SIDB1 '' file2 file2.manifest
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
}
doc_AddThenExtractManifest="Extract manifest after one add"
@ -171,7 +171,7 @@ setup_AddThenExtractManifest() {
echo "A test file" >file1
executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest
executeOk_servald rhizome list ''
assert_rhizome_list file1
assert_rhizome_list file1@$SIDB1
extract_manifest_id manifestid file1.manifest
extract_manifest_version version file1.manifest
extract_manifest_filehash filehash file1.manifest
@ -179,14 +179,15 @@ setup_AddThenExtractManifest() {
test_AddThenExtractManifest() {
executeOk_servald rhizome extract manifest $manifestid file1x.manifest
assert cmp file1.manifest file1x.manifest
assertStdoutLineCount '==' 6
assertStdoutLineCount '==' 7
local size=$(( $(cat file1 | wc -c) + 0 ))
assertStdoutGrep --matches=1 "^service:file$"
assertStdoutGrep --matches=1 "^manifestid:$manifestid$"
assertStdoutGrep --matches=1 "^version:$version$"
assertStdoutGrep --matches=1 "^inserttime:[0-9]\+$"
assertStdoutGrep --matches=1 "^filehash:$filehash$"
assertStdoutGrep --matches=1 "^filesize:$size$"
assertStdoutGrep --matches=1 "^manifestid:$manifestid\$"
assertStdoutGrep --matches=1 "^version:$version\$"
assertStdoutGrep --matches=1 "^inserttime:[0-9]\+\$"
assertStdoutGrep --matches=1 "^\.author:$SIDB1\$"
assertStdoutGrep --matches=1 "^filehash:$filehash\$"
assertStdoutGrep --matches=1 "^filesize:$size\$"
}
doc_ExtractMissingManifest="Extract non-existent manifest"
@ -226,7 +227,7 @@ setup_AddThenExtractFile() {
executeOk_servald rhizome add file $SIDB1 '' file1 file1.manifest
tfw_cat --stderr
executeOk_servald rhizome list ''
assert_rhizome_list file1
assert_rhizome_list file1@$SIDB1
extract_manifest_filehash filehash file1.manifest
}
test_AddThenExtractFile() {
@ -284,7 +285,7 @@ setup_AddDuplicate() {
extract_stdout_secret file2_secret
# Make sure they are both in the list.
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
}
test_AddDuplicate() {
# Add first file again - nothing should change in its manifests, and it
@ -294,7 +295,7 @@ test_AddDuplicate() {
assert [ -s file1.manifestA ]
assert_stdout_add_file file1
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
strip_signatures file1.manifest file1.manifestA
assert diff file1.manifest file1.manifestA
# Repeat for second file.
@ -302,7 +303,7 @@ test_AddDuplicate() {
assert [ -s file2.manifestA ]
assert_stdout_add_file file2
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
strip_signatures file2.manifest file2.manifestA
assert diff file2.manifest file2.manifestA
}
@ -320,7 +321,7 @@ test_AddMismatched() {
assert cmp file1.manifest file1_2.manifest
# And rhizome store should be unchanged.
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
}
doc_AddUpdateSameVersion="Add new payload to existing manifest with same version fails"
@ -343,7 +344,7 @@ test_AddUpdateSameVersion() {
assert cmp file1_2.manifest file1_2.manifest.orig
# And rhizome store should be unchanged.
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
}
doc_AddUpdateNewVersion="Add new payload to existing manifest with new version"
@ -357,11 +358,12 @@ setup_AddUpdateNewVersion() {
test_AddUpdateNewVersion() {
tfw_cat -v file1_2.manifest
executeOk_servald rhizome add file $SIDB1 '' file1_2 file1_2.manifest
tfw_cat --stderr
assert_stdout_add_file file1_2 name=file1
assert_manifest_newer file1.manifest file1_2.manifest
# Rhizome store contents reflect new payload.
executeOk_servald rhizome list ''
assert_rhizome_list file1_2 file2
assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1
}
doc_AddUpdateNoAuthor="Cannot add new payload to authorless manifest"
@ -376,7 +378,7 @@ test_AddUpdateNoAuthor() {
assertExitStatus '!=' 0
# Rhizome store contents have old payload.
executeOk_servald rhizome list ''
assert_rhizome_list file1 file2
assert_rhizome_list file1@$SIDB1 file2@$SIDB1
}
doc_AddUpdateNoAuthorWithSecret="Add new payload to authorless manifest with bundle secret"
@ -389,7 +391,7 @@ test_AddUpdateNoAuthorWithSecret() {
tfw_cat --stderr
# Rhizome store contents have new payload.
executeOk_servald rhizome list ''
assert_rhizome_list file1_2! file2
assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1
}
doc_AddUpdateAutoVersion="Add new payload to existing manifest with automatic version"