Make "rhizome add file" work for MeshMS

This commit is contained in:
Andrew Bettison 2012-05-21 00:09:14 +09:30
parent b739bfd572
commit ddd17db1c4
4 changed files with 104 additions and 69 deletions

View File

@ -1092,11 +1092,13 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
rhizome_manifest *m = NULL;
int manifest_file_supplied = 0;
if (manifestpath[0] && access(manifestpath, R_OK) == 0) {
if (debug & DEBUG_RHIZOME) DEBUGF("reading manifest from %s", manifestpath);
m = rhizome_read_manifest_file(manifestpath, 0, 0); // no verify
if (!m)
return WHY("Manifest file could not be loaded -- not added to rhizome");
manifest_file_supplied = 1;
} else {
if (debug & DEBUG_RHIZOME) DEBUGF("manifest file %s does not exist", manifestpath);
m = rhizome_new_manifest();
if (!m)
return WHY("Manifest struct could not be allocated -- not added to rhizome");
@ -1109,15 +1111,23 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
if (service == NULL) {
rhizome_manifest_set(m, "service", (service = RHIZOME_SERVICE_FILE));
if (debug & DEBUG_RHIZOME) DEBUGF("missing 'service', set default service=%s", service);
} else {
if (debug & DEBUG_RHIZOME) DEBUGF("manifest contains service=%s", service);
}
if (rhizome_manifest_get(m, "date", NULL, 0) == NULL) {
rhizome_manifest_set_ll(m, "date", gettime_ms());
if (debug & DEBUG_RHIZOME) DEBUGF("missing 'date', set default date=%s", rhizome_manifest_get(m, "date", NULL, 0));
}
if (strcasecmp(RHIZOME_SERVICE_FILE, service) == 0) {
if (rhizome_manifest_get(m, "name", NULL, 0) == NULL) {
const char *name = strrchr(filepath, '/');
const char *name = rhizome_manifest_get(m, "name", NULL, 0);
if (name == NULL) {
name = strrchr(filepath, '/');
name = name ? name + 1 : filepath;
rhizome_manifest_set(m, "name", name);
if (debug & DEBUG_RHIZOME) DEBUGF("missing 'name', set default name=\"%s\"", name);
} else {
if (debug & DEBUG_RHIZOME) DEBUGF("manifest contains name=\"%s\"", name);
}
}
/* Add the manifest and its associated file to the Rhizome database, generating an "id" in the

View File

@ -159,11 +159,11 @@ int rhizome_add_manifest(rhizome_manifest *m_in,
} else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) {
const char *sender = rhizome_manifest_get(m_in, "sender", NULL, 0);
const char *recipient = rhizome_manifest_get(m_in, "recipient", NULL, 0);
if (sender == NULL || sender[0])
if (sender == NULL || !sender[0])
return WHY("Manifest missing 'sender' field");
if (!validateSid(sender))
return WHY("Manifest contains invalid 'sender' field");
if (recipient == NULL || recipient[0])
if (recipient == NULL || !recipient[0])
return WHY("Manifest missing 'recipient' field");
if (!validateSid(recipient))
return WHY("Manifest contains invalid 'recipient' field");

View File

@ -31,8 +31,7 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
if (bufferP) {
m->manifest_bytes=bufferP;
memcpy(m->manifestdata, filename, m->manifest_bytes);
}
else {
} else {
FILE *f=fopen(filename,"r");
if (!f) {
WHYF("Could not open manifest file %s for reading.", filename);
@ -71,25 +70,25 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
/* Parse property lines */
/* This could be improved to parse Java's Properties.store() output, by handling backlash
escapes and continuation lines */
if (sscanf(line,"%[^=]=%[^\n\r]",var,value)==2)
{
if (rhizome_manifest_get(m,var,NULL,0)!=NULL) {
if (debug&DEBUG_RHIZOME) fprintf(stderr, "Error in manifest file (duplicate variable \"%s\"-- keeping first value)\n", var);
m->errors++;
if (sscanf(line,"%[^=]=%[^\n\r]", var, value)==2) {
if (rhizome_manifest_get(m,var,NULL,0)) {
WARNF("Ill formed manifest file, duplicate variable \"%s\"-- keeping first value)", var);
m->errors++;
} else if (m->var_count<MAX_MANIFEST_VARS) {
/*`
if (debug & DEBUG_RHIZOME) {
char buf[80];
DEBUGF("read manifest line: %s=%s", var, catv(value, buf, sizeof buf));
}
if (m->var_count<MAX_MANIFEST_VARS)
{
m->vars[m->var_count]=strdup(var);
m->values[m->var_count]=strdup(value);
m->var_count++;
}
}
else
{
/* Error in manifest file.
Silently ignore for now. */
WHY("Error in manifest file (badly formatted line).");
*/
m->vars[m->var_count]=strdup(var);
m->values[m->var_count]=strdup(value);
m->var_count++;
}
} else {
char buf[80];
WARNF("Skipping malformed line in manifest file %s: %s", bufferP ? "<buffer>" : filename, catv(line, buf, sizeof buf));
}
}
/* The null byte gets included in the check sum */
if (ofs<m->manifest_bytes) ofs++;
@ -104,9 +103,7 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
/* Read signature blocks from file. */
while(ofs<m->manifest_bytes) {
if (debug&DEBUG_RHIZOME)
fprintf(stderr,"ofs=0x%x, m->manifest_bytes=0x%x\n",
ofs,m->manifest_bytes);
if (debug & DEBUG_RHIZOME) DEBUGF("ofs=0x%x, m->manifest_bytes=0x%x", ofs,m->manifest_bytes);
rhizome_manifest_extract_signature(m,&ofs);
}
@ -117,10 +114,10 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
/* Make sure that id variable is correct */
{
char *id=rhizome_manifest_get(m,"id",NULL,0);
if (!id) {
if (debug&DEBUG_RHIZOME) fprintf(stderr,"Manifest lacks id variable.\n");
m->errors++; }
WARN("Manifest lacks 'id' field");
m->errors++;
}
else {
unsigned char manifest_bytes[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES];
rhizome_hex_to_bytes(id,manifest_bytes,
@ -131,13 +128,12 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
{
if (debug&DEBUG_RHIZOME) {
if (m->sig_count>0) {
fprintf(stderr,
"Manifest id variable does not match first signature block.\n");
fprintf(stderr," (signature key is %s)\n",
DEBUGF("Manifest id variable does not match first signature block (signature key is %s)",
/* XXX bit of a hack that relies on SIDs and signing public keys being the same length */
overlay_render_sid(&m->signatories[0][0]));
overlay_render_sid(&m->signatories[0][0])
);
} else {
fprintf(stderr,"Manifest has no signature blocks, but should have self-signature block");
DEBUG("Manifest has no signature blocks, but should have self-signature block");
}
}
m->errors++;
@ -147,7 +143,7 @@ rhizome_manifest *rhizome_read_manifest_file(const char *filename, int bufferP,
}
if (debug&DEBUG_RHIZOME)
fprintf(stderr, "Group membership determination not implemented (see which signatories are groups? what about manifests signed by groups we don't yet know about?)\n");
DEBUG("Group membership determination not implemented (see which signatories are groups? what about manifests signed by groups we don't yet know about?)");
}
m->manifest_bytes=end_of_text;
@ -404,7 +400,7 @@ int rhizome_manifest_pack_variables(rhizome_manifest *m)
}
m->manifestdata[ofs++]=0x00;
m->manifest_bytes=ofs;
if (debug&DEBUG_RHIZOME) fprintf(stderr, "Repacked variables in manifest.\n");
if (debug&DEBUG_RHIZOME) DEBUG("Repacked variables in manifest.");
m->manifest_all_bytes=ofs;
/* Recalculate hash */

View File

@ -537,29 +537,23 @@ char *rhizome_safe_encode(unsigned char *in,int len)
int rhizome_list_manifests(const char *service, const char *sender_sid, const char *recipient_sid, int limit, int offset)
{
char sqlcmd[1024];
int n = snprintf(sqlcmd, sizeof(sqlcmd),
strbuf b = strbuf_alloca(1024);
strbuf_sprintf(b,
"SELECT files.id, files.length, manifests.id, manifests.manifest, manifests.version, manifests.inserttime"
" FROM files, filemanifests, manifests"
" WHERE files.id = filemanifests.fileid AND filemanifests.manifestid = manifests.id AND files.datavalid <> 0"
" ORDER BY files.id ASC"
);
if (n >= sizeof(sqlcmd))
return WHY("SQL command too long");
if (limit) {
n += snprintf(&sqlcmd[n], sizeof(sqlcmd) - n, " LIMIT %u", limit);
if (n >= sizeof(sqlcmd))
return WHY("SQL command too long");
}
if (offset) {
n += snprintf(&sqlcmd[n], sizeof(sqlcmd) - n, " OFFSET %u", offset);
if (n >= sizeof(sqlcmd))
return WHY("SQL command too long");
}
if (limit)
strbuf_sprintf(b, " LIMIT %u", limit);
if (offset)
strbuf_sprintf(b, " OFFSET %u", offset);
if (strbuf_overrun(b))
return WHYF("SQL command too long: ", strbuf_str(b));
sqlite3_stmt *statement;
const char *cmdtail;
int ret = 0;
if (sqlite3_prepare_v2(rhizome_db, sqlcmd, strlen(sqlcmd) + 1, &statement, &cmdtail) != SQLITE_OK) {
if (sqlite3_prepare_v2(rhizome_db, strbuf_str(b), strbuf_len(b) + 1, &statement, &cmdtail) != SQLITE_OK) {
sqlite3_finalize(statement);
ret = WHY(sqlite3_errmsg(rhizome_db));
} else {
@ -810,9 +804,23 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found)
{
if (!m->fileHashedP)
return WHY("Manifest payload is not hashed");
const char *name = rhizome_manifest_get(m, "name", NULL, 0);
if (!name)
return WHY("Manifest has no name");
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
const char *name = NULL;
const char *sender = NULL;
const char *recipient = NULL;
if (service == NULL) {
return WHY("Manifest has no service");
} else if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) {
name = rhizome_manifest_get(m, "name", NULL, 0);
if (!name) return WHY("Manifest has no name");
} else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) {
sender = rhizome_manifest_get(m, "sender", NULL, 0);
recipient = rhizome_manifest_get(m, "recipient", NULL, 0);
if (!sender) return WHY("Manifest has no sender");
if (!recipient) return WHY("Manifest has no recipient");
} else {
return WHYF("Unsupported service '%s'", service);
}
char sqlcmd[1024];
char *s = sqlcmd;
s += snprintf(s, &sqlcmd[sizeof sqlcmd] - s,
@ -855,13 +863,13 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found)
size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob()
long long q_version = sqlite3_column_int64(statement, 2);
rhizome_manifest *blob_m = rhizome_read_manifest_file(manifestblob, manifestblobsize, 0);
const char *blob_service = rhizome_manifest_get(blob_m, "service", NULL, 0);
const char *blob_id = rhizome_manifest_get(blob_m, "id", NULL, 0);
const char *blob_name = rhizome_manifest_get(blob_m, "name", NULL, 0);
long long blob_version = rhizome_manifest_get_ll(blob_m, "version");
const char *blob_filehash = rhizome_manifest_get(blob_m, "filehash", NULL, 0);
long long blob_filesize = rhizome_manifest_get_ll(blob_m, "filesize");
if (debug & DEBUG_RHIZOME)
DEBUGF("Consider manifest.id=%s manifest.name=\"%s\" manifest.version=%lld", q_manifestid, blob_name, blob_version);
DEBUGF("Consider manifest.service=%s manifest.id=%s manifest.version=%lld", blob_service, q_manifestid, blob_version);
/* Perform consistency checks, because we're paranoid. */
int inconsistent = 0;
if (blob_id && strcasecmp(blob_id, q_manifestid)) {
@ -887,19 +895,40 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found)
WARNF("SELECT query with version=%lld returned incorrect row: manifests.version=%lld -- skipped", m->version, q_version);
++inconsistent;
}
/* The "name" comparison is the only one we can't do in the SELECT, so we do it here. */
if (!inconsistent && blob_name && !strcmp(blob_name, name)) {
rhizome_hex_to_bytes(q_manifestid, blob_m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
memcpy(blob_m->fileHexHash, m->fileHexHash, SHA512_DIGEST_STRING_LENGTH);
blob_m->fileHashedP = 1;
blob_m->fileLength = m->fileLength;
blob_m->version = q_version;
*found = blob_m;
if (debug & DEBUG_RHIZOME)
DEBUGF("Found duplicate payload: name=\"%s\" version=%llu hexhash=%s -- not adding\n", blob_m, blob_m->version, blob_m->fileHexHash);
ret = 1;
if (debug & DEBUG_RHIZOME) DEBUG("found");
break;
if (blob_service == NULL) {
WARNF("MANIFESTS row id=%s has blob with no 'service' -- skipped", q_manifestid, blob_id);
++inconsistent;
}
if (!inconsistent) {
strbuf b = strbuf_alloca(1024);
if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) {
const char *blob_name = rhizome_manifest_get(blob_m, "name", NULL, 0);
if (blob_name && !strcmp(blob_name, name)) {
if (debug & DEBUG_RHIZOME)
strbuf_sprintf(b, " name=\"%s\"", blob_name);
ret = 1;
}
} else if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 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)) {
if (debug & DEBUG_RHIZOME)
strbuf_sprintf(b, " sender=%s recipient=%s", blob_sender, blob_recipient);
ret = 1;
}
}
if (ret == 1) {
rhizome_hex_to_bytes(q_manifestid, blob_m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
memcpy(blob_m->fileHexHash, m->fileHexHash, SHA512_DIGEST_STRING_LENGTH);
blob_m->fileHashedP = 1;
blob_m->fileLength = m->fileLength;
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
);
break;
}
}
rhizome_manifest_free(blob_m);
}