mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-04-07 19:14:17 +00:00
Fix handling of empty payload (filesize = 0)
Do not add 'filehash' var to manifest if filesize=0 Do not accept 'filehash' var when parsing manifest with filesize=0 When responding to a new rhizome advertisement, do not try to HTTP request a payload if filesize=0, just import the manifest directly Various operations, eg "rhizome file add", do not report 'filehash' fields where 'filesize' is zero Do not delete rows from MANIFESTS table which have empty filehash Various related bug fixes
This commit is contained in:
parent
9d69a3c2bd
commit
b50943d09c
@ -1108,23 +1108,43 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
|
||||
ret = WHY("Could not overwrite manifest file.");
|
||||
service = rhizome_manifest_get(mwritten, "service", NULL, 0);
|
||||
if (service) {
|
||||
cli_puts("service"); cli_delim(":"); cli_puts(service); cli_delim("\n");
|
||||
cli_puts("service");
|
||||
cli_delim(":");
|
||||
cli_puts(service);
|
||||
cli_delim("\n");
|
||||
}
|
||||
{
|
||||
char bid[RHIZOME_MANIFEST_ID_STRLEN + 1];
|
||||
rhizome_bytes_to_hex_upper(mwritten->cryptoSignPublic, bid, RHIZOME_MANIFEST_ID_BYTES);
|
||||
cli_puts("manifestid"); cli_delim(":"); cli_puts(bid); cli_delim("\n");
|
||||
cli_puts("manifestid");
|
||||
cli_delim(":");
|
||||
cli_puts(bid);
|
||||
cli_delim("\n");
|
||||
}
|
||||
{
|
||||
char secret[RHIZOME_BUNDLE_KEY_STRLEN + 1];
|
||||
rhizome_bytes_to_hex_upper(mwritten->cryptoSignSecret, secret, RHIZOME_BUNDLE_KEY_BYTES);
|
||||
cli_puts("secret"); cli_delim(":"); cli_puts(secret); cli_delim("\n");
|
||||
cli_puts("secret");
|
||||
cli_delim(":");
|
||||
cli_puts(secret);
|
||||
cli_delim("\n");
|
||||
}
|
||||
cli_puts("filesize");
|
||||
cli_delim(":");
|
||||
cli_printf("%lld", mwritten->fileLength);
|
||||
cli_delim("\n");
|
||||
if (mwritten->fileLength != 0) {
|
||||
cli_puts("filehash");
|
||||
cli_delim(":");
|
||||
cli_puts(mwritten->fileHexHash);
|
||||
cli_delim("\n");
|
||||
}
|
||||
cli_puts("filehash"); cli_delim(":"); cli_puts(mwritten->fileHexHash); cli_delim("\n");
|
||||
cli_puts("filesize"); cli_delim(":"); cli_printf("%lld", mwritten->fileLength); cli_delim("\n");
|
||||
const char *name = rhizome_manifest_get(mwritten, "name", NULL, 0);
|
||||
if (name) {
|
||||
cli_puts("name"); cli_delim(":"); cli_puts(name); cli_delim("\n");
|
||||
cli_puts("name");
|
||||
cli_delim(":");
|
||||
cli_puts(name);
|
||||
cli_delim("\n");
|
||||
}
|
||||
rhizome_manifest_free(m);
|
||||
if (mout != m)
|
||||
@ -1178,14 +1198,16 @@ int app_rhizome_import_bundle(int argc, const char *const *argv, struct command_
|
||||
cli_puts(alloca_tohex(m->cryptoSignPublic, RHIZOME_MANIFEST_ID_BYTES));
|
||||
cli_delim("\n");
|
||||
}
|
||||
cli_puts("filehash");
|
||||
cli_delim(":");
|
||||
cli_puts(m->fileHexHash);
|
||||
cli_delim("\n");
|
||||
cli_puts("filesize");
|
||||
cli_delim(":");
|
||||
cli_printf("%lld", m->fileLength);
|
||||
cli_delim("\n");
|
||||
if (m->fileLength != 0) {
|
||||
cli_puts("filehash");
|
||||
cli_delim(":");
|
||||
cli_puts(m->fileHexHash);
|
||||
cli_delim("\n");
|
||||
}
|
||||
const char *name = rhizome_manifest_get(m, "name", NULL, 0);
|
||||
if (name) {
|
||||
cli_puts("name");
|
||||
|
75
rhizome.c
75
rhizome.c
@ -83,7 +83,7 @@ int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out,
|
||||
}
|
||||
|
||||
/* Add the manifest and its associated file to the Rhizome database. */
|
||||
m->dataFileName=strdup(filename);
|
||||
m->dataFileName = strdup(filename);
|
||||
if (rhizome_manifest_check_file(m))
|
||||
return WHY("File does not belong to manifest");
|
||||
int ret=rhizome_manifest_check_duplicate(m,NULL);
|
||||
@ -207,15 +207,19 @@ int rhizome_manifest_bind_file(rhizome_manifest *m_in,const char *filename,int e
|
||||
DEBUGF("filename=%s, fileLength=%lld", filename, m_in->fileLength);
|
||||
rhizome_manifest_set_ll(m_in,"filesize",m_in->fileLength);
|
||||
|
||||
/* Compute hash of payload */
|
||||
char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (rhizome_hash_file(m_in,filename, hexhashbuf))
|
||||
return WHY("Could not hash file.");
|
||||
memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
|
||||
|
||||
/* Store hash of payload */
|
||||
rhizome_manifest_set(m_in, "filehash", m_in->fileHexHash);
|
||||
m_in->fileHashedP=1;
|
||||
/* Compute hash of non-empty payload */
|
||||
if (m_in->fileLength != 0) {
|
||||
char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (rhizome_hash_file(m_in,filename, hexhashbuf))
|
||||
return WHY("Could not hash file.");
|
||||
memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
|
||||
rhizome_manifest_set(m_in, "filehash", m_in->fileHexHash);
|
||||
m_in->fileHashedP = 1;
|
||||
} else {
|
||||
m_in->fileHexHash[0] = '\0';
|
||||
rhizome_manifest_del(m_in, "filehash");
|
||||
m_in->fileHashedP = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -237,34 +241,43 @@ int rhizome_manifest_check_file(rhizome_manifest *m_in)
|
||||
|
||||
/* Check payload file is accessible and discover its length, then check that it matches
|
||||
the file size stored in the manifest */
|
||||
long long mfilesize = rhizome_manifest_get_ll(m_in, "filesize");
|
||||
m_in->fileLength = 0;
|
||||
if (m_in->dataFileName[0]) {
|
||||
struct stat stat;
|
||||
if (lstat(m_in->dataFileName,&stat))
|
||||
return WHYF("Could not stat() payload file '%s'",m_in->dataFileName);
|
||||
m_in->fileLength = stat.st_size;
|
||||
} else
|
||||
m_in->fileLength = 0;
|
||||
if (lstat(m_in->dataFileName,&stat) == -1) {
|
||||
if (errno != ENOENT || mfilesize != 0)
|
||||
return WHYF_perror("stat(%s)", m_in->dataFileName);
|
||||
} else {
|
||||
m_in->fileLength = stat.st_size;
|
||||
}
|
||||
}
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("filename=%s, fileLength=%lld", m_in->dataFileName, m_in->fileLength);
|
||||
long long mfilesize = rhizome_manifest_get_ll(m_in, "filesize");
|
||||
if (mfilesize != -1 && mfilesize != m_in->fileLength) {
|
||||
WHYF("Manifest.filesize (%lld) != actual file size (%lld)", mfilesize, m_in->fileLength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compute hash of payload */
|
||||
char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (rhizome_hash_file(m_in,m_in->dataFileName, hexhashbuf))
|
||||
return WHY("Could not hash file.");
|
||||
memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
|
||||
m_in->fileHashedP = 1;
|
||||
|
||||
/* Check that payload hash matches manifest */
|
||||
/* If payload is empty, ensure manifest has not file hash, otherwis compute the hash of the
|
||||
payload and check that it matches manifest. */
|
||||
const char *mhexhash = rhizome_manifest_get(m_in, "filehash", NULL, 0);
|
||||
if (!mhexhash) return WHY("manifest contains no file hash");
|
||||
if (mhexhash && strcmp(m_in->fileHexHash, mhexhash)) {
|
||||
WHYF("Manifest.filehash (%s) does not match payload hash (%s)", mhexhash, m_in->fileHexHash);
|
||||
return -1;
|
||||
if (m_in->fileLength != 0) {
|
||||
char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (rhizome_hash_file(m_in,m_in->dataFileName, hexhashbuf))
|
||||
return WHY("Could not hash file.");
|
||||
memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
|
||||
m_in->fileHashedP = 1;
|
||||
if (!mhexhash) return WHY("manifest contains no file hash");
|
||||
if (mhexhash && strcmp(m_in->fileHexHash, mhexhash)) {
|
||||
WHYF("Manifest.filehash (%s) does not match payload hash (%s)", mhexhash, m_in->fileHexHash);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (mhexhash != NULL) {
|
||||
WHYF("Manifest.filehash (%s) should be absent for empty payload", mhexhash);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -324,8 +337,6 @@ int rhizome_add_manifest(rhizome_manifest *m_in,int ttl)
|
||||
|
||||
/* If the manifest already has an ID */
|
||||
char id[SID_STRLEN + 1];
|
||||
char ofilehash[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
ofilehash[0] = '\0';
|
||||
if (rhizome_manifest_get(m_in, "id", id, SID_STRLEN + 1)) {
|
||||
str_toupper_inplace(id);
|
||||
/* Discard the new manifest unless it is newer than the most recent known version with the same ID */
|
||||
@ -346,10 +357,6 @@ int rhizome_add_manifest(rhizome_manifest *m_in,int ttl)
|
||||
default:
|
||||
return WHY("Select found too many rows!");
|
||||
}
|
||||
strbuf b = strbuf_local(ofilehash, sizeof ofilehash);
|
||||
sqlite_exec_strbuf(b, "SELECT filehash from manifests where id='%s';", id);
|
||||
if (strbuf_overrun(b))
|
||||
return WHYF("fileid too long: '%s'", strbuf_str(b));
|
||||
} else {
|
||||
/* no manifest ID */
|
||||
return WHY("Manifest does not have an ID");
|
||||
|
@ -177,6 +177,7 @@ char *rhizome_manifest_get(const rhizome_manifest *m, const char *var, char *out
|
||||
long long rhizome_manifest_get_ll(rhizome_manifest *m, const char *var);
|
||||
int rhizome_manifest_set_ll(rhizome_manifest *m,char *var,long long value);
|
||||
int rhizome_manifest_set(rhizome_manifest *m, const char *var, const char *value);
|
||||
int rhizome_manifest_del(rhizome_manifest *m, const char *var);
|
||||
long long rhizome_file_size(char *filename);
|
||||
void _rhizome_manifest_free(const char *sourcefile,const char *funcname,int line,
|
||||
rhizome_manifest *m);
|
||||
|
@ -281,6 +281,10 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu
|
||||
WARNF("Missing filehash field");
|
||||
m->errors++;
|
||||
}
|
||||
if (have_filehash && m->fileLength == 0) {
|
||||
WARNF("Spurious filehash field");
|
||||
m->errors++;
|
||||
}
|
||||
|
||||
// TODO Determine group membership here.
|
||||
|
||||
@ -370,13 +374,33 @@ double rhizome_manifest_get_double(rhizome_manifest *m,char *var,double default_
|
||||
return default_value;
|
||||
}
|
||||
|
||||
/* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_manifest_del(rhizome_manifest *m, const char *var)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
for (i = 0; i < m->var_count; ++i)
|
||||
if (strcmp(m->vars[i], var) == 0) {
|
||||
free(m->vars[i]);
|
||||
free(m->values[i]);
|
||||
--m->var_count;
|
||||
m->finalised = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
for (; i < m->var_count; ++i) {
|
||||
m->vars[i] = m->vars[i + 1];
|
||||
m->values[i] = m->values[i + 1];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rhizome_manifest_set(rhizome_manifest *m, const char *var, const char *value)
|
||||
{
|
||||
if (!m)
|
||||
return WHY("m == NULL");
|
||||
int i;
|
||||
|
||||
if (!m) return -1;
|
||||
|
||||
for(i=0;i<m->var_count;i++)
|
||||
if (!strcmp(m->vars[i],var)) {
|
||||
free(m->values[i]);
|
||||
@ -384,14 +408,12 @@ int rhizome_manifest_set(rhizome_manifest *m, const char *var, const char *value
|
||||
m->finalised=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->var_count>=MAX_MANIFEST_VARS) return -1;
|
||||
|
||||
if (m->var_count >= MAX_MANIFEST_VARS)
|
||||
return WHY("no more manifest vars");
|
||||
m->vars[m->var_count]=strdup(var);
|
||||
m->values[m->var_count]=strdup(value);
|
||||
m->var_count++;
|
||||
m->finalised=0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -622,27 +644,31 @@ int rhizome_manifest_dump(rhizome_manifest *m, const char *msg)
|
||||
|
||||
int rhizome_manifest_finalise(rhizome_manifest *m)
|
||||
{
|
||||
/* set fileHexHash */
|
||||
if (!m->fileHashedP) {
|
||||
if (rhizome_hash_file(m,m->dataFileName,m->fileHexHash))
|
||||
return WHY("rhizome_hash_file() failed during finalisation of manifest.");
|
||||
m->fileHashedP=1;
|
||||
/* set fileLength and "filesize" var */
|
||||
if (m->dataFileName[0]) {
|
||||
struct stat stat;
|
||||
if (lstat(m->dataFileName, &stat)) {
|
||||
WHY_perror("lstat");
|
||||
return WHY("Could not stat() associated file");
|
||||
}
|
||||
m->fileLength = stat.st_size;
|
||||
} else
|
||||
m->fileLength = 0;
|
||||
rhizome_manifest_set_ll(m, "filesize", m->fileLength);
|
||||
|
||||
/* set fileLength */
|
||||
if (m->dataFileName[0]) {
|
||||
struct stat stat;
|
||||
if (lstat(m->dataFileName, &stat)) {
|
||||
WHY_perror("lstat");
|
||||
return WHY("Could not stat() associated file");
|
||||
}
|
||||
m->fileLength = stat.st_size;
|
||||
} else
|
||||
m->fileLength = 0;
|
||||
/* set fileHexHash and "filehash" var */
|
||||
if (m->fileLength != 0) {
|
||||
if (!m->fileHashedP) {
|
||||
if (rhizome_hash_file(m, m->dataFileName, m->fileHexHash))
|
||||
return WHY("rhizome_hash_file() failed during finalisation of manifest.");
|
||||
m->fileHashedP = 1;
|
||||
}
|
||||
rhizome_manifest_set(m, "filehash", m->fileHexHash);
|
||||
} else {
|
||||
m->fileHexHash[0] = '\0';
|
||||
m->fileHashedP = 0;
|
||||
rhizome_manifest_del(m, "filehash");
|
||||
}
|
||||
|
||||
/* Set file hash and size information */
|
||||
rhizome_manifest_set(m,"filehash",m->fileHexHash);
|
||||
rhizome_manifest_set_ll(m,"filesize",m->fileLength);
|
||||
|
||||
/* set fileHighestPriority based on group associations.
|
||||
XXX - Should probably be set as groups are added */
|
||||
|
@ -165,7 +165,7 @@ int rhizome_opendb()
|
||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "CREATE INDEX IF NOT EXISTS IDX_MANIFESTS_HASH ON MANIFESTS(filehash);");
|
||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "DELETE FROM MANIFESTS WHERE filehash IS NULL;");
|
||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "DELETE FROM FILES WHERE NOT EXISTS( SELECT 1 FROM MANIFESTS WHERE MANIFESTS.filehash = FILES.id);");
|
||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "DELETE FROM MANIFESTS WHERE NOT EXISTS( SELECT 1 FROM FILES WHERE MANIFESTS.filehash = FILES.id);");
|
||||
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "DELETE FROM MANIFESTS WHERE filehash != '' AND NOT EXISTS( SELECT 1 FROM FILES WHERE MANIFESTS.filehash = FILES.id);");
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
@ -527,21 +527,14 @@ int rhizome_store_bundle(rhizome_manifest *m)
|
||||
} else {
|
||||
/* We don't have the secret for this manifest, so only allow updates if
|
||||
the self-signature is valid */
|
||||
if (!m->selfSigned) {
|
||||
WHY("*** Insert into manifests failed (-2).");
|
||||
if (!m->selfSigned)
|
||||
return WHY("Manifest is not signed, and I don't have the key. Manifest might be forged or corrupt.");
|
||||
}
|
||||
}
|
||||
|
||||
char manifestid[RHIZOME_MANIFEST_ID_STRLEN + 1];
|
||||
rhizome_manifest_get(m, "id", manifestid, sizeof manifestid);
|
||||
str_toupper_inplace(manifestid);
|
||||
|
||||
char filehash[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
strncpy(filehash, m->fileHexHash, sizeof filehash);
|
||||
str_toupper_inplace(filehash);
|
||||
|
||||
|
||||
char *err;
|
||||
int sql_ret;
|
||||
sqlite3_stmt *stmt;
|
||||
@ -550,14 +543,21 @@ int rhizome_store_bundle(rhizome_manifest *m)
|
||||
unsigned char bar[RHIZOME_BAR_BYTES];
|
||||
rhizome_manifest_to_bar(m,bar);
|
||||
|
||||
// we should add the file in the same transaction, but closing the blob seems to cause some issues.
|
||||
/* Store the file */
|
||||
// TODO encrypted payloads - pass encryption key here
|
||||
if (m->fileLength>0){
|
||||
if (rhizome_store_file(m,NULL)){
|
||||
char filehash[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
if (m->fileLength > 0) {
|
||||
if (!m->fileHashedP)
|
||||
return WHY("Manifest payload hash unknown");
|
||||
strncpy(filehash, m->fileHexHash, sizeof filehash);
|
||||
str_toupper_inplace(filehash);
|
||||
// TODO encrypted payloads - pass encryption key here
|
||||
// We should add the file in the same transaction, but closing the blob seems to cause some issues.
|
||||
if (rhizome_store_file(m, NULL)) {
|
||||
WHY("Could not store file");
|
||||
sql_ret = 1;
|
||||
}
|
||||
} else {
|
||||
filehash[0] = '\0';
|
||||
}
|
||||
|
||||
if (!rhizome_db) rhizome_opendb();
|
||||
@ -697,6 +697,7 @@ int rhizome_list_manifests(const char *service, const char *sender_sid, const ch
|
||||
break;
|
||||
}
|
||||
const char *q_manifestid = (const char *) sqlite3_column_text(statement, 0);
|
||||
DEBUGF("id = %s", q_manifestid);
|
||||
const char *manifestblob = (char *) sqlite3_column_blob(statement, 1);
|
||||
size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob()
|
||||
long long q_version = sqlite3_column_int64(statement, 2);
|
||||
@ -976,8 +977,6 @@ int rhizome_update_file_priority(const char *fileid)
|
||||
int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
|
||||
int checkVersionP)
|
||||
{
|
||||
if (!m->fileHashedP)
|
||||
return WHY("Manifest payload is not hashed");
|
||||
const char *service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||
const char *name = NULL;
|
||||
const char *sender = NULL;
|
||||
@ -996,29 +995,37 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
|
||||
return WHYF("Unsupported service '%s'", service);
|
||||
}
|
||||
char sqlcmd[1024];
|
||||
char *s = sqlcmd;
|
||||
s += snprintf(s, &sqlcmd[sizeof sqlcmd] - s,
|
||||
"SELECT id, manifest, version FROM manifests"
|
||||
" WHERE filehash = ?"
|
||||
);
|
||||
if (checkVersionP && s < &sqlcmd[sizeof sqlcmd])
|
||||
s += snprintf(s, sqlcmd + sizeof(sqlcmd) - s, " AND version = ?");
|
||||
if (s >= &sqlcmd[sizeof sqlcmd])
|
||||
return WHY("SQL command too long");
|
||||
strbuf b = strbuf_local(sqlcmd, sizeof sqlcmd);
|
||||
strbuf_puts(b, "SELECT id, manifest, version FROM manifests WHERE ");
|
||||
if (m->fileLength != 0) {
|
||||
if (!m->fileHashedP)
|
||||
return WHY("Manifest payload is not hashed");
|
||||
strbuf_puts(b, "filehash = ?");
|
||||
} else
|
||||
strbuf_puts(b, "filesize = 0");
|
||||
if (checkVersionP)
|
||||
strbuf_puts(b, " AND version = ?");
|
||||
if (strbuf_overrun(b))
|
||||
return WHYF("SQL command too long: %s", strbuf_str(b));
|
||||
int ret = 0;
|
||||
sqlite3_stmt *statement;
|
||||
const char *cmdtail;
|
||||
if (debug&DEBUG_RHIZOME) DEBUGF("sql query: %s",sqlcmd);
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("sql query: %s", sqlcmd);
|
||||
if (sqlite3_prepare_v2(rhizome_db, sqlcmd, strlen(sqlcmd) + 1, &statement, &cmdtail) != SQLITE_OK) {
|
||||
ret = WHY(sqlite3_errmsg(rhizome_db));
|
||||
} else {
|
||||
int field = 1;
|
||||
char filehash[RHIZOME_FILEHASH_STRLEN + 1];
|
||||
strncpy(filehash, m->fileHexHash, sizeof filehash);
|
||||
str_toupper_inplace(filehash);
|
||||
if (debug & DEBUG_RHIZOME) DEBUGF("filehash=\"%s\"", filehash);
|
||||
sqlite3_bind_text(statement, 1, filehash, -1, SQLITE_STATIC);
|
||||
if (m->fileLength != 0) {
|
||||
strncpy(filehash, m->fileHexHash, sizeof filehash);
|
||||
str_toupper_inplace(filehash);
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("filehash=\"%s\"", filehash);
|
||||
sqlite3_bind_text(statement, field++, filehash, -1, SQLITE_STATIC);
|
||||
}
|
||||
if (checkVersionP)
|
||||
sqlite3_bind_int64(statement, 2, m->version);
|
||||
sqlite3_bind_int64(statement, field++, m->version);
|
||||
size_t rows = 0;
|
||||
while (sqlite3_step(statement) == SQLITE_ROW) {
|
||||
++rows;
|
||||
@ -1071,16 +1078,24 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found,
|
||||
q_manifestid, q_version, blob_version);
|
||||
++inconsistent;
|
||||
}
|
||||
if (!blob_filehash && strcasecmp(blob_filehash, m->fileHexHash)) {
|
||||
WARNF("MANIFESTS row id=%s joined to FILES row id=%s has inconsistent blob: blob.filehash=%s -- skipped",
|
||||
q_manifestid, m->fileHexHash, blob_filehash);
|
||||
++inconsistent;
|
||||
}
|
||||
if (blob_filesize != -1 && blob_filesize != m->fileLength) {
|
||||
WARNF("MANIFESTS row id=%s joined to FILES row id=%s has inconsistent blob: known file size %lld, blob.filesize=%lld -- skipped",
|
||||
q_manifestid, m->fileHexHash, m->fileLength, blob_filesize);
|
||||
++inconsistent;
|
||||
}
|
||||
if (m->fileLength != 0) {
|
||||
if (!blob_filehash && strcasecmp(blob_filehash, m->fileHexHash)) {
|
||||
WARNF("MANIFESTS row id=%s joined to FILES row id=%s has inconsistent blob: blob.filehash=%s -- skipped",
|
||||
q_manifestid, m->fileHexHash, blob_filehash);
|
||||
++inconsistent;
|
||||
}
|
||||
} else {
|
||||
if (!blob_filehash) {
|
||||
WARNF("MANIFESTS row id=%s joined to FILES row id=%s has inconsistent blob: blob.filehash should be absent -- skipped",
|
||||
q_manifestid, m->fileHexHash);
|
||||
++inconsistent;
|
||||
}
|
||||
}
|
||||
if (checkVersionP && q_version != m->version) {
|
||||
WARNF("SELECT query with version=%lld returned incorrect row: manifests.version=%lld -- skipped", m->version, q_version);
|
||||
++inconsistent;
|
||||
@ -1182,23 +1197,30 @@ int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest **mp)
|
||||
const char *blob_service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||
if (blob_service == NULL)
|
||||
ret = WHY("Manifest is missing 'service' field");
|
||||
long long filesizeq = rhizome_manifest_get_ll(m, "filesize");
|
||||
if (filesizeq == -1)
|
||||
ret = WHY("Manifest is missing 'filesize' field");
|
||||
else
|
||||
m->fileLength = filesizeq;
|
||||
const char *blob_filehash = rhizome_manifest_get(m, "filehash", NULL, 0);
|
||||
if (blob_filehash == NULL)
|
||||
ret = WHY("Manifest is missing 'filehash' field");
|
||||
else {
|
||||
memcpy(m->fileHexHash, blob_filehash, RHIZOME_FILEHASH_STRLEN + 1);
|
||||
m->fileHashedP = 1;
|
||||
if (m->fileLength != 0) {
|
||||
if (blob_filehash == NULL)
|
||||
ret = WHY("Manifest is missing 'filehash' field");
|
||||
else {
|
||||
memcpy(m->fileHexHash, blob_filehash, RHIZOME_FILEHASH_STRLEN + 1);
|
||||
m->fileHashedP = 1;
|
||||
}
|
||||
} else {
|
||||
if (blob_filehash != NULL)
|
||||
WARN("Manifest contains spurious 'filehash' field");
|
||||
m->fileHexHash[0] = '\0';
|
||||
m->fileHashedP = 0;
|
||||
}
|
||||
long long blob_version = rhizome_manifest_get_ll(m, "version");
|
||||
if (blob_version == -1)
|
||||
ret = WHY("Manifest is missing 'version' field");
|
||||
else
|
||||
m->version = blob_version;
|
||||
long long filesizeq = rhizome_manifest_get_ll(m, "filesize");
|
||||
if (filesizeq == -1)
|
||||
ret = WHY("Manifest is missing 'filesize' field");
|
||||
else
|
||||
m->fileLength = filesizeq;
|
||||
if (ret == 1) {
|
||||
cli_puts("service"); cli_delim(":");
|
||||
cli_puts(blob_service); cli_delim("\n");
|
||||
@ -1208,10 +1230,12 @@ 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");
|
||||
cli_puts("filehash"); cli_delim(":");
|
||||
cli_puts(m->fileHexHash); cli_delim("\n");
|
||||
cli_puts("filesize"); cli_delim(":");
|
||||
cli_printf("%lld", (long long) m->fileLength); cli_delim("\n");
|
||||
if (m->fileLength != 0) {
|
||||
cli_puts("filehash"); cli_delim(":");
|
||||
cli_puts(m->fileHexHash); cli_delim("\n");
|
||||
}
|
||||
// Could write the manifest blob to the CLI output here, but that would require the output to
|
||||
// support byte[] fields as well as String fields.
|
||||
}
|
||||
|
@ -381,20 +381,41 @@ int rhizome_position_candidate(int position)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rhizome_import_received_bundle(struct rhizome_manifest *m)
|
||||
{
|
||||
// TODO: We already have the manifest struct in memory, should import the bundle
|
||||
// directly from that, not by writing it to a file and re-reading it!
|
||||
const char *id = rhizome_manifest_get(m, "id", NULL, 0);
|
||||
if (id == NULL) {
|
||||
WHY("Manifest missing ID");
|
||||
return;
|
||||
}
|
||||
if (create_rhizome_import_dir() == -1)
|
||||
return;
|
||||
char filename[1024];
|
||||
if (!FORM_RHIZOME_IMPORT_PATH(filename, "manifest.%s", id))
|
||||
return;
|
||||
/* Do really write the manifest unchanged */
|
||||
m->finalised = 1;
|
||||
m->manifest_bytes = m->manifest_all_bytes;
|
||||
if (debug & DEBUG_RHIZOME_RX) {
|
||||
DEBUGF("manifest bid=%s len=%d has %d signatories", id, m->manifest_bytes, m->sig_count);
|
||||
dump("manifest", m->manifestdata, m->manifest_all_bytes);
|
||||
}
|
||||
if (rhizome_write_manifest_file(m, filename) != -1)
|
||||
rhizome_bundle_import(m, NULL, id, m->ttl - 1 /* TTL */);
|
||||
}
|
||||
|
||||
/* Verifies manifests as late as possible to avoid wasting time. */
|
||||
int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, struct sockaddr_in *peerip)
|
||||
{
|
||||
IN();
|
||||
/* must free manifest when done with it */
|
||||
char *id=rhizome_manifest_get(m,"id",NULL,0);
|
||||
long long filesize=rhizome_manifest_get_ll(m,"filesize");
|
||||
char *id = rhizome_manifest_get(m, "id", NULL, 0);
|
||||
int priority=100; /* normal priority */
|
||||
int i;
|
||||
|
||||
m->version = rhizome_manifest_get_ll(m,"version");
|
||||
|
||||
if (debug & DEBUG_RHIZOME_RX)
|
||||
DEBUGF("Considering manifest import bid=%s version=%lld size=%lld priority=%d:", id, m->version, filesize, priority);
|
||||
DEBUGF("Considering manifest import bid=%s version=%lld size=%lld priority=%d:", id, m->version, m->fileLength, priority);
|
||||
|
||||
if (rhizome_manifest_version_cache_lookup(m)) {
|
||||
if (debug & DEBUG_RHIZOME_RX)
|
||||
@ -409,7 +430,20 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, struct sockaddr_i
|
||||
DEBUGF(" is new (have version %lld)", stored_version);
|
||||
}
|
||||
|
||||
if (m->fileLength == 0) {
|
||||
if (rhizome_manifest_verify(m) != 0) {
|
||||
WHY("Error verifying manifest when considering for import");
|
||||
/* Don't waste time looking at this manifest again for a while */
|
||||
rhizome_queue_ignore_manifest(m, peerip, 60000);
|
||||
rhizome_manifest_free(m);
|
||||
RETURN(-1);
|
||||
}
|
||||
rhizome_import_received_bundle(m);
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
/* work out where to put it in the list */
|
||||
int i;
|
||||
for(i=0;i<candidate_count;i++)
|
||||
{
|
||||
/* If this manifest is already in the list, stop.
|
||||
@ -421,11 +455,9 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, struct sockaddr_i
|
||||
/* duplicate.
|
||||
XXX - Check versions! We should replace older with newer,
|
||||
and then update position in queue based on size */
|
||||
long long list_version=rhizome_manifest_get_ll(candidates[i].manifest, "version");
|
||||
long long this_version=rhizome_manifest_get_ll(m,"version");
|
||||
if (list_version>=this_version) {
|
||||
/* this version is older than the one in the list,
|
||||
so don't list this one */
|
||||
long long list_version = rhizome_manifest_get_ll(candidates[i].manifest, "version");
|
||||
if (list_version >= m->version) {
|
||||
/* this version is older than the one in the list, so don't list this one */
|
||||
rhizome_manifest_free(m);
|
||||
RETURN(0);
|
||||
} else {
|
||||
@ -451,7 +483,7 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, struct sockaddr_i
|
||||
the list down. */
|
||||
if (candidates[i].priority>priority
|
||||
||(candidates[i].priority==priority
|
||||
&&candidates[i].size>filesize))
|
||||
&&candidates[i].size>m->fileLength))
|
||||
break;
|
||||
}
|
||||
if (i>=MAX_CANDIDATES) {
|
||||
@ -482,7 +514,7 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, struct sockaddr_i
|
||||
bytes);
|
||||
/* put new candidate in */
|
||||
candidates[i].manifest=m;
|
||||
candidates[i].size=filesize;
|
||||
candidates[i].size=m->fileLength;
|
||||
candidates[i].priority=priority;
|
||||
candidates[i].peer=*peerip;
|
||||
|
||||
@ -766,37 +798,11 @@ void rhizome_write_content(rhizome_file_fetch_record *q, char *buffer, int bytes
|
||||
/* got all of file */
|
||||
if (debug & DEBUG_RHIZOME_RX)
|
||||
DEBUGF("Received all of file via rhizome -- now to import it");
|
||||
{
|
||||
fclose(q->file);
|
||||
q->file = NULL;
|
||||
// TODO: We already have the manifest struct in memory, should import the bundle
|
||||
// directly from that, not by writing it to a file and re-reading it!
|
||||
const char *id = rhizome_manifest_get(q->manifest, "id", NULL, 0);
|
||||
if (id == NULL)
|
||||
{ WHY("Manifest missing ID"); return; }
|
||||
if (create_rhizome_import_dir() == -1)
|
||||
return;
|
||||
char filename[1024];
|
||||
if (!FORM_RHIZOME_IMPORT_PATH(filename,"manifest.%s", id))
|
||||
return;
|
||||
/* Do really write the manifest unchanged */
|
||||
if (debug & DEBUG_RHIZOME_RX) {
|
||||
DEBUGF("manifest has %d signatories",q->manifest->sig_count);
|
||||
DEBUGF("manifest bid=%s len=%d",
|
||||
rhizome_manifest_get(q->manifest, "id", NULL, 0),
|
||||
q->manifest->manifest_bytes);
|
||||
dump("manifest",&q->manifest->manifestdata[0],
|
||||
q->manifest->manifest_all_bytes);
|
||||
}
|
||||
q->manifest->finalised=1;
|
||||
q->manifest->manifest_bytes=q->manifest->manifest_all_bytes;
|
||||
if (rhizome_write_manifest_file(q->manifest,filename) != -1) {
|
||||
rhizome_bundle_import(q->manifest, NULL, id,
|
||||
q->manifest->ttl - 1 /* TTL */);
|
||||
}
|
||||
rhizome_manifest_free(q->manifest);
|
||||
q->manifest = NULL;
|
||||
}
|
||||
fclose(q->file);
|
||||
q->file = NULL;
|
||||
rhizome_import_received_bundle(q->manifest);
|
||||
rhizome_manifest_free(q->manifest);
|
||||
q->manifest = NULL;
|
||||
rhizome_fetch_close(q);
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user