STDMETHODIMP InterfaceSSLCertificate::Save() { try { if (!m_pObject) return GetAccessDenied(); if (!m_pAuthentication->GetIsServerAdmin()) return m_pAuthentication->GetAccessDenied(); if (HM::PersistentSSLCertificate::SaveObject(m_pObject)) { // Add to parent collection AddToParentCollection(); } return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceWhiteListAddress::Save() { try { if (!object_) return GetAccessDenied(); if (!authentication_->GetIsServerAdmin()) return authentication_->GetAccessDenied(); if (HM::PersistentWhiteListAddress::SaveObject(object_)) { // Add to parent collection AddToParentCollection(); } return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceAntiVirus::get_BlockedAttachments(IInterfaceBlockedAttachments **pVal) { try { if (!GetIsServerAdmin()) return GetAccessDenied(); CComObject<InterfaceBlockedAttachments>* pInterface = new CComObject<InterfaceBlockedAttachments>; pInterface->SetAuthentication(authentication_); shared_ptr<HM::BlockedAttachments> pBlockedAttachments = HM::Configuration::Instance()->GetBlockedAttachments(); pInterface->Attach(pBlockedAttachments); pInterface->AddRef(); *pVal = pInterface; return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceAntiVirus::get_Action(eAntivirusAction *pVal) { try { if (!GetIsServerAdmin()) return GetAccessDenied(); switch (antiVirusConfiguration_.AVAction()) { case HM::AntiVirusConfiguration::ActionDelete: *pVal = hDeleteEmail; break; case HM::AntiVirusConfiguration::ActionStripAttachments: *pVal = hDeleteAttachments; break; } return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceDatabase::CreateExternalDatabase(eDBtype ServerType, BSTR ServerName, long lPort, BSTR DatabaseName, BSTR Username, BSTR Password) { try { if (!config_) return GetAccessDenied(); if (!GetIsServerAdmin()) return GetAccessDenied(); const HM::String sEmpty; const HM::String sServerName = ServerName; const HM::String sDatabaseName = DatabaseName; const HM::String sUsername = Username; const HM::String sPassword = Password; if (sDatabaseName.Find(_T(" ")) >= 0) return COMError::GenerateError("The database name may not contain spaces."); // Create a settings object for the connection ... std::shared_ptr<HM::DatabaseSettings> pSettings = std::shared_ptr<HM::DatabaseSettings>( new HM::DatabaseSettings(sServerName, sEmpty, sUsername, sPassword, sEmpty, sEmpty,(HM::DatabaseSettings::SQLDBType) ServerType, lPort)); // Connect to the database serve std::shared_ptr<HM::DALConnection> pConn = HM::DALConnectionFactory::CreateConnection(pSettings); HM::String sErrorMessage; if (pConn->Connect(sErrorMessage) != HM::DALConnection::Connected) return COMError::GenerateError(sErrorMessage); // Create the database HM::String sCreateDB = HM::SQLStatement::GetCreateDatabase(pSettings, sDatabaseName); if (!pConn->Execute(HM::SQLCommand(sCreateDB), sErrorMessage, 0, 0)) return COMError::GenerateError(sErrorMessage); // Disconnect again. pConn->Disconnect(); // Create a new settings object where we specify the database name as well. pSettings = std::shared_ptr<HM::DatabaseSettings>( new HM::DatabaseSettings(sServerName, sDatabaseName, sUsername, sPassword, sEmpty, sEmpty,(HM::DatabaseSettings::SQLDBType) ServerType, lPort)); // Reconnect to the new database. pConn = HM::DALConnectionFactory::CreateConnection(pSettings); if (pConn->Connect(sErrorMessage) != HM::DALConnection::Connected) return COMError::GenerateError(sErrorMessage); // Run the scripts HM::SQLScriptRunner scriptRunner; if (!scriptRunner.ExecuteScript(pConn, pSettings->GetDefaultScript(), sErrorMessage)) return COMError::GenerateError(sErrorMessage); ini_file_settings_->SetDatabaseDirectory(""); ini_file_settings_->SetDatabaseType((HM::DatabaseSettings::SQLDBType) ServerType); ini_file_settings_->SetUsername(sUsername); ini_file_settings_->SetPassword(sPassword); ini_file_settings_->SetDatabasePort(lPort); ini_file_settings_->SetDatabaseServer(sServerName); ini_file_settings_->SetDatabaseName(sDatabaseName); ini_file_settings_->SetIsInternalDatabase(false); return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceDatabase::CreateInternalDatabase() { try { if (!config_) return GetAccessDenied(); if (!GetIsServerAdmin()) return GetAccessDenied(); // Make sure we have the latest settings. ini_file_settings_->LoadSettings(); HM::String sDirectory = ini_file_settings_->GetDatabaseDirectory(); HM::String sDatabaseName = "hMailServer"; HM::String sPassword = HM::PasswordGenerator::Generate(); HM::String sErrorMessage; if (!HM::SQLCEConnection::CreateDatabase(sDirectory, sDatabaseName, sPassword, sErrorMessage)) return COMError::GenerateError(sErrorMessage); HM::String sEmpty; // Create a settings object which we use to connect to the server. std::shared_ptr<HM::DatabaseSettings> pSettings = std::shared_ptr<HM::DatabaseSettings>( new HM::DatabaseSettings(sEmpty, sDatabaseName, sEmpty, sPassword, sDirectory, sEmpty, HM::DatabaseSettings::TypeMSSQLCompactEdition, 0)); // Connect to the new database std::shared_ptr<HM::DALConnection> pConn = HM::DALConnectionFactory::CreateConnection(pSettings); if (pConn->Connect(sErrorMessage) != HM::DALConnection::Connected) { return COMError::GenerateError(sErrorMessage); } // Create the tables HM::SQLScriptRunner scriptRunner; if (!scriptRunner.ExecuteScript(pConn, pSettings->GetDefaultScript(), sErrorMessage)) { return COMError::GenerateError(sErrorMessage); } ini_file_settings_->SetDatabaseDirectory(sDirectory); ini_file_settings_->SetDatabaseType(HM::DatabaseSettings::TypeMSSQLCompactEdition); ini_file_settings_->SetUsername(""); ini_file_settings_->SetPassword(sPassword); ini_file_settings_->SetDatabasePort(0); ini_file_settings_->SetDatabaseServer(""); ini_file_settings_->SetDatabaseName(sDatabaseName); ini_file_settings_->SetIsInternalDatabase(true); return S_OK; } catch (_com_error &err) { _bstr_t bstrSource(err.Source()); _bstr_t bstrDescription(err.Description()); LPCSTR lpcSource = bstrSource; HM::String sErrSource = lpcSource; LPCSTR lpcDesc = bstrDescription; HM::String sErrDesc = lpcDesc; return COMError::GenerateGenericMessage(); } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceMessages::DeleteByDBID(hyper lDBID) { try { if (!messages_) return GetAccessDenied(); std::shared_ptr<HM::Message> pMsg = messages_->GetItemByDBID(lDBID); if (!pMsg) { // No such message exists return DISP_E_BADINDEX; } // Expunge the mailbox. Will cause the message to be // deleted from disk and database. std::function<bool(int, std::shared_ptr<HM::Message>)> filter = [lDBID](int index, std::shared_ptr<HM::Message> message) { if (message->GetID() == lDBID) { return true; } return false; }; messages_->DeleteMessages(filter); // If we're aren't browsing in the message cache already, // we need to delete the message from the cache now. This // is needed if the messages are accessed using the // Account.Messages property. When messages are accessed // via Account.IMAPFolders, we access the message cache // directly, and when we don't need to remove message here. // (Since it was done like 10 lines up). __int64 iFolderID = messages_->GetFolderID(); if (iFolderID == -1) { // We're not browsing the message cache. __int64 iAccountID = messages_->GetAccountID(); std::vector<__int64> affectedMessages; affectedMessages.push_back(lDBID); // Notify clients that the message has been dropped. std::shared_ptr<HM::ChangeNotification> notification = std::shared_ptr<HM::ChangeNotification>(new HM::ChangeNotification(messages_->GetAccountID(), messages_->GetFolderID(), HM::ChangeNotification::NotificationMessageDeleted, affectedMessages)); HM::Application::Instance()->GetNotificationServer()->SendNotification(notification); } return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }
STDMETHODIMP InterfaceMessage::Save() { try { if (!m_pObject) return GetAccessDenied(); // Check that the message has a valid date header. HM::String sDate = _GetMessageData()->GetSentTime(); if (sDate.IsEmpty()) { // Date was not specified. Specify it now. sDate = HM::Time::GetCurrentMimeDate(); _GetMessageData()->SetSentTime(sDate); } shared_ptr<const HM::Account> account; if (m_pObject->GetAccountID() > 0) { account = HM::CacheContainer::Instance()->GetAccount(m_pObject->GetAccountID()); } // Save the message to disk. const HM::String fileName = HM::PersistentMessage::GetFileName(account, m_pObject); if (!_GetMessageData()->Write(fileName)) { return COMError::GenerateError("Unable to write to message file."); } // A message can be in a number of different states: // Case 1) New message which should be delivered -> Save in file and add to database // Case 2) New message which should be added to an existing IMAP folder -> Update message file and save to database// // case 3) Existing message which is being delivered. -> Only update the message fil // Case 4) Existing message in IMAP folder which should just be re-saved -> Update message file HM::Message::State state = m_pObject->GetState(); switch (state) { case HM::Message::Created: { // Handle new message. It can either be Case 1 or Case 2. If the message is already // connected to an account, it means that it should be stored in a specific IMAP folder if (m_pObject->GetFolderID() == 0 && m_pObject->GetAccountID() == 0) { // Case 1: The message should be delivered. Change the state to delivering m_pObject->SetState(HM::Message::Delivering); if (!HM::PersistentMessage::SaveObject(m_pObject)) { return COMError::GenerateError("Message could not be saved in database."); } HM::Application::Instance()->SubmitPendingEmail(); } else { // Case 2. It's a new message but it should be added to an existing IMAP folder. m_pObject->SetState(HM::Message::Delivered); return _SaveNewMessageToIMAPFolder(); } break; } case HM::Message::Delivering: { // Handle message which is being delivered. Saving in database will be taken // care about by the delivery process. Since the file has already been updated // on disk, there's not more for us to do here. break; } case HM::Message::Delivered: { // The message has already been delivered. It's placed inside an account mailbox. // All we need to do is to update it in the database. if (!HM::PersistentMessage::SaveObject(m_pObject)) return S_FALSE; break; } default: { // Unhandled case. return COMError::GenerateError("The message could not be saevd. It is in an unknown state."); } } return S_OK; } catch (...) { return COMError::GenerateGenericMessage(); } }