Example #1
0
void MojoDatabase::ReserveIds(Signal::SlotRef slot, int count)
{
	if (count > RESERVE_ID_MAX)
		count = RESERVE_ID_MAX;
	MojErr err = m_dbClient.reserveIds(slot, count);
	ErrorToException(err);
}
Example #2
0
void MojoDatabase::MoveDeletedEmailToTrash (Signal::SlotRef slot, const MojObject& emailId, const MojObject& trashFolderId)
{
	MojObject email;
	MojErr err = email.put(PopEmailAdapter::ID, emailId);
	ErrorToException(err);

	err = email.put(EmailSchema::FOLDER_ID, trashFolderId);
	ErrorToException(err);

	err = email.put("_del", false);
	ErrorToException(err);

	MojLogInfo(PopClient::s_log, "Moving email '%s' to trash folder '%s'", AsJsonString(emailId).c_str(), AsJsonString(trashFolderId).c_str());
	err = m_dbClient.merge(slot, email);
	ErrorToException(err);
}
void MovePopEmailsCommand::RunImpl()
{
	CommandTraceFunction();
	try {

		if (!m_client.GetAccount().get()) {
			MojString err;
			err.format("Account is not loaded for '%s'", AsJsonString(
					m_client.GetAccountId()).c_str());
			throw MailException(err.data(), __FILE__, __LINE__);
		}

		MojErr err = m_payload.getRequired("accountId", m_accountId);
		ErrorToException(err);

		m_activity = ActivityParser::GetActivityFromPayload(m_payload);

		if (m_activity.get()) {
			m_activity->SetSlots(m_activityUpdateSlot, m_activityErrorSlot);
			m_activity->Adopt(m_client);
			return;
		} else {
			GetEmailsToMove();
		}
	} catch (const std::exception& ex) {
		m_msg->replyError(MojErrInternal, ex.what());
		Failure(ex);
	} catch (...) {
		MailException ex("unknown exception", __FILE__, __LINE__);
		m_msg->replyError(MojErrInternal, ex.what());
		Failure(ex);
	}
}
void MockRequest::ReplySuccess(MojObject response)
{
	MojErr err = response.put("returnValue", true);
	ErrorToException(err);

	Reply(response, MojErrNone);
}
MojErr MovePopEmailsCommand::EmailsMovedResponse(MojObject& response, MojErr err)
{
	try {
		ErrorToException(err);

		ActivityBuilder ab;
		m_client.GetActivityBuilderFactory()->BuildMoveEmailsWatch(ab);
		m_activity->UpdateAndComplete(m_client, ab.GetActivityObject());

		m_msg->replySuccess();

		if (m_inboxEmailsMoved.size() > 0) {
			// add the list of UIDs into UidCache
			GetUidCache();
		} else {
			Complete();
		}
	} catch (const std::exception& ex) {
		m_msg->replyError(MojErrInternal, ex.what());
		Failure(ex);
	} catch (...) {
		m_msg->replyError(MojErrInternal);
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}

	return MojErrNone;
}
void SyncAccountCommand::RunImpl()
{
	try {
		if (!m_client.GetAccount().get()) {
			MojString err;
			err.format("Account is not loaded for '%s'", AsJsonString(
					m_client.GetAccountId()).c_str());
			throw MailException(err.data(), __FILE__, __LINE__);
		}

		m_account = m_client.GetAccount();
		if(m_account->HasPassword()) {
			m_accountId = m_account->GetAccountId();
			MojObject inboxFolderId = m_account->GetInboxFolderId();

			MojLogInfo(m_log, "Creating command to sync inbox emails");

			MojErr err = m_payload.put(EmailSchema::FOLDER_ID, inboxFolderId);
			ErrorToException(err);

			m_client.SyncFolder(m_payload);
		} else {
			MojLogInfo(m_log, "No password!  Sync aborted!");
		}

		Complete();
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("Unknown exception", __FILE__, __LINE__));
	}
}
Example #7
0
void MojoDatabase::UpdateAccountInitialSync(Signal::SlotRef slot, const MojObject& accountId, bool sync)
{
	//MojLogInfo(PopClient::s_log, "Updating account '%s' initialSynced to %d", AsJsonString(accountId).c_str(), sync);
	MojObject account;
	MojErr err = account.putBool(PopAccountAdapter::INITIAL_SYNC, sync);
	ErrorToException(err);

	MojDbQuery query;
	err = query.from(PopAccountAdapter::POP_ACCOUNT_KIND);
	ErrorToException(err);
	err = query.where(PopAccountAdapter::ACCOUNT_ID, MojDbQuery::OpEq, accountId);
	ErrorToException(err);

	err = m_dbClient.merge(slot, query, account);
	ErrorToException(err);
}
Example #8
0
MojRefCountedPtr<MojServiceRequest> BusClient::CreateRequest()
{
	MojRefCountedPtr<MojServiceRequest> req;
	MojErr err = m_service->createRequest(req);
	ErrorToException(err);
	return req;
}
MojErr AuthYahooCommand::GetYahooCookiesSlot(MojObject& response, MojErr err)
{
	MojLogTrace(m_log);
	try {
		ResponseToException(response, err);

		MojObject object;
		err = response.getRequired("tCookie", m_tCookie);
		ErrorToException(err);
	
		err = response.getRequired("yCookie", m_yCookie);
		ErrorToException(err);
	
	} catch (const std::exception& e) {
		MojLogInfo(m_log, "Failed to retrieve Yahoo cookies, failing login: %s", e.what());
		
		// FIXME: We should possibly try to decode and pass along a specific error
		
		SmtpSession::SmtpError error;
		error.errorCode = MailError::ACCOUNT_UNAVAILABLE;
		error.errorOnAccount = true;
		error.internalError = std::string("Unable to retrieve yahoo cookies: ") + e.what();
		m_session.AuthYahooFailure(error);
		Complete();
		
		return MojErrNone;
	} catch (...) {
		MojLogInfo(m_log, "Failed to retrieve Yahoo cookies, failing login: unknown exception");

		// FIXME: We should possibly try to decode and pass along a specific error

		SmtpSession::SmtpError error;
		error.errorCode = MailError::ACCOUNT_UNAVAILABLE;
		error.errorOnAccount = true;
		error.internalError = "Unable to retrieve yahoo cookies: unknown exception";
		m_session.AuthYahooFailure(error);
		Complete();

		return MojErrNone;
	}

	m_state = State_SendingYCookie;
	WriteCommand();
	
	return MojErrNone;
}
void AccountFinderCommand::GetAccount()
{
	CommandTraceFunction();

	try {
		MojObject params;
		MojErr err = params.put("accountId", m_accountId);
		ErrorToException(err);

		err = m_client.CreateRequest()->send(m_getAccountSlot, "com.palm.service.accounts","getAccountInfo", params);
		ErrorToException(err);
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}
}
Example #11
0
void BusClient::SendRequest(MojServiceRequest::ReplySignal::SlotRef handler, const MojChar* service,
		const MojChar* method, const MojObject& payload, MojUInt32 numReplies)
{
	MojRefCountedPtr<MojServiceRequest> req = CreateRequest();

	MojErr err = req->send(handler, service, method, payload, numReplies);
	ErrorToException(err);
}
MojString ImapActivityFactory::FormatName(const char* name, const MojObject& accountId, const MojObject& folderId)
{
	MojString formattedName;
	MojErr err = formattedName.format("%s/accountId=%s/folderId=%s",
			name, AsJsonString(accountId).c_str(), AsJsonString(folderId).c_str());
	ErrorToException(err);
	return formattedName;
}
MojErr PopAccountUpdateCommand::GetPasswordResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		// check the result first
		ErrorToException(err);

		MojObject credentials;
		err = response.getRequired("credentials", credentials);
		ErrorToException(err);

		MojString password;
		err = credentials.getRequired("password", password);
		ErrorToException(err);

		boost::shared_ptr<PopAccount> newPopAccount(new PopAccount());
		PopAccountAdapter::GetPopAccountFromTransportObject(m_transportObj, *(newPopAccount.get()));
		newPopAccount->SetPassword(password.data());

		boost::shared_ptr<PopAccount> oldPopAccount = m_client.GetAccount();

		if (!oldPopAccount.get()) {
			m_callSyncFolderOnClient = true;
		} else if (newPopAccount->GetPort() != oldPopAccount->GetPort() ||
			newPopAccount->GetEncryption() != oldPopAccount->GetEncryption() ||
			newPopAccount->GetUsername() != oldPopAccount->GetUsername() ||
			newPopAccount->GetSyncFrequencyMins() != oldPopAccount->GetSyncWindowDays() ||
			newPopAccount->GetHostName() != oldPopAccount->GetHostName()) {
			m_callSyncFolderOnClient = true;
		}
		
		// Should be initial sync if the old account does not exist 
		// or the old account is in initial sync state.
		newPopAccount->SetInitialSync(!oldPopAccount.get() || oldPopAccount->IsInitialSync());
		m_client.SetAccount(newPopAccount);
		UpdateAccountWatchActivity();
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}

	return MojErrNone;
}
Example #14
0
void MojoDatabase::UpdateEmailParts(Signal::SlotRef slot, const MojObject& emailId, const MojObject& parts, bool autoDownload)
{
	MojObject email;
	MojErr err = email.put(PopEmailAdapter::ID, emailId);
	ErrorToException(err);

	err = email.put(EmailSchema::PARTS, parts);
	ErrorToException(err);

	if ((!parts.undefined() && !parts.null() && parts.size() > 0) || !autoDownload) {
		err = email.put(PopEmailAdapter::DOWNLOADED, true);
		ErrorToException(err);
	}

	MojLogDebug(PopClient::s_log, "Updating email '%s' with parts: '%s'", AsJsonString(emailId).c_str(), AsJsonString(parts).c_str());
	err = m_dbClient.merge(slot, email);
	ErrorToException(err);
}
Example #15
0
void MojoDatabase::GetEmails(Signal::SlotRef slot, const MojObject& folderId, MojInt32 limit)
{
	MojDbQuery q;
	MojErr err = q.from(PopEmailAdapter::POP_EMAIL_KIND);
	ErrorToException(err);

	err = q.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId);
	ErrorToException(err);

	err = q.order(EmailSchema::TIMESTAMP);
	ErrorToException(err);

	q.limit(limit);
	q.desc(true);

	err = m_dbClient.find(slot, q);
	ErrorToException(err);
}
void PopAccountUpdateCommand::GetPassword()
{
	try {
		MojObject params;
		MojErr err = params.put("accountId", m_accountId);
		ErrorToException(err);

		err = params.putString("name", "common");
		ErrorToException(err);

		err = m_client.CreateRequest()->send(m_getPasswordSlot, "com.palm.service.accounts","readCredentials", params);
		ErrorToException(err);
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}
}
void FileCacheClient::ExpireCacheObject(ReplySignal::SlotRef slot, const char* pathName)
{
    MojErr err;
    MojObject payload;

    err = payload.putString("pathName", pathName);
    ErrorToException(err);

    m_busClient.SendRequest(slot, FILECACHE_SERVICE, "ExpireCacheObject", payload);
}
MojErr PopAccountUpdateCommand::CreateActivityResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();
	try {
		ErrorToException(err);

		MojString json;
		err = response.toJson(json);
		ErrorToException(err);

		Sync();
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}

	return MojErrNone;
}
void ScheduleRetryCommand::ScheduleRetry()
{
	CommandTraceFunction();

	ImapActivityFactory factory;
	ActivityBuilder ab;

	// Get current retry interval from account
	EmailAccount::RetryStatus retryStatus = m_client.GetAccount().GetRetry();

	int interval = retryStatus.GetInterval();

	if(interval < INITIAL_RETRY_SECONDS) {
		interval = INITIAL_RETRY_SECONDS;
	} else if(interval < SECOND_RETRY_SECONDS) {
		interval = SECOND_RETRY_SECONDS;
	} else if(interval >= MAX_RETRY_SECONDS) {
		interval = MAX_RETRY_SECONDS;
	} else {
		// TODO: only update this on actual retry?
		interval *= RETRY_MULTIPLIER;
	}

	// Update account just in case it wasn't within the limit
	retryStatus.SetInterval(interval);
	retryStatus.SetCount(retryStatus.GetCount() + 1);
	m_client.GetAccount().SetRetry(retryStatus);

	factory.BuildSyncRetry(ab, m_client.GetAccountId(), m_folderId, interval, m_reason);

	MojErr err;
	MojObject payload;
	err = payload.put("activity", ab.GetActivityObject());
	ErrorToException(err);
	err = payload.put("start", true);
	ErrorToException(err);
	err = payload.put("replace", true);

	MojLogInfo(m_log, "scheduling retry in %.1f minutes for account %s", float(interval) / 60, m_client.GetAccountIdString().c_str());

	m_client.SendRequest(m_scheduleRetrySlot, "com.palm.activitymanager", "create", payload);
}
MojErr UpSyncSentEmailsCommand::GetSentFolderNameResponse(MojObject& response, MojErr err)
{
	try {
			ErrorToException(err);

			MojObject folderObj;
			DatabaseAdapter::GetOneResult(response, folderObj);

			MojString sentFolderName;
			err = folderObj.getRequired(ImapFolderAdapter::SERVER_FOLDER_NAME, sentFolderName);
			ErrorToException(err);

			m_sentFolderName.assign(sentFolderName);

			GetSentEmails();

		} CATCH_AS_FAILURE

		return MojErrNone;
}
void SmtpAccountEnableCommand::CreateSmtpConfigWatch()
{
	SmtpActivityFactory factory;
	ActivityBuilder ab;

	factory.BuildSmtpConfigWatch(ab, m_client.GetAccountId(), m_accountRev);

	// Create payload
	MojObject payload;
	MojErr err;

	err = payload.put("activity", ab.GetActivityObject());
	ErrorToException(err);
	err = payload.put("start", true);
	ErrorToException(err);
	err = payload.put("replace", true);
	ErrorToException(err);

	m_client.SendRequest(m_createSmtpConfigWatchSlot, "com.palm.activitymanager", "create", payload);
}
MojErr PopAccountUpdateCommand::GetAccountResponse(MojObject& response, MojErr err)
{
	try {
		ErrorToException(err);

		MojObject results;
		err = response.getRequired(_T("results"), results);
		ErrorToException(err);

		if (results.size() > 0 && results.at(0, m_transportObj)) {
			GetPassword();
		}
	} catch (const std::exception& ex) {
		Failure(ex);
	} catch (...) {
		Failure(MailException("unknown exception", __FILE__, __LINE__));
	}

	return MojErrNone;
}
void PopAccountUpdateCommand::RunImpl()
{
	MojString json;
	MojErr err = m_payload.toJson(json);
	ErrorToException(err);
	MojLogDebug(m_log, "PopAccountUpdateCommand with payload %s", json.data());

	m_accountId = m_client.GetAccountId();
	m_activityBuilderFactory->SetAccountId(m_accountId);
	m_client.GetDatabaseInterface().GetAccount(m_getAccountSlot, m_accountId);
}
void SaveEmailCommand::WriteToFileCache(MojObject &part, const MojString &pathName)
{
	MojErr err;
	MojString content;
	err = part.getRequired("content", content);
	ErrorToException(err);
	
	// FIXME: make this async
	FILE *fp = fopen(pathName.data(), "w");
	if(fp) {
		fwrite(content.data(), sizeof(MojChar), content.length(), fp);
		fclose(fp);
	} else {
		throw MailException("error opening file cache path", __FILE__, __LINE__);
	}
	
	// Cancel subscription to signal that we're done writing
	m_fileCacheInsertedSlot.cancel();

	MojString type;
	err = part.getRequired(EmailSchema::Part::TYPE, type);
	ErrorToException(err);

	if (type == EmailSchema::Part::Type::BODY) {
		std::string previewText = PreviewTextGenerator::GeneratePreviewText(content.data(), MAX_SUMMARY_LENGTH, true);
		err = m_email.putString(EmailSchema::SUMMARY, previewText.c_str());
		ErrorToException(err);
	}

	// Delete content field so it doesn't get written to the database
	bool wasDeleted;
	part.del("content", wasDeleted);
	
	// Next step
	if(m_partsIt == m_partsArray.arrayEnd())
		PersistToDatabase(); // done
	else
		CreateNextCacheObject(); // more parts remaining
	
	return;
}
void SmtpActivityFactory::BuildSmtpConfigWatch(ActivityBuilder& ab, const MojObject& accountId, MojInt64 rev)
{
	MojErr err;

	MojString name;
	err = name.format(ACCOUNT_WATCH_ACTIVITY_FMT, AsJsonString(accountId).c_str());
	ErrorToException(err);

	// description of watch
	MojString desc;
	err = desc.format("Watches SMTP config on account %s", AsJsonString(accountId).c_str());
	ErrorToException(err);

	// activity to setup watch
	ab.SetName(name);
	ab.SetDescription(desc.data());
	ab.SetPersist(true);
	ab.SetExplicit(true);
	ab.SetRequiresInternet(false); // trigger even if we don't have a network connection
	ab.SetImmediate(true, ActivityBuilder::PRIORITY_LOW);

	// setup trigger
	// NOTE: how to trigger only on SMTP config change?
	MojDbQuery trigger;
	err = trigger.from("com.palm.mail.account:1");
	ErrorToException(err);
	err = trigger.where("accountId", MojDbQuery::OpEq, accountId);
	ErrorToException(err);

	if (rev > 0) {
		trigger.where("_revSmtp", MojDbQuery::OpGreaterThan, rev);
	}
	ab.SetDatabaseWatchTrigger(trigger);

	MojObject params;
	err = params.put("accountId", accountId);
	ErrorToException(err);

	ab.SetCallback(ACCOUNT_UPDATED_BUS_METHOD, params);
	ab.SetMetadata(params);
}
void SaveEmailCommand::CreateNextCacheObject()
{
	MojErr err;
	
	for(; m_partsIt != m_partsArray.arrayEnd(); ++m_partsIt) {
		MojObject& part = *m_partsIt;
		
		bool hasContent;
		MojString content;
		err = part.get("content", content, hasContent);
		ErrorToException(err);
		
		if(hasContent) {
			MojString cacheType;
			cacheType.assign("email");
			
			bool hasDisplayName;
			MojString displayName;
			err = part.get("displayName", displayName, hasDisplayName);
			ErrorToException(err);
			
			MojString cacheFileName;
			
			if(hasDisplayName && displayName.length() > 0) {
				cacheFileName.assign(displayName);
			} else {
				// FIXME only for HTML parts
				cacheFileName.assign("body.html");
			}
			
			MojLogDebug(m_log, "creating a file cache entry");
			m_client.GetFileCacheClient().InsertCacheObject(m_fileCacheInsertedSlot, cacheType, cacheFileName, content.length(), EMAIL_FILECACHE_COST, EMAIL_NO_LIFE_TIME);
			
			// Exit method and wait for response
			return;
		}
	}
	
	// If this is the last part with content, persist to database now
	PersistToDatabase();
}
MojErr ScheduleRetryCommand::UpdateAccountResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ErrorToException(err);

		Complete();
	} CATCH_AS_FAILURE

	return MojErrNone;
}
//  Tell SMTP that the account has been updated; only if the credentials changed
void PopAccountUpdateCommand::NotifySmtp()
{
	CommandTraceFunction();

	MojErr err;
	MojObject payload;

	err = payload.put("accountId", m_client.GetAccountId());
	ErrorToException(err);

	m_client.SendRequest(m_notifySmtpSlot, "com.palm.smtp", "credentialsChanged", payload);
}
MojErr ScheduleRetryCommand::ScheduleRetryResponse(MojObject& response, MojErr err)
{
	CommandTraceFunction();

	try {
		ErrorToException(err);

		CancelActivities();
	} CATCH_AS_FAILURE

	return MojErrNone;
}
void FileCacheClient::InsertCacheObject(ReplySignal::SlotRef slot, const char* typeName, const char* fileName, MojInt64 size, MojInt64 cost, MojInt64 lifetime)
{
    MojErr err;
    MojObject payload;

    err = payload.putString("typeName", typeName);
    ErrorToException(err);

    err = payload.putString("fileName", fileName);
    ErrorToException(err);

    // Size must be >0 and larger than the actual content.
    // If the content is empty, we'll use 1 so FileCache doesn't complain.
    err = payload.put("size", size > 0 ? size : 1);
    ErrorToException(err);

    if(cost >= 0) {
        err = payload.put("cost", cost);
        ErrorToException(err);
    }

    if(lifetime >= 0) {
        err = payload.put("lifetime", lifetime);
        ErrorToException(err);
    }

    err = payload.put("subscribe", true);
    ErrorToException(err);

    m_busClient.SendRequest(slot, FILECACHE_SERVICE, "InsertCacheObject", payload, MojServiceRequest::Unlimited);
}