示例#1
0
/**
 * @brief	Update a mail message's parent folder in the database.
 * @brief	usernum			the numerical id of the user to whom the mail message belongs.
 * @brief	messagenum		the numerical id of the target mail message of the operation.
 * @brief	source			the numerical id of the parent folder in which the mail message currently resides.
 * @brief	target			the numerical id of the destination folder which is to be the new parent of the mail message.
 * @brief	transaction		a transaction id for the database operation, in case the caller needs to roll back changes on failure.
 * @return	-1 on failure, 0 if the target message could not be located in the database, or 1 on success.
 */
int_t mail_db_update_message_folder(uint64_t usernum, uint64_t messagenum, uint64_t source, uint64_t target, int64_t transaction) {

	uint64_t result;
	MYSQL_BIND parameters[4];

	if (!usernum || !messagenum || !source || !target || transaction < 0) {
		log_pedantic("Passed an invalid message parameter.");
		return -1;
	}

	mm_wipe(parameters, sizeof(parameters));

	// Target Folder
	parameters[0].buffer_type = MYSQL_TYPE_LONGLONG;
	parameters[0].buffer_length = sizeof(uint64_t);
	parameters[0].buffer = &target;
	parameters[0].is_unsigned = true;

	// Messagenum
	parameters[1].buffer_type = MYSQL_TYPE_LONGLONG;
	parameters[1].buffer_length = sizeof(uint64_t);
	parameters[1].buffer = &messagenum;
	parameters[1].is_unsigned = true;

	// Usernum
	parameters[2].buffer_type = MYSQL_TYPE_LONGLONG;
	parameters[2].buffer_length = sizeof(uint64_t);
	parameters[2].buffer = &usernum;
	parameters[2].is_unsigned = true;

	// Source Folder
	parameters[3].buffer_type = MYSQL_TYPE_LONGLONG;
	parameters[3].buffer_length = sizeof(uint64_t);
	parameters[3].buffer = &source;
	parameters[3].is_unsigned = true;

	// Since the result is unsigned, an error is indicated by a return value of (my_ulonglong)-1.
	if ((result = stmt_exec_affected_conn(stmts.update_message_folder, parameters, transaction)) != 1 && result == (my_ulonglong)-1) {
		log_pedantic("An error occurred while trying to move a message into a different folder. { user = %lu / message = %lu / source = %lu / "
			"target = %lu / query = -1 / error = %u = %s }", usernum, messagenum, source, target, mysql_stmt_errno_d(pool_get_obj(sql_pool, transaction)),
			mysql_stmt_error_d(pool_get_obj(sql_pool, transaction)));
		return -1;
	}

#ifdef MAGMA_PEDANTIC
	else if (result > 1) {
		log_pedantic("The message folder update affected more than one database row. Since we supplied the primary key this should never happen! "
			"{ user = %lu / message = %lu / source = %lu / target = %lu }", usernum, messagenum, source, target);
		return -1;
	}
#endif

	// If the message couldn't be located we return zero.
	if (!result) {
		return 0;
	}

	return 1;
}
示例#2
0
文件: dspam.c 项目: lavabit/magma
/// HIGH: Return a result structure with the disposition, confidence, probability and signature data. Then store the analysis result with the message. Either in the DB or
/// by adding a custom header to the message. Return codes should become 0 for success, or a negative integer for errors. Add statistical updates to check and train functions.
/// Result: result=\"%s\"; class=\"%s\"; probability=%01.4f; confidence=%02.2f; signature=%lu; key=%lu;
/// Layman's terms: How spammy is this message
int_t dspam_check(uint64_t usernum, stringer_t *message, stringer_t **signature) {

	DSPAM_CTX *ctx;
	chr_t unum[20];
	uint32_t connection;
	int_t result = 2, ret;
	struct _mysql_drv_dbh dbh;
	stringer_t *tmpdir, *output;

	// Generate a string version of the dispatch number.
	if (snprintf(unum, 20, "%lu", usernum) <= 0 || !(tmpdir = spool_path(MAGMA_SPOOL_DATA))) {
		log_pedantic("Context setup error.");
		return -1;
	}
	// Initialize the DSPAM context.
	else if (!(ctx = dspam_create_d(unum, NULL, st_char_get(tmpdir), DSM_PROCESS, DSF_SIGNATURE | DSF_NOISE | DSF_WHITELIST))) {
		log_pedantic("An error occurred inside the DSPAM library. {dspam_create = NULL}");
		st_free(tmpdir);
    return -1;
 	}

	st_free(tmpdir);

	if (pool_pull(sql_pool, &connection) != PL_RESERVED) {
		log_info("Unable to get an available connection for the query.");
		dspam_destroy_d(ctx);
		return -1;
	}
	else if (sql_ping(connection) < 0 || !stmt_rebuild(connection)) {
		log_info("The database connection has been lost and the reconnection attempt failed.");
		dspam_destroy_d(ctx);
		return -1;
	}

	// Setup the database handle in a structure format.
	dbh.dbh_read = pool_get_obj(sql_pool, connection);
	dbh.dbh_write = pool_get_obj(sql_pool, connection);

	if ((ret = dspam_attach_d(ctx, &dbh))) {
   	if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}
		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while attaching to the statistical database. {dspam_attach = %i}", ret);
		dspam_destroy_d(ctx);
		return -1;
  }

	// Tokenization method and statistical algorithm.
	ctx->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
	ctx->tokenizer = DSZ_CHAIN;

	// To prevent the message tokens from being stored in the database we disable training.
	ctx->training_mode = DST_NOTRAIN;

	// This actually processes the message.
	if ((ret = dspam_process_d(ctx, st_char_get(message)))) {
		if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}
		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while analyzing an email with DSPAM. {dspam_process = %i}", ret);
		dspam_destroy_d(ctx);
    return -1;
	}

	// We assume that the SQL connection will no longer be needed.
	if ((ret = dspam_detach_d(ctx))) {
		log_pedantic("Could not detach the DB connection. {dspam_detach = %i}", ret);
		pool_release(sql_pool, connection);
		dspam_destroy_d(ctx);
    return -1;
	}

	// Return the connection to our pool.
	pool_release(sql_pool, connection);

	// Check to see if the message is junk mail.
	if (ctx->result == DSR_ISSPAM) {
		result = -2;
	}
	else {
		result = 1;
	}

	//log_pedantic("Probability: %2.4f Confidence: %2.4f, Result: %s", ctx->probability, ctx->confidence,
 	//	(ctx->result == DSR_ISSPAM) ? "JUNK" : "INNOCENT");

	// See what happens if we don't get a signature back.
	if (ctx->signature == NULL) {
		log_error("DSPAM did not return a signature. {ctx->signature = NULL}");
		dspam_destroy_d(ctx);
    return result;
  }

	// Copy over the signature.
	if (!(output = st_import(ctx->signature->data, ctx->signature->length))) {
		log_pedantic("Could not import the statistical signature. {length = %lu}", ctx->signature->length);
		dspam_destroy_d(ctx);
		return result;
  }

	if (signature) {
		*signature = output;
	}

	// Destroy the context and return the result.
	dspam_destroy_d(ctx);
	return result;
}
示例#3
0
文件: dspam.c 项目: lavabit/magma
/**
 *  @note	The disposition parameter marks whether or not the signature is currently marked as junk.
 *  		So training the signature means that it will toggle its status.
 *  @param	usernum			the numerical id of the user making the spam training request.
 *  @param	disposition		if 0, dspam will mark the signature as junk; otherwise, mark as OK.
 *  @param	signature		a managed string containing the spam signature to be trained.
 *  @return	true on success or false on failure.
 */
bool_t dspam_train(uint64_t usernum, int_t disposition, stringer_t *signature) {

	int_t ret;
	DSPAM_CTX *ctx;
	chr_t unum[20];
	stringer_t *tmpdir;
	uint32_t connection;
	struct _mysql_drv_dbh dbh;
	struct _ds_spam_signature sig;

	// Generate a string version of the dispatch number.
	if (snprintf(unum, 20, "%lu", usernum) <= 0 || !(tmpdir = spool_path(MAGMA_SPOOL_DATA))) {
		log_pedantic("Context setup error.");
		return false;
	}
	// Initialize the DSPAM context.
	else if (!(ctx = dspam_create_d(unum, NULL, st_char_get(tmpdir), DSM_PROCESS, DSF_SIGNATURE | DSF_NOISE | DSF_WHITELIST))) {
		log_pedantic("An error occurred inside the DSPAM library. {dspam_create = NULL}");
		st_free(tmpdir);
		return false;
 	}

	st_free(tmpdir);

	// Get a DB connection.
	if (pool_pull(sql_pool, &connection) != PL_RESERVED) {
		log_info("Unable to get an available connection for the query.");
		dspam_destroy_d(ctx);
		return false;
	}
	else if (sql_ping(connection) < 0 || !stmt_rebuild(connection)) {
		log_info("The database connection has been lost and the reconnection attempt failed.");
		dspam_destroy_d(ctx);
		return false;
	}

	// Setup the database handle in a structure format.
	dbh.dbh_read = pool_get_obj(sql_pool, connection);
	dbh.dbh_write = pool_get_obj(sql_pool, connection);

	if ((ret = dspam_attach_d(ctx, &dbh))) {

		if (dspam_detach_d(ctx) != 0) {
			log_pedantic("Could not detach the DB connection.");
		}

		pool_release(sql_pool, connection);
		log_pedantic("An error occurred while attaching to the statistical database. {dspam_attach = %i}", ret);
		dspam_destroy_d(ctx);
		return false;
	}

	// Tokenization method and statistical algorithm.
	ctx->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
	ctx->tokenizer = DSZ_CHAIN;

	// Setup the classification as opposite of what the original was.
	ctx->classification = disposition ? DSR_ISINNOCENT : DSR_ISSPAM;

	// Set up the context for error correction.
	ctx->source = DSS_ERROR;

	// Setup the signature.
	sig.length = st_length_get(signature);
	sig.data = st_char_get(signature);
	ctx->signature = &sig;

	// Call DSPAM, and then destroy the context.
	ret = dspam_process_d(ctx, NULL);
	dspam_detach_d(ctx);
	dspam_destroy_d(ctx);
	pool_release(sql_pool, connection);

	if (ret) {
		log_pedantic("An error occurred while training message signature. {dspam_process = %i}", ret);
		return false;
	}

	return true;
}