bool 
   PersistentGreyList::AddObject(shared_ptr<GreyListTriplet> pTriplet)
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Adds a new greylist triple into the database.
   //---------------------------------------------------------------------------()
   {
      String sSenderAddress = pTriplet->GetSenderAddress().Left(200);
      String sRecipientAddress = pTriplet->GetRecipientAddress().Left(200);
   
      // Update the triplet
      SQLStatement oStatement;

      IPAddressSQLHelper helper;

      oStatement.SetTable("hm_greylisting_triplets");
      oStatement.AddColumn("glcreatetime", pTriplet->GetCreateTime());
      oStatement.AddColumn("glblockendtime", pTriplet->GetBlockEndTime());
      oStatement.AddColumn("gldeletetime", pTriplet->GetDeleteTime());
      
      helper.AppendStatement(oStatement, pTriplet->GetIPAddress(), "glipaddress1", "glipaddress2");

      oStatement.AddColumn("glsenderaddress", sSenderAddress);
      oStatement.AddColumn("glrecipientaddress", sRecipientAddress);
      oStatement.AddColumn("glpassedcount", "0");
      oStatement.AddColumn("glblockedcount", "0");

      oStatement.SetStatementType(SQLStatement::STInsert);
      oStatement.SetIdentityColumn("glid");

      bool bResult = Application::Instance()->GetDBManager()->Execute(oStatement, 0, DALConnection::DALErrorInSQL);

      return bResult;
   }
   bool 
   PersistentBlockedAttachment::SaveObject(shared_ptr<BlockedAttachment> pObject)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_blocked_attachments");
      
      if (pObject->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("baid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         String sWhere;
         sWhere.Format(_T("baid = %I64d"), pObject->GetID());
         oStatement.SetWhereClause(sWhere);
         
      }

      oStatement.AddColumn(_T("bawildcard"), pObject->GetWildcard());
      oStatement.AddColumn(_T("badescription"), pObject->GetDescription());

      bool bNewObject = pObject->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pObject->SetID((int) iDBID);


      return true;
   }
   bool
   PersistentFetchAccountUID::SaveObject(shared_ptr<FetchAccountUID> pUID, String &result)
   {
      SQLStatement oStatement;

      oStatement.SetTable("hm_fetchaccounts_uids");

      oStatement.AddColumnInt64("uidfaid", pUID->GetAccountID());
      oStatement.AddColumn("uidvalue", pUID->GetUID());
      oStatement.AddColumnDate("uidtime", pUID->GetCreationDate());

      if (pUID->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("uidid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         oStatement.SetWhereClause(Formatter::Format("uidid = {0}", pUID->GetID()));
      }

      bool bNewObject = pUID->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pUID->SetID((int) iDBID);

      return bRetVal;

   }
   bool
   PersistentRouteAddress::SaveObject(shared_ptr<RouteAddress> pRA)
   {

      SQLStatement oStatement;
      oStatement.AddColumnInt64("routeaddressrouteid", pRA->GetRouteID());
      oStatement.AddColumn("routeaddressaddress", pRA->GetAddress());

      oStatement.SetTable("hm_routeaddresses");

      if (pRA->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("routeaddressid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("routeaddressid = %I64d"), pRA->GetID());
         oStatement.SetWhereClause(sWhere);
      }

      bool bNewObject = pRA->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pRA->SetID((int) iDBID);

      return bRetVal;
   }
   bool
   PersistentSecurityRange::Exists(const String &name)
   {
      String whereClause = "rangename = '" + SQLStatement::Escape(name) + "'";

      SQLStatement oStatement;
      oStatement.SetStatementType(SQLStatement::STSelect);
      oStatement.SetTable("hm_securityranges");
      oStatement.AddColumn("count(*) as c");
      oStatement.SetWhereClause(whereClause);

      shared_ptr<DALRecordset> pRS = Application::Instance()->GetDBManager()->OpenRecordset(oStatement);
      if (!pRS)
         return false;

      bool bRetVal = false;
      if (!pRS->IsEOF())
      {
         int count = pRS->GetLongValue("c");
         if (count > 0)
            return true;
      }

      return false;
   }
   bool
   PersistentSecurityRange::SaveObject(shared_ptr<SecurityRange> pSR, String &result)
   {
      if (!Validate(pSR, result))
         return false;

      DateTime rangeExpiresTime = pSR->GetExpiresTime();
      if (rangeExpiresTime.GetStatus() != DateTime::valid)
         rangeExpiresTime.SetDateTime(2001,01,01,0,0,0);

      String name = pSR->GetName();
      if (name.GetLength() > 100)
         name = name.Mid(0, 100);

      IPAddressSQLHelper helper;

      SQLStatement oStatement;
      oStatement.SetTable("hm_securityranges");

      oStatement.AddColumn("rangename", name);
      oStatement.AddColumn("rangepriorityid", pSR->GetPriority());

      helper.AppendStatement(oStatement, pSR->GetLowerIP(), "rangelowerip1", "rangelowerip2");
      helper.AppendStatement(oStatement, pSR->GetUpperIP(), "rangeupperip1", "rangeupperip2");

      oStatement.AddColumn("rangeoptions", pSR->GetOptions());
      oStatement.AddColumn("rangeexpires", pSR->GetExpires());
      oStatement.AddColumn("rangeexpirestime", Time::GetTimeStampFromDateTime(rangeExpiresTime));

      if (pSR->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("rangeid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("rangeid = %I64d"), pSR->GetID());
         oStatement.SetWhereClause(sWhere);
      }


      bool bNewObject = pSR->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pSR->SetID((int) iDBID);

      if (!bRetVal)
         result = "Failed to save. Please see the hMailServer error log for details.";

      return bRetVal;
   }
   /*
      Delete metadata info for messages no longer in the system.
   */
   bool 
   PersistentMessageMetaData::DeleteOrphanedItems()
   {
      SQLStatement statement;
      statement.SetTable("hm_message_metadata");
      statement.SetStatementType(SQLStatement::STDelete);
      statement.SetWhereClause("not exists (select messageid from hm_messages where messageid = metadata_messageid)");;

      return Application::Instance()->GetDBManager()->Execute(statement);
   }
   bool 
   PersistentTCPIPPort::SaveObject(shared_ptr<TCPIPPort> pObject)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_tcpipports");
      
      if (pObject->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("portid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         String sWhere;
         sWhere.Format(_T("portid = %I64d"), pObject->GetID());
         oStatement.SetWhereClause(sWhere);
         
      }

      __int64 iAddress = 0;

      IPAddressSQLHelper helper;
      

      oStatement.AddColumn("portprotocol", pObject->GetProtocol());
      oStatement.AddColumn("portnumber", pObject->GetPortNumber());
      oStatement.AddColumnInt64("portsslcertificateid", pObject->GetSSLCertificateID());
      helper.AppendStatement(oStatement, pObject->GetAddress(), "portaddress1", "portaddress2");
      //JDR: Added to store the the UseSTARTLS setting.
      if (pObject->GetUseSSL() == true)
      {
         oStatement.AddColumn("portusessl", 1);
      }
      else if ( pObject->GetUseSTARTTLS() == true)
      {
         oStatement.AddColumn("portusessl", 2);
      }
      else
      {
         oStatement.AddColumn("portusessl", 0);
      }
     //JDR: end edit

      bool bNewObject = pObject->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pObject->SetID((int) iDBID);


      return true;
   }
   bool
   PersistentAlias::ReadObject(std::shared_ptr<Alias> pAlias, const String & sName)
   {
      SQLStatement statement;

      statement.SetStatementType(SQLStatement::STSelect);
      statement.SetTable("hm_aliases");
      statement.AddWhereClauseColumn("aliasname", sName);

      return ReadObject(pAlias, statement.GetCommand());
   }
   bool
   PersistentDistributionList::ReadObject(std::shared_ptr<DistributionList> pDistList, const String &sAddress)
   {
      SQLStatement statement;

      statement.SetStatementType(SQLStatement::STSelect);
      statement.SetTable("hm_distributionlists");
      statement.AddWhereClauseColumn("distributionlistaddress", sAddress);

      return ReadObject(pDistList, statement.GetCommand());
   }  
   bool 
   PersistentTCPIPPort::SaveObject(std::shared_ptr<TCPIPPort> pObject, String &errorMessage, PersistenceMode mode)
   {
      if (mode == PersistenceModeNormal)
      {
         if (pObject->GetSSLCertificateID() == 0 &&
             (pObject->GetConnectionSecurity() == CSSSL || pObject->GetConnectionSecurity() == CSSTARTTLSOptional || pObject->GetConnectionSecurity() == CSSTARTTLSRequired))
         {
            errorMessage = "Certificate must be specified.";
            return false;
         }
      }

      SQLStatement oStatement;
      oStatement.SetTable("hm_tcpipports");

      if (pObject->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("portid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         String sWhere;
         sWhere.Format(_T("portid = %I64d"), pObject->GetID());
         oStatement.SetWhereClause(sWhere);
         
      }

      __int64 iAddress = 0;

      IPAddressSQLHelper helper;
      

      oStatement.AddColumn("portprotocol", pObject->GetProtocol());
      oStatement.AddColumn("portnumber", pObject->GetPortNumber());
      oStatement.AddColumnInt64("portsslcertificateid", pObject->GetSSLCertificateID());
      helper.AppendStatement(oStatement, pObject->GetAddress(), "portaddress1", "portaddress2");
      oStatement.AddColumn("portconnectionsecurity", pObject->GetConnectionSecurity());
      
      bool bNewObject = pObject->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pObject->SetID((int) iDBID);


      return true;
   }
bool
PersistentAccount::ReadObject(boost::shared_ptr<Account> pAccount, const String & sAddress)
{
    SQLStatement statement;
    statement.SetStatementType(SQLStatement::STSelect);
    statement.SetTable("hm_accounts");
    statement.AddWhereClauseColumn("accountaddress", sAddress);

    bool bResult = ReadObject(pAccount, statement.GetCommand());

    return bResult;

}
   bool 
   PersistentFetchAccount::SaveObject(shared_ptr<FetchAccount> pFA)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_fetchaccounts");

      bool bNewObject = pFA->GetID() == 0;

      oStatement.AddColumnInt64("faaccountid", pFA->GetAccountID());
      oStatement.AddColumn("faactive", pFA->GetActive() ? 1 : 0);
      oStatement.AddColumn("faaccountname", pFA->GetName());
      oStatement.AddColumn("faserveraddress", pFA->GetServerAddress());
      oStatement.AddColumn("faserverport", pFA->GetPort());
      oStatement.AddColumn("faservertype", pFA->GetServerType());
      oStatement.AddColumn("fausername", pFA->GetUsername());
      oStatement.AddColumn("fapassword", Crypt::Instance()->EnCrypt(pFA->GetPassword(), Crypt::ETBlowFish));
      oStatement.AddColumn("faminutes", pFA->GetMinutesBetweenTry());
      oStatement.AddColumn("fadaystokeep", pFA->GetDaysToKeep());
      oStatement.AddColumn("fanexttry", Time::GetCurrentDateTime());
      oStatement.AddColumn("faprocessmimerecipients", pFA->GetProcessMIMERecipients());
      oStatement.AddColumn("faprocessmimedate", pFA->GetProcessMIMEDate());
      oStatement.AddColumn("fausessl", pFA->GetUseSSL());
      oStatement.AddColumn("fauseantispam", pFA->GetUseAntiSpam());
      oStatement.AddColumn("fauseantivirus", pFA->GetUseAntiVirus());
      oStatement.AddColumn("faenablerouterecipients", pFA->GetEnableRouteRecipients());

      if (bNewObject)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("faid");

         oStatement.AddColumn("falocked", 0);
      }
      else
      {
         String sWhere;
         sWhere.Format(_T("faid = %I64d"), pFA->GetID());

         oStatement.SetStatementType(SQLStatement::STUpdate);
         oStatement.SetWhereClause(sWhere);
      }

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pFA->SetID((int) iDBID);

      return bRetVal;
   }
   bool 
   PersistentLogonFailure::AddFailure(const IPAddress &ipaddress)
   {
      SQLStatement statement;

      IPAddressSQLHelper helper;
      helper.AppendStatement(statement, ipaddress, "ipaddress1", "ipaddress2");

      statement.AddColumnCommand("failuretime", SQLStatement::GetCurrentTimestamp());
      statement.SetStatementType(SQLStatement::STInsert);
      statement.SetTable("hm_logon_failures");

      return Application::Instance()->GetDBManager()->Execute(statement);
   }
   bool 
   PersistentLogonFailure::ClearOldFailures(int olderThanMinutes)
   {
      String whereClause;
      whereClause.Format(_T("failuretime < %s"), SQLStatement::GetCurrentTimestampPlusMinutes(-olderThanMinutes));

      SQLStatement statement;
      statement.SetStatementType(SQLStatement::STDelete);
      statement.SetWhereClause(whereClause);
      statement.SetTable("hm_logon_failures");

      return Application::Instance()->GetDBManager()->Execute(statement);

   }
   bool
   PersistentIMAPFolder::SaveObject(std::shared_ptr<IMAPFolder> pFolder)
   {
      bool bNewObject = true;
      if (pFolder->GetID())
         bNewObject = false;
      
      SQLStatement oStatement;
      
      oStatement.SetTable("hm_imapfolders");
      
      if (bNewObject)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("folderid");

         DateTime creationTime = pFolder->GetCreationTime();
         if (pFolder->GetCreationTime().GetStatus() == DateTime::invalid)
            pFolder->SetCreationTime(DateTime::GetCurrentTime());

         // This column is always updated by GetUniqueMessageID below
         // but we still need to create it.
         oStatement.AddColumn("foldercurrentuid", pFolder->GetCurrentUID());
         oStatement.AddColumnDate("foldercreationtime", pFolder->GetCreationTime());
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("folderid = %I64d"), pFolder->GetID());

         oStatement.SetWhereClause(sWhere);
      }

      oStatement.AddColumnInt64("folderaccountid", pFolder->GetAccountID());
      oStatement.AddColumnInt64("folderparentid", pFolder->GetParentFolderID());
      oStatement.AddColumn("foldername", pFolder->GetFolderName());
      oStatement.AddColumn("folderissubscribed", pFolder->GetIsSubscribed() ? 1 : 0);

      
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);      
      if (bRetVal && bNewObject)
         pFolder->SetID((int) iDBID);


      return true;
   }
   bool 
   PersistentRoute::SaveObject(std::shared_ptr<Route> pRoute, String &sErrorMessage, PersistenceMode mode)
   {
      if (!PreSaveLimitationsCheck::CheckLimitations(mode, pRoute, sErrorMessage))
         return false;

      SQLStatement oStatement;
      
      oStatement.SetTable("hm_routes");

      oStatement.AddColumn("routedomainname", pRoute->DomainName());
      oStatement.AddColumn("routedescription", pRoute->GetDescription());
      oStatement.AddColumn("routetargetsmthost", pRoute->TargetSMTPHost());
      oStatement.AddColumn("routetargetsmtport", pRoute->TargetSMTPPort());
      oStatement.AddColumn("routenooftries", pRoute->NumberOfTries());
      oStatement.AddColumn("routeminutesbetweentry", pRoute->MinutesBetweenTry());
      oStatement.AddColumn("routealladdresses", pRoute->ToAllAddresses() ? 1 : 0);

      oStatement.AddColumn("routeuseauthentication", pRoute->GetRelayerRequiresAuth() ? 1 : 0);
      oStatement.AddColumn("routeauthenticationusername", pRoute->GetRelayerAuthUsername());
      oStatement.AddColumn("routeauthenticationpassword", Crypt::Instance()->EnCrypt(pRoute->GetRelayerAuthPassword(), Crypt::ETBlowFish));
      oStatement.AddColumn("routetreatsecurityaslocal", pRoute->GetTreatRecipientAsLocalDomain() ? 1 : 0);
      oStatement.AddColumn("routetreatsenderaslocaldomain", pRoute->GetTreatSenderAsLocalDomain() ? 1 : 0);
      oStatement.AddColumn("routeconnectionsecurity", pRoute->GetConnectionSecurity() );

      if (pRoute->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("routeid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("routeid = %I64d"), pRoute->GetID());
         oStatement.SetWhereClause(sWhere);
      }

      bool bNewObject = pRoute->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pRoute->SetID((int) iDBID);

      return true;
   }
   bool 
   PersistentLogonFailure::ClearFailuresByIP(const IPAddress &ipaddress)
   {
      IPAddressSQLHelper helper;

      String whereClause;
      whereClause.Format(_T("ipaddress1 %s and ipaddress2 %s"), 
         String(helper.GetAddress1Equals(ipaddress)),
         String(helper.GetAddress2Equals(ipaddress)));

      SQLStatement statement;
      statement.SetStatementType(SQLStatement::STDelete);
      statement.SetWhereClause(whereClause);
      statement.SetTable("hm_logon_failures");

      return Application::Instance()->GetDBManager()->Execute(statement);
   }
   bool
   PersistentDistributionList::SaveObject(std::shared_ptr<DistributionList> pDistList, String &sErrorMessage, PersistenceMode mode)
   {
      if (!PreSaveLimitationsCheck::CheckLimitations(mode, pDistList, sErrorMessage))
         return false;

      SQLStatement oStatement;
      oStatement.SetTable("hm_distributionlists");

      oStatement.AddColumnInt64("distributionlistdomainid", pDistList->GetDomainID());
      oStatement.AddColumn("distributionlistenabled", pDistList->GetActive() ? 1 : 0);
      oStatement.AddColumn("distributionlistaddress", pDistList->GetAddress());
      oStatement.AddColumn("distributionlistrequireauth", pDistList->GetRequireAuth() ? 1 : 0);
      oStatement.AddColumn("distributionlistrequireaddress", pDistList->GetRequireAddress());
      oStatement.AddColumn("distributionlistmode", pDistList->GetListMode());

      if (pDistList->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("distributionlistid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("distributionlistid = %I64d"), pDistList->GetID());
         oStatement.SetWhereClause(sWhere);
      }

      bool bNewObject = pDistList->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pDistList->SetID((int) iDBID);

      Cache<DistributionList>::Instance()->RemoveObject(pDistList);

      return bRetVal;
   }
   bool
   PersistentAlias::SaveObject(std::shared_ptr<Alias> pAlias, String &sErrorMessage, PersistenceMode mode)
   {
      if (!PreSaveLimitationsCheck::CheckLimitations(mode, pAlias, sErrorMessage))
         return false;

      SQLStatement oStatement;
      
      oStatement.SetTable("hm_aliases");

      oStatement.AddColumnInt64("aliasdomainid", pAlias->GetDomainID());
      oStatement.AddColumn("aliasname", pAlias->GetName());
      oStatement.AddColumn("aliasvalue", pAlias->GetValue());
      oStatement.AddColumn("aliasactive", pAlias->GetIsActive());

      if (pAlias->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("aliasid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("aliasid = %I64d"), pAlias->GetID());
         oStatement.SetWhereClause(sWhere);
      }

      bool bNewObject = pAlias->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pAlias->SetID((int) iDBID);

      Cache<Alias>::Instance()->RemoveObject(pAlias);

      return bRetVal;
   }
   bool
   PersistentRuleCriteria::SaveObject(std::shared_ptr<RuleCriteria> pRuleCriteria)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_rule_criterias");

      bool bNewObject = pRuleCriteria->GetID() == 0;

      if (bNewObject)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("criteriaid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         
         String sWhere;
         sWhere.Format(_T("criteriaid = %I64d"), pRuleCriteria->GetID());
         oStatement.SetWhereClause(sWhere);

      }

      oStatement.AddColumnInt64("criteriaruleid", pRuleCriteria->GetRuleID());
      oStatement.AddColumn("criteriausepredefined", pRuleCriteria->GetUsePredefined());
      oStatement.AddColumn("criteriapredefinedfield", pRuleCriteria->GetPredefinedField());
      oStatement.AddColumn("criteriaheadername", pRuleCriteria->GetHeaderField());
      oStatement.AddColumn("criteriamatchtype", pRuleCriteria->GetMatchType());
      oStatement.AddColumn("criteriamatchvalue", pRuleCriteria->GetMatchValue());

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pRuleCriteria->SetID((int) iDBID);

      return bRetVal;

   }
   bool 
   PersistentGroupMember::SaveObject(shared_ptr<GroupMember> pObject)
   {
      SQLStatement oStatement;

      oStatement.AddColumnInt64("membergroupid", pObject->GetGroupID());
      oStatement.AddColumnInt64("memberaccountid", pObject->GetAccountID());

      oStatement.SetTable("hm_group_members");


      if (pObject->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("memberid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("memberid = %I64d"), pObject->GetID());

         oStatement.SetWhereClause(sWhere);

      }

      bool bNewObject = pObject->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pObject->SetID((long) iDBID);

      Cache<Group, PersistentGroup>::Instance()->RemoveObject(pObject->GetGroupID());

      return bRetVal;     
   }
   bool 
   PersistentDomainAlias::SaveObject(shared_ptr<DomainAlias> oDA, String &sErrorMessage)
   {
      if (!PreSaveLimitationsCheck::CheckLimitations(oDA, sErrorMessage))
         return false;

      SQLStatement oStatement;
      oStatement.SetTable("hm_domain_aliases");

      bool bNewObject = oDA->GetID() == 0;

      oStatement.AddColumnInt64("dadomainid", oDA->GetDomainID());
      oStatement.AddColumn("daalias", oDA->GetAlias());

      if (bNewObject)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("daid");
      }
      else
      {
         String sWhere;
         sWhere.Format(_T("daid = %I64d"), oDA->GetID());

         oStatement.SetStatementType(SQLStatement::STUpdate);
         oStatement.SetWhereClause(sWhere);
      }

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         oDA->SetID((int) iDBID);

      ObjectCache::Instance()->SetDomainAliasesNeedsReload();

      return true;
   }
   bool 
   PersistentMessageMetaData::SaveObject(boost::shared_ptr<MessageMetaData> metaData)
   {
      SQLStatement statement;
      statement.SetTable("hm_message_metadata");
      statement.SetStatementType(SQLStatement::STInsert);
      statement.SetIdentityColumn("metadata_id");
      statement.AddColumn("metadata_accountid", metaData->GetAccountID());
      statement.AddColumn("metadata_folderid", metaData->GetFolderID());
      statement.AddColumnInt64("metadata_messageid", metaData->GetMessageID());
      statement.AddColumnDate("metadata_dateutc", metaData->GetDate());
      statement.AddColumn("metadata_from", metaData->GetFrom(), 100);
      statement.AddColumn("metadata_subject", metaData->GetSubject(), 100);
      statement.AddColumn("metadata_to", metaData->GetTo(), 100);
      statement.AddColumn("metadata_cc", metaData->GetCC(), 100);

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(statement, &iDBID);
      metaData->SetID((int) iDBID);

      return bRetVal;
   }
   bool 
   PersistentSURBLServer::SaveObject(shared_ptr<SURBLServer> pObject)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_surblservers");
      
      if (pObject->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("surblid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);
         String sWhere;
         sWhere.Format(_T("surblid = %I64d"), pObject->GetID());
         oStatement.SetWhereClause(sWhere);
         
      }

      oStatement.AddColumn("surblactive", pObject->GetIsActive() == 1);
      oStatement.AddColumn("surblhost", pObject->GetDNSHost());
      oStatement.AddColumn("surblrejectmessage", pObject->GetRejectMessage());
      oStatement.AddColumn("surblscore", pObject->GetScore());

      bool bNewObject = pObject->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pObject->SetID((int) iDBID);


      return true;
   }
   bool
   PersistentIncomingRelay::SaveObject(boost::shared_ptr<IncomingRelay> pSR)
   {
      SQLStatement oStatement;
      oStatement.SetTable("hm_incoming_relays");

      oStatement.AddColumn("relayname", pSR->GetName());

      IPAddressSQLHelper helper;

      helper.AppendStatement(oStatement, pSR->GetLowerIP(), "relaylowerip1", "relaylowerip2");
      helper.AppendStatement(oStatement, pSR->GetUpperIP(), "relayupperip1", "relayupperip2");

      if (pSR->GetID() == 0)
      {
         oStatement.SetStatementType(SQLStatement::STInsert);
         oStatement.SetIdentityColumn("relayid");
      }
      else
      {
         oStatement.SetStatementType(SQLStatement::STUpdate);

         String sWhere;
         sWhere.Format(_T("relayid = %d"), (unsigned int) pSR->GetID());
         oStatement.SetWhereClause(sWhere);
      }

      bool bNewObject = pSR->GetID() == 0;

      // Save and fetch ID
      __int64 iDBID = 0;
      bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
      if (bRetVal && bNewObject)
         pSR->SetID((int) iDBID);
      return bRetVal;
   }
bool
PersistentAccount::SaveObject(boost::shared_ptr<Account> pAccount, String &sErrorMessage, bool createInbox)
{
    if (!PreSaveLimitationsCheck::CheckLimitations(pAccount, sErrorMessage))
        return false;

    __int64 iID = pAccount->GetID();
    if (iID > 0)
    {
        // First read the domain to see if we've changed its name.
        boost::shared_ptr<Account> tempAccount = boost::shared_ptr<Account>(new Account());
        if (!PersistentAccount::ReadObject(tempAccount, iID))
            return false;

        if (tempAccount->GetAddress().CompareNoCase(pAccount->GetAddress()) != 0)
        {
            // Check if this account contains messages with full path. If so, the user cannot
            // rename it at this point.
            // Disallow change, if not all files are partial in the database.
            if (!PersistentMessage::GetAllMessageFilesArePartialNames())
            {
                sErrorMessage = "As of hMailServer 5.4, partial file names are stored in the database, rather than the full path\r\n"
                                "To be able to rename the account, you must first migrate your database to the new partial paths scheme. To do\r\n"
                                "this, run Data Directory Synchronizer.";
                return false;
            }

            // Name has been changed. Rename all sub objects first.
            NameChanger nameChanger;
            if (!nameChanger.RenameAccount(tempAccount->GetAddress(), pAccount, sErrorMessage))
                return false;

            // Remove the old account from the cache.
            Cache<Account, PersistentAccount>::Instance()->RemoveObject(tempAccount->GetAddress());
        }
    }

    SQLStatement oStatement;
    oStatement.AddColumnInt64("accountdomainid", pAccount->GetDomainID());
    oStatement.AddColumn("accountaddress", pAccount->GetAddress());
    oStatement.AddColumn("accountpassword", pAccount->GetPassword());
    oStatement.AddColumn("accountactive", pAccount->GetActive());
    oStatement.AddColumn("accountisad", pAccount->GetIsAD());
    oStatement.AddColumn("accountaddomain", pAccount->GetADDomain());
    oStatement.AddColumn("accountadusername", pAccount->GetADUsername());
    oStatement.AddColumn("accountmaxsize", pAccount->GetAccountMaxSize());

    oStatement.AddColumn("accountvacationmessageon", pAccount->GetVacationMessageIsOn());
    oStatement.AddColumn("accountvacationmessage", pAccount->GetVacationMessage());
    oStatement.AddColumn("accountvacationsubject", pAccount->GetVacationSubject());
    oStatement.AddColumn("accountvacationexpires", pAccount->GetVacationExpires());
    oStatement.AddColumn("accountvacationexpiredate", pAccount->GetVacationExpiresDate());

    oStatement.AddColumn("accountpwencryption", pAccount->GetPasswordEncryption());
    oStatement.AddColumn("accountadminlevel", pAccount->GetAdminLevel());

    oStatement.AddColumn("accountforwardenabled", pAccount->GetForwardEnabled());
    oStatement.AddColumn("accountforwardaddress", pAccount->GetForwardAddress());
    oStatement.AddColumn("accountforwardkeeporiginal", pAccount->GetForwardKeepOriginal());

    oStatement.AddColumn("accountenablesignature", pAccount->GetEnableSignature());
    oStatement.AddColumn("accountsignatureplaintext", pAccount->GetSignaturePlainText());
    oStatement.AddColumn("accountsignaturehtml", pAccount->GetSignatureHTML());

    oStatement.AddColumn("accountlastlogontime", pAccount->GetLastLogonTime());

    oStatement.AddColumn("accountpersonfirstname", pAccount->GetPersonFirstName());
    oStatement.AddColumn("accountpersonlastname", pAccount->GetPersonLastName());

    oStatement.SetTable("hm_accounts");


    if (pAccount->GetID() == 0)
    {
        oStatement.SetStatementType(SQLStatement::STInsert);
        oStatement.SetIdentityColumn("accountid");
    }
    else
    {
        oStatement.SetStatementType(SQLStatement::STUpdate);

        String sWhere;
        sWhere.Format(_T("accountid = %I64d"), pAccount->GetID());

        oStatement.SetWhereClause(sWhere);

    }

    bool bNewObject = pAccount->GetID() == 0;

    // Save and fetch ID
    __int64 iDBID = 0;
    bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
    if (bRetVal && bNewObject)
    {
        pAccount->SetID((long) iDBID);

        if (createInbox)
        {
            if (!CreateInbox(*pAccount))
            {
                PersistentAccount::DeleteObject(pAccount);
            }
        }
    }

    if (!bNewObject)
        Cache<Account, PersistentAccount>::Instance()->RemoveObject(pAccount);

    return bRetVal;
}
Exemple #28
0
bool
PersistentRule::SaveObject(shared_ptr<Rule> pRule)
{
    SQLStatement oStatement;
    oStatement.SetTable("hm_rules");

    bool bNewObject = pRule->GetID() == 0;

    if (bNewObject)
    {
        oStatement.SetStatementType(SQLStatement::STInsert);
        oStatement.SetIdentityColumn("ruleid");
    }
    else
    {
        oStatement.SetStatementType(SQLStatement::STUpdate);
        String sWhere;
        sWhere.Format(_T("ruleid = %I64d"), pRule->GetID());
        oStatement.SetWhereClause(sWhere);
    }

    oStatement.AddColumnInt64("ruleaccountid", pRule->GetAccountID());
    oStatement.AddColumn("rulename", pRule->GetName());
    oStatement.AddColumn("ruleactive", 0);
    oStatement.AddColumn("ruleuseand", pRule->GetUseAND());
    oStatement.AddColumn("rulesortorder", pRule->GetSortOrder());

    // Save and fetch ID
    __int64 iDBID = 0;
    bool bRetVal = Application::Instance()->GetDBManager()->Execute(oStatement, bNewObject ? &iDBID : 0);
    if (bRetVal && bNewObject)
        pRule->SetID((int) iDBID);

    // Save criterias.
    __int64 iRuleID = pRule->GetID();
    shared_ptr<RuleCriterias> pRuleCriterias = pRule->GetCriterias();
    for (int i = 0; i < pRuleCriterias->GetCount(); i++)
    {
        shared_ptr<RuleCriteria> pRuleCriteria = pRuleCriterias->GetItem(i);
        pRuleCriteria->SetRuleID(iRuleID);
        PersistentRuleCriteria::SaveObject(pRuleCriteria);
    }

    // Save actions
    shared_ptr<RuleActions> pRuleActions = pRule->GetActions();
    for (int i = 0; i < pRuleActions->GetCount(); i++)
    {
        shared_ptr<RuleAction> pRuleAction = pRuleActions->GetItem(i);
        pRuleAction->SetRuleID(iRuleID);
        PersistentRuleAction::SaveObject(pRuleAction);
    }

    // Set the rule to active again.
    SQLCommand command("update hm_rules set ruleactive = @ACTIVE where ruleid = @RULEID");
    command.AddParameter("@ACTIVE", pRule->GetActive());
    command.AddParameter("@RULEID", iRuleID);

    bRetVal = Application::Instance()->GetDBManager()->Execute(command);

    _NotifyReload(pRule);

    return bRetVal;

}
   // 2011-11-15 JDR: Modified this function to include quickIndex to pick a specific query.
   set<boost::shared_ptr<PersistentMessageMetaData::MessageInfo> >
   PersistentMessageMetaData::GetMessagesToIndex(bool quickIndex = false)
   {
      set<boost::shared_ptr<MessageInfo> > result;

      SQLStatement statement;
      statement.AddColumn("messageid");
      statement.AddColumn("messageaccountid");
      statement.AddColumn("messagefolderid");
      statement.AddColumn("messagefilename");
      statement.AddColumn("accountaddress");
      statement.SetStatementType(SQLStatement::STSelect);
      statement.SetTable("hm_messages");
      // Are we doing a quick index? 
      if (quickIndex == true) {
         // 1000 default
         int iIndexerQuickLimit = IniFileSettings::Instance()->GetIndexerQuickLimit();

         // yes, only pick the last iIndexerQuickLimit records... very quick compared to full
         String whereClause;
         whereClause.Format(_T("hm_messages.messagetype = 2 AND hm_messages.messageid > (select max(hm_messages.messageid) - %d from hm_messages) AND hm_message_metadata.metadata_id IS NULL"), iIndexerQuickLimit);
         statement.SetWhereClause(whereClause);
         statement.SetAdditionalSQL("LEFT JOIN hm_accounts ON hm_messages.messageaccountid = hm_accounts.accountid LEFT JOIN hm_message_metadata ON hm_messages.messageid = hm_message_metadata.metadata_messageid ");

         LOG_DEBUG("Doing QUICK index...");
      } else {
         // 25000 default
         int iIndexerFullLimit = IniFileSettings::Instance()->GetIndexerFullLimit();

         // Otherwise do the old/standard way (pick iIndexerFullLimit records max)
         statement.SetWhereClause("messagetype = 2 AND NOT EXISTS (SELECT metadata_messageid FROM hm_message_metadata WHERE hm_messages.messagetype = 2 and hm_messages.messageid = hm_message_metadata.metadata_messageid)");
         statement.SetAdditionalSQL("left join hm_accounts on hm_messages.messageaccountid = hm_accounts.accountid");
         statement.SetTopRows(iIndexerFullLimit);
         LOG_DEBUG("Doing FULL index... ");
      }

      boost::shared_ptr<DALRecordset> pRS = Application::Instance()->GetDBManager()->OpenRecordset(statement);

      if (!pRS)
         return result;

      while (!pRS->IsEOF())
      {
         boost::shared_ptr<MessageInfo> messageInfo = boost::shared_ptr<MessageInfo>(new MessageInfo);
         messageInfo->MessageID = pRS->GetInt64Value("messageid");
         messageInfo->AccountID = pRS->GetLongValue("messageaccountid");
         messageInfo->FolderID = pRS->GetLongValue("messagefolderid");
         
         String accountAddress = pRS->GetStringValue("accountaddress");
         String fileName = pRS->GetStringValue("messagefilename");

         boost::shared_ptr<Message> dummyMessage = boost::shared_ptr<Message>(new Message);
         dummyMessage->SetID(messageInfo->MessageID);
         dummyMessage->SetAccountID(messageInfo->AccountID);
         dummyMessage->SetFolderID(messageInfo->FolderID);
         dummyMessage->SetPartialFileName(fileName);

         String fullPath = PersistentMessage::GetFileName(accountAddress, dummyMessage);
         
         messageInfo->FileName = fullPath;

         result.insert(messageInfo);
         pRS->MoveNext();
      }

      return result;
   }
   void
   PersistentMessageMetaData::GetMetaData(int accountID, int folderID, const String &headerField, map<__int64, String > &result)
   {
      MessageMetaData::MetaDataField field = MessageMetaData::GetMetaDataField(headerField);
      
      SQLStatement sql;
      sql.SetStatementType(SQLStatement::STSelect);
      sql.SetTable("hm_message_metadata");
      sql.AddColumn("metadata_messageid");

      switch (field)
      {
      case MessageMetaData::From:
         sql.AddColumn("metadata_from");
         break;
      case MessageMetaData::Date:
         sql.AddColumn("metadata_dateutc");
         break;
      case MessageMetaData::Subject:
         sql.AddColumn("metadata_subject");
         break;
      case MessageMetaData::To:
         sql.AddColumn("metadata_to");
         break;
      case MessageMetaData::CC:
         sql.AddColumn("metadata_cc");
         break;
      }
      
      String whereClause;
      whereClause.Format(_T("metadata_accountid = %d and metadata_folderid = %d"), accountID, folderID);
      sql.SetWhereClause(whereClause);

      boost::shared_ptr<DALRecordset> pRS = Application::Instance()->GetDBManager()->OpenRecordset(sql);

      while (!pRS->IsEOF())
      {
         String value;
         __int64 messageID = pRS->GetInt64Value("metadata_messageid");     

         switch (field)
         {
         case MessageMetaData::From:
            value = pRS->GetStringValue("metadata_from");
            break;
         case MessageMetaData::Date:
            value = pRS->GetStringValue("metadata_dateutc");
            break;
         case MessageMetaData::Subject:
            value = pRS->GetStringValue("metadata_subject");
            break;
         case MessageMetaData::To:
            value = pRS->GetStringValue("metadata_to");
            break;
         case MessageMetaData::CC:
            value = pRS->GetStringValue("metadata_cc");
            break;
         }

         result.insert(std::make_pair(messageID, value));

         pRS->MoveNext();
      }

   }