コード例 #1
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionGetFileInfo(SLNSessionRef const session, strarg_t const URI, SLNFileInfo *const info) {
	DB_env *db = NULL;
	int rc = SLNSessionDBOpen(session, SLN_RDONLY, &db);
	if(rc < 0) return rc;
	DB_txn *txn = NULL;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) {
		SLNSessionDBClose(session, &db);
		return rc;
	}

	DB_cursor *cursor;
	rc = db_txn_cursor(txn, &cursor);
	assert(!rc);

	DB_range fileIDs[1];
	SLNURIAndFileIDRange1(fileIDs, txn, URI);
	DB_val URIAndFileID_key[1];
	rc = db_cursor_firstr(cursor, fileIDs, URIAndFileID_key, NULL, +1);
	DB_val file_val[1];
	if(rc >= 0) {
		strarg_t URI2;
		uint64_t fileID;
		SLNURIAndFileIDKeyUnpack(URIAndFileID_key, txn, &URI2, &fileID);
		assert(0 == strcmp(URI, URI2));
		if(info) {
			DB_val fileID_key[1];
			SLNFileByIDKeyPack(fileID_key, txn, fileID);
			rc = db_get(txn, fileID_key, file_val);
		}
	}
	if(rc < 0) {
		db_txn_abort(txn); txn = NULL;
		SLNSessionDBClose(session, &db);
		return rc;
	}

	if(info) {
		// Clear padding for later assert_zeroed.
		memset(info, 0, sizeof(*info));

		strarg_t const internalHash = db_read_string(file_val, txn);
		strarg_t const type = db_read_string(file_val, txn);
		uint64_t const size = db_read_uint64(file_val);
		info->hash = strdup(internalHash);
		info->path = SLNRepoCopyInternalPath(SLNSessionGetRepo(session), internalHash);
		info->type = strdup(type);
		info->size = size;
		if(!info->hash || !info->path || !info->type) {
			SLNFileInfoCleanup(info);
			db_txn_abort(txn); txn = NULL;
			SLNSessionDBClose(session, &db);
			return DB_ENOMEM;
		}
	}

	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	return 0;
}
コード例 #2
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionCreateSession(SLNSessionRef const session, SLNSessionRef *const out) {
	assert(out);
	if(!session) return DB_EACCES;

	SLNSessionCacheRef const cache = session->cache;
	uint64_t const userID = session->userID;
	SLNMode const mode = session->mode;
	strarg_t const username = session->username;
	DB_env *db = NULL;
	DB_txn *txn = NULL;
	SLNSessionRef alt = NULL;

	byte_t key_raw[SESSION_KEY_LEN];
	int rc = async_random(key_raw, sizeof(key_raw));
	if(rc < 0) goto cleanup;

	byte_t key_enc[SHA256_DIGEST_LENGTH];
	SHA256(key_raw, sizeof(key_raw), key_enc);

	str_t key_str[SESSION_KEY_HEX+1];
	tohex(key_str, key_enc, SESSION_KEY_LEN);
	key_str[SESSION_KEY_HEX] = '\0';

	rc = SLNSessionDBOpen(session, SLN_RDWR, &db); // TODO: Custom permission?
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDWR, &txn);
	if(rc < 0) goto cleanup;

	uint64_t const sessionID = db_next_id(SLNSessionByID, txn);
	DB_val key[1], val[1];
	SLNSessionByIDKeyPack(key, txn, sessionID);
	SLNSessionByIDValPack(val, txn, userID, key_str);
	rc = db_put(txn, key, val, DB_NOOVERWRITE_FAST);
	if(rc < 0) goto cleanup;

	rc = db_txn_commit(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	if(rc < 0) goto cleanup;

	rc = SLNSessionCreateInternal(cache, sessionID, key_raw, key_enc, userID, mode, username, &alt);
	if(rc < 0) goto cleanup;

	*out = alt; alt = NULL;

cleanup:
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	SLNSessionRelease(&alt);
	return rc;
}
コード例 #3
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionGetNextMetaMapURI(SLNSessionRef const session, strarg_t const targetURI, uint64_t *const metaMapID, str_t *out, size_t const max) {
	// TODO: We should handle URI synonyms.
	// That might mean accepting a fileID instead of targetURI...

	assert(metaMapID);
	assert(out);

	uint64_t const sessionID = SLNSessionGetID(session);
	DB_env *db = NULL;
	DB_txn *txn = NULL;
	DB_cursor *cursor = NULL;
	int rc = 0;
	size_t count = 0;

	rc = SLNSessionDBOpen(session, SLN_RDONLY, &db);
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) goto cleanup;

	rc = db_cursor_open(txn, &cursor);
	if(rc < 0) goto cleanup;

	DB_range range[1];
	DB_val key[1];
	SLNTargetURISessionIDAndMetaMapIDRange2(range, txn, targetURI, sessionID);
	SLNTargetURISessionIDAndMetaMapIDKeyPack(key, txn, targetURI, sessionID, *metaMapID);
	rc = db_cursor_seekr(cursor, range, key, NULL, +1);
	if(rc < 0) goto cleanup;

	strarg_t u;
	uint64_t s;
	SLNTargetURISessionIDAndMetaMapIDKeyUnpack(key, txn, &u, &s, metaMapID);

	DB_val row[1], val[1];
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIKeyPack(row, txn, sessionID, *metaMapID);
	rc = db_get(txn, row, val);
	if(rc < 0) goto cleanup;

	strarg_t metaURI, t;
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIValUnpack(val, txn, &metaURI, &t);
	db_assert(metaURI);

	strlcpy(out, metaURI, max); // TODO: Handle err

cleanup:
	db_cursor_close(cursor); cursor = NULL;
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	if(rc < 0) return rc;
	return count;
}
コード例 #4
0
ssize_t SLNFilterCopyURIs(SLNFilterRef const filter, SLNSessionRef const session, SLNFilterPosition *const pos, int const dir, bool const meta, str_t *URIs[], size_t const max) {
	assert(URIs);
	if(!SLNSessionHasPermission(session, SLN_RDONLY)) return DB_EACCES;
	if(0 == pos->dir) return DB_EINVAL;
	if(0 == dir) return DB_EINVAL;
	if(0 == max) return 0;

	DB_env *db = NULL;
	DB_txn *txn = NULL;
	ssize_t rc = 0;

	rc = SLNSessionDBOpen(session, SLN_RDONLY, &db);
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) goto cleanup;

	rc = SLNFilterPrepare(filter, txn);
	if(rc < 0) goto cleanup;
	rc = SLNFilterSeekToPosition(filter, pos, txn);
	if(rc < 0) goto cleanup;

	int const stepdir = pos->dir * dir;
	size_t i = 0;
	for(; i < max; i++) {
		size_t const x = stepdir > 0 ? i : max-1-i;
		rc = SLNFilterGetPosition(filter, pos, txn);
		if(DB_NOTFOUND == rc) {
			rc = 0;
			break;
		}
		rc = SLNFilterCopyURI(filter, pos->fileID, meta, txn, &URIs[x]);
		if(rc < 0) goto cleanup;
		assert(URIs[x]);
		SLNFilterStep(filter, pos->dir);
	}

	// The results should always be in the first `i` slots, even when
	// filling them in reverse order.
	if(stepdir < 0) {
		memmove(URIs+0, URIs+(max-i), sizeof(*URIs) * i);
	}

	assert(rc >= 0);
	rc = i;

cleanup:
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);

	return rc;
}
コード例 #5
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionCopyLastSubmissionURIs(SLNSessionRef const session, str_t *const outFileURI, str_t *const outMetaURI) {
	DB_env *db = NULL;
	DB_txn *txn = NULL;
	int rc = SLNSessionDBOpen(session, SLN_RDWR, &db);
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
	if(rc < 0) goto cleanup;

	if(outFileURI) {
		DB_val key[1], val[1];
		DB_VAL_STORAGE(key, DB_VARINT_MAX*2);
		db_bind_uint64(key, SLNLastFileURIBySessionID);
		db_bind_uint64(key, session->sessionID);
		DB_VAL_STORAGE_VERIFY(key);
		rc = db_get(txn, key, val);
		if(rc >= 0) {
			strarg_t const URI = db_read_string(val, txn);
			strlcpy(outFileURI, URI, SLN_URI_MAX);
		} else if(DB_NOTFOUND == rc) {
			outFileURI[0] = '\0';
			rc = 0;
		} else {
			goto cleanup;
		}
	}
	if(outMetaURI) {
		DB_val key[1], val[1];
		DB_VAL_STORAGE(key, DB_VARINT_MAX*2);
		db_bind_uint64(key, SLNLastMetaURIBySessionID);
		db_bind_uint64(key, session->sessionID);
		DB_VAL_STORAGE_VERIFY(key);
		rc = db_get(txn, key, val);
		if(rc >= 0) {
			strarg_t const URI = db_read_string(val, txn);
			strlcpy(outMetaURI, URI, SLN_URI_MAX);
		} else if(DB_NOTFOUND == rc) {
			outMetaURI[0] = '\0';
			rc = 0;
		} else {
			goto cleanup;
		}
	}

cleanup:
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	return rc;
}
コード例 #6
0
ファイル: SLNSession.c プロジェクト: seclu/stronglink
int SLNSessionAddMetaMap(SLNSessionRef const session, strarg_t const metaURI, strarg_t const targetURI) {
	uint64_t const sessionID = SLNSessionGetID(session);

	DB_env *db = NULL;
	DB_txn *txn = NULL;
	int rc = SLNSessionDBOpen(session, SLN_RDWR, &db);
	if(rc < 0) goto cleanup;
	rc = db_txn_begin(db, NULL, DB_RDWR, &txn);
	if(rc < 0) goto cleanup;

	uint64_t nextID = SLNNextMetaMapID(txn, sessionID);
	if(!nextID) rc = DB_EIO;
	if(rc < 0) goto cleanup;

	DB_val mainkey[1], mainval[1];
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIKeyPack(mainkey, txn, sessionID, nextID);
	SLNSessionIDAndMetaMapIDToMetaURIAndTargetURIValPack(mainval, txn, metaURI, targetURI);
	rc = db_put(txn, mainkey, mainval, DB_NOOVERWRITE_FAST);
	if(rc < 0) goto cleanup;

	DB_val fwdkey[1], fwdval[1];
	SLNMetaURIAndSessionIDToMetaMapIDKeyPack(fwdkey, txn, metaURI, sessionID);
	SLNMetaURIAndSessionIDToMetaMapIDValPack(fwdval, txn, nextID);
	rc = db_put(txn, fwdkey, fwdval, DB_NOOVERWRITE_FAST);
	if(rc < 0) goto cleanup;

	DB_val revkey[1], revval[1];
	SLNTargetURISessionIDAndMetaMapIDKeyPack(revkey, txn, targetURI, sessionID, nextID);
	db_nullval(revval);
	rc = db_put(txn, revkey, revval, DB_NOOVERWRITE_FAST);
	if(rc < 0) goto cleanup;

	rc = db_txn_commit(txn); txn = NULL;
cleanup:
	db_txn_abort(txn); txn = NULL;
	SLNSessionDBClose(session, &db);
	return rc;
}
コード例 #7
0
// TODO
static str_t *preview_metadata(preview_state const *const state, strarg_t const var) {
	int rc;
	strarg_t unsafe = NULL;
	str_t buf[URI_MAX];
	if(0 == strcmp(var, "rawURI")) {
		str_t algo[SLN_ALGO_SIZE]; // SLN_INTERNAL_ALGO
		str_t hash[SLN_HASH_SIZE];
		SLNParseURI(state->fileURI, algo, hash);
		snprintf(buf, sizeof(buf), "/sln/file/%s/%s", algo, hash);
		unsafe = buf;
	}
	if(0 == strcmp(var, "queryURI")) {
		str_t *escaped = QSEscape(state->fileURI, strlen(state->fileURI), true);
		snprintf(buf, sizeof(buf), "/?q=%s", escaped);
		FREE(&escaped);
		unsafe = buf;
	}
	if(0 == strcmp(var, "hashURI")) {
		unsafe = state->fileURI;
	}
	if(0 == strcmp(var, "fileSize")) {
		// TODO: Really, we should already have this info from when
		// we got the URI in the first place.
		SLNFileInfo info[1];
		rc = SLNSessionGetFileInfo(state->session, state->fileURI, info);
		if(rc >= 0) {
			double const size = info->size;
			double base = 1.0;
			strarg_t const units[] = { "B", "KB", "MB", "GB", "TB" };
			size_t i = 0;
			for(; base * 1024.0 <= size && i < numberof(units); i++) base *= 1024.0;
			if(0 == i) {
				snprintf(buf, sizeof(buf), "%.0f %s", size/base, units[i]);
			} else {
				snprintf(buf, sizeof(buf), "%.1f %s", size/base, units[i]);
			}
			unsafe = buf;
			// P.S. F**k scientific prefixes.
		}
		SLNFileInfoCleanup(info);
	}
	if(unsafe) return htmlenc(unsafe);

	str_t value[1024 * 4];
	// TODO: Load all vars for the template in one transaction.
	DB_env *db = NULL;
	rc = SLNSessionDBOpen(state->session, SLN_RDONLY, &db);
	if(rc >= 0) {
		DB_txn *txn = NULL;
		rc = db_txn_begin(db, NULL, DB_RDONLY, &txn);
		if(rc >= 0) {
			rc = SLNSessionGetValueForField(state->session, txn, state->fileURI, var, value, sizeof(value));
			if(rc >= 0 && '\0' != value[0]) unsafe = value;
			db_txn_abort(txn); txn = NULL;
		}
		SLNSessionDBClose(state->session, &db);
	}

	if(!unsafe) {
		if(0 == strcmp(var, "thumbnailURI")) unsafe = "/file.png";
		if(0 == strcmp(var, "title")) unsafe = "(no title)";
		if(0 == strcmp(var, "description")) unsafe = "(no description)";
	}

	return htmlenc(unsafe);
}