diff --git a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscription.java b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscription.java index ad53995e..cef07e8e 100644 --- a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscription.java +++ b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscription.java @@ -2,18 +2,19 @@ package org.servalproject.servaldna.meshmb; import org.servalproject.servaldna.BundleId; import org.servalproject.servaldna.SigningKey; +import org.servalproject.servaldna.Subscriber; /** * Created by jeremy on 11/01/17. */ public class MeshMBSubscription { - public final SigningKey id; + public final Subscriber subscriber; public final String name; public final long timestamp; public final String lastMessage; - public MeshMBSubscription(SigningKey id, String name, long timestamp, String lastMessage){ - this.id = id; + public MeshMBSubscription(Subscriber subscriber, String name, long timestamp, String lastMessage){ + this.subscriber = subscriber; this.name = name; this.lastMessage = lastMessage; this.timestamp = timestamp; diff --git a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscriptionList.java b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscriptionList.java index 1dd8f952..01024e3c 100644 --- a/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscriptionList.java +++ b/java-api/src/org/servalproject/servaldna/meshmb/MeshMBSubscriptionList.java @@ -6,6 +6,7 @@ import org.servalproject.servaldna.ServalDHttpConnectionFactory; import org.servalproject.servaldna.ServalDInterfaceException; import org.servalproject.servaldna.SigningKey; import org.servalproject.servaldna.Subscriber; +import org.servalproject.servaldna.SubscriberId; import java.io.IOException; import java.util.Map; @@ -21,6 +22,7 @@ public class MeshMBSubscriptionList extends AbstractJsonList row, long rowCount) throws ServalDInterfaceException { return new MeshMBSubscription( - (SigningKey) row.get("id"), + new Subscriber((SubscriberId)row.get("author"), + (SigningKey) row.get("id"), + true), (String) row.get("name"), (Long) row.get("timestamp"), (String) row.get("last_message") diff --git a/meshmb.c b/meshmb.c index e293f500..d4d1a17e 100644 --- a/meshmb.c +++ b/meshmb.c @@ -60,6 +60,7 @@ static void update_stats(struct meshmb_feeds *feeds, struct feed_metadata *metad free((void*)metadata->details.name); metadata->details.name = NULL; } + metadata->details.author = reader->author; if (reader->name){ size_t len = strlen(reader->name); @@ -147,9 +148,12 @@ static int write_metadata(void **record, void *context) unsigned msg_len = (metadata->details.last_message ? strlen(metadata->details.last_message) : 0) + 1; assert(msg_len <= MAX_MSG_LEN); - uint8_t buffer[sizeof (rhizome_bid_t) + 1 + 12*4 + name_len + msg_len]; - bcopy(metadata->ply.bundle_id.binary, buffer, sizeof (rhizome_bid_t)); - size_t len = sizeof (rhizome_bid_t); + uint8_t buffer[sizeof (rhizome_bid_t) + sizeof (sid_t) + 1 + 12*4 + name_len + msg_len]; + size_t len = 0; + bcopy(metadata->ply.bundle_id.binary, &buffer[len], sizeof (rhizome_bid_t)); + len += sizeof (rhizome_bid_t); + bcopy(metadata->details.author.binary, &buffer[len], sizeof (sid_t)); + len += sizeof (sid_t); buffer[len++]=0;// flags? len+=pack_uint(&buffer[len], metadata->size); len+=pack_uint(&buffer[len], metadata->size - metadata->last_message_offset); @@ -166,7 +170,11 @@ static int write_metadata(void **record, void *context) buffer[len]=0; len+=msg_len; assert(len < sizeof buffer); - DEBUGF(meshmb, "Write %u bytes of metadata for %s", len, alloca_tohex_rhizome_bid_t(metadata->ply.bundle_id)); + DEBUGF(meshmb, "Write %u bytes of metadata for %s/%s", + len, + alloca_tohex_rhizome_bid_t(metadata->ply.bundle_id), + alloca_tohex_sid_t(metadata->details.author) + ); return rhizome_write_buffer(write, buffer, len); } @@ -267,7 +275,7 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read) { struct rhizome_read_buffer buff; bzero(&buff, sizeof(buff)); - uint8_t buffer[sizeof (rhizome_bid_t) + 12*3 + MAX_NAME_LEN + MAX_MSG_LEN]; + uint8_t buffer[sizeof (rhizome_bid_t) + sizeof (sid_t) + 12*3 + MAX_NAME_LEN + MAX_MSG_LEN]; uint8_t version=0xFF; if (rhizome_read_buffered(read, &buff, &version, 1)==-1) @@ -291,40 +299,46 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read) const rhizome_bid_t *bid = (const rhizome_bid_t *)&buffer[0]; unsigned offset = sizeof(rhizome_bid_t); if (offset >= (unsigned)bytes) - return WHY("Buffer overflow while parsing metadata"); + goto error; + + const sid_t *author = (const sid_t *)&buffer[offset]; + offset+= sizeof(sid_t); + if (offset >= (unsigned)bytes) + goto error; + //uint8_t flags = buffer[offset++]; offset++; if (offset >= (unsigned)bytes) - return WHY("Buffer overflow while parsing metadata"); + goto error; if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &size)) == -1) - return WHY("Buffer overflow while parsing metadata"); + goto error; offset += unpacked; if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1) - return WHY("Buffer overflow while parsing metadata"); + goto error; offset += unpacked; last_message_offset = size - delta; if ((unpacked = unpack_uint(buffer+offset, bytes-offset, &delta)) == -1) - return WHY("Buffer overflow while parsing metadata"); + goto error; offset += unpacked; last_seen = size - delta; if ((unpacked = unpack_uint(buffer+offset, bytes-offset, ×tamp)) == -1) - return WHY("Buffer overflow while parsing metadata"); + goto error; offset += unpacked; const char *name = (const char *)&buffer[offset]; while(buffer[offset++]){ if (offset >= (unsigned)bytes) - return WHY("Buffer overflow while parsing metadata"); + goto error; } const char *msg = (const char *)&buffer[offset]; while(buffer[offset++]){ if (offset >= (unsigned)bytes) - return WHY("Buffer overflow while parsing metadata"); + goto error; } read->offset += offset - bytes; @@ -336,14 +350,22 @@ static int read_metadata(struct meshmb_feeds *feeds, struct rhizome_read *read) result->last_seen = last_seen; result->size = size; result->details.bundle_id = *bid; + result->details.author = *author; result->details.name = (name && *name) ? str_edup(name) : NULL; result->details.last_message = (msg && *msg) ? str_edup(msg) : NULL; result->details.timestamp = timestamp; - DEBUGF(meshmb, "Processed %u bytes of metadata for %s", offset, alloca_tohex_rhizome_bid_t(result->ply.bundle_id)); + DEBUGF(meshmb, "Processed %u bytes of metadata for %s", + offset, + alloca_tohex_rhizome_bid_t(result->ply.bundle_id), + alloca_tohex_sid_t(result->details.author) + ); } feeds->dirty = 0; return 0; + +error: + return WHY("Buffer overflow while parsing metadata"); } int meshmb_open(keyring_identity *id, struct meshmb_feeds **feeds) diff --git a/meshmb.h b/meshmb.h index 48bc6a63..fa7279bb 100644 --- a/meshmb.h +++ b/meshmb.h @@ -11,6 +11,7 @@ enum meshmb_send_status{ // details of a feed that you are following struct meshmb_feed_details{ rhizome_bid_t bundle_id; + sid_t author; const char *name; const char *last_message; time_s_t timestamp; diff --git a/meshmb_cli.c b/meshmb_cli.c index ee0c3e51..01654021 100644 --- a/meshmb_cli.c +++ b/meshmb_cli.c @@ -140,6 +140,7 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context * const char *names[]={ "_id", "id", + "author", "version", "date", "name" @@ -154,6 +155,20 @@ static int app_meshmb_find(const struct cli_parsed *parsed, struct cli_context * rhizome_manifest *m = cursor.manifest; cli_put_long(context, m->rowid, ":"); cli_put_hexvalue(context, m->keypair.public_key.binary, sizeof m->keypair.public_key.binary, ":"); + + switch (m->authorship) { + case AUTHOR_NOT_CHECKED: + case AUTHOR_AUTHENTIC: + case AUTHOR_LOCAL: + case AUTHOR_REMOTE: + cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":"); + break; + + default: + cli_put_string(context, NULL, ":"); + break; + } + cli_put_long(context, m->version, ":"); cli_put_long(context, m->has_date ? m->date : 0, ":"); cli_put_string(context, m->name, "\n"); @@ -232,6 +247,7 @@ static int list_callback(struct meshmb_feed_details *details, void *context) enum_context->rowcount++; cli_put_long(enum_context->context, enum_context->rowcount, ":"); cli_put_string(enum_context->context, alloca_tohex_rhizome_bid_t(details->bundle_id), ":"); + cli_put_string(enum_context->context, alloca_tohex_sid_t(details->author), ":"); cli_put_string(enum_context->context, details->name, ":"); cli_put_long(enum_context->context, details->timestamp ? (long)(gettime() - details->timestamp) : (long)-1, ":"); cli_put_string(enum_context->context, details->last_message, "\n"); @@ -271,6 +287,7 @@ static int app_meshmb_list(const struct cli_parsed *parsed, struct cli_context * const char *names[]={ "_id", "id", + "author", "name", "age", "last_message" diff --git a/meshmb_restful.c b/meshmb_restful.c index c4a38cf3..f2c08b4c 100644 --- a/meshmb_restful.c +++ b/meshmb_restful.c @@ -508,6 +508,8 @@ static int restful_feedlist_enum(struct meshmb_feed_details *details, void *cont strbuf_puts(state->buffer, "\n["); strbuf_json_hex(state->buffer, details->bundle_id.binary, sizeof details->bundle_id.binary); strbuf_puts(state->buffer, ","); + strbuf_json_hex(state->buffer, details->author.binary, sizeof details->author.binary); + strbuf_puts(state->buffer, ","); strbuf_json_string(state->buffer, details->name); strbuf_puts(state->buffer, ","); strbuf_sprintf(state->buffer, "%d", details->timestamp); @@ -530,6 +532,7 @@ static int restful_meshmb_feedlist_json_content_chunk(struct http_request *hr, s httpd_request *r = (httpd_request *) hr; const char *headers[] = { "id", + "author", "name", "timestamp", "last_message" diff --git a/message_ply.c b/message_ply.c index 03217eb8..8fe66038 100644 --- a/message_ply.c +++ b/message_ply.c @@ -17,6 +17,7 @@ static int message_ply_load_manifest(const keyring_identity *id, struct message_ if (!m->haveSecret || m->authorship != AUTHOR_AUTHENTIC) return -1; assert(m->author_identity == id); + ply->author=m->author; return 0; } @@ -58,6 +59,7 @@ static int message_ply_fill_manifest(const keyring_identity *id, const sid_t *re assert(m->haveSecret); assert(!recipient || m->payloadEncryption == PAYLOAD_ENCRYPTED); ply->bundle_id = m->keypair.public_key; + ply->author = m->author; ply->found = ply->known_bid = 1; } return ret; @@ -142,6 +144,7 @@ int message_ply_read_open(struct message_ply_read *ply, const rhizome_bid_t *bid && rhizome_open_decrypt_read(m, &ply->read) == RHIZOME_PAYLOAD_STATUS_STORED){ assert(m->filesize != RHIZOME_SIZE_UNSET); + ply->author = m->author; ply->read.offset = ply->read.length = m->filesize; if (m->name && *m->name) ply->name = str_edup(m->name); diff --git a/message_ply.h b/message_ply.h index e2228699..b2989655 100644 --- a/message_ply.h +++ b/message_ply.h @@ -11,6 +11,7 @@ // the manifest details for one ply struct message_ply { rhizome_bid_t bundle_id; + sid_t author; uint64_t version; uint64_t tail; uint64_t size; @@ -26,6 +27,8 @@ struct message_ply_read { struct rhizome_read_buffer buff; // copy of the manifest name field const char *name; + // copy of the manifest author + sid_t author; // details of the current record uint64_t record_end_offset; uint16_t record_length; @@ -48,4 +51,4 @@ void message_ply_append_message(struct overlay_buffer *b, const char *message, s int message_ply_append(const struct keyring_identity *id, const char *service, const sid_t *recipient, struct message_ply *ply, struct overlay_buffer *b, const char *name, unsigned nassignments, const struct rhizome_manifest_field_assignment *assignments); -#endif \ No newline at end of file +#endif diff --git a/rhizome_cli.c b/rhizome_cli.c index be08a433..7e588be9 100644 --- a/rhizome_cli.c +++ b/rhizome_cli.c @@ -76,7 +76,7 @@ static void cli_put_manifest(struct cli_context *context, const rhizome_manifest cli_field_name(context, ".secret", ":"); cli_put_string(context, secret, "\n"); } - if (m->authorship == AUTHOR_AUTHENTIC) { + if (m->authorship == AUTHOR_AUTHENTIC || m->authorship == AUTHOR_REMOTE) { cli_field_name(context, ".author", ":"); cli_put_string(context, alloca_tohex_sid_t(m->author), "\n"); } diff --git a/tests/meshmb b/tests/meshmb index 4b7b00e4..bc5d05cd 100755 --- a/tests/meshmb +++ b/tests/meshmb @@ -65,10 +65,10 @@ setup_meshmbListFeeds() { test_meshmbListFeeds() { executeOk_servald meshmb find tfw_cat --stdout - assertStdoutGrep --matches=1 "^_id:id:version:date:name$" - assertStdoutGrep --matches=1 ":${IDA1}:" - assertStdoutGrep --matches=1 ":${IDA2}:" - assertStdoutGrep --matches=1 ":${IDA3}:" + assertStdoutGrep --matches=1 "^_id:id:author:version:date:name$" + assertStdoutGrep --matches=1 ":${IDA1}:${SIDA1}:" + assertStdoutGrep --matches=1 ":${IDA2}:${SIDA2}:" + assertStdoutGrep --matches=1 ":${IDA3}:${SIDA3}:" assertStdoutLineCount '==' 5 } @@ -85,16 +85,16 @@ setup_meshmbFollow() { test_meshmbFollow() { executeOk_servald meshmb follow $IDA1 $IDA2 executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$" - assertStdoutGrep --matches=0 ":$IDA3:Feed C:[0-9]\+:Message 3\$" + assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$" + assertStdoutGrep --matches=0 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$" executeOk_servald meshmb follow $IDA1 $IDA3 executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=1 ":$IDA2:Feed B:[0-9]\+:Message 2\$" - assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$" + assertStdoutGrep --matches=1 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$" + assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$" executeOk_servald meshmb ignore $IDA1 $IDA2 executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=0 ":$IDA2:Feed B:[0-9]\+:Message 2\$" - assertStdoutGrep --matches=1 ":$IDA3:Feed C:[0-9]\+:Message 3\$" + assertStdoutGrep --matches=0 ":$IDA2:$SIDA2:Feed B:[0-9]\+:Message 2\$" + assertStdoutGrep --matches=1 ":$IDA3:$SIDA3:Feed C:[0-9]\+:Message 3\$" } runTests "$@" diff --git a/tests/meshmbrestful b/tests/meshmbrestful index c5f939be..72d471c1 100755 --- a/tests/meshmbrestful +++ b/tests/meshmbrestful @@ -113,8 +113,8 @@ test_MeshMBRestFollow() { --request POST \ "http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA2" executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=1 ":$IDA2::[0-9]\+:Message 2\$" - assertStdoutGrep --matches=0 ":$IDA3::[0-9]\+:Message 3\$" + assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$" + assertStdoutGrep --matches=0 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$" executeOk curl \ -H "Expect:" \ --silent --fail --show-error \ @@ -123,8 +123,8 @@ test_MeshMBRestFollow() { --request POST \ "http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/follow/$IDA3" executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=1 ":$IDA2::[0-9]\+:Message 2\$" - assertStdoutGrep --matches=1 ":$IDA3::[0-9]\+:Message 3\$" + assertStdoutGrep --matches=1 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$" + assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$" executeOk curl \ -H "Expect:" \ --silent --fail --show-error \ @@ -133,8 +133,8 @@ test_MeshMBRestFollow() { --request POST \ "http://$addr_localhost:$PORTA/restful/meshmb/$IDA1/ignore/$IDA2" executeOk_servald meshmb list following $IDA1 - assertStdoutGrep --matches=0 ":$IDA2::[0-9]\+:Message 2\$" - assertStdoutGrep --matches=1 ":$IDA3::[0-9]\+:Message 3\$" + assertStdoutGrep --matches=0 ":$IDA2:$SIDA2::[0-9]\+:Message 2\$" + assertStdoutGrep --matches=1 ":$IDA3:$SIDA3::[0-9]\+:Message 3\$" } doc_MeshMBRestFeeds="Restful list subscribed feeds"