Пример #1
0
/**
 * @brief	Update a session's underlying data and its refresh timestamp.
 * @note	This function ensures the session's associated meta user data, mail folders and messages, and contact folders and contact entries are all current.
 * @param	sess	a pointer to the session object to be updated.
 * @return	This function returns no value.
 */
void sess_update(session_t *sess) {

	if (sess) {
		// Flush the update trackers to discourage unnecessary refreshes.
		sess_refresh_flush(sess);

		meta_user_update(sess->user, META_NEED_LOCK);
		meta_folders_update(sess->user, META_NEED_LOCK);
		meta_messages_update(sess->user, META_NEED_LOCK);
		meta_contacts_update(sess->user, META_NEED_LOCK);
	}

	return;
}
Пример #2
0
/**
 * Returns 0 if the selected folder wasn't modified, or 1 if things changed and the updated status should be sent to the client. A -1
 * is used to indicate the update check encountered a problem and should be retried later.
 */
int_t imap_session_update(connection_t *con) {

	int_t result = 0;
	inx_cursor_t *cursor;
	meta_message_t *active;
	uint64_t recent = 0, exists = 0, checkpoint;

	// Check for the right state.
	if (con->imap.session_state != 1 || con->imap.user == NULL || con->imap.selected == 0) {
		return -1;
	}

	if ((checkpoint = serial_get(OBJECT_USER, con->imap.user->usernum)) != con->imap.user_checkpoint) {
		meta_user_wlock(con->imap.user);

		// Update the user preferences.
		if (checkpoint != con->imap.user->serials.user) {
			meta_user_update(con->imap.user, META_LOCKED);
		}

		// Store the new checkpoint.
		con->imap.user_checkpoint = con->imap.user->serials.user;
		meta_user_unlock(con->imap.user);
	}

	if ((checkpoint = serial_get(OBJECT_FOLDERS, con->imap.user->usernum)) != con->imap.folders_checkpoint) {
		meta_user_wlock(con->imap.user);

	   // Update the list of folders.
		if (checkpoint != con->imap.user->serials.folders) {
			meta_folders_update(con->imap.user, META_LOCKED);
		}

		// Store the new checkpoint.
		con->imap.folders_checkpoint = con->imap.user->serials.folders;
		meta_user_unlock(con->imap.user);
	}

	if ((checkpoint = serial_get(OBJECT_MESSAGES, con->imap.user->usernum)) != con->imap.messages_checkpoint) {
		meta_user_wlock(con->imap.user);

		if (checkpoint != con->imap.user->serials.messages) {
			meta_messages_update(con->imap.user, META_LOCKED);
		}

		// If there is a selected folder, scan the status.
		if ((cursor = inx_cursor_alloc(con->imap.user->messages))) {

			while ((active = inx_cursor_value_next(cursor))) {

				if (active->foldernum == con->imap.selected && (active->status & MAIL_STATUS_RECENT) == MAIL_STATUS_RECENT) {
					recent++;
					exists++;
				}
				else if (active->foldernum == con->imap.selected) {
					exists++;
				}

			}

			inx_cursor_free(cursor);
		}

		// If the folder has changed, output the current status.
		if (con->imap.messages_recent != recent || con->imap.messages_total != exists) {
			con->imap.messages_recent = recent;
			con->imap.messages_total = exists;
			result = 1;
		}

		// Store the new checkpoint.
		con->imap.messages_checkpoint = con->imap.user->serials.messages;

		meta_user_unlock(con->imap.user);
	}

	return result;
}
Пример #3
0
/**
 * @brief	Lookup user and return their meta user object.
 *
 * @note	If the user is not found in the local session cache, the session will be constructed using the database, and then cached.
 *
 * @param 	usernum			the numeric identifier for the user account.
 * @param 	username		the official username stored in the database.
 * @param	salt			the user specific salt value.
 * @param	master			the user account's master encryption key which will be used to unlock the private storage key.
 * @param 	verification	the verification token.
 * @param	protocol			a set of protocol specifying the protocol used by the calling function. Values can be META_PROT_NONE,
 * 							META_PROT_SMTP, META_PROT_POP, META_PROT_IMAP, META_PROT_WEB, or META_PROT_GENERIC.
 * @param	get				a set of protocol specifying the data to be retrieved (META_GET_NONE, META_GET_MESSAGES,
 * 							META_GET_FOLDERS, or META_GET_CONTACTS)
 * @param	output			the address of a meta user object that will store a pointer to the result of the lookup.
 *
 * @return	-1 on error, 0 on success, 1 for an authentication issue.
 */
int_t meta_get(uint64_t usernum, stringer_t *username, stringer_t *salt, stringer_t *master, stringer_t *verification, META_PROTOCOL protocol, META_GET get, meta_user_t **output) {

	int_t state;
	meta_user_t *user = NULL;

	// If the auth structure is empty, or the usernum is invalid, return an error immediately.
	if (!usernum || !st_populated(username, master, verification)) {
		log_pedantic("Invalid parameters were used to get the meta data object.");
		return -1;
	}

	// Pull the user context using the usernum, or add an empty context if it doesn't exist.
	if (!(user = meta_inx_find(usernum, protocol))) {
		log_pedantic("Could not find an existing user object, nor could we create one.");
		return -1;
	}

	meta_user_wlock(user);

	// Pull the user information.
	if ((state = meta_update_user(user, META_LOCKED)) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return state;
	}

	// The auth_t object should have checked the verification token already, but we check here just to be sure.
	else if (st_empty(user->verification) || st_cmp_cs_eq(verification, user->verification)) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return 1;
	}

	// Are we supposed to get the realm keys.
	if ((get & META_GET_KEYS) && meta_update_realms(user, salt, master, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to get the mailbox keys.
	if ((get & META_GET_KEYS) && meta_update_keys(user, META_LOCKED) < 0) {

		// If key decryption fails, then the master key is likely invalid, so we need to ensure we don't cache an invalid
		// realm key as a result.
		st_cleanup(user->realm.mail);
		user->realm.mail = NULL;
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

 	 // Are we supposed to get the mailbox aliases.
	if ((get & META_GET_ALIASES) && meta_update_aliases(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to get the messages.
	if ((get & META_GET_MESSAGES) && meta_messages_update(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	if ((get & META_GET_FOLDERS) && meta_update_message_folders(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to update the folders.
	if ((get & META_GET_FOLDERS) && meta_update_folders(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	// Are we supposed to update the folders.
	if ((get & META_GET_CONTACTS) && meta_update_contacts(user, META_LOCKED) < 0) {
		meta_user_unlock(user);
		meta_inx_remove(usernum, protocol);
		return -1;
	}

	*output = user;
	meta_user_unlock(user);

	return 0;
}